summaryrefslogtreecommitdiffstats
path: root/src/pacman/sync.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pacman/sync.c')
-rw-r--r--src/pacman/sync.c259
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);