]>
cygwin.com Git - cygwin-apps/setup.git/blob - package_meta.cc
2 * Copyright (c) 2001, Robert Collins.
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 Robert Collins <rbtcollins@hotmail.com>
17 static const char *cvsid
= "\n%%% $Id$\n";
20 #include "package_meta.h"
26 #include "io_stream.h"
29 #include "filemanip.h"
31 #include "LogSingleton.h"
32 /* io_stream needs a bit of tweaking to get rid of this. TODO */
34 /* this goes at the same time */
41 #include "package_version.h"
42 #include "cygpackage.h"
43 #include "package_db.h"
47 static const char *standard_dirs
[] = {
67 hash::add_subdirs (String
const &tpath
)
70 char *path
= tpath
.cstr();
71 for (nonp
= path
; *nonp
== '\\' || *nonp
== '/'; nonp
++);
72 for (pp
= path
+ strlen (path
) - 1; pp
> nonp
; pp
--)
73 if (*pp
== '/' || *pp
== '\\')
78 for (i
= 0; standard_dirs
[i
]; i
++)
79 if (strcmp (standard_dirs
[i
] + 1, path
) == 0)
92 CategoryPackage::~CategoryPackage()
94 CategoryPackage
**temp
= &key
.packages
;
96 temp
= &((*temp
)->next
);
103 packagemeta::_actions
104 packagemeta::Default_action (0);
106 packagemeta::_actions
107 packagemeta::Install_action (1);
109 packagemeta::_actions
110 packagemeta::Reinstall_action (2);
112 packagemeta::_actions
113 packagemeta::Uninstall_action (3);
116 packagemeta::_actions::caption ()
129 // Pacify GCC: (all case options are checked above)
133 packagemeta::packagemeta (packagemeta
const &rhs
) :
134 name (rhs
.name
), key (rhs
.name
), installed_from (),
135 Categories(rhs
.Categories
), versions (rhs
.versions
),
136 installed (rhs
.installed
), prev (rhs
.prev
),
137 prevtimestamp (rhs
.prevtimestamp
), curr (rhs
.curr
),
138 currtimestamp (rhs
.currtimestamp
), exp (rhs
.exp
),
139 exptimestamp (rhs
.exptimestamp
), desired (rhs
.desired
),
140 architecture (rhs
.architecture
), priority (rhs
.priority
)
145 packagemeta::_actions
& packagemeta::_actions::operator++ ()
153 packagemeta::~packagemeta()
155 while (Categories
.number ())
157 CategoryPackage
*catpkg
= Categories
.removebyindex (1);
164 packagemeta::add_version (packageversion
& thepkg
)
166 /* todo: check return value */
167 versions
.insert (thepkg
);
170 /* assumption: package thepkg is already in the metadata list. */
172 packagemeta::set_installed (packageversion
& thepkg
)
174 set
<packageversion
>::const_iterator temp
= versions
.find (thepkg
);
175 if (temp
!= versions
.end())
179 /* uninstall a package if it's installed */
181 packagemeta::uninstall ()
185 /* this will need to be pushed down to the version, or even the source level
186 * to allow differences between formats to be seamlessly managed
187 * but for now: here is ok
190 String line
= installed
.getfirstfile ();
192 try_run_script ("/etc/preremove/", name
);
195 dirs
.add_subdirs (line
);
197 String d
= cygpath (String ("/") + line
);
198 DWORD dw
= GetFileAttributes (d
.cstr_oneuse());
199 if (dw
!= INVALID_FILE_ATTRIBUTES
200 && !(dw
& FILE_ATTRIBUTE_DIRECTORY
))
202 log (LOG_BABBLE
) << "unlink " << d
<< endLog
;
203 SetFileAttributes (d
.cstr_oneuse(), dw
& ~FILE_ATTRIBUTE_READONLY
);
204 DeleteFile (d
.cstr_oneuse());
206 /* Check for Windows shortcut of same name. */
208 dw
= GetFileAttributes (d
.cstr_oneuse());
209 if (dw
!= INVALID_FILE_ATTRIBUTES
210 && !(dw
& FILE_ATTRIBUTE_DIRECTORY
))
212 log (LOG_BABBLE
) << "unlink " << d
<< endLog
;
213 SetFileAttributes (d
.cstr_oneuse(),
214 dw
& ~FILE_ATTRIBUTE_READONLY
);
215 DeleteFile (d
.cstr_oneuse());
217 line
= installed
.getnextfile ();
219 installed
.uninstall ();
221 dirs
.reverse_sort ();
223 while ((subdir
= dirs
.enumerate (subdir
)) != 0)
225 String d
= cygpath (String ("/") + subdir
);
226 if (RemoveDirectory (d
.cstr_oneuse()))
227 log (LOG_BABBLE
) << "rmdir " << d
<< endLog
;
229 try_run_script ("/etc/postremove/", name
);
231 installed
= packageversion();
236 packagemeta::add_category (Category
& cat
)
238 /* add a new record for the package list */
239 CategoryPackage
& catpack
= Categories
.registerbykey (cat
);
244 hasSDesc(packageversion
const &pkg
)
246 return pkg
.SDesc().size();
250 packagemeta::SDesc () const
252 set
<packageversion
>::iterator i
= find_if (versions
.begin(), versions
.end(), hasSDesc
);
253 if (i
== versions
.end())
258 /* Return an appropriate caption given the current action. */
260 packagemeta::action_caption ()
262 if (!desired
&& installed
)
266 else if (desired
== installed
&& desired
.picked())
269 return db
.task
== PackageDB_Install
? "Reinstall" : "Retrieve";
271 else if (desired
== installed
&& desired
.sourcePackage() && desired
.sourcePackage().picked())
272 /* FIXME: Redo source should come up if the tarball is already present locally */
274 else if (desired
== installed
) /* and neither src nor bin */
277 return desired
.Canonical_version ();
280 /* Set the next action given a current action. */
282 packagemeta::set_action (packageversion
const &default_version
)
284 /* actions are the following:
286 for install modes (from net/local)
289 install the source for this version
290 and a boolean flag - force install to allow reinstallation, or bypassing requirements
292 install the source for the current version.
294 to uninstall a package, the desired version is set to NULL;
296 for mirroring modes (download only)
298 download this version
299 download source for this version
301 these are represented by the following:
302 the desired pointer in the packagemetadata indicated which version we are operating on.
303 if we are operating on the installed version, reinstall is a valid option.
304 for the selected version, forceinstall means Do an install no matter what, and
305 srcpicked means download the source.
307 The default action for any installed package is to install the 'curr version'
308 if it is not already installed.
310 The default action for any non-installed package is to do nothing.
312 To achieve a no-op, set desired==installed, and if (installed) set forceinstall=0 and
315 Iteration through versions should follow the following rules:
316 selected radio button (prev/curr/test) (show as reinstall if that is the
317 current version) ->source only (only if the package is installed) ->oldest version....s
318 kip version of radio button...
319 newest version->uninstall->no-op->selected radio button.
321 If any state cannot be set (ie because (say) no prev entry exists for a package
322 simply progress to the next option.
326 /* We were set to uninstall the package */
327 if (!desired
&& installed
)
329 /* No-op - keep whatever we've got */
333 desired
.pick (false);
334 desired
.sourcePackage().pick (false);
338 else if (desired
== installed
&&
340 // neither bin nor source are being installed
341 (!(installed
.picked() || installed
.sourcePackage().picked()) &&
342 // bin or source are available
343 (installed
.accessible() || installed
.sourcePackage().accessible()) ))
345 /* Install the default trust version - this is a 'reinstall' for installed
349 desired
= default_version
;
352 if (desired
.accessible())
355 desired
.sourcePackage().pick (true);
359 /* are we currently on the radio button selection and installed */
360 if (desired
== default_version
&& installed
&&
361 (!desired
|| desired
.picked())
362 && (desired
&& desired
.sourcePackage().accessible())
365 /* source only this file */
367 desired
.pick (false);
368 desired
.sourcePackage().pick (true);
371 /* are we currently on source only or on the radio button but not installed */
372 else if ((desired
== installed
373 && installed
.sourcePackage().picked ()) || desired
== default_version
)
375 /* move onto the loop through versions */
376 set
<packageversion
>::iterator i
= versions
.begin();
377 if (*i
== default_version
)
379 if (i
!= versions
.end())
383 desired
.sourcePackage ().pick (false);
386 desired
= packageversion ();
391 /* preserve the src tick box */
392 bool sourceticked
= desired
.sourcePackage().picked();
393 /* bump the version selected, skipping the radio button trust along the way */
394 set
<packageversion
>::iterator i
;
395 for (i
=versions
.begin(); i
!= versions
.end() && *i
!= desired
; ++i
);
396 /* i points at desired in the versions set */
398 if (i
!= versions
.end ())
400 if (default_version
== *i
)
402 if (i
!= versions
.end ())
405 if (desired
.sourcePackage().accessible ())
406 desired
.sourcePackage ().pick (sourceticked
);
408 desired
.sourcePackage ().pick (false);
412 /* went past the end - uninstall the package */
413 desired
= packageversion ();
418 checkForInstalled (PackageSpecification
*spec
)
421 packagemeta
*required
= db
.findBinary (*spec
);
424 if (spec
->satisfies (required
->installed
))
425 /* done, found a satisfactory installed version */
431 checkForUpgradeable (PackageSpecification
*spec
)
434 packagemeta
*required
= db
.findBinary (*spec
);
435 if (!required
|| !required
->installed
)
437 for (set
<packageversion
>::iterator i
= required
->versions
.begin();
438 i
!= required
->versions
.end(); ++i
)
439 if (spec
->satisfies (*i
))
445 checkForSatisfiable (PackageSpecification
*spec
)
448 packagemeta
*required
= db
.findBinary (*spec
);
451 for (set
<packageversion
>::iterator i
= required
->versions
.begin();
452 i
!= required
->versions
.end(); ++i
)
453 if (spec
->satisfies (*i
))
459 packagemeta::set_requirements (trusts deftrust
= TRUST_CURR
, size_t depth
= 0)
462 if (!desired
|| (desired
!= installed
&& !desired
.picked ()))
463 /* uninstall || source only */
466 vector
<vector
<PackageSpecification
*> *>::iterator dp
= desired
.depends ()->begin();
468 /* cheap test for too much recursion */
471 /* walk through each and clause */
472 while (dp
!= desired
.depends ()->end())
475 1) is a satisfactory or clause installed?
476 2) is an unsatisfactory version of an or clause which has
477 a satisfactory version available installed?
478 3) is a satisfactory package available?
480 /* check each or clause for an installed match */
481 vector
<PackageSpecification
*>::iterator i
=
482 find_if ((*dp
)->begin(), (*dp
)->end(), checkForInstalled
);
483 if (i
!= (*dp
)->end())
485 /* we found an installed ok package */
486 /* todo: ensure that it will remain installed */
487 /* next and clause */
491 /* check each or clause for an upgradeable version */
492 i
= find_if ((*dp
)->begin(), (*dp
)->end(), checkForUpgradeable
);
493 if (i
!= (*dp
)->end())
495 /* we found a package that can be up/downgraded to meet the
498 /* TODO: set an appropriate desired version */
503 /* check each or clause for an installable version */
504 i
= find_if ((*dp
)->begin(), (*dp
)->end(), checkForSatisfiable
);
505 if (i
!= (*dp
)->end())
507 /* we found a package that can be installed to meet the
510 /* TODO: set an appropriate desired version */
516 // version updating and installing code, once the package is selected
517 if (!required
->desired
)
519 /* it's set to uninstall */
520 required
->set_action (required
->trustp (deftrust
));
522 else if (required
->desired
!= required
->installed
523 && !required
->desired
.picked())
525 /* it's set to change to a different version source only */
526 required
->desired
.pick (true);
528 /* does this requirement have requirements? */
529 changed
+= required
->set_requirements (deftrust
, depth
+ 1);
537 // Set a particular type of action.
539 packagemeta::set_action (_actions action
, packageversion
const &default_version
)
542 if (action
== Default_action
)
544 // XXX fix the list use to allow const ref usage.
545 Category
tempCategory("Misc");
547 || Categories
.getbykey (db
.categories
.registerbykey ("Base"))
548 || Categories
.getbykey (tempCategory
))
550 desired
= default_version
;
553 desired
.pick (desired
== installed
);
554 desired
.sourcePackage ().pick (false);
558 desired
= packageversion ();
561 else if (action
== Install_action
)
563 desired
= default_version
;
566 if (desired
!= installed
)
567 if (desired
.source()->sites
.number())
570 desired
.sourcePackage ().pick (false);
574 desired
.pick (false);
575 desired
.sourcePackage ().pick (true);
579 desired
.pick (false);
580 desired
.sourcePackage ().pick (false);
585 else if (action
== Reinstall_action
)
591 desired
.sourcePackage ().pick (false);
594 else if (action
== Uninstall_action
)
596 desired
= packageversion ();
601 packagemeta::accessible () const
603 for (set
<packageversion
>::iterator i
=versions
.begin();
604 i
!= versions
.end(); ++i
)
611 packagemeta::sourceAccessible () const
613 for (set
<packageversion
>::iterator i
=versions
.begin();
614 i
!= versions
.end(); ++i
)
616 packageversion bin
=*i
;
617 if (bin
.sourcePackage().accessible())
This page took 0.112314 seconds and 5 git commands to generate.