diff options
Diffstat (limited to 'src/pacman/sync.c')
-rw-r--r-- | src/pacman/sync.c | 259 |
1 files changed, 179 insertions, 80 deletions
diff --git a/src/pacman/sync.c b/src/pacman/sync.c index b2994389..7af1667a 100644 --- a/src/pacman/sync.c +++ b/src/pacman/sync.c @@ -1,7 +1,7 @@ /* * sync.c * - * Copyright (c) 2006-2010 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -37,13 +37,12 @@ #include "package.h" #include "conf.h" -extern pmdb_t *db_local; - -/* if keep_used != 0, then the dirnames which match an used syncdb +/* if keep_used != 0, then the db files which match an used syncdb * will be kept */ 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) { @@ -51,39 +50,56 @@ 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; - if(!strcmp(dname, ".") || !strcmp(dname, "..")) { + if(strcmp(dname, ".") == 0 || strcmp(dname, "..") == 0) { continue; } /* skip the local and sync directories */ - if(!strcmp(dname, "sync") || !strcmp(dname, "local")) { + if(strcmp(dname, "sync") == 0 || strcmp(dname, "local") == 0) { + continue; + } + /* skip the db.lck file */ + if(strcmp(dname, "db.lck") == 0) { continue; } /* build the full path */ snprintf(path, PATH_MAX, "%s%s", dbpath, dname); - /* skip entries that are not dirs (lock file, etc.) */ + + /* remove all non-skipped directories and non-database files */ stat(path, &buf); - if(!S_ISDIR(buf.st_mode)) { + len = strlen(path); + 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); + closedir(dir); + return(1); + } continue; } if(keep_used) { - syncdbs = alpm_option_get_syncdbs(); + alpm_list_t *i; + len = strlen(dname); + 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(dname, alpm_db_get_name(db)); + found = !strcmp(dbname, alpm_db_get_name(db)); } + free(dbname); } - /* We have a directory that doesn't match any syncdb. + /* We have a database that doesn't match any syncdb. * Ask the user if he wants to remove it. */ if(!found) { if(!yesno(_("Do you want to remove %s?"), path)) { @@ -92,7 +108,7 @@ static int sync_cleandb(const char *dbpath, int keep_used) { if(rmrf(path)) { pm_fprintf(stderr, PM_LOG_ERROR, - _("could not remove repository directory\n")); + _("could not remove %s\n"), path); closedir(dir); return(1); } @@ -112,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 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/"); @@ -128,27 +144,28 @@ static int sync_cleancache(int level) { alpm_list_t *i; alpm_list_t *sync_dbs = alpm_option_get_syncdbs(); + pmdb_t *db_local = alpm_option_get_localdb(); int ret = 0; for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) { 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")); } else { @@ -176,9 +193,10 @@ 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, ".") || !strcmp(ent->d_name, "..")) { + if(strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { continue; } /* build the full filepath */ @@ -202,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); @@ -279,7 +298,7 @@ static int sync_synctree(int level, alpm_list_t *syncs) return(success > 0); } -static void print_installed(pmpkg_t *pkg) +static void print_installed(pmdb_t *db_local, pmpkg_t *pkg) { const char *pkgname = alpm_pkg_get_name(pkg); const char *pkgver = alpm_pkg_get_version(pkg); @@ -300,6 +319,7 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t *targets) alpm_list_t *i, *j, *ret; int freelist; int found = 0; + pmdb_t *db_local = alpm_option_get_localdb(); for(i = syncs; i; i = alpm_list_next(i)) { pmdb_t *db = alpm_list_getdata(i); @@ -308,7 +328,7 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t *targets) ret = alpm_db_search(db, targets); freelist = 1; } else { - ret = alpm_db_get_pkgcache(db); + ret = alpm_db_get_pkgcache_list(db); freelist = 0; } if(ret == NULL) { @@ -330,7 +350,7 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t *targets) /* print the package size with the output if ShowSize option set */ if(!config->quiet && config->showsize) { /* Convert byte size to MB */ - double mbsize = alpm_pkg_get_size(pkg) / (1024.0 * 1024.0); + double mbsize = (double)alpm_pkg_get_size(pkg) / (1024.0 * 1024.0); printf(" [%.2f MB]", mbsize); } @@ -350,7 +370,7 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t *targets) printf(")"); } - print_installed(pkg); + print_installed(db_local, pkg); /* we need a newline and initial indent first */ printf("\n "); @@ -449,7 +469,7 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) return(1); } - for(k = alpm_db_get_pkgcache(db); k; k = alpm_list_next(k)) { + for(k = alpm_db_get_pkgcache_list(db); k; k = alpm_list_next(k)) { pmpkg_t *pkg = alpm_list_getdata(k); if(strcmp(alpm_pkg_get_name(pkg), pkgstr) == 0) { @@ -470,7 +490,7 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) for(j = syncs; j; j = alpm_list_next(j)) { pmdb_t *db = alpm_list_getdata(j); - for(k = alpm_db_get_pkgcache(db); k; k = alpm_list_next(k)) { + for(k = alpm_db_get_pkgcache_list(db); k; k = alpm_list_next(k)) { pmpkg_t *pkg = alpm_list_getdata(k); if(strcmp(alpm_pkg_get_name(pkg), pkgstr) == 0) { @@ -491,7 +511,7 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) for(i = syncs; i; i = alpm_list_next(i)) { pmdb_t *db = alpm_list_getdata(i); - for(j = alpm_db_get_pkgcache(db); j; j = alpm_list_next(j)) { + for(j = alpm_db_get_pkgcache_list(db); j; j = alpm_list_next(j)) { dump_pkg_sync(alpm_list_getdata(j), alpm_db_get_name(db), config->op_s_info); } } @@ -503,6 +523,7 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) static int sync_list(alpm_list_t *syncs, alpm_list_t *targets) { alpm_list_t *i, *j, *ls = NULL; + pmdb_t *db_local = alpm_option_get_localdb(); if(targets) { for(i = targets; i; i = alpm_list_next(i)) { @@ -534,13 +555,13 @@ static int sync_list(alpm_list_t *syncs, alpm_list_t *targets) for(i = ls; i; i = alpm_list_next(i)) { pmdb_t *db = alpm_list_getdata(i); - for(j = alpm_db_get_pkgcache(db); j; j = alpm_list_next(j)) { + for(j = alpm_db_get_pkgcache_list(db); j; j = alpm_list_next(j)) { pmpkg_t *pkg = alpm_list_getdata(j); if (!config->quiet) { printf("%s %s %s", alpm_db_get_name(db), alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); - print_installed(pkg); + print_installed(db_local, pkg); printf("\n"); } else { printf("%s\n", alpm_pkg_get_name(pkg)); @@ -555,7 +576,7 @@ static int sync_list(alpm_list_t *syncs, alpm_list_t *targets) return(0); } -static alpm_list_t *syncfirst() { +static alpm_list_t *syncfirst(void) { alpm_list_t *i, *res = NULL; for(i = config->syncfirst; i; i = alpm_list_next(i)) { @@ -573,6 +594,82 @@ static alpm_list_t *syncfirst() { return(res); } +static pmdb_t *get_db(const char *dbname) +{ + alpm_list_t *i; + for(i = alpm_option_get_syncdbs(); i; i = i->next) { + pmdb_t *db = i->data; + if(strcmp(alpm_db_get_name(db), dbname) == 0) { + return(db); + } + } + return(NULL); +} + +static int process_pkg(pmpkg_t *pkg) +{ + int ret = alpm_add_pkg(pkg); + + if(ret == -1) { + if(pm_errno == PM_ERR_TRANS_DUP_TARGET + || pm_errno == PM_ERR_PKG_IGNORED) { + /* just skip duplicate or ignored targets */ + pm_printf(PM_LOG_WARNING, _("skipping target: %s\n"), alpm_pkg_get_name(pkg)); + return(0); + } else { + pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", alpm_pkg_get_name(pkg), + alpm_strerrorlast()); + return(1); + } + } + return(0); +} + +static int process_group(alpm_list_t *dbs, char *group) +{ + int ret = 0; + alpm_list_t *i; + alpm_list_t *pkgs = alpm_find_grp_pkgs(dbs, group); + int count = alpm_list_count(pkgs); + + if(!count) { + pm_fprintf(stderr, PM_LOG_ERROR, _("target not found: %s\n"), group); + return(1); + } + + printf(_(":: There are %d members in group %s:\n"), count, + group); + select_display(pkgs); + char *array = malloc(count); + multiselect_question(array, count); + int n = 0; + for(i = pkgs; i; i = alpm_list_next(i)) { + if(array[n++] == 0) + continue; + pmpkg_t *pkg = alpm_list_getdata(i); + + if(process_pkg(pkg) == 1) { + ret = 1; + goto cleanup; + } + } +cleanup: + alpm_list_free(pkgs); + free(array); + return(ret); +} + +static int process_targname(alpm_list_t *dblist, char *targname) +{ + pmpkg_t *pkg = alpm_find_dbs_satisfier(dblist, targname); + + if(pkg) { + return(process_pkg(pkg)); + } + /* fallback on group */ + return(process_group(dblist, targname)); +} + static int process_target(char *target) { /* process targets */ @@ -580,28 +677,30 @@ static int process_target(char *target) char *targname = strchr(targstring, '/'); char *dbname = NULL; int ret = 0; + alpm_list_t *dblist = NULL; + if(targname) { + pmdb_t *db = NULL; + *targname = '\0'; targname++; dbname = targstring; - ret = alpm_sync_dbtarget(dbname,targname); - } else { - targname = targstring; - ret = alpm_sync_target(targname); - } - - if(ret == -1) { - if(pm_errno == PM_ERR_TRANS_DUP_TARGET - || pm_errno == PM_ERR_PKG_IGNORED) { - /* just skip duplicate or ignored targets */ - pm_printf(PM_LOG_WARNING, _("skipping target: %s\n"), target); - } else { - pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", target, - alpm_strerrorlast()); + db = get_db(dbname); + if(!db) { + pm_fprintf(stderr, PM_LOG_ERROR, _("database not found: %s\n"), + dbname); ret = 1; + goto cleanup; } + dblist = alpm_list_add(dblist, db); + ret = process_targname(dblist, targname); + alpm_list_free(dblist); + } else { + targname = targstring; + dblist = alpm_option_get_syncdbs(); + ret = process_targname(dblist, targname); } - +cleanup: free(targstring); return(ret); } @@ -666,7 +765,7 @@ static int sync_trans(alpm_list_t *targets) const char *package2 = alpm_conflict_get_package2(conflict); const char *reason = alpm_conflict_get_reason(conflict); /* only print reason if it contains new information */ - if(!strcmp(package1, reason) || !strcmp(package2, reason)) { + if(strcmp(package1, reason) == 0 || strcmp(package2, reason) == 0) { printf(_(":: %s and %s are in conflict\n"), package1, package2); } else { printf(_(":: %s and %s are in conflict (%s)\n"), package1, package2, reason); |