[pacman-dev] [PATCH 1/4] pactest: allow checking for cache file existence
This will allow some tests to be added for cache cleaning. Signed-off-by: Dan McGee <dan@archlinux.org> --- test/pacman/pmrule.py | 7 +++++++ test/pacman/pmtest.py | 19 ++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletions(-) diff --git a/test/pacman/pmrule.py b/test/pacman/pmrule.py index 6263045..c68d085 100755 --- a/test/pacman/pmrule.py +++ b/test/pacman/pmrule.py @@ -146,6 +146,13 @@ def check(self, test): else: print "FILE rule '%s' not found" % case success = -1 + elif kind == "CACHE": + cachedir = os.path.join(test.root, util.PM_CACHEDIR) + if case == "EXISTS": + pkg = test.findpkg(key, value, allow_local=True) + if not pkg or not os.path.isfile( + os.path.join(cachedir, pkg.filename())): + success = 0 else: print "Rule kind '%s' not found" % kind success = -1 diff --git a/test/pacman/pmtest.py b/test/pacman/pmtest.py index 958e263..82dfda6 100755 --- a/test/pacman/pmtest.py +++ b/test/pacman/pmtest.py @@ -55,6 +55,22 @@ def addpkg(self, pkg): """ self.localpkgs.append(pkg) + def findpkg(self, name, version, allow_local=False): + """Find a package object matching the name and version specified in + either sync databases or the local package collection. The local database + is allowed to match if allow_local is True.""" + for db in self.db.itervalues(): + if db.treename == "local" and not allow_local: + continue + pkg = db.getpkg(name) + if pkg and pkg.version == version: + return pkg + for pkg in self.localpkgs: + if pkg.name == name and pkg.version == version: + return pkg + + return None + def addrule(self, rulename): """ """ @@ -76,6 +92,7 @@ def load(self): "local": pmdb.pmdb("local", self.root) } self.localpkgs = [] + self.createlocalpkgs = False self.filesystem = [] self.description = "" @@ -131,7 +148,7 @@ def generate(self): vprint("\t%s" % os.path.join(util.TMPDIR, pkg.filename())) pkg.makepkg(tmpdir) for key, value in self.db.iteritems(): - if key == "local": + if key == "local" and not self.createlocalpkgs: continue for pkg in value.pkgs: vprint("\t%s" % os.path.join(util.PM_CACHEDIR, pkg.filename())) -- 1.7.3.5
The first two are rather standard tests of our two available clean options, and the third is attempting to test a reported bug (and failing to make the given case fail). Signed-off-by: Dan McGee <dan@archlinux.org> --- test/pacman/tests/clean001.py | 26 ++++++++++++++++++++++++++ test/pacman/tests/clean002.py | 26 ++++++++++++++++++++++++++ test/pacman/tests/clean003.py | 16 ++++++++++++++++ 3 files changed, 68 insertions(+), 0 deletions(-) create mode 100644 test/pacman/tests/clean001.py create mode 100644 test/pacman/tests/clean002.py create mode 100644 test/pacman/tests/clean003.py diff --git a/test/pacman/tests/clean001.py b/test/pacman/tests/clean001.py new file mode 100644 index 0000000..ad86250 --- /dev/null +++ b/test/pacman/tests/clean001.py @@ -0,0 +1,26 @@ +self.description = "CleanMethod = KeepInstalled" + +sp = pmpkg("dummy", "2.0-1") +self.addpkg2db("sync", sp) + +sp = pmpkg("bar", "2.0-1") +self.addpkg2db("sync", sp) + +sp = pmpkg("baz", "2.0-1") +self.addpkg2db("sync", sp) + +lp = pmpkg("dummy", "1.0-1") +self.addpkg2db("local", lp) + +lp = pmpkg("bar", "2.0-1") +self.addpkg2db("local", lp) + +self.args = "-Sc" +self.option['CleanMethod'] = ['KeepInstalled'] +self.createlocalpkgs = True + +self.addrule("PACMAN_RETCODE=0") +self.addrule("!CACHE_EXISTS=dummy|2.0-1") +self.addrule("CACHE_EXISTS=dummy|1.0-1") +self.addrule("CACHE_EXISTS=bar|2.0-1") +self.addrule("!CACHE_EXISTS=baz|2.0-1") diff --git a/test/pacman/tests/clean002.py b/test/pacman/tests/clean002.py new file mode 100644 index 0000000..5dddbc5 --- /dev/null +++ b/test/pacman/tests/clean002.py @@ -0,0 +1,26 @@ +self.description = "CleanMethod = KeepCurrent" + +sp = pmpkg("dummy", "2.0-1") +self.addpkg2db("sync", sp) + +sp = pmpkg("bar", "2.0-1") +self.addpkg2db("sync", sp) + +sp = pmpkg("baz", "2.0-1") +self.addpkg2db("sync", sp) + +lp = pmpkg("dummy", "1.0-1") +self.addpkg2db("local", lp) + +lp = pmpkg("bar", "2.0-1") +self.addpkg2db("local", lp) + +self.args = "-Sc" +self.option['CleanMethod'] = ['KeepCurrent'] +self.createlocalpkgs = True + +self.addrule("PACMAN_RETCODE=0") +self.addrule("CACHE_EXISTS=dummy|2.0-1") +self.addrule("!CACHE_EXISTS=dummy|1.0-1") +self.addrule("CACHE_EXISTS=bar|2.0-1") +self.addrule("CACHE_EXISTS=baz|2.0-1") diff --git a/test/pacman/tests/clean003.py b/test/pacman/tests/clean003.py new file mode 100644 index 0000000..0d3f451 --- /dev/null +++ b/test/pacman/tests/clean003.py @@ -0,0 +1,16 @@ +self.description = "CleanMethod = KeepInstalled with IgnorePkg (FS#22653)" + +sp = pmpkg("dummy", "2.0-1") +self.addpkg2db("sync", sp) + +lp = pmpkg("dummy", "1.0-1") +self.addpkg2db("local", lp) + +self.args = "-Sc" +self.option['CleanMethod'] = ['KeepInstalled'] +self.option['IgnorePkg'] = ['dummy'] +self.createlocalpkgs = True + +self.addrule("PACMAN_RETCODE=0") +self.addrule("!CACHE_EXISTS=dummy|2.0-1") +self.addrule("CACHE_EXISTS=dummy|1.0-1") -- 1.7.3.5
Signed-off-by: Dan McGee <dan@archlinux.org> --- src/pacman/sync.c | 16 +++++++++------- 1 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/pacman/sync.c b/src/pacman/sync.c index 7353f7e..b3f5891 100644 --- a/src/pacman/sync.c +++ b/src/pacman/sync.c @@ -42,6 +42,7 @@ static int sync_cleandb(const char *dbpath, int keep_used) { DIR *dir; struct dirent *ent; + alpm_list_t *syncdbs; dir = opendir(dbpath); if(dir == NULL) { @@ -49,12 +50,13 @@ static int sync_cleandb(const char *dbpath, int keep_used) { return(1); } + syncdbs = alpm_option_get_syncdbs(); + rewinddir(dir); /* step through the directory one file at a time */ while((ent = readdir(dir)) != NULL) { char path[PATH_MAX]; struct stat buf; - alpm_list_t *syncdbs = NULL, *i; int found = 0; const char *dname = ent->d_name; size_t len; @@ -77,7 +79,7 @@ static int sync_cleandb(const char *dbpath, int keep_used) { /* remove all non-skipped directories and non-database files */ stat(path, &buf); len = strlen(path); - if(S_ISDIR(buf.st_mode) || strcmp(path+(len-3),".db") != 0) { + if(S_ISDIR(buf.st_mode) || strcmp(path + len - 3, ".db") != 0) { if(rmrf(path)) { pm_fprintf(stderr, PM_LOG_ERROR, _("could not remove %s\n"), path); @@ -88,9 +90,9 @@ static int sync_cleandb(const char *dbpath, int keep_used) { } if(keep_used) { + alpm_list_t *i; len = strlen(dname); - char *dbname = strndup(dname, len-3); - syncdbs = alpm_option_get_syncdbs(); + char *dbname = strndup(dname, len - 3); for(i = syncdbs; i && !found; i = alpm_list_next(i)) { pmdb_t *db = alpm_list_getdata(i); found = !strcmp(dbname, alpm_db_get_name(db)); @@ -126,9 +128,9 @@ static int sync_cleandb_all(void) { if(!yesno(_("Do you want to remove unused repositories?"))) { return(0); } - /* The sync dbs were previously put in dbpath/, but are now in dbpath/sync/, - * so we will clean everything in dbpath/ (except dbpath/local/ and dbpath/sync/ - * and db.lck) and only the unused sync dbs in dbpath/sync/ */ + /* The sync dbs were previously put in dbpath/ but are now in dbpath/sync/. + * We will clean everything in dbpath/ except local/, sync/ and db.lck, and + * only the unused sync dbs in dbpath/sync/ */ ret += sync_cleandb(dbpath, 0); sprintf(newdbpath, "%s%s", dbpath, "sync/"); -- 1.7.3.5
No reason to disallow this- it allows keeping even more packages around in the cache. Test cases included for this case and to ensure the default behavior is preserved. Signed-off-by: Dan McGee <dan@archlinux.org> --- doc/pacman.conf.5.txt | 6 ++- src/pacman/conf.h | 4 +- src/pacman/pacman.c | 22 +++++++----- src/pacman/sync.c | 78 +++++++++++++++++++++-------------------- test/pacman/tests/clean004.py | 30 ++++++++++++++++ test/pacman/tests/clean005.py | 29 +++++++++++++++ 6 files changed, 118 insertions(+), 51 deletions(-) create mode 100644 test/pacman/tests/clean004.py create mode 100644 test/pacman/tests/clean005.py diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt index ae4d748..cb4c589 100644 --- a/doc/pacman.conf.5.txt +++ b/doc/pacman.conf.5.txt @@ -136,14 +136,16 @@ Options These files refer to files in the package archive, so do not include the leading slash (the RootDir) when specifying them. -*CleanMethod =* KeepInstalled | KeepCurrent:: +*CleanMethod =* KeepInstalled &| KeepCurrent:: If set to `KeepInstalled` (the default), the '-Sc' operation will clean packages that are no longer installed (not present in the local database). If set to `KeepCurrent`, '-Sc' will clean outdated packages (not present in any sync database). The second behavior is useful when the package cache is shared among multiple machines, where the local databases are usually different, but the - sync databases in use could be the same. + sync databases in use could be the same. If both values are specified, + packages are only cleaned if not installed locally and not present in any + known sync database. *UseSyslog*:: Log action messages through syslog(). This will insert log entries into diff --git a/src/pacman/conf.h b/src/pacman/conf.h index ff7a9c7..92c379f 100644 --- a/src/pacman/conf.h +++ b/src/pacman/conf.h @@ -111,8 +111,8 @@ enum { /* clean method */ enum { - PM_CLEAN_KEEPINST = 0, /* default */ - PM_CLEAN_KEEPCUR + PM_CLEAN_KEEPINST = 1, + PM_CLEAN_KEEPCUR = (1 << 1) }; /* global config variable */ diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index 45500cf..21d0210 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -792,6 +792,18 @@ static void option_add_syncfirst(const char *name) { config->syncfirst = alpm_list_add(config->syncfirst, strdup(name)); } +/* helper for being used with setrepeatingoption */ +static void option_add_cleanmethod(const char *value) { + if (strcmp(value, "KeepInstalled") == 0) { + config->cleanmethod |= PM_CLEAN_KEEPINST; + } else if (strcmp(value, "KeepCurrent") == 0) { + config->cleanmethod |= PM_CLEAN_KEEPCUR; + } else { + pm_printf(PM_LOG_ERROR, _("invalid value for 'CleanMethod' : '%s'\n"), + value); + } +} + /** Add repeating options such as NoExtract, NoUpgrade, etc to libalpm * settings. Refactored out of the parseconfig code since all of them did * the exact same thing and duplicated code. @@ -1008,15 +1020,7 @@ static int _parse_options(char *key, char *value) alpm_option_set_fetchcb(download_with_xfercommand); pm_printf(PM_LOG_DEBUG, "config: xfercommand: %s\n", value); } else if (strcmp(key, "CleanMethod") == 0) { - if (strcmp(value, "KeepInstalled") == 0) { - config->cleanmethod = PM_CLEAN_KEEPINST; - } else if (strcmp(value, "KeepCurrent") == 0) { - config->cleanmethod = PM_CLEAN_KEEPCUR; - } else { - pm_printf(PM_LOG_ERROR, _("invalid value for 'CleanMethod' : '%s'\n"), value); - return(1); - } - pm_printf(PM_LOG_DEBUG, "config: cleanmethod: %s\n", value); + setrepeatingoption(value, "CleanMethod", option_add_cleanmethod); } else { pm_printf(PM_LOG_ERROR, _("directive '%s' with a value not recognized\n"), key); return(1); diff --git a/src/pacman/sync.c b/src/pacman/sync.c index b3f5891..fc23fd1 100644 --- a/src/pacman/sync.c +++ b/src/pacman/sync.c @@ -151,23 +151,23 @@ static int sync_cleancache(int level) printf(_("Cache directory: %s\n"), (char*)alpm_list_getdata(i)); } + if(!config->cleanmethod) { + /* default to KeepInstalled if user did not specify */ + config->cleanmethod = PM_CLEAN_KEEPINST; + } + if(level == 1) { - switch(config->cleanmethod) { - case PM_CLEAN_KEEPINST: - if(!yesno(_("Do you want to remove uninstalled packages from cache?"))) { - return(0); - } - break; - case PM_CLEAN_KEEPCUR: - if(!yesno(_("Do you want to remove outdated packages from cache?"))) { - return(0); - } - break; - default: - /* this should not happen : the config parsing doesn't set any other value */ - return(1); + printf(_("Packages to keep:\n")); + if(config->cleanmethod & PM_CLEAN_KEEPINST) { + printf(_(" All locally installed packages\n")); + } + if(config->cleanmethod & PM_CLEAN_KEEPCUR) { + printf(_(" All current sync database packages\n")); + } + if(!yesno(_("Do you want to remove all other packages from cache?"))) { + return(0); } - printf(_("removing old packages from cache...\n")); + printf(_("removing stale packages from cache...\n")); } else { if(!noyes(_("Do you want to remove ALL files from cache?"))) { return(0); @@ -193,6 +193,7 @@ static int sync_cleancache(int level) char path[PATH_MAX]; int delete = 1; pmpkg_t *localpkg = NULL, *pkg = NULL; + const char *local_name, *local_version; alpm_list_t *j; if(strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { @@ -219,32 +220,33 @@ static int sync_cleancache(int level) } continue; } - switch(config->cleanmethod) { - case PM_CLEAN_KEEPINST: - /* check if this package is in the local DB */ - pkg = alpm_db_get_pkg(db_local, alpm_pkg_get_name(localpkg)); - if(pkg != NULL && alpm_pkg_vercmp(alpm_pkg_get_version(localpkg), + local_name = alpm_pkg_get_name(localpkg); + local_version = alpm_pkg_get_version(localpkg); + + if(config->cleanmethod & PM_CLEAN_KEEPINST) { + /* check if this package is in the local DB */ + pkg = alpm_db_get_pkg(db_local, local_name); + if(pkg != NULL && alpm_pkg_vercmp(local_version, + alpm_pkg_get_version(pkg)) == 0) { + /* package was found in local DB and version matches, keep it */ + pm_printf(PM_LOG_DEBUG, "pkg %s-%s found in local db\n", + local_name, local_version); + delete = 0; + } + } + if(config->cleanmethod & PM_CLEAN_KEEPCUR) { + /* check if this package is in a sync DB */ + for(j = sync_dbs; j && delete; j = alpm_list_next(j)) { + pmdb_t *db = alpm_list_getdata(j); + pkg = alpm_db_get_pkg(db, local_name); + if(pkg != NULL && alpm_pkg_vercmp(local_version, alpm_pkg_get_version(pkg)) == 0) { - /* package was found in local DB and version matches, keep it */ + /* package was found in a sync DB and version matches, keep it */ + pm_printf(PM_LOG_DEBUG, "pkg %s-%s found in sync db\n", + local_name, local_version); delete = 0; } - break; - case PM_CLEAN_KEEPCUR: - /* check if this package is in a sync DB */ - for(j = sync_dbs; j && delete; j = alpm_list_next(j)) { - pmdb_t *db = alpm_list_getdata(j); - pkg = alpm_db_get_pkg(db, alpm_pkg_get_name(localpkg)); - if(pkg != NULL && alpm_pkg_vercmp(alpm_pkg_get_version(localpkg), - alpm_pkg_get_version(pkg)) == 0) { - /* package was found in a sync DB and version matches, keep it */ - delete = 0; - } - } - break; - default: - /* this should not happen : the config parsing doesn't set any other value */ - delete = 0; - break; + } } /* free the local file package */ alpm_pkg_free(localpkg); diff --git a/test/pacman/tests/clean004.py b/test/pacman/tests/clean004.py new file mode 100644 index 0000000..09137f3 --- /dev/null +++ b/test/pacman/tests/clean004.py @@ -0,0 +1,30 @@ +self.description = "CleanMethod = KeepInstalled KeepCurrent" + +sp = pmpkg("dummy", "2.0-1") +self.addpkg2db("sync", sp) + +sp = pmpkg("bar", "2.0-1") +self.addpkg2db("sync", sp) + +sp = pmpkg("baz", "2.0-1") +self.addpkg2db("sync", sp) + +lp = pmpkg("dummy", "1.0-1") +self.addpkg2db("local", lp) + +lp = pmpkg("bar", "2.0-1") +self.addpkg2db("local", lp) + +op = pmpkg("foo", "2.0-1") +self.addpkg(op) + +self.args = "-Sc" +self.option['CleanMethod'] = ['KeepInstalled KeepCurrent'] +self.createlocalpkgs = True + +self.addrule("PACMAN_RETCODE=0") +self.addrule("CACHE_EXISTS=dummy|2.0-1") +self.addrule("CACHE_EXISTS=dummy|1.0-1") +self.addrule("CACHE_EXISTS=bar|2.0-1") +self.addrule("CACHE_EXISTS=baz|2.0-1") +self.addrule("!CACHE_EXISTS=foo|2.0-1") diff --git a/test/pacman/tests/clean005.py b/test/pacman/tests/clean005.py new file mode 100644 index 0000000..f85248e --- /dev/null +++ b/test/pacman/tests/clean005.py @@ -0,0 +1,29 @@ +self.description = "CleanMethod = unspecified" + +sp = pmpkg("dummy", "2.0-1") +self.addpkg2db("sync", sp) + +sp = pmpkg("bar", "2.0-1") +self.addpkg2db("sync", sp) + +sp = pmpkg("baz", "2.0-1") +self.addpkg2db("sync", sp) + +lp = pmpkg("dummy", "1.0-1") +self.addpkg2db("local", lp) + +lp = pmpkg("bar", "2.0-1") +self.addpkg2db("local", lp) + +op = pmpkg("foo", "2.0-1") +self.addpkg(op) + +self.args = "-Sc" +self.createlocalpkgs = True + +self.addrule("PACMAN_RETCODE=0") +self.addrule("!CACHE_EXISTS=dummy|2.0-1") +self.addrule("CACHE_EXISTS=dummy|1.0-1") +self.addrule("CACHE_EXISTS=bar|2.0-1") +self.addrule("!CACHE_EXISTS=baz|2.0-1") +self.addrule("!CACHE_EXISTS=foo|2.0-1") -- 1.7.3.5
On 30/01/11 04:11, Dan McGee wrote:
No reason to disallow this- it allows keeping even more packages around in the cache. Test cases included for this case and to ensure the default behavior is preserved.
Signed-off-by: Dan McGee<dan@archlinux.org>
Ack-by: Allan <snip>
- printf(_("removing old packages from cache...\n")); + printf(_("removing stale packages from cache...\n"));
Not sure about "stale". Perhaps: removing unwanted packages from cache...
participants (2)
-
Allan McRae
-
Dan McGee