2 * Copyright (c) 2005 Brian Dessent
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * A copy of the GNU General Public License can be found at
12 * Written by Brian Dessent <brian@dessent.net>
17 static const char *cvsid
=
33 #include "propsheet.h"
36 #include "LogSingleton.h"
37 #include "ControlAdjuster.h"
38 #include "package_db.h"
39 #include "package_meta.h"
42 // Sizing information.
43 static ControlAdjuster::ControlInfo PrereqControlsInfo
[] = {
44 {IDC_PREREQ_CHECK
, CP_LEFT
, CP_BOTTOM
},
45 {IDC_PREREQ_EDIT
, CP_STRETCH
, CP_STRETCH
},
49 extern ThreeBarProgressPage Progress
;
51 // ---------------------------------------------------------------------------
52 // implements class PrereqPage
53 // ---------------------------------------------------------------------------
55 PrereqPage::PrereqPage ()
57 sizeProcessor
.AddControlInfo (PrereqControlsInfo
);
63 return PropertyPage::Create (IDD_PREREQ
);
69 // start with the checkbox set
70 CheckDlgButton (GetHWND (), IDC_PREREQ_CHECK
, BST_CHECKED
);
72 // set the edit-area to a larger font
73 SetDlgItemFont(IDC_PREREQ_EDIT
, "MS Shell Dlg", 10);
77 PrereqPage::OnActivate()
79 // if we have gotten this far, then PrereqChecker has already run isMet
80 // and found that there were missing packages; so we can just call
81 // getUnmetString to format the results and display it
86 SetDlgItemText (GetHWND (), IDC_PREREQ_EDIT
, s
.c_str ());
88 SetFocus (GetDlgItem (IDC_PREREQ_CHECK
));
96 if (!IsDlgButtonChecked (h
, IDC_PREREQ_CHECK
))
98 // breakage imminent! danger, danger
99 int res
= MessageBox (h
,
100 "If you continue without correcting the listed conflicts, your "
101 "Cygwin installation will not function properly.\r\n"
102 "We strongly recommend that you let Setup install the listed packages.\r\n\r\n"
103 "Are you sure you want to proceed?",
104 "WARNING - Required Packages Not Selected",
105 MB_YESNO
| MB_ICONEXCLAMATION
| MB_DEFBUTTON2
);
110 "NOTE! User refused suggested missing dependencies! "
111 "Expect some packages to give errors or not function at all." << endLog
;
115 // add the missing requirements
119 if (source
== IDC_SOURCE_CWD
)
122 Progress
.SetActivateTask (WM_APP_START_INSTALL
);
126 // Next, start download from internet
127 Progress
.SetActivateTask (WM_APP_START_DOWNLOAD
);
133 PrereqPage::OnBack ()
139 // ---------------------------------------------------------------------------
140 // implements class PrereqChecker
141 // ---------------------------------------------------------------------------
143 // instantiate the static members
144 map
<packagemeta
*, vector
<packagemeta
*>, packagemeta_ltcomp
> PrereqChecker::unmet
;
145 trusts
PrereqChecker::theTrust
= TRUST_CURR
;
147 /* This function builds a list of unmet dependencies to present to the user on
148 the PrereqPage propsheet. The data is stored as an associative map of
149 unmet[missing-package] = vector of packages that depend on missing-package */
151 PrereqChecker::isMet ()
155 // unmet is static - clear it each time this is called
158 // packages that need to be checked for dependencies
159 queue
<packagemeta
*> todo
;
161 // go through all packages, adding desired ones to the initial work list
162 for (vector
<packagemeta
*>::iterator p
= db
.packages
.begin ();
163 p
!= db
.packages
.end (); ++p
)
169 // churn through the work list
170 while (!todo
.empty ())
172 // get the first package off the work list
173 packagemeta
*pack
= todo
.front ();
176 // Fetch the dependencies of the package. This assumes that the
177 // dependencies of the prev, curr, and exp versions are all the same.
178 vector
<vector
<PackageSpecification
*> *> *deps
= pack
->curr
.depends ();
180 // go through the package's dependencies
181 for (vector
<vector
<PackageSpecification
*> *>::iterator d
=
182 deps
->begin (); d
!= deps
->end (); ++d
)
184 // XXX: the following assumes that there is only a single
185 // node in each OR clause, which is currently the case.
186 // if setup is ever pushed to use AND/OR in "depends:"
187 // lines this will have to be updated
188 PackageSpecification
*dep_spec
= (*d
)->at(0);
189 packagemeta
*dep
= db
.findBinary (*dep_spec
);
191 if (dep
&& !(dep
->desired
&& dep_spec
->satisfies (dep
->desired
)))
193 // we've got an unmet dependency
194 if (unmet
.find (dep
) == unmet
.end ())
196 // newly found dependency: add to worklist
199 unmet
[dep
].push_back (pack
);
204 return unmet
.empty ();
207 /* Formats 'unmet' as a string for display to the user. */
209 PrereqChecker::getUnmetString (std::string
&s
)
213 map
<packagemeta
*, vector
<packagemeta
*>, packagemeta_ltcomp
>::iterator i
;
214 for (i
= unmet
.begin(); i
!= unmet
.end(); i
++)
216 s
= s
+ i
->first
->name
217 + "\t(" + i
->first
->trustp (theTrust
).Canonical_version ()
218 + ")\r\n\t" + i
->first
->SDesc ()
219 + "\r\n\tRequired by: ";
220 for (unsigned int j
= 0; j
< i
->second
.size(); j
++)
222 s
+= i
->second
[j
]->name
;
223 if (j
!= i
->second
.size() - 1)
230 /* Takes the keys of 'unmet' and selects them, using the current trust. */
232 PrereqChecker::selectMissing ()
236 // provide a default, even though this should have been set for us
238 theTrust
= TRUST_CURR
;
240 // get each of the keys of 'unmet'
241 map
<packagemeta
*, vector
<packagemeta
*>, packagemeta_ltcomp
>::iterator i
;
242 for (i
= unmet
.begin(); i
!= unmet
.end(); i
++)
244 packageversion vers
= i
->first
->trustp (theTrust
);
245 i
->first
->desired
= vers
;
246 vers
.sourcePackage ().pick (false, NULL
);
248 if (vers
== i
->first
->installed
)
250 vers
.pick (false, NULL
);
251 log (LOG_PLAIN
) << "Adding required dependency " << i
->first
->name
<<
252 ": Selecting already-installed version " <<
253 i
->first
->installed
.Canonical_version () << "." << endLog
;
257 vers
.pick (vers
.accessible (), i
->first
);
258 log (LOG_PLAIN
) << "Adding required dependency " << i
->first
->name
<<
259 ": Selecting version " << vers
.Canonical_version () <<
260 " for installation." << endLog
;