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