When using a local repo as a cachedir pacman -Scc or pacman -Sc without KeepCurrent will delete the repo database and packages resulting in a lost database and non functional pacman. So special case file:/// repos in cache to not get nuked and foce KeepCurrent on. --- src/pacman/sync.c | 64 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 9 deletions(-) diff --git a/src/pacman/sync.c b/src/pacman/sync.c index b6da1a36..129d3f5c 100644 --- a/src/pacman/sync.c +++ b/src/pacman/sync.c @@ -151,34 +151,71 @@ static int sync_cleandb_all(void) return ret; } -static int sync_cleancache(int level) +static int is_local_repo(char *dir) +{ + alpm_list_t *j, *k; + char *sanatized_dir = strdup(dir); + int len = strlen(sanatized_dir); + int ret = 0; + + if(sanatized_dir[len - 1] == '/') { + sanatized_dir[len - 1] = '\0'; + } + + for(j = alpm_get_syncdbs(config->handle); j; j = alpm_list_next(j)) { + alpm_db_t *db = j->data; + + for(k = alpm_db_get_servers(db); k; k = alpm_list_next(k)) { + char *server = k->data; + + if(strncmp(server, "file://", 7) == 0) { + server += 7; + + if(strcmp(server, sanatized_dir) == 0) { + ret = 1; + goto cleanup; + } + } + } + + } + +cleanup: + free(sanatized_dir); + return ret; +} + +static int sync_cleancache(int config_level) { alpm_list_t *i; alpm_list_t *sync_dbs = alpm_get_syncdbs(config->handle); alpm_db_t *db_local = alpm_get_localdb(config->handle); alpm_list_t *cachedirs = alpm_option_get_cachedirs(config->handle); + int config_cleanmethod = config->cleanmethod; int ret = 0; - if(!config->cleanmethod) { + if(config_cleanmethod) { /* default to KeepInstalled if user did not specify */ - config->cleanmethod = PM_CLEAN_KEEPINST; + config_cleanmethod = PM_CLEAN_KEEPINST; } - if(level == 1) { + if(config_level == 1) { printf(_("Packages to keep:\n")); - if(config->cleanmethod & PM_CLEAN_KEEPINST) { + if(config_cleanmethod & PM_CLEAN_KEEPINST) { printf(_(" All locally installed packages\n")); } - if(config->cleanmethod & PM_CLEAN_KEEPCUR) { + if(config_cleanmethod & PM_CLEAN_KEEPCUR) { printf(_(" All current sync database packages\n")); } } printf("\n"); for(i = cachedirs; i; i = alpm_list_next(i)) { - const char *cachedir = i->data; + char *cachedir = i->data; DIR *dir; struct dirent *ent; + int cleanmethod = config_cleanmethod; + int level = config_level; printf(_("Cache directory: %s\n"), (const char *)i->data); @@ -196,6 +233,15 @@ static int sync_cleancache(int level) printf(_("removing all files from cache...\n")); } + if(is_local_repo(cachedir)) { + pm_printf(ALPM_LOG_DEBUG, + _("cachedir '%s' is a local repo, keeping packages\n"), cachedir); + + level = 1; + cleanmethod |= PM_CLEAN_KEEPCUR; + cleanmethod &= ~PM_CLEAN_KEEPINST; + } + dir = opendir(cachedir); if(dir == NULL) { pm_printf(ALPM_LOG_ERROR, @@ -258,7 +304,7 @@ static int sync_cleancache(int level) local_name = alpm_pkg_get_name(localpkg); local_version = alpm_pkg_get_version(localpkg); - if(config->cleanmethod & PM_CLEAN_KEEPINST) { + if(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, @@ -269,7 +315,7 @@ static int sync_cleancache(int level) delete = 0; } } - if(config->cleanmethod & PM_CLEAN_KEEPCUR) { + if(cleanmethod & PM_CLEAN_KEEPCUR) { alpm_list_t *j; /* check if this package is in a sync DB */ for(j = sync_dbs; j && delete; j = alpm_list_next(j)) { -- 2.32.0