Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/pacman.8.txt3
-rw-r--r--doc/pacman.conf.5.txt9
-rw-r--r--src/pacman/conf.h13
-rw-r--r--src/pacman/pacman.c10
-rw-r--r--src/pacman/sync.c69
5 files changed, 83 insertions, 21 deletions
diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt
index 6f6942d7..15d31096 100644
--- a/doc/pacman.8.txt
+++ b/doc/pacman.8.txt
@@ -244,6 +244,9 @@ Sync Options[[SO]]
packages that are no longer installed; use two to remove all packages
from the cache. In both cases, you will have a yes or no option to
remove packages and/or unused downloaded databases.
++
+If you use a network shared cache, see the 'CleanMethod' option in
+linkman:pacman.conf[5].
*-g, \--groups*::
Display all the members for each package group specified. If no group
diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt
index 3cdd2906..d1b3bda1 100644
--- a/doc/pacman.conf.5.txt
+++ b/doc/pacman.conf.5.txt
@@ -119,6 +119,15 @@ 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::
+ 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.
+
*UseSyslog*::
Log action messages through syslog(). This will insert log entries into
``/var/log/messages'' or equivalent.
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index a28c77f4..28ac4b96 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -65,9 +65,10 @@ typedef struct __config_t {
unsigned short chomp; /* I Love Candy! */
unsigned short usecolor; /* enable colorful output */
unsigned short showsize; /* show individual package sizes */
- unsigned short totaldownload; /* When downloading, display the amount
- downloaded, rate, ETA, and percent
- downloaded of the total download list */
+ /* When downloading, display the amount downloaded, rate, ETA, and percent
+ * downloaded of the total download list */
+ unsigned short totaldownload;
+ unsigned short cleanmethod; /* select -Sc behavior */
} config_t;
/* Operations */
@@ -80,6 +81,12 @@ enum {
PM_OP_DEPTEST
};
+/* clean method */
+enum {
+ PM_CLEAN_KEEPINST = 0, /* default */
+ PM_CLEAN_KEEPCUR
+};
+
/* global config variable */
extern config_t *config;
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index 6bc284a3..7240e0fa 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -692,6 +692,16 @@ static int _parseconfig(const char *file, const char *givensection,
} else if (strcmp(key, "XferCommand") == 0) {
alpm_option_set_xfercommand(ptr);
pm_printf(PM_LOG_DEBUG, "config: xfercommand: %s\n", ptr);
+ } else if (strcmp(key, "CleanMethod") == 0) {
+ if (strcmp(ptr, "KeepInstalled") == 0) {
+ config->cleanmethod = PM_CLEAN_KEEPINST;
+ } else if (strcmp(ptr, "KeepCurrent") == 0) {
+ config->cleanmethod = PM_CLEAN_KEEPCUR;
+ } else {
+ pm_printf(PM_LOG_ERROR, _("invalid value for 'CleanMethod' : '%s'\n"), ptr);
+ return(1);
+ }
+ pm_printf(PM_LOG_DEBUG, "config: cleanmethod: %s\n", ptr);
} else {
pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' not recognized.\n"),
file, linenum, key);
diff --git a/src/pacman/sync.c b/src/pacman/sync.c
index f2d8f4bc..460933ae 100644
--- a/src/pacman/sync.c
+++ b/src/pacman/sync.c
@@ -133,13 +133,23 @@ static int sync_cleancache(int level)
/* incomplete cleanup */
DIR *dir;
struct dirent *ent;
- /* Let's vastly improve the way this is done. Before, we went by package
- * name. Instead, let's only keep packages we have installed. Open up each
- * package and see if it has an entry in the local DB; if not, delete it.
- */
+ /* Open up each package and see if it should be deleted,
+ * depending on the clean method used */
printf(_("Cache directory: %s\n"), cachedir);
- if(!yesno(1, _("Do you want to remove uninstalled packages from cache?"))) {
- return(0);
+ switch(config->cleanmethod) {
+ case PM_CLEAN_KEEPINST:
+ if(!yesno(1, _("Do you want to remove uninstalled packages from cache?"))) {
+ return(0);
+ }
+ break;
+ case PM_CLEAN_KEEPCUR:
+ if(!yesno(1, _("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(_("removing old packages from cache... "));
@@ -153,13 +163,16 @@ static int sync_cleancache(int level)
/* step through the directory one file at a time */
while((ent = readdir(dir)) != NULL) {
char path[PATH_MAX];
- pmpkg_t *localpkg = NULL, *dbpkg = NULL;
+ int delete = 1;
+ pmpkg_t *localpkg = NULL, *pkg = NULL;
+ alpm_list_t *sync_dbs = alpm_option_get_syncdbs();
+ alpm_list_t *j;
if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) {
continue;
}
/* build the full filepath */
- snprintf(path, PATH_MAX, "%s/%s", cachedir, ent->d_name);
+ snprintf(path, PATH_MAX, "%s%s", cachedir, ent->d_name);
/* attempt to load the package, skip file on failures as we may have
* files here that aren't valid packages. we also don't need a full
@@ -167,19 +180,39 @@ static int sync_cleancache(int level)
if(alpm_pkg_load(path, 0, &localpkg) != 0 || localpkg == NULL) {
continue;
}
- /* check if this package is in the local DB */
- dbpkg = alpm_db_get_pkg(db_local, alpm_pkg_get_name(localpkg));
- if(dbpkg == NULL) {
- /* delete package, not present in local DB */
- unlink(path);
- } else if(alpm_pkg_vercmp(alpm_pkg_get_version(localpkg),
- alpm_pkg_get_version(dbpkg)) != 0) {
- /* delete package, it was found but version differs */
- unlink(path);
+ 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),
+ alpm_pkg_get_version(pkg)) == 0) {
+ /* package was found in local DB and version matches, keep it */
+ 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;
}
- /* else version was the same, so keep the package */
/* free the local file package */
alpm_pkg_free(localpkg);
+
+ if(delete) {
+ unlink(path);
+ }
}
printf(_("done.\n"));
} else {