]> cygwin.com Git - cygwin-apps/setup.git/blame - package_meta.cc
2002-04-26 Robert Collins <rbtcollins@hotmail.com>
[cygwin-apps/setup.git] / package_meta.cc
CommitLineData
7939f6d1
RC
1/*
2 * Copyright (c) 2001, Robert Collins.
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 Robert Collins <rbtcollins@hotmail.com>
13 *
14 */
15
16#if 0
7e8fc33c 17static const char *cvsid = "\n%%% $Id$\n";
7939f6d1
RC
18#endif
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <unistd.h>
23#include <strings.h>
7939f6d1
RC
24
25#include "io_stream.h"
26#include "compress.h"
27
28#include "filemanip.h"
fa0c0d10
RC
29#include "hash.h"
30#include "log.h"
31/* io_stream needs a bit of tweaking to get rid of this. TODO */
32#include "mount.h"
33/* this goes at the same time */
34#include "win32.h"
7939f6d1 35
bb849dbd
RC
36
37#include "category.h"
8e9aa511 38#include "script.h"
bb849dbd 39
fa0c0d10 40#include "package_version.h"
7939f6d1
RC
41#include "cygpackage.h"
42#include "package_meta.h"
cbfc4215 43#include "package_db.h"
7939f6d1 44
fa0c0d10 45static const char *standard_dirs[] = {
204315f9
RC
46 "bin",
47 "etc",
48 "lib",
49 "tmp",
50 "usr",
51 "usr/bin",
52 "usr/lib",
53 "usr/src",
54 "usr/local",
55 "usr/local/bin",
56 "usr/local/etc",
57 "usr/local/lib",
58 "usr/tmp",
59 "var/run",
60 "var/tmp",
fa0c0d10
RC
61 0
62};
63
64void
3c054baf 65hash::add_subdirs (String const &tpath)
fa0c0d10
RC
66{
67 char *nonp, *pp;
3c054baf 68 char *path = tpath.cstr();
fa0c0d10
RC
69 for (nonp = path; *nonp == '\\' || *nonp == '/'; nonp++);
70 for (pp = path + strlen (path) - 1; pp > nonp; pp--)
71 if (*pp == '/' || *pp == '\\')
72 {
73 int i, s = 0;
74 char c = *pp;
75 *pp = 0;
76 for (i = 0; standard_dirs[i]; i++)
77 if (strcmp (standard_dirs[i] + 1, path) == 0)
78 {
79 s = 1;
80 break;
81 }
82 if (s == 0)
83 add (path);
84 *pp = c;
85 }
86}
87
7c6ef2c3
RC
88/*****************/
89
90CategoryPackage::~CategoryPackage()
91{
92 CategoryPackage **temp = &key.packages;
93 while (*temp != this)
94 temp = &((*temp)->next);
95 *temp = next;
96}
97
98/*****************/
99
7e8fc33c
RC
100const
101 packagemeta::_actions
102packagemeta::Default_action (0);
103const
104 packagemeta::_actions
105packagemeta::Install_action (1);
106const
107 packagemeta::_actions
108packagemeta::Reinstall_action (2);
109const
110 packagemeta::_actions
111packagemeta::Uninstall_action (3);
112
113char const *
114packagemeta::_actions::caption ()
115{
116 switch (_value)
117 {
118 case 0:
119 return "Default";
120 case 1:
121 return "Install";
122 case 2:
123 return "Reinstall";
124 case 3:
125 return "Uninstall";
126 }
127 // Pacify GCC: (all case options are checked above)
128 return 0;
129}
130
131packagemeta::_actions & packagemeta::_actions::operator++ ()
132{
133 ++_value;
134 if (_value > 3)
135 _value = 0;
136 return *this;
137}
138
7c6ef2c3
RC
139packagemeta::~packagemeta()
140{
141 while (Categories.number ())
142 {
143 CategoryPackage *catpkg = Categories.removebyindex (1);
144 delete catpkg;
145 }
146 while (versions.number ())
147 {
148 packageversion *pv = versions.removebyindex(1);
149 delete pv;
150 }
151}
152
7939f6d1 153void
fa0c0d10 154packagemeta::add_version (packageversion & thepkg)
7939f6d1 155{
bb849dbd 156 versions.registerbyobject (thepkg);
7939f6d1
RC
157}
158
159/* assumption: package thepkg is already in the metadata list. */
160void
fa0c0d10 161packagemeta::set_installed (packageversion & thepkg)
7939f6d1 162{
bb849dbd
RC
163 packageversion *temp = versions.getbykey (thepkg.key);
164 if (temp == &thepkg)
165 installed = &thepkg;
7939f6d1 166}
fa0c0d10
RC
167
168/* uninstall a package if it's installed */
169void
170packagemeta::uninstall ()
171{
172 if (installed)
173 {
174 /* this will need to be pushed down to the version, or even the source level
175 * to allow differences between formats to be seamlessly managed
176 * but for now: here is ok
177 */
178 hash dirs;
3c054baf 179 String line = installed->getfirstfile ();
8e9aa511
RC
180
181 try_run_script ("/etc/preremove/", name);
3c054baf 182 while (line.size())
fa0c0d10
RC
183 {
184 dirs.add_subdirs (line);
185
1ac649ed 186 String d = cygpath (String ("/") + line);
3c054baf 187 DWORD dw = GetFileAttributes (d.cstr_oneuse());
7e8fc33c
RC
188 if (dw != INVALID_FILE_ATTRIBUTES
189 && !(dw & FILE_ATTRIBUTE_DIRECTORY))
fa0c0d10 190 {
3c054baf
RC
191 log (LOG_BABBLE, String("unlink ")+ d);
192 SetFileAttributes (d.cstr_oneuse(), dw & ~FILE_ATTRIBUTE_READONLY);
193 DeleteFile (d.cstr_oneuse());
edef4f57
CV
194 }
195 /* Check for Windows shortcut of same name. */
3c054baf
RC
196 d += ".lnk";
197 dw = GetFileAttributes (d.cstr_oneuse());
7e8fc33c
RC
198 if (dw != INVALID_FILE_ATTRIBUTES
199 && !(dw & FILE_ATTRIBUTE_DIRECTORY))
edef4f57 200 {
3c054baf 201 log (LOG_BABBLE, String("unlink ") + d);
1ac649ed
RC
202 SetFileAttributes (d.cstr_oneuse(),
203 dw & ~FILE_ATTRIBUTE_READONLY);
3c054baf 204 DeleteFile (d.cstr_oneuse());
fa0c0d10
RC
205 }
206 line = installed->getnextfile ();
207 }
208 installed->uninstall ();
209
210 dirs.reverse_sort ();
211 char *subdir = 0;
212 while ((subdir = dirs.enumerate (subdir)) != 0)
213 {
1ac649ed 214 String d = cygpath (String ("/") + subdir);
3c054baf 215 if (RemoveDirectory (d.cstr_oneuse()))
1ac649ed 216 log (LOG_BABBLE, String("rmdir ") + d);
fa0c0d10 217 }
8e9aa511 218 try_run_script ("/etc/postremove/", name);
fa0c0d10
RC
219 }
220 installed = 0;
221}
bb849dbd
RC
222
223
224void
225packagemeta::add_category (Category & cat)
226{
227 /* add a new record for the package list */
4fe323f9
RC
228 CategoryPackage & catpack = Categories.registerbykey (cat);
229 catpack.pkg = this;
bb849dbd
RC
230}
231
3c054baf 232String const
df62e023 233packagemeta::SDesc () const
bb849dbd 234{
7e8fc33c 235 for (size_t n = 1; n <= versions.number (); ++n)
3c054baf 236 if (versions[n]->SDesc ().size())
bcf20115
RC
237 return versions[n]->SDesc ();
238 return NULL;
bb849dbd 239};
cbfc4215
RC
240
241/* Return an appropriate caption given the current action. */
3c054baf 242String
cbfc4215
RC
243packagemeta::action_caption ()
244{
245 if (!desired && installed)
246 return "Uninstall";
247 else if (!desired)
248 return "Skip";
249 else if (desired == installed && desired->binpicked)
250 {
251 packagedb db;
252 return db.task == PackageDB_Install ? "Reinstall" : "Retrieve";
253 }
254 else if (desired == installed && desired->srcpicked)
255 /* FIXME: Redo source should come up if the tarball is already present locally */
256 return "Source";
257 else if (desired == installed) /* and neither src nor bin */
258 return "Keep";
259 else
260 return desired->Canonical_version ();
261}
262
263/* Set the next action given a current action. */
264void
265packagemeta::set_action (packageversion * default_version)
266{
267 /* actions are the following:
268
269 for install modes (from net/local)
270 for each version:
271 install this version
272 install the source for this version
273 and a boolean flag - force install to allow reinstallation, or bypassing requirements
274 globally:
275 install the source for the current version.
276
277 to uninstall a package, the desired version is set to NULL;
278
279 for mirroring modes (download only)
280 for each version
281 download this version
282 download source for this version
283
284 these are represented by the following:
285 the desired pointer in the packagemetadata indicated which version we are operating on.
286 if we are operating on the installed version, reinstall is a valid option.
287 for the selected version, forceinstall means Do an install no matter what, and
288 srcpicked means download the source.
289
290 The default action for any installed package is to install the 'curr version'
291 if it is not already installed.
292
293 The default action for any non-installed package is to do nothing.
294
295 To achieve a no-op, set desired==installed, and if (installed) set forceinstall=0 and
296 srcpicked = 0;
297
298 Iteration through versions should follow the following rules:
299 selected radio button (prev/curr/test) (show as reinstall if that is the
300 current version) ->source only (only if the package is installed) ->oldest version....s
301 kip version of radio button...
302 newest version->uninstall->no-op->selected radio button.
303
304 If any state cannot be set (ie because (say) no prev entry exists for a package
305 simply progress to the next option.
306
307 */
308
309 /* We were set to uninstall the package */
310 if (!desired && installed)
311 {
312 /* No-op - keep whatever we've got */
313 desired = installed;
314 if (desired)
315 {
316 desired->binpicked = 0;
317 desired->srcpicked = 0;
318 }
319 return;
320 }
321 else if (desired == installed
7e8fc33c 322 && (!installed || !(installed->binpicked || installed->srcpicked)))
cbfc4215
RC
323 /* Install the default trust version - this is a 'reinstall' for installed
324 * packages */
325 {
326 desired = NULL;
327 /* No-op */
328 desired = default_version;
329 if (desired)
330 {
331 desired->binpicked = 1;
332 return;
333 }
334 }
335 /* are we currently on the radio button selection and installed */
336 if (desired == default_version && installed &&
337 (!desired || desired->binpicked)
338 && (desired &&
339 (desired->src.Cached () || desired->src.sites.number ())))
340 {
341 /* source only this file */
342 desired = installed;
343 desired->binpicked = 0;
344 desired->srcpicked = 1;
345 return;
346 }
347 /* are we currently on source only or on the radio button but not installed */
348 else if ((desired == installed && installed
349 && installed->srcpicked) || desired == default_version)
350 {
351 /* move onto the loop through versions */
352 desired = versions[1];
353 if (desired == default_version)
354 desired = versions.number () > 1 ? versions[2] : NULL;
355 if (desired)
356 {
357 desired->binpicked = 1;
358 desired->srcpicked = 0;
359 }
360 return;
361 }
362 else
363 {
364 /* preserve the src tick box */
365 int source = desired->srcpicked;
366 /* bump the version selected, skipping the radio button trust along the way */
367 size_t n;
7e8fc33c 368 for (n = 1; n <= versions.number () && desired != versions[n]; n++);
cbfc4215
RC
369 /* n points at pkg->desired */
370 n++;
371 if (n <= versions.number ())
372 {
373 if (default_version == versions[n])
374 n++;
375 if (n <= versions.number ())
376 {
377 desired = versions[n];
378 desired->srcpicked = source;
379 return;
380 }
381 }
382 /* went past the end - uninstall the package */
383 desired = NULL;
384 }
385}
97647369
RC
386
387int
388packagemeta::set_requirements (trusts deftrust = TRUST_CURR, size_t depth = 0)
389{
390 Dependency *dp;
391 packagemeta *required;
392 int changed = 0;
7e8fc33c 393 if (!desired || (desired != installed && !desired->binpicked))
97647369
RC
394 /* uninstall || source only */
395 return 0;
396
397 dp = desired->required;
398 packagedb db;
399 /* cheap test for too much recursion */
400 if (depth > 5)
401 return 0;
402 while (dp)
403 {
404 if ((required = db.packages.getbykey (dp->package)) == NULL)
7e8fc33c
RC
405 {
406 dp = dp->next;
407 changed++;
408 continue;
409 }
97647369 410 if (!required->desired)
7e8fc33c
RC
411 {
412 /* it's set to uninstall */
413 required->set_action (required->trustp (deftrust));
414 }
97647369 415 else if (required->desired != required->installed
7e8fc33c
RC
416 && !required->desired->binpicked)
417 {
418 /* it's set to change to a different version source only */
419 required->desired->binpicked = 1;
420 }
97647369
RC
421 /* does this requirement have requirements? */
422 changed += required->set_requirements (deftrust, depth + 1);
423 dp = dp->next;
424 }
425 return changed;
426}
7e8fc33c
RC
427
428
429// Set a particular type of action.
430void
431packagemeta::set_action (_actions action, packageversion * default_version)
432{
433 packagedb db;
434 if (action == Default_action)
435 {
436 // XXX fix the list use to allow const ref usage.
437 Category tempCategory("Misc");
438 if (installed
439 || Categories.getbykey (db.categories.registerbykey ("Base"))
440 || Categories.getbykey (tempCategory))
441 {
442 desired = default_version;
443 if (desired)
444 {
445 desired->binpicked = desired == installed ? 0 : 1;
446 desired->srcpicked = 0;
447 }
448 }
449 else
450 desired = 0;
451 return;
452 }
453 else if (action == Install_action)
454 {
455 desired = default_version;
456 if (desired)
457 {
458 if (desired != installed)
459 desired->binpicked = 1;
460 else
461 desired->binpicked = 0;
462 desired->srcpicked = 0;
463 }
464 return;
465 }
466 else if (action == Reinstall_action)
467 {
468 desired = installed;
469 if (desired)
470 {
471 desired->binpicked = 1;
472 desired->srcpicked = 0;
473 }
474 }
475 else if (action == Uninstall_action)
476 {
477 desired = 0;
478 }
479}
This page took 0.07249 seconds and 5 git commands to generate.