]> cygwin.com Git - cygwin-apps/setup.git/blob - prereq.cc
Use solver to check for problems and produce a list of package transactions
[cygwin-apps/setup.git] / prereq.cc
1 /*
2 * Copyright (c) 2005 Brian Dessent
3 *
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.
8 *
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by Brian Dessent <brian@dessent.net>
13 *
14 */
15
16 #include "win32.h"
17 #include <commctrl.h>
18 #include <stdio.h>
19 #include <io.h>
20 #include <ctype.h>
21 #include <process.h>
22 #include <queue>
23
24 #include "prereq.h"
25 #include "dialog.h"
26 #include "resource.h"
27 #include "state.h"
28 #include "propsheet.h"
29 #include "threebar.h"
30 #include "Generic.h"
31 #include "LogSingleton.h"
32 #include "ControlAdjuster.h"
33 #include "package_db.h"
34 #include "package_meta.h"
35 #include "msg.h"
36 #include "Exception.h"
37 #include "getopt++/BoolOption.h"
38
39 // Sizing information.
40 static ControlAdjuster::ControlInfo PrereqControlsInfo[] = {
41 {IDC_PREREQ_CHECK, CP_LEFT, CP_BOTTOM},
42 {IDC_PREREQ_EDIT, CP_STRETCH, CP_STRETCH},
43 {0, CP_LEFT, CP_TOP}
44 };
45
46 extern ThreeBarProgressPage Progress;
47 BoolOption IncludeSource (false, 'I', "include-source", "Automatically install source for every package installed");
48
49 // ---------------------------------------------------------------------------
50 // implements class PrereqPage
51 // ---------------------------------------------------------------------------
52
53 PrereqPage::PrereqPage ()
54 {
55 sizeProcessor.AddControlInfo (PrereqControlsInfo);
56 }
57
58 bool
59 PrereqPage::Create ()
60 {
61 return PropertyPage::Create (IDD_PREREQ);
62 }
63
64 void
65 PrereqPage::OnInit ()
66 {
67 // start with the checkbox set
68 CheckDlgButton (GetHWND (), IDC_PREREQ_CHECK, BST_CHECKED);
69
70 // set the edit-area to a larger font
71 SetDlgItemFont(IDC_PREREQ_EDIT, "MS Shell Dlg", 10);
72 }
73
74 void
75 PrereqPage::OnActivate()
76 {
77 // if we have gotten this far, then PrereqChecker has already run isMet
78 // and found that there were problems; so we can just call
79 // getUnmetString to format the results and display it
80
81 std::string s;
82 PrereqChecker p;
83 p.getUnmetString (s);
84 SetDlgItemText (GetHWND (), IDC_PREREQ_EDIT, s.c_str ());
85
86 SetFocus (GetDlgItem (IDC_PREREQ_CHECK));
87 }
88
89 long
90 PrereqPage::OnNext ()
91 {
92 HWND h = GetHWND ();
93
94 if (!IsDlgButtonChecked (h, IDC_PREREQ_CHECK))
95 {
96 return -1;
97 }
98
99 return whatNext();
100 }
101
102 long
103 PrereqPage::whatNext ()
104 {
105 if (source == IDC_SOURCE_LOCALDIR)
106 {
107 // Next, install
108 Progress.SetActivateTask (WM_APP_START_INSTALL);
109 }
110 else
111 {
112 // Next, start download from internet
113 Progress.SetActivateTask (WM_APP_START_DOWNLOAD);
114 }
115 return IDD_INSTATUS;
116 }
117
118 long
119 PrereqPage::OnBack ()
120 {
121 return IDD_CHOOSE;
122 }
123
124 long
125 PrereqPage::OnUnattended ()
126 {
127 // in chooser-only mode, show this page so the user can choose to fix dependency problems or not
128 if (unattended_mode == chooseronly)
129 return -1;
130
131 return whatNext();
132 }
133
134 bool
135 PrereqPage::OnMessageCmd (int id, HWND hwndctl, UINT code)
136 {
137 if ((code == BN_CLICKED) && (id == IDC_PREREQ_CHECK))
138 {
139 GetOwner ()->SetButtons (PSWIZB_BACK | (IsButtonChecked (id) ? PSWIZB_NEXT : 0));
140 return true;
141 }
142
143 return false;
144 }
145
146 // ---------------------------------------------------------------------------
147 // implements class PrereqChecker
148 // ---------------------------------------------------------------------------
149
150 // instantiate the static members
151 bool PrereqChecker::upgrade;
152 bool PrereqChecker::use_test_packages;
153
154 bool
155 PrereqChecker::isMet ()
156 {
157 packagedb db;
158
159 Progress.SetText1 ("Solving dependencies...");
160 Progress.SetText2 ("");
161 Progress.SetText3 ("");
162
163 // go through all packages, adding changed ones to the solver task list
164 SolverTasks q;
165
166 for (packagedb::packagecollection::iterator p = db.packages.begin ();
167 p != db.packages.end (); ++p)
168 {
169 packagemeta *pkg = p->second;
170
171 // decode UI state to action
172 // skip and keep don't change dependency solution
173 if (pkg->installed != pkg->desired)
174 {
175 if (pkg->desired)
176 q.add(pkg->desired, SolverTasks::taskInstall); // install/upgrade
177 else
178 q.add(pkg->installed, SolverTasks::taskUninstall); // uninstall
179 }
180 else
181 if (pkg->picked())
182 q.add(pkg->installed, SolverTasks::taskReinstall); // reinstall
183
184 // only install action makes sense for source packages
185 if (pkg->srcpicked())
186 {
187 if (pkg->desired)
188 q.add(pkg->desired.sourcePackage(), SolverTasks::taskInstall);
189 else
190 q.add(pkg->installed.sourcePackage(), SolverTasks::taskInstall);
191 }
192 }
193
194 // apply solver to those tasks and the chooser global state (keep, curr, test)
195 return db.solution.update(q, upgrade, use_test_packages, IncludeSource);
196 }
197
198 /* Formats problems and solutions as a string for display to the user. */
199 void
200 PrereqChecker::getUnmetString (std::string &s)
201 {
202 packagedb db;
203 s = db.solution.report();
204
205 //
206 size_t pos = 0;
207 while ((pos = s.find("\n", pos)) != std::string::npos)
208 {
209 s.replace(pos, 1, "\r\n");
210 pos += 2;
211 }
212 }
213
214 // ---------------------------------------------------------------------------
215 // progress page glue
216 // ---------------------------------------------------------------------------
217
218 static int
219 do_prereq_check_thread(HINSTANCE h, HWND owner)
220 {
221 PrereqChecker p;
222 int retval;
223
224 if (p.isMet ())
225 {
226 if (source == IDC_SOURCE_LOCALDIR)
227 Progress.SetActivateTask (WM_APP_START_INSTALL); // install
228 else
229 Progress.SetActivateTask (WM_APP_START_DOWNLOAD); // start download
230 retval = IDD_INSTATUS;
231 }
232 else
233 {
234 // rut-roh, some required things are not selected
235 retval = IDD_PREREQ;
236 }
237
238 return retval;
239 }
240
241 static DWORD WINAPI
242 do_prereq_check_reflector (void *p)
243 {
244 HANDLE *context;
245 context = (HANDLE *) p;
246
247 try
248 {
249 int next_dialog = do_prereq_check_thread ((HINSTANCE) context[0], (HWND) context[1]);
250
251 // Tell the progress page that we're done prereq checking
252 Progress.PostMessageNow (WM_APP_PREREQ_CHECK_THREAD_COMPLETE, 0, next_dialog);
253 }
254 TOPLEVEL_CATCH((HWND) context[1], "prereq_check");
255
256 ExitThread(0);
257 }
258
259 static HANDLE context[2];
260
261 void
262 do_prereq_check (HINSTANCE h, HWND owner)
263 {
264 context[0] = h;
265 context[1] = owner;
266
267 DWORD threadID;
268 CreateThread (NULL, 0, do_prereq_check_reflector, context, 0, &threadID);
269 }
This page took 0.046004 seconds and 5 git commands to generate.