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
=
32 #include "propsheet.h"
35 #include "LogSingleton.h"
36 #include "ControlAdjuster.h"
37 #include "package_db.h"
38 #include "package_meta.h"
41 // Sizing information.
42 static ControlAdjuster::ControlInfo PrereqControlsInfo
[] = {
43 {IDC_PREREQ_CHECK
, CP_LEFT
, CP_BOTTOM
},
44 {IDC_PREREQ_EDIT
, CP_STRETCH
, CP_STRETCH
},
48 extern ThreeBarProgressPage Progress
;
50 // ---------------------------------------------------------------------------
51 // implements class PrereqPage
52 // ---------------------------------------------------------------------------
54 PrereqPage::PrereqPage ()
56 sizeProcessor
.AddControlInfo (PrereqControlsInfo
);
62 return PropertyPage::Create (IDD_PREREQ
);
68 // start with the checkbox set
69 CheckDlgButton (GetHWND (), IDC_PREREQ_CHECK
, BST_CHECKED
);
71 // set the edit-area to a larger font
72 SetDlgItemFont(IDC_PREREQ_EDIT
, "MS Shell Dlg", 10);
76 PrereqPage::OnActivate()
78 // if we have gotten this far, then PrereqChecker has already run isMet
79 // and found that there were missing packages; so we can just call
80 // getUnmetString to format the results and display it
85 SetDlgItemText (GetHWND (), IDC_PREREQ_EDIT
, s
.c_str ());
87 SetFocus (GetDlgItem (IDC_PREREQ_CHECK
));
95 if (!IsDlgButtonChecked (h
, IDC_PREREQ_CHECK
))
97 // breakage imminent! danger, danger
98 int res
= MessageBox (h
,
99 "If you continue without correcting the listed conflicts, your "
100 "Cygwin installation will not function properly.\r\n"
101 "We strongly recommend that you let Setup install the listed packages.\r\n\r\n"
102 "Are you sure you want to proceed?",
103 "WARNING - Required Packages Not Selected",
104 MB_YESNO
| MB_ICONEXCLAMATION
| MB_DEFBUTTON2
);
109 "NOTE! User refused suggested missing dependencies! "
110 "Expect some packages to give errors or not function at all." << endLog
;
114 // add the missing requirements
118 if (source
== IDC_SOURCE_CWD
)
121 Progress
.SetActivateTask (WM_APP_START_INSTALL
);
125 // Next, start download from internet
126 Progress
.SetActivateTask (WM_APP_START_DOWNLOAD
);
132 PrereqPage::OnBack ()
138 // ---------------------------------------------------------------------------
139 // implements class PrereqChecker
140 // ---------------------------------------------------------------------------
142 // instantiate the static members
143 map
<packagemeta
*, vector
<packagemeta
*>, packagemeta_ltcomp
> PrereqChecker::unmet
;
144 trusts
PrereqChecker::theTrust
= TRUST_CURR
;
146 /* This function builds a list of unmet dependencies to present to the user on
147 the PrereqPage propsheet. The data is stored as an associative map of
148 unmet[missing-package] = vector of packages that depend on missing-package */
150 PrereqChecker::isMet ()
153 bool foundUnmet
= false;
155 // unmet is static - clear it each time this is called
158 // loop through each package
159 for (vector
<packagemeta
*>::iterator n
= db
.packages
.begin ();
160 n
!= db
.packages
.end (); ++n
)
162 // if the package is installed or selected to be installed...
165 // loop through each dependency
166 for (vector
<vector
<PackageSpecification
*> *>::iterator i
=
167 (*n
)->desired
.depends ()->begin ();
168 i
!= (*n
)->desired
.depends ()->end (); ++i
)
170 // XXX: the following assumes that there is only a single
171 // node in each OR clause, which is currently the case.
172 // if setup is ever pushed to use AND/OR in "depends:"
173 // lines this will have to be updated
174 PackageSpecification
*spec
= (*i
)->at(0);
176 packagemeta
*pack
= db
.findBinary (*spec
);
178 continue; // asking for a package that doesn't exist - error?
180 if (pack
->desired
&& spec
->satisfies (pack
->desired
))
187 unmet
[pack
].push_back (*n
);
196 /* Formats 'unmet' as a string for display to the user. */
198 PrereqChecker::getUnmetString (String
&s
)
202 map
<packagemeta
*, vector
<packagemeta
*>, packagemeta_ltcomp
>::iterator i
;
203 for (i
= unmet
.begin(); i
!= unmet
.end(); i
++)
205 s
= s
+ "Package: " + i
->first
->name
+ "\r\n\tRequired by: ";
206 for (unsigned int j
= 0; j
< i
->second
.size(); j
++)
208 s
+= i
->second
[j
]->name
;
209 if (j
!= i
->second
.size() - 1)
216 /* Takes the keys of 'unmet' and selects them, using the current trust. */
218 PrereqChecker::selectMissing ()
222 // provide a default, even though this should have been set for us
224 theTrust
= TRUST_CURR
;
226 // get each of the keys of 'unmet'
227 map
<packagemeta
*, vector
<packagemeta
*>, packagemeta_ltcomp
>::iterator i
;
228 for (i
= unmet
.begin(); i
!= unmet
.end(); i
++)
230 packageversion vers
= i
->first
->trustp (theTrust
);
231 i
->first
->desired
= vers
;
232 vers
.sourcePackage ().pick (false);
234 if (vers
== i
->first
->installed
)
237 log (LOG_PLAIN
) << "Adding required dependency " << i
->first
->name
<<
238 ": Selecting already-installed version " <<
239 i
->first
->installed
.Canonical_version () << "." << endLog
;
243 vers
.pick (vers
.accessible ());
244 log (LOG_PLAIN
) << "Adding required dependency " << i
->first
->name
<<
245 ": Selecting version " << vers
.Canonical_version () <<
246 " for installation." << endLog
;