diff options
Diffstat (limited to 'src/pacman')
-rw-r--r-- | src/pacman/Makefile.am | 7 | ||||
-rw-r--r-- | src/pacman/callback.c | 142 | ||||
-rw-r--r-- | src/pacman/callback.h | 7 | ||||
-rw-r--r-- | src/pacman/conf.c | 8 | ||||
-rw-r--r-- | src/pacman/conf.h | 17 | ||||
-rw-r--r-- | src/pacman/deptest.c | 46 | ||||
-rw-r--r-- | src/pacman/package.c | 22 | ||||
-rw-r--r-- | src/pacman/pacman.c | 136 | ||||
-rw-r--r-- | src/pacman/pacman.h | 9 | ||||
-rw-r--r-- | src/pacman/query.c | 69 | ||||
-rw-r--r-- | src/pacman/remove.c | 47 | ||||
-rw-r--r-- | src/pacman/sync.c | 383 | ||||
-rw-r--r-- | src/pacman/upgrade.c (renamed from src/pacman/add.c) | 65 | ||||
-rw-r--r-- | src/pacman/util.c | 131 | ||||
-rw-r--r-- | src/pacman/util.h | 4 |
15 files changed, 549 insertions, 544 deletions
diff --git a/src/pacman/Makefile.am b/src/pacman/Makefile.am index 5e287404..e5f8cb36 100644 --- a/src/pacman/Makefile.am +++ b/src/pacman/Makefile.am @@ -21,8 +21,12 @@ INCLUDES = -I$(top_srcdir)/lib/libalpm AM_CFLAGS = -pedantic -D_GNU_SOURCE +if USE_GIT_VERSION +GIT_VERSION := $(shell sh -c 'git describe --abbrev=4 | sed s/^v//')-dirty +DEFS += -DGIT_VERSION=\"$(GIT_VERSION)\" +endif + pacman_SOURCES = \ - add.c \ conf.h conf.c \ deptest.c \ package.h package.c \ @@ -31,6 +35,7 @@ pacman_SOURCES = \ remove.c \ sync.c \ callback.h callback.c \ + upgrade.c \ util.h util.c LDADD = $(LTLIBINTL) $(top_builddir)/lib/libalpm/.libs/libalpm.la diff --git a/src/pacman/callback.c b/src/pacman/callback.c index a7686483..ff125c36 100644 --- a/src/pacman/callback.c +++ b/src/pacman/callback.c @@ -23,6 +23,7 @@ #include <stdlib.h> #include <string.h> #include <sys/time.h> +#include <sys/types.h> /* off_t */ #include <unistd.h> #include <dirent.h> #include <wchar.h> @@ -34,12 +35,11 @@ #include "util.h" #include "conf.h" -/* TODO this should not have to be defined twice- trans.c & log.c */ -#define LOG_STR_LEN 256 - /* download progress bar */ static float rate_last; -static int xfered_last; +static off_t xfered_last; +static off_t list_xfered = 0.0; +static off_t list_total = 0.0; static struct timeval initial_time; /* transaction progress bar */ @@ -86,17 +86,15 @@ static float get_update_timediff(int first_call) } /* refactored from cb_trans_progress */ -static void fill_progress(const int graph_percent, const int display_percent, +static void fill_progress(const int bar_percent, const int disp_percent, const int proglen) { const unsigned int hashlen = proglen - 8; - const unsigned int hash = graph_percent * hashlen / 100; + const unsigned int hash = bar_percent * hashlen / 100; static unsigned int lasthash = 0, mouth = 0; unsigned int i; - /* printf("\ndebug: proglen: %i\n", proglen); DEBUG*/ - - if(graph_percent == 0) { + if(bar_percent == 0) { lasthash = 0; mouth = 0; } @@ -141,10 +139,12 @@ static void fill_progress(const int graph_percent, const int display_percent, } /* print percent after progress bar */ if(proglen > 5) { - printf(" %3d%%", display_percent); + /* use disp_percent if it is not 0, else show bar_percent */ + int p = disp_percent ? disp_percent : bar_percent; + printf(" %3d%%", p); } - if(graph_percent == 100) { + if(bar_percent == 100) { printf("\n"); } else { printf("\r"); @@ -157,8 +157,6 @@ static void fill_progress(const int graph_percent, const int display_percent, /* callback to handle messages/notifications from libalpm transactions */ void cb_trans_evt(pmtransevt_t event, void *data1, void *data2) { - char str[LOG_STR_LEN] = ""; - switch(event) { case PM_TRANS_EVT_CHECKDEPS_START: printf(_("checking dependencies...\n")); @@ -180,10 +178,9 @@ void cb_trans_evt(pmtransevt_t event, void *data1, void *data2) } break; case PM_TRANS_EVT_ADD_DONE: - snprintf(str, LOG_STR_LEN, "installed %s (%s)\n", + alpm_logaction("installed %s (%s)\n", alpm_pkg_get_name(data1), alpm_pkg_get_version(data1)); - alpm_logaction(str); break; case PM_TRANS_EVT_REMOVE_START: if(config->noprogressbar) { @@ -191,10 +188,9 @@ void cb_trans_evt(pmtransevt_t event, void *data1, void *data2) } break; case PM_TRANS_EVT_REMOVE_DONE: - snprintf(str, LOG_STR_LEN, "removed %s (%s)\n", + alpm_logaction("removed %s (%s)\n", alpm_pkg_get_name(data1), alpm_pkg_get_version(data1)); - alpm_logaction(str); break; case PM_TRANS_EVT_UPGRADE_START: if(config->noprogressbar) { @@ -202,11 +198,10 @@ void cb_trans_evt(pmtransevt_t event, void *data1, void *data2) } break; case PM_TRANS_EVT_UPGRADE_DONE: - snprintf(str, LOG_STR_LEN, "upgraded %s (%s -> %s)\n", + alpm_logaction("upgraded %s (%s -> %s)\n", (char *)alpm_pkg_get_name(data1), (char *)alpm_pkg_get_version(data2), (char *)alpm_pkg_get_version(data1)); - alpm_logaction(str); break; case PM_TRANS_EVT_INTEGRITY_START: printf(_("checking package integrity...\n")); @@ -237,7 +232,6 @@ void cb_trans_evt(pmtransevt_t event, void *data1, void *data2) break; /* all the simple done events, with fallthrough for each */ case PM_TRANS_EVT_FILECONFLICTS_DONE: - case PM_TRANS_EVT_EXTRACT_DONE: case PM_TRANS_EVT_CHECKDEPS_DONE: case PM_TRANS_EVT_RESOLVEDEPS_DONE: case PM_TRANS_EVT_INTERCONFLICTS_DONE: @@ -255,67 +249,46 @@ void cb_trans_evt(pmtransevt_t event, void *data1, void *data2) void cb_trans_conv(pmtransconv_t event, void *data1, void *data2, void *data3, int *response) { - char str[LOG_STR_LEN] = ""; - switch(event) { case PM_TRANS_CONV_INSTALL_IGNOREPKG: if(data2) { /* TODO we take this route based on data2 being not null? WTF */ - snprintf(str, LOG_STR_LEN, _(":: %s requires installing %s from IgnorePkg/IgnoreGroup. Install anyway? [Y/n] "), + *response = yesno(1, _(":: %s requires installing %s from IgnorePkg/IgnoreGroup. Install anyway?"), alpm_pkg_get_name(data1), alpm_pkg_get_name(data2)); - *response = yesno(str); } else { - snprintf(str, LOG_STR_LEN, _(":: %s is in IgnorePkg/IgnoreGroup. Install anyway? [Y/n] "), + *response = yesno(1, _(":: %s is in IgnorePkg/IgnoreGroup. Install anyway?"), alpm_pkg_get_name(data1)); - *response = yesno(str); } break; case PM_TRANS_CONV_REMOVE_HOLDPKG: - snprintf(str, LOG_STR_LEN, _(":: %s is designated as a HoldPkg. Remove anyway? [Y/n] "), + *response = yesno(1, _(":: %s is designated as a HoldPkg. Remove anyway?"), alpm_pkg_get_name(data1)); - *response = yesno(str); break; case PM_TRANS_CONV_REPLACE_PKG: - if(!config->noconfirm) { - snprintf(str, LOG_STR_LEN, _(":: Replace %s with %s/%s? [Y/n] "), - alpm_pkg_get_name(data1), - (char *)data3, - alpm_pkg_get_name(data2)); - *response = yesno(str); - } else { - printf(_("Replacing %s with %s/%s\n"), - alpm_pkg_get_name(data1), - (char *)data3, - alpm_pkg_get_name(data2)); - *response = 1; - } + *response = yesno(1, _(":: Replace %s with %s/%s?"), + alpm_pkg_get_name(data1), + (char *)data3, + alpm_pkg_get_name(data2)); break; case PM_TRANS_CONV_CONFLICT_PKG: - snprintf(str, LOG_STR_LEN, _(":: %s conflicts with %s. Remove %s? [Y/n] "), + *response = yesno(1, _(":: %s conflicts with %s. Remove %s?"), (char *)data1, (char *)data2, (char *)data2); - *response = yesno(str); break; case PM_TRANS_CONV_LOCAL_NEWER: if(!config->op_s_downloadonly) { - snprintf(str, LOG_STR_LEN, _(":: %s-%s: local version is newer. Upgrade anyway? [Y/n] "), + *response = yesno(1, _(":: %s-%s: local version is newer. Upgrade anyway?"), alpm_pkg_get_name(data1), alpm_pkg_get_version(data1)); - *response = yesno(str); } else { *response = 1; } break; case PM_TRANS_CONV_CORRUPTED_PKG: - if(!config->noconfirm) { - snprintf(str, LOG_STR_LEN, _(":: File %s is corrupted. Do you want to delete it? [Y/n] "), - (char *)data1); - *response = yesno(str); - } else { - *response = 1; - } + *response = yesno(1, _(":: File %s is corrupted. Do you want to delete it?"), + (char *)data1); break; } } @@ -442,9 +415,19 @@ void cb_trans_progress(pmtransprog_t event, const char *pkgname, int percent, } } +/* callback to handle receipt of total download value */ +void cb_dl_total(off_t total) +{ + list_total = total; + /* if we get a 0 value, it means this list has finished downloading, + * so clear out our list_xfered as well */ + if(total == 0) { + list_xfered = 0; + } +} + /* callback to handle display of download progress */ -void cb_dl_progress(const char *filename, int file_xfered, int file_total, - int list_xfered, int list_total) +void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total) { const int infolen = 50; const int filenamelen = infolen - 27; @@ -453,44 +436,37 @@ void cb_dl_progress(const char *filename, int file_xfered, int file_total, int len, wclen, wcwid, padwid; wchar_t *wcfname; + off_t xfered, total; float rate = 0.0, timediff = 0.0, f_xfered = 0.0; unsigned int eta_h = 0, eta_m = 0, eta_s = 0; - int graph_percent = 0, display_percent = 0; + int file_percent = 0, total_percent = 0; char rate_size = 'K', xfered_size = 'K'; - int xfered = 0, total = 0; - - /* Need this variable when TotalDownload is set to know if we should - * reset xfered_last and rate_last. */ - static int has_init = 0; if(config->noprogressbar) { return; } - /* Choose how to display the amount downloaded, rate, ETA, and - * percentage depending on the TotalDownload option. */ - if (config->totaldownload && list_total > 0) { - xfered = list_xfered; + /* only use TotalDownload if enabled and we have a callback value */ + if(config->totaldownload && list_total) { + xfered = list_xfered + file_xfered; total = list_total; } else { xfered = file_xfered; total = file_total; } - /* this is basically a switch on file_xferred: 0, file_total, and + /* this is basically a switch on xfered: 0, total, and * anything else */ if(file_xfered == 0) { - /* set default starting values, but only once for TotalDownload */ - if (!(config->totaldownload && list_total > 0) || - (config->totaldownload && list_total > 0 && !has_init)) { + /* set default starting values, ensure we only call this once + * if TotalDownload is enabled */ + if(!(config->totaldownload) + || (config->totaldownload && list_xfered == 0)) { gettimeofday(&initial_time, NULL); - timediff = get_update_timediff(1); - xfered_last = 0; + xfered_last = (off_t)0; rate_last = 0.0; - has_init = 1; + timediff = get_update_timediff(1); } - rate = 0.0; - eta_s = 0; } else if(file_xfered == file_total) { /* compute final values */ struct timeval current_time; @@ -514,12 +490,24 @@ void cb_dl_progress(const char *filename, int file_xfered, int file_total, } rate = (xfered - xfered_last) / (timediff * 1024.0); /* average rate to reduce jumpiness */ - rate = (rate + 2*rate_last) / 3; + rate = (rate + 2 * rate_last) / 3; eta_s = (total - xfered) / (rate * 1024.0); rate_last = rate; xfered_last = xfered; } + file_percent = (int)((float)file_xfered) / ((float)file_total) * 100; + + if(config->totaldownload && list_total) { + total_percent = (int)((float)list_xfered + file_xfered) / + ((float)list_total) * 100; + + /* if we are at the end, add the completed file to list_xfered */ + if(file_xfered == file_total) { + list_xfered += file_total; + } + } + /* fix up time for display */ eta_h = eta_s / 3600; eta_s -= eta_h * 3600; @@ -591,11 +579,7 @@ void cb_dl_progress(const char *filename, int file_xfered, int file_total, free(fname); free(wcfname); - /* The progress bar is based on the file percent regardless of the - * TotalDownload option. */ - graph_percent = (int)((float)file_xfered) / ((float)file_total) * 100; - display_percent = (int)((float)xfered) / ((float)total) * 100; - fill_progress(graph_percent, display_percent, getcols() - infolen); + fill_progress(file_percent, total_percent, getcols() - infolen); return; } diff --git a/src/pacman/callback.h b/src/pacman/callback.h index aa8d9370..2961be84 100644 --- a/src/pacman/callback.h +++ b/src/pacman/callback.h @@ -19,6 +19,8 @@ #ifndef _PM_CALLBACK_H #define _PM_CALLBACK_H +#include <sys/types.h> /* off_t */ + #include <alpm.h> /* callback to handle messages/notifications from libalpm transactions */ @@ -32,9 +34,10 @@ void cb_trans_conv(pmtransconv_t event, void *data1, void *data2, void cb_trans_progress(pmtransprog_t event, const char *pkgname, int percent, int howmany, int remain); +/* callback to handle receipt of total download value */ +void cb_dl_total(off_t total); /* callback to handle display of download progress */ -void cb_dl_progress(const char *filename, int file_xfered, int file_total, - int list_xfered, int list_total); +void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total); /* callback to handle messages/notifications from pacman library */ void cb_log(pmloglevel_t level, char *fmt, va_list args); diff --git a/src/pacman/conf.c b/src/pacman/conf.c index bf3a4624..48c927bf 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -25,6 +25,7 @@ /* pacman */ #include "conf.h" +#include "util.h" /* global config variable */ config_t *config = NULL; @@ -33,8 +34,9 @@ config_t *config_new(void) { config_t *newconfig = calloc(1, sizeof(config_t)); if(!newconfig) { - fprintf(stderr, "malloc failure: could not allocate %zd bytes\n", - sizeof(config_t)); + pm_fprintf(stderr, PM_LOG_ERROR, + _("malloc failure: could not allocate %zd bytes\n"), + sizeof(config_t)); return(NULL); } /* defaults which may get overridden later */ @@ -45,6 +47,7 @@ config_t *config_new(void) newconfig->rootdir = NULL; newconfig->dbpath = NULL; newconfig->logfile = NULL; + newconfig->syncfirst = NULL; return(newconfig); } @@ -55,6 +58,7 @@ int config_free(config_t *oldconfig) return(-1); } + FREELIST(oldconfig->syncfirst); free(oldconfig->configfile); free(oldconfig->rootdir); free(oldconfig->dbpath); diff --git a/src/pacman/conf.h b/src/pacman/conf.h index f804f560..874ce708 100644 --- a/src/pacman/conf.h +++ b/src/pacman/conf.h @@ -27,7 +27,6 @@ typedef struct __config_t { unsigned short verbose; unsigned short version; unsigned short help; - unsigned short upgrade; unsigned short noconfirm; unsigned short noprogressbar; unsigned short logmask; @@ -53,7 +52,6 @@ typedef struct __config_t { unsigned short op_q_upgrade; unsigned short op_s_clean; - unsigned short op_s_dependsonly; unsigned short op_s_downloadonly; unsigned short op_s_info; unsigned short op_s_sync; @@ -67,15 +65,16 @@ 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 */ + alpm_list_t *syncfirst; } config_t; /* Operations */ enum { PM_OP_MAIN = 1, - PM_OP_ADD, PM_OP_REMOVE, PM_OP_UPGRADE, PM_OP_QUERY, @@ -83,6 +82,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/deptest.c b/src/pacman/deptest.c index 2481c0b6..2feca5c4 100644 --- a/src/pacman/deptest.c +++ b/src/pacman/deptest.c @@ -31,53 +31,23 @@ #include "util.h" #include "conf.h" -/* TODO: This should use _alpm_checkdeps() */ int pacman_deptest(alpm_list_t *targets) { - int retval = 0; alpm_list_t *i; - if(targets == NULL) { + alpm_list_t *deps = alpm_deptest(alpm_option_get_localdb(), targets); + if(deps == NULL) { return(0); } - for(i = targets; i; i = alpm_list_next(i)) { - int found = 0; - pmpkg_t *pkg; - pmdepend_t *dep; - const char *target; - alpm_list_t *j, *provides; + for(i = deps; i; i = alpm_list_next(i)) { + const char *dep; - target = alpm_list_getdata(i); - dep = alpm_splitdep(target); - - pkg = alpm_db_get_pkg(alpm_option_get_localdb(), - alpm_dep_get_name(dep)); - if(pkg && alpm_depcmp(pkg, dep)) { - found = 1; - } else { - /* not found, can we find anything that provides this in the local DB? */ - provides = alpm_db_whatprovides(alpm_option_get_localdb(), - alpm_dep_get_name(dep)); - for(j = provides; j; j = alpm_list_next(j)) { - pmpkg_t *pkg; - pkg = alpm_list_getdata(j); - - if(pkg && alpm_depcmp(pkg, dep)) { - found = 1; - break; - } - } - alpm_list_free(provides); - } - - if(!found) { - printf("%s\n", target); - retval = 127; - } - free(dep); + dep = alpm_list_getdata(i); + printf("%s\n", dep); } - return(retval); + alpm_list_free(deps); + return(127); } /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/package.c b/src/pacman/package.c index 7019e7e6..06800378 100644 --- a/src/pacman/package.c +++ b/src/pacman/package.c @@ -22,8 +22,8 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <unistd.h> #include <limits.h> -#include <sys/stat.h> #include <wchar.h> #include <alpm.h> @@ -90,9 +90,6 @@ void dump_pkg_full(pmpkg_t *pkg, int level) } /* actual output */ - if(level == 0) { - string_display(_("Filename :"), alpm_pkg_get_filename(pkg)); - } string_display(_("Name :"), alpm_pkg_get_name(pkg)); string_display(_("Version :"), alpm_pkg_get_version(pkg)); string_display(_("URL :"), alpm_pkg_get_url(pkg)); @@ -179,7 +176,6 @@ void dump_pkg_backups(pmpkg_t *pkg) if(alpm_pkg_get_backup(pkg)) { /* package has backup files, so print them */ for(i = alpm_pkg_get_backup(pkg); i; i = alpm_list_next(i)) { - struct stat buf; char path[PATH_MAX]; char *str = strdup(alpm_list_getdata(i)); char *ptr = index(str, '\t'); @@ -191,12 +187,12 @@ void dump_pkg_backups(pmpkg_t *pkg) ptr++; snprintf(path, PATH_MAX-1, "%s%s", root, str); /* if we find the file, calculate checksums, otherwise it is missing */ - if(!stat(path, &buf)) { + if(access(path, R_OK) == 0) { char *md5sum = alpm_get_md5sum(path); if(md5sum == NULL) { - fprintf(stderr, _("error: could not calculate checksums for %s\n"), - path); + pm_fprintf(stderr, PM_LOG_ERROR, + _("could not calculate checksums for %s\n"), path); free(str); continue; } @@ -225,17 +221,14 @@ void dump_pkg_files(pmpkg_t *pkg) { const char *pkgname, *root, *filestr; alpm_list_t *i, *pkgfiles; - char path[PATH_MAX]; pkgname = alpm_pkg_get_name(pkg); pkgfiles = alpm_pkg_get_files(pkg); root = alpm_option_get_root(); for(i = pkgfiles; i; i = alpm_list_next(i)) { - filestr = (char*)alpm_list_getdata(i); - /* build a path so we can stat the filename */ - snprintf(path, PATH_MAX-1, "%s%s", root, filestr); - fprintf(stdout, "%s %s\n", pkgname, path); + filestr = alpm_list_getdata(i); + fprintf(stdout, "%s %s%s\n", pkgname, root, filestr); } fflush(stdout); @@ -248,8 +241,7 @@ void dump_pkg_changelog(pmpkg_t *pkg) void *fp = NULL; if((fp = alpm_pkg_changelog_open(pkg)) == NULL) { - /* TODO after string freeze use pm_fprintf */ - fprintf(stderr, _("error: no changelog available for '%s'.\n"), + pm_fprintf(stderr, PM_LOG_ERROR, _("no changelog available for '%s'.\n"), alpm_pkg_get_name(pkg)); return; } else { diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index c2b61fcd..813a7284 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -19,6 +19,12 @@ #include "config.h" +/* special handling of package version for GIT */ +#if defined(GIT_VERSION) +#undef PACKAGE_VERSION +#define PACKAGE_VERSION GIT_VERSION +#endif + #include <stdlib.h> /* atoi */ #include <stdio.h> #include <limits.h> @@ -68,31 +74,27 @@ static void usage(int op, const char * const myname) printf("%s:\n", str_opt); printf(" %s {-h --help}\n", myname); printf(" %s {-V --version}\n", myname); - printf(" %s {-A --add} [%s] <%s>\n", myname, str_opt, str_file); printf(" %s {-Q --query} [%s] [%s]\n", myname, str_opt, str_pkg); printf(" %s {-R --remove} [%s] <%s>\n", myname, str_opt, str_pkg); printf(" %s {-S --sync} [%s] [%s]\n", myname, str_opt, str_pkg); printf(" %s {-U --upgrade} [%s] <%s>\n", myname, str_opt, str_file); printf(_("\nuse '%s --help' with other options for more syntax\n"), myname); } else { - if(op == PM_OP_ADD) { - printf("%s: %s {-A --add} [%s] <%s>\n", str_usg, myname, str_opt, str_file); - printf("%s:\n", str_opt); - printf(_(" --asdeps install packages as non-explicitly installed\n")); - printf(_(" -d, --nodeps skip dependency checks\n")); - printf(_(" -f, --force force install, overwrite conflicting files\n")); - } else if(op == PM_OP_REMOVE) { + if(op == PM_OP_REMOVE) { printf("%s: %s {-R --remove} [%s] <%s>\n", str_usg, myname, str_opt, str_pkg); printf("%s:\n", str_opt); printf(_(" -c, --cascade remove packages and all packages that depend on them\n")); printf(_(" -d, --nodeps skip dependency checks\n")); printf(_(" -k, --dbonly only remove database entry, do not remove files\n")); printf(_(" -n, --nosave remove configuration files as well\n")); - printf(_(" -s, --recursive remove dependencies also (that won't break packages)\n")); + printf(_(" -s, --recursive remove dependencies also (that won't break packages)\n" + " (-ss includes explicitly installed dependencies too)\n")); + printf(_(" -u, --unneeded remove unneeded packages (that won't break packages)\n")); } else if(op == PM_OP_UPGRADE) { printf("%s: %s {-U --upgrade} [%s] <%s>\n", str_usg, myname, str_opt, str_file); printf("%s:\n", str_opt); printf(_(" --asdeps install packages as non-explicitly installed\n")); + printf(_(" --asexplicit install packages as explicitly installed\n")); printf(_(" -d, --nodeps skip dependency checks\n")); printf(_(" -f, --force force install, overwrite conflicting files\n")); } else if(op == PM_OP_QUERY) { @@ -115,9 +117,9 @@ static void usage(int op, const char * const myname) printf("%s: %s {-S --sync} [%s] [%s]\n", str_usg, myname, str_opt, str_pkg); printf("%s:\n", str_opt); printf(_(" --asdeps install packages as non-explicitly installed\n")); + printf(_(" --asexplicit install packages as explicitly installed\n")); printf(_(" -c, --clean remove old packages from cache directory (-cc for all)\n")); printf(_(" -d, --nodeps skip dependency checks\n")); - printf(_(" -e, --dependsonly install dependencies only\n")); printf(_(" -f, --force force install, overwrite conflicting files\n")); printf(_(" -g, --groups view all members of a package group\n")); printf(_(" -i, --info view package information\n")); @@ -151,11 +153,11 @@ static void version(void) { printf("\n"); printf(" .--. Pacman v%s - libalpm v%s\n", PACKAGE_VERSION, alpm_version()); - printf("/ _.-' .-. .-. .-. Copyright (C) 2002-2008 Judd Vinet <jvinet@zeroflux.org>\n"); - printf("\\ '-. '-' '-' '-'\n"); + printf("/ _.-' .-. .-. .-. Copyright (C) 2006-2008 Dan McGee <dan@archlinux.org>\n"); + printf("\\ '-. '-' '-' '-' Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>\n"); printf(" '--'\n"); printf(_(" This program may be freely redistributed under\n" - " the terms of the GNU General Public License\n")); + " the terms of the GNU General Public License.\n")); printf("\n"); } @@ -212,14 +214,15 @@ static void cleanup(int ret) { * in a consistant state. * @param signum the thrown signal */ -static void handler(int signum) +static RETSIGTYPE handler(int signum) { if(signum==SIGSEGV) { /* write a log message and write to stderr */ - pm_printf(PM_LOG_ERROR, "segmentation fault\n"); - pm_fprintf(stderr, PM_LOG_ERROR, "Internal pacman error: Segmentation fault.\n" - "Please submit a full bug report with --debug if appropriate.\n"); + pm_printf(PM_LOG_ERROR, _("segmentation fault\n")); + pm_fprintf(stderr, PM_LOG_ERROR, + _("Internal pacman error: Segmentation fault.\n" + "Please submit a full bug report with --debug if appropriate.\n")); exit(signum); } else if((signum == SIGINT)) { if(alpm_trans_interrupt() == 0) { @@ -305,7 +308,6 @@ static int parseargs(int argc, char *argv[]) int option_index = 0; static struct option opts[] = { - {"add", no_argument, 0, 'A'}, {"query", no_argument, 0, 'Q'}, {"remove", no_argument, 0, 'R'}, {"sync", no_argument, 0, 'S'}, @@ -318,7 +320,6 @@ static int parseargs(int argc, char *argv[]) {"clean", no_argument, 0, 'c'}, {"nodeps", no_argument, 0, 'd'}, {"deps", no_argument, 0, 'd'}, - {"dependsonly",no_argument, 0, 'e'}, {"explicit", no_argument, 0, 'e'}, {"force", no_argument, 0, 'f'}, {"groups", no_argument, 0, 'g'}, @@ -338,6 +339,7 @@ static int parseargs(int argc, char *argv[]) {"unrequired", no_argument, 0, 't'}, {"upgrades", no_argument, 0, 'u'}, {"sysupgrade", no_argument, 0, 'u'}, + {"unneeded", no_argument, 0, 'u'}, {"verbose", no_argument, 0, 'v'}, {"downloadonly", no_argument, 0, 'w'}, {"refresh", no_argument, 0, 'y'}, @@ -352,10 +354,11 @@ static int parseargs(int argc, char *argv[]) {"logfile", required_argument, 0, 1009}, {"ignoregroup", required_argument, 0, 1010}, {"needed", no_argument, 0, 1011}, + {"asexplicit", no_argument, 0, 1012}, {0, 0, 0, 0} }; - while((opt = getopt_long(argc, argv, "ARUFQSTr:b:vkhscVfmnoldepqituwygz", opts, &option_index))) { + while((opt = getopt_long(argc, argv, "RUFQSTr:b:vkhscVfmnoldepqituwygz", opts, &option_index))) { alpm_list_t *list = NULL, *item = NULL; /* lists for splitting strings */ if(opt < 0) { @@ -423,7 +426,9 @@ static int parseargs(int argc, char *argv[]) FREELIST(list); break; case 1011: config->flags |= PM_TRANS_FLAG_NEEDED; break; - case 'A': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_ADD); break; + case 1012: + config->flags |= PM_TRANS_FLAG_ALLEXPLICIT; + break; case 'Q': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_QUERY); break; case 'R': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_REMOVE); break; case 'S': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_SYNC); break; @@ -444,7 +449,6 @@ static int parseargs(int argc, char *argv[]) break; case 'e': config->op_q_explicit = 1; - config->flags |= PM_TRANS_FLAG_DEPENDSONLY; break; case 'f': config->flags |= PM_TRANS_FLAG_FORCE; break; case 'g': (config->group)++; break; @@ -468,7 +472,11 @@ static int parseargs(int argc, char *argv[]) case 's': config->op_s_search = 1; config->op_q_search = 1; - config->flags |= PM_TRANS_FLAG_RECURSE; + if(config->flags & PM_TRANS_FLAG_RECURSE) { + config->flags |= PM_TRANS_FLAG_RECURSEALL; + } else { + config->flags |= PM_TRANS_FLAG_RECURSE; + } break; case 't': config->op_q_unrequired = 1; @@ -476,6 +484,7 @@ static int parseargs(int argc, char *argv[]) case 'u': config->op_s_upgrade = 1; config->op_q_upgrade = 1; + config->flags |= PM_TRANS_FLAG_UNNEEDED; break; case 'v': (config->verbose)++; break; case 'w': @@ -512,6 +521,11 @@ static int parseargs(int argc, char *argv[]) return(0); } +/* helper for being used with setrepeatingoption */ +static void option_add_syncfirst(const char *name) { + config->syncfirst = alpm_list_add(config->syncfirst, strdup(name)); +} + /** 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. @@ -599,7 +613,7 @@ static int _parseconfig(const char *file, const char *givensection, } } else { /* directive */ - char *key, *upperkey; + char *key; /* strsep modifies the 'line' string: 'key \0 ptr' */ key = line; ptr = line; @@ -612,11 +626,7 @@ static int _parseconfig(const char *file, const char *givensection, file, linenum); return(1); } - /* For each directive, compare to the uppercase and camelcase string. - * This prevents issues with certain locales where characters don't - * follow the toupper() rules we may expect, e.g. tr_TR where i != I. - */ - upperkey = strtoupper(strdup(key)); + /* For each directive, compare to the camelcase string. */ if(section == NULL) { pm_printf(PM_LOG_ERROR, _("config file %s, line %d: All directives must belong to a section.\n"), file, linenum); @@ -624,25 +634,25 @@ static int _parseconfig(const char *file, const char *givensection, } if(ptr == NULL && strcmp(section, "options") == 0) { /* directives without settings, all in [options] */ - if(strcmp(key, "NoPassiveFTP") == 0 || strcmp(upperkey, "NOPASSIVEFTP") == 0) { + if(strcmp(key, "NoPassiveFTP") == 0) { alpm_option_set_nopassiveftp(1); pm_printf(PM_LOG_DEBUG, "config: nopassiveftp\n"); - } else if(strcmp(key, "UseSyslog") == 0 || strcmp(upperkey, "USESYSLOG") == 0) { + } else if(strcmp(key, "UseSyslog") == 0) { alpm_option_set_usesyslog(1); pm_printf(PM_LOG_DEBUG, "config: usesyslog\n"); - } else if(strcmp(key, "ILoveCandy") == 0 || strcmp(upperkey, "ILOVECANDY") == 0) { + } else if(strcmp(key, "ILoveCandy") == 0) { config->chomp = 1; pm_printf(PM_LOG_DEBUG, "config: chomp\n"); - } else if(strcmp(key, "UseColor") == 0 || strcmp(upperkey, "USECOLOR") == 0) { + } else if(strcmp(key, "UseColor") == 0) { config->usecolor = 1; pm_printf(PM_LOG_DEBUG, "config: usecolor\n"); - } else if(strcmp(key, "ShowSize") == 0 || strcmp(upperkey, "SHOWSIZE") == 0) { + } else if(strcmp(key, "ShowSize") == 0) { config->showsize = 1; pm_printf(PM_LOG_DEBUG, "config: showsize\n"); - } else if(strcmp(key, "UseDelta") == 0 || strcmp(upperkey, "USEDELTA") == 0) { + } else if(strcmp(key, "UseDelta") == 0) { alpm_option_set_usedelta(1); pm_printf(PM_LOG_DEBUG, "config: usedelta\n"); - } else if(strcmp(key, "TotalDownload") == 0 || strcmp(upperkey, "TOTALDOWNLOAD") == 0) { + } else if(strcmp(key, "TotalDownload") == 0) { config->totaldownload = 1; pm_printf(PM_LOG_DEBUG, "config: totaldownload\n"); } else { @@ -652,59 +662,66 @@ static int _parseconfig(const char *file, const char *givensection, } } else { /* directives with settings */ - if(strcmp(key, "Include") == 0 || strcmp(upperkey, "INCLUDE") == 0) { + if(strcmp(key, "Include") == 0) { pm_printf(PM_LOG_DEBUG, "config: including %s\n", ptr); _parseconfig(ptr, section, db); /* Ignore include failures... assume non-critical */ } else if(strcmp(section, "options") == 0) { - if(strcmp(key, "NoUpgrade") == 0 - || strcmp(upperkey, "NOUPGRADE") == 0) { + if(strcmp(key, "NoUpgrade") == 0) { setrepeatingoption(ptr, "NoUpgrade", alpm_option_add_noupgrade); - } else if(strcmp(key, "NoExtract") == 0 - || strcmp(upperkey, "NOEXTRACT") == 0) { + } else if(strcmp(key, "NoExtract") == 0) { setrepeatingoption(ptr, "NoExtract", alpm_option_add_noextract); - } else if(strcmp(key, "IgnorePkg") == 0 - || strcmp(upperkey, "IGNOREPKG") == 0) { + } else if(strcmp(key, "IgnorePkg") == 0) { setrepeatingoption(ptr, "IgnorePkg", alpm_option_add_ignorepkg); - } else if(strcmp(key, "IgnoreGroup") == 0 - || strcmp(upperkey, "IGNOREGROUP") == 0) { + } else if(strcmp(key, "IgnoreGroup") == 0) { setrepeatingoption(ptr, "IgnoreGroup", alpm_option_add_ignoregrp); - } else if(strcmp(key, "HoldPkg") == 0 - || strcmp(upperkey, "HOLDPKG") == 0) { + } else if(strcmp(key, "HoldPkg") == 0) { setrepeatingoption(ptr, "HoldPkg", alpm_option_add_holdpkg); - } else if(strcmp(key, "DBPath") == 0 || strcmp(upperkey, "DBPATH") == 0) { + } else if(strcmp(key, "SyncFirst") == 0) { + setrepeatingoption(ptr, "SyncFirst", option_add_syncfirst); + } else if(strcmp(key, "DBPath") == 0) { /* don't overwrite a path specified on the command line */ if(!config->dbpath) { config->dbpath = strdup(ptr); pm_printf(PM_LOG_DEBUG, "config: dbpath: %s\n", ptr); } - } else if(strcmp(key, "CacheDir") == 0 || strcmp(upperkey, "CACHEDIR") == 0) { + } else if(strcmp(key, "CacheDir") == 0) { if(alpm_option_add_cachedir(ptr) != 0) { pm_printf(PM_LOG_ERROR, _("problem adding cachedir '%s' (%s)\n"), ptr, alpm_strerrorlast()); return(1); } pm_printf(PM_LOG_DEBUG, "config: cachedir: %s\n", ptr); - } else if(strcmp(key, "RootDir") == 0 || strcmp(upperkey, "ROOTDIR") == 0) { + } else if(strcmp(key, "RootDir") == 0) { /* don't overwrite a path specified on the command line */ if(!config->rootdir) { config->rootdir = strdup(ptr); pm_printf(PM_LOG_DEBUG, "config: rootdir: %s\n", ptr); } - } else if (strcmp(key, "LogFile") == 0 || strcmp(upperkey, "LOGFILE") == 0) { + } else if (strcmp(key, "LogFile") == 0) { if(!config->logfile) { config->logfile = strdup(ptr); pm_printf(PM_LOG_DEBUG, "config: logfile: %s\n", ptr); } - } else if (strcmp(key, "XferCommand") == 0 || strcmp(upperkey, "XFERCOMMAND") == 0) { + } 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); return(1); } - } else if(strcmp(key, "Server") == 0 || strcmp(upperkey, "SERVER") == 0) { + } else if(strcmp(key, "Server") == 0) { /* let's attempt a replacement for the current repo */ char *server = strreplace(ptr, "$repo", section); @@ -720,7 +737,6 @@ static int _parseconfig(const char *file, const char *givensection, return(1); } } - free(upperkey); } } fclose(fp); @@ -753,7 +769,7 @@ int main(int argc, char *argv[]) { int ret = 0; struct sigaction new_action, old_action; -#if defined(HAVE_GETEUID) +#if defined(HAVE_GETEUID) && !defined(CYGWIN) /* geteuid undefined in CYGWIN */ uid_t myuid = geteuid(); #endif @@ -834,7 +850,12 @@ int main(int argc, char *argv[]) cleanup(ret); } -#if defined(HAVE_GETEUID) + /* set TotalDownload callback if option enabled */ + if(config->totaldownload) { + alpm_option_set_totaldlcb(cb_dl_total); + } + +#if defined(HAVE_GETEUID) && !defined(CYGWIN) /* check if we have sufficient permission for the requested operation */ if(myuid > 0 && needs_transaction()) { pm_printf(PM_LOG_ERROR, _("you cannot perform this operation unless you are root.\n")); @@ -867,9 +888,6 @@ int main(int argc, char *argv[]) /* start the requested operation */ switch(config->op) { - case PM_OP_ADD: - ret = pacman_add(pm_targets); - break; case PM_OP_REMOVE: ret = pacman_remove(pm_targets); break; diff --git a/src/pacman/pacman.h b/src/pacman/pacman.h index 9d23a89c..97d0301e 100644 --- a/src/pacman/pacman.h +++ b/src/pacman/pacman.h @@ -21,15 +21,14 @@ #include <alpm_list.h> -/* add.c, this should merge with upgrade.c */ -int pacman_add(alpm_list_t *targets); -int pacman_upgrade(alpm_list_t *targets); -/* sync.c */ -int pacman_sync(alpm_list_t *targets); /* query.c */ int pacman_query(alpm_list_t *targets); /* remove.c */ int pacman_remove(alpm_list_t *targets); +/* sync.c */ +int pacman_sync(alpm_list_t *targets); +/* upgrade.c */ +int pacman_upgrade(alpm_list_t *targets); /* deptest.c */ int pacman_deptest(alpm_list_t *targets); diff --git a/src/pacman/query.c b/src/pacman/query.c index e999a328..74d3ff21 100644 --- a/src/pacman/query.c +++ b/src/pacman/query.c @@ -1,7 +1,7 @@ /* * query.c * - * Copyright (c) 2002-2007 by Judd Vinet <jvinet@zeroflux.org> + * Copyright (c) 2002-2008 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -62,28 +62,28 @@ static int query_fileowner(alpm_list_t *targets) /* This code is here for safety only */ if(targets == NULL) { - fprintf(stderr, _("error: no file was specified for --owns\n")); + pm_fprintf(stderr, PM_LOG_ERROR, _("no file was specified for --owns\n")); return(1); } for(t = targets; t; t = alpm_list_next(t)) { int found = 0; char *filename = alpm_list_getdata(t); - char *bname; - char *dname; - char *rpath; + char *bname, *dname, *rpath; + const char *root; struct stat buf; alpm_list_t *i, *j; if(stat(filename, &buf) == -1) { - fprintf(stderr, _("error: failed to read file '%s': %s\n"), + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to read file '%s': %s\n"), filename, strerror(errno)); ret++; continue; } if(S_ISDIR(buf.st_mode)) { - fprintf(stderr, _("error: cannot determine ownership of a directory\n")); + pm_fprintf(stderr, PM_LOG_ERROR, + _("cannot determine ownership of a directory\n")); ret++; continue; } @@ -94,20 +94,22 @@ static int query_fileowner(alpm_list_t *targets) free(dname); if(!rpath) { - fprintf(stderr, _("error: cannot determine real path for '%s': %s\n"), + pm_fprintf(stderr, PM_LOG_ERROR, _("cannot determine real path for '%s': %s\n"), filename, strerror(errno)); free(rpath); ret++; continue; } + root = alpm_option_get_root(); + for(i = alpm_db_getpkgcache(db_local); i && !found; i = alpm_list_next(i)) { pmpkg_t *info = alpm_list_getdata(i); for(j = alpm_pkg_get_files(info); j && !found; j = alpm_list_next(j)) { char path[PATH_MAX], *ppath, *pdname; snprintf(path, PATH_MAX, "%s%s", - alpm_option_get_root(), (const char *)alpm_list_getdata(j)); + root, (const char *)alpm_list_getdata(j)); /* avoid the costly resolve_path usage if the basenames don't match */ if(strcmp(mbasename(path), bname) != 0) { @@ -119,15 +121,20 @@ static int query_fileowner(alpm_list_t *targets) free(pdname); if(ppath && strcmp(ppath, rpath) == 0) { - printf(_("%s is owned by %s %s\n"), filename, - alpm_pkg_get_name(info), alpm_pkg_get_version(info)); + if (!config->quiet) { + printf(_("%s is owned by %s %s\n"), filename, + alpm_pkg_get_name(info), alpm_pkg_get_version(info)); + } else { + printf("%s %s\n", alpm_pkg_get_name(info), + alpm_pkg_get_version(info)); + } found = 1; } free(ppath); } } if(!found) { - fprintf(stderr, _("error: No package owns %s\n"), filename); + pm_fprintf(stderr, PM_LOG_ERROR, _("No package owns %s\n"), filename); ret++; } free(rpath); @@ -155,7 +162,6 @@ static int query_search(alpm_list_t *targets) } for(i = searchlist; i; i = alpm_list_next(i)) { - char *group = NULL; alpm_list_t *grp; pmpkg_t *pkg = alpm_list_getdata(i); @@ -176,8 +182,17 @@ static int query_search(alpm_list_t *targets) if (!config->quiet) { if((grp = alpm_pkg_get_groups(pkg)) != NULL) { - group = alpm_list_getdata(grp); - printf(" (%s)", (char *)alpm_list_getdata(grp)); + alpm_list_t *k; + printf(" ("); + for(k = grp; k; k = alpm_list_next(k)) { + const char *group = alpm_list_getdata(k); + printf("%s", group); + if(alpm_list_next(k)) { + /* only print a spacer if there are more groups */ + printf(" "); + } + } + printf(")"); } /* we need a newline and initial indent first */ @@ -197,33 +212,33 @@ static int query_search(alpm_list_t *targets) static int query_group(alpm_list_t *targets) { alpm_list_t *i, *j; - char *package = NULL; + char *grpname = NULL; int ret = 0; if(targets == NULL) { for(j = alpm_db_getgrpcache(db_local); j; j = alpm_list_next(j)) { pmgrp_t *grp = alpm_list_getdata(j); - const alpm_list_t *p, *pkgnames; + const alpm_list_t *p, *packages; const char *grpname; grpname = alpm_grp_get_name(grp); - pkgnames = alpm_grp_get_pkgs(grp); + packages = alpm_grp_get_pkgs(grp); - for(p = pkgnames; p; p = alpm_list_next(p)) { - printf("%s %s\n", grpname, (char *)alpm_list_getdata(p)); + for(p = packages; p; p = alpm_list_next(p)) { + printf("%s %s\n", grpname, alpm_pkg_get_name(alpm_list_getdata(p))); } } } else { for(i = targets; i; i = alpm_list_next(i)) { pmgrp_t *grp; - package = alpm_list_getdata(i); - grp = alpm_db_readgrp(db_local, package); + grpname = alpm_list_getdata(i); + grp = alpm_db_readgrp(db_local, grpname); if(grp) { - const alpm_list_t *p, *pkgnames = alpm_grp_get_pkgs(grp); - for(p = pkgnames; p; p = alpm_list_next(p)) { - printf("%s %s\n", package, (char *)alpm_list_getdata(p)); + const alpm_list_t *p, *packages = alpm_grp_get_pkgs(grp); + for(p = packages; p; p = alpm_list_next(p)) { + printf("%s %s\n", grpname, alpm_pkg_get_name(alpm_list_getdata(p))); } } else { - fprintf(stderr, _("error: group \"%s\" was not found\n"), package); + pm_fprintf(stderr, PM_LOG_ERROR, _("group \"%s\" was not found\n"), grpname); ret++; } } @@ -401,7 +416,7 @@ int pacman_query(alpm_list_t *targets) } if(pkg == NULL) { - fprintf(stderr, _("error: package \"%s\" not found\n"), strname); + pm_fprintf(stderr, PM_LOG_ERROR, _("package \"%s\" not found\n"), strname); ret++; continue; } diff --git a/src/pacman/remove.c b/src/pacman/remove.c index e3750e4c..4fe9bc81 100644 --- a/src/pacman/remove.c +++ b/src/pacman/remove.c @@ -29,24 +29,10 @@ /* pacman */ #include "pacman.h" #include "util.h" -#include "callback.h" #include "conf.h" extern pmdb_t *db_local; -/* Free the current transaction and print an error if unsuccessful */ -static int remove_cleanup(void) -{ - int ret = alpm_trans_release(); - if(ret != 0) { - pm_printf(PM_LOG_ERROR, _("failed to release transaction (%s)\n"), - alpm_strerrorlast()); - ret = 1; - } - - return(ret); -} - /** * @brief Remove a specified list of packages. * @@ -75,11 +61,11 @@ int pacman_remove(alpm_list_t *targets) printf(_(":: group %s:\n"), alpm_grp_get_name(grp)); list_display(" ", pkgnames); - all = yesno(_(" Remove whole content? [Y/n] ")); + all = yesno(1, _(" Remove whole content?")); for(p = pkgnames; p; p = alpm_list_next(p)) { char *pkg = alpm_list_getdata(p); - if(all || yesno(_(":: Remove %s from group %s? [Y/n] "), pkg, (char *)alpm_list_getdata(i))) { + if(all || yesno(1, _(":: Remove %s from group %s?"), pkg, (char *)alpm_list_getdata(i))) { finaltargs = alpm_list_add(finaltargs, strdup(pkg)); } } @@ -90,14 +76,7 @@ int pacman_remove(alpm_list_t *targets) } /* Step 1: create a new transaction */ - if(alpm_trans_init(PM_TRANS_TYPE_REMOVE, config->flags, - cb_trans_evt, cb_trans_conv, cb_trans_progress) == -1) { - fprintf(stderr, _("error: failed to init transaction (%s)\n"), - alpm_strerrorlast()); - if(pm_errno == PM_ERR_HANDLE_LOCK) { - printf(_(" if you're sure a package manager is not already\n" - " running, you can remove %s.\n"), alpm_option_get_lockfile()); - } + if(trans_init(PM_TRANS_TYPE_REMOVE, config->flags) == -1) { FREELIST(finaltargs); return(1); } @@ -107,9 +86,9 @@ int pacman_remove(alpm_list_t *targets) for(i = finaltargs; i; i = alpm_list_next(i)) { char *targ = alpm_list_getdata(i); if(alpm_trans_addtarget(targ) == -1) { - fprintf(stderr, _("error: '%s': %s\n"), + pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerrorlast()); - remove_cleanup(); + trans_release(); FREELIST(finaltargs); return(1); } @@ -117,7 +96,7 @@ int pacman_remove(alpm_list_t *targets) /* Step 2: prepare the transaction based on its type, targets and flags */ if(alpm_trans_prepare(&data) == -1) { - fprintf(stderr, _("error: failed to prepare transaction (%s)\n"), + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), alpm_strerrorlast()); switch(pm_errno) { case PM_ERR_UNSATISFIED_DEPS: @@ -134,7 +113,7 @@ int pacman_remove(alpm_list_t *targets) default: break; } - remove_cleanup(); + trans_release(); FREELIST(finaltargs); return(1); } @@ -153,8 +132,8 @@ int pacman_remove(alpm_list_t *targets) list_display(_("Targets:"), lst); FREELIST(lst); /* get confirmation */ - if(yesno(_("\nDo you want to remove these packages? [Y/n] ")) == 0) { - remove_cleanup(); + if(yesno(1, _("\nDo you want to remove these packages?")) == 0) { + trans_release(); FREELIST(finaltargs); return(1); } @@ -163,15 +142,17 @@ int pacman_remove(alpm_list_t *targets) /* Step 3: actually perform the removal */ if(alpm_trans_commit(NULL) == -1) { - fprintf(stderr, _("error: failed to commit transaction (%s)\n"), + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"), alpm_strerrorlast()); - remove_cleanup(); + trans_release(); FREELIST(finaltargs); return(1); } /* Step 4: release transaction resources */ - retval = remove_cleanup(); + if(trans_release() == -1) { + retval = 1; + } FREELIST(finaltargs); return(retval); } diff --git a/src/pacman/sync.c b/src/pacman/sync.c index e3e87703..47ab4ebb 100644 --- a/src/pacman/sync.c +++ b/src/pacman/sync.c @@ -29,15 +29,11 @@ #include <alpm.h> #include <alpm_list.h> -#include <download.h> /* downloadLastErrString */ -/* TODO remove above download.h inclusion once we abstract more, and also - * remove it from Makefile.am on the pacman side */ /* pacman */ #include "pacman.h" #include "util.h" #include "package.h" -#include "callback.h" #include "conf.h" extern pmdb_t *db_local; @@ -50,7 +46,7 @@ static int sync_cleandb(const char *dbpath, int keep_used) { dir = opendir(dbpath); if(dir == NULL) { - fprintf(stderr, _("error: could not access database directory\n")); + pm_fprintf(stderr, PM_LOG_ERROR, _("could not access database directory\n")); return(1); } @@ -61,7 +57,7 @@ static int sync_cleandb(const char *dbpath, int keep_used) { struct stat buf; alpm_list_t *syncdbs = NULL, *i; int found = 0; - char *dname = ent->d_name; + const char *dname = ent->d_name; if(!strcmp(dname, ".") || !strcmp(dname, "..")) { continue; @@ -72,7 +68,7 @@ static int sync_cleandb(const char *dbpath, int keep_used) { } /* build the full path */ - snprintf(path, PATH_MAX, "%s%s", dbpath, ent->d_name); + snprintf(path, PATH_MAX, "%s%s", dbpath, dname); /* skip entries that are not dirs (lock file, etc.) */ stat(path, &buf); if(!S_ISDIR(buf.st_mode)) { @@ -89,12 +85,13 @@ static int sync_cleandb(const char *dbpath, int keep_used) { /* We have a directory 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? [Y/n] "), path)) { + if(!yesno(1, _("Do you want to remove %s?"), path)) { continue; } if(rmrf(path)) { - fprintf(stderr, _("error: could not remove repository directory\n")); + pm_fprintf(stderr, PM_LOG_ERROR, + _("could not remove repository directory\n")); return(1); } } @@ -108,7 +105,7 @@ static int sync_cleandb_all(void) { char newdbpath[PATH_MAX]; printf(_("Database directory: %s\n"), dbpath); - if(!yesno(_("Do you want to remove unused repositories? [Y/n] "))) { + if(!yesno(1, _("Do you want to remove unused repositories?"))) { return(0); } /* The sync dbs were previously put in dbpath/, but are now in dbpath/sync/, @@ -133,19 +130,29 @@ 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(_("Do you want to remove uninstalled packages from cache? [Y/n] "))) { - 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... ")); dir = opendir(cachedir); if(dir == NULL) { - fprintf(stderr, _("error: could not access cache directory\n")); + pm_fprintf(stderr, PM_LOG_ERROR, _("could not access cache directory\n")); return(1); } @@ -153,13 +160,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,36 +177,56 @@ 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 { /* full cleanup */ printf(_("Cache directory: %s\n"), cachedir); - if(!yesno(_("Do you want to remove ALL packages from cache? [Y/n] "))) { + if(!yesno(0, _("Do you want to remove ALL packages from cache?"))) { return(0); } printf(_("removing all packages from cache... ")); if(rmrf(cachedir)) { - fprintf(stderr, _("error: could not remove cache directory\n")); + pm_fprintf(stderr, PM_LOG_ERROR, _("could not remove cache directory\n")); return(1); } if(makepath(cachedir)) { - fprintf(stderr, _("error: could not create new cache directory\n")); + pm_fprintf(stderr, PM_LOG_ERROR, _("could not create new cache directory\n")); return(1); } printf(_("done.\n")); @@ -205,52 +235,22 @@ static int sync_cleancache(int level) return(0); } -static int sync_trans_init(pmtransflag_t flags) { - if(alpm_trans_init(PM_TRANS_TYPE_SYNC, flags, cb_trans_evt, - cb_trans_conv, cb_trans_progress) == -1) { - fprintf(stderr, _("error: failed to init transaction (%s)\n"), - alpm_strerrorlast()); - if(pm_errno == PM_ERR_HANDLE_LOCK) { - printf(_(" if you're sure a package manager is not already\n" - " running, you can remove %s.\n"), alpm_option_get_lockfile()); - } - return(-1); - } - return(0); -} - -static int sync_trans_release() { - if(alpm_trans_release() == -1) { - fprintf(stderr, _("error: failed to release transaction (%s)\n"), - alpm_strerrorlast()); - return(-1); - } - return(0); -} static int sync_synctree(int level, alpm_list_t *syncs) { alpm_list_t *i; int success = 0, ret; + if(trans_init(PM_TRANS_TYPE_SYNC, 0) == -1) { + return(0); + } + for(i = syncs; i; i = alpm_list_next(i)) { pmdb_t *db = alpm_list_getdata(i); ret = alpm_db_update((level < 2 ? 0 : 1), db); if(ret < 0) { - if(pm_errno == PM_ERR_DB_SYNC) { - /* use libdownload error */ - /* TODO breaking abstraction barrier here? - * pacman -> libalpm -> libdownload - * - * Yes. This will be here until we add a nice pacman "pm_errstr" or - * something, OR add all libdownload error codes into the pm_error enum - */ - fprintf(stderr, _("error: failed to synchronize %s: %s\n"), - alpm_db_get_name(db), downloadLastErrString); - } else { - fprintf(stderr, _("error: failed to update %s (%s)\n"), - alpm_db_get_name(db), alpm_strerrorlast()); - } + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to update %s (%s)\n"), + alpm_db_get_name(db), alpm_strerrorlast()); } else if(ret == 1) { printf(_(" %s is up to date\n"), alpm_db_get_name(db)); success++; @@ -259,10 +259,16 @@ static int sync_synctree(int level, alpm_list_t *syncs) } } + if(trans_release() == -1) { + return(0); + } /* We should always succeed if at least one DB was upgraded - we may possibly * fail later with unresolved deps, but that should be rare, and would be * expected */ + if(!success) { + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to synchronize any databases\n")); + } return(success > 0); } @@ -289,8 +295,6 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t *targets) found = 1; } for(j = ret; j; j = alpm_list_next(j)) { - /* print repo/name (group) info about each package in our list */ - char *group = NULL; alpm_list_t *grp; pmpkg_t *pkg = alpm_list_getdata(j); @@ -311,8 +315,17 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t *targets) if (!config->quiet) { if((grp = alpm_pkg_get_groups(pkg)) != NULL) { - group = alpm_list_getdata(grp); - printf(" (%s)", (char *)alpm_list_getdata(grp)); + alpm_list_t *k; + printf(" ("); + for(k = grp; k; k = alpm_list_next(k)) { + const char *group = alpm_list_getdata(k); + printf("%s", group); + if(alpm_list_next(k)) { + /* only print a spacer if there are more groups */ + printf(" "); + } + } + printf(")"); } /* we need a newline and initial indent first */ @@ -332,19 +345,21 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t *targets) static int sync_group(int level, alpm_list_t *syncs, alpm_list_t *targets) { - alpm_list_t *i, *j; + alpm_list_t *i, *j, *k; if(targets) { for(i = targets; i; i = alpm_list_next(i)) { - char *grpname = alpm_list_getdata(i); + const char *grpname = alpm_list_getdata(i); for(j = syncs; j; j = alpm_list_next(j)) { pmdb_t *db = alpm_list_getdata(j); pmgrp_t *grp = alpm_db_readgrp(db, grpname); if(grp) { - /* TODO this should be a lot cleaner, why two outputs? */ - printf("%s\n", (char *)alpm_grp_get_name(grp)); - list_display(" ", alpm_grp_get_pkgs(grp)); + /* get names of packages in group */ + for(k = alpm_grp_get_pkgs(grp); k; k = alpm_list_next(k)) { + printf("%s %s\n", grpname, + alpm_pkg_get_name(alpm_list_getdata(k))); + } } } } @@ -354,10 +369,16 @@ static int sync_group(int level, alpm_list_t *syncs, alpm_list_t *targets) for(j = alpm_db_getgrpcache(db); j; j = alpm_list_next(j)) { pmgrp_t *grp = alpm_list_getdata(j); + const char *grpname = alpm_grp_get_name(grp); - printf("%s\n", (char *)alpm_grp_get_name(grp)); - if(grp && level > 1) { - list_display(" ", alpm_grp_get_pkgs(grp)); + if(level > 1) { + for(k = alpm_grp_get_pkgs(grp); k; k = alpm_list_next(k)) { + printf("%s %s\n", grpname, + alpm_pkg_get_name(alpm_list_getdata(k))); + } + } else { + /* print grp names only, no package names */ + printf("%s\n", grpname); } } } @@ -395,7 +416,8 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) } if(!db) { - fprintf(stderr, _("error: repository '%s' does not exist\n"), repo); + pm_fprintf(stderr, PM_LOG_ERROR, + _("repository '%s' does not exist\n"), repo); return(1); } @@ -410,7 +432,8 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) } if(!foundpkg) { - fprintf(stderr, _("error: package '%s' was not found in repository '%s'\n"), pkgstr, repo); + pm_fprintf(stderr, PM_LOG_ERROR, + _("package '%s' was not found in repository '%s'\n"), pkgstr, repo); ret++; } } else { @@ -430,7 +453,8 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) } } if(!foundpkg) { - fprintf(stderr, _("error: package '%s' was not found\n"), pkgstr); + pm_fprintf(stderr, PM_LOG_ERROR, + _("package '%s' was not found\n"), pkgstr); ret++; } } @@ -467,7 +491,8 @@ static int sync_list(alpm_list_t *syncs, alpm_list_t *targets) } if(db == NULL) { - fprintf(stderr, _("error: repository \"%s\" was not found.\n"),repo); + pm_fprintf(stderr, PM_LOG_ERROR, + _("repository \"%s\" was not found.\n"),repo); alpm_list_free(ls); return(1); } @@ -499,74 +524,43 @@ static int sync_list(alpm_list_t *syncs, alpm_list_t *targets) return(0); } -static int sync_trans(alpm_list_t *targets, int sync_only) +static alpm_list_t *syncfirst() { + alpm_list_t *i, *res = NULL; + + for(i = config->syncfirst; i; i = alpm_list_next(i)) { + char *pkgname = alpm_list_getdata(i); + pmpkg_t *pkg = alpm_db_get_pkg(alpm_option_get_localdb(), pkgname); + if(pkg == NULL) { + continue; + } + + if(alpm_sync_newversion(pkg, alpm_option_get_syncdbs())) { + res = alpm_list_add(res, strdup(pkgname)); + } + } + + return(res); +} + +static int sync_trans(alpm_list_t *targets) { int retval = 0; alpm_list_t *data = NULL; alpm_list_t *sync_dbs = alpm_option_get_syncdbs(); /* Step 1: create a new transaction... */ - if(sync_trans_init(config->flags) == -1) { + if(trans_init(PM_TRANS_TYPE_SYNC, config->flags) == -1) { return(1); } - if(config->op_s_sync) { - /* grab a fresh package list */ - printf(_(":: Synchronizing package databases...\n")); - alpm_logaction("synchronizing package lists\n"); - if(!sync_synctree(config->op_s_sync, sync_dbs)) { - fprintf(stderr, _("error: failed to synchronize any databases\n")); - retval = 1; - goto cleanup; - } - if(sync_only) { - goto cleanup; - } - } - if(config->op_s_upgrade) { - alpm_list_t *pkgs, *i; - printf(_(":: Starting full system upgrade...\n")); alpm_logaction("starting full system upgrade\n"); if(alpm_trans_sysupgrade() == -1) { - fprintf(stderr, _("error: %s\n"), alpm_strerrorlast()); + pm_fprintf(stderr, PM_LOG_ERROR, "%s\n", alpm_strerrorlast()); retval = 1; goto cleanup; } - - if(!(alpm_trans_get_flags() & (PM_TRANS_FLAG_DOWNLOADONLY | PM_TRANS_FLAG_PRINTURIS))) { - /* check if pacman itself is one of the packages to upgrade. - * this can prevent some of the "syntax error" problems users can have - * when sysupgrade'ing with an older version of pacman. - */ - pkgs = alpm_trans_get_pkgs(); - for(i = pkgs; i; i = alpm_list_next(i)) { - pmsyncpkg_t *sync = alpm_list_getdata(i); - pmpkg_t *spkg = alpm_sync_get_pkg(sync); - /* TODO pacman name should probably not be hardcoded. In addition, we - * have problems on an -Syu if pacman has to pull in deps, so recommend - * an '-S pacman' operation */ - if(strcmp("pacman", alpm_pkg_get_name(spkg)) == 0) { - printf("\n"); - printf(_(":: pacman has detected a newer version of itself.\n")); - if(yesno(_(":: Do you want to cancel the current operation\n" - ":: and install the new pacman version now? [Y/n] "))) { - if(sync_trans_release() == -1) { - return(1); - } - if(sync_trans_init(0) == -1) { - return(1); - } - if(alpm_trans_addtarget("pacman") == -1) { - fprintf(stderr, _("error: pacman: %s\n"), alpm_strerrorlast()); - return(1); - } - break; - } - } - } - } } else { alpm_list_t *i; @@ -583,7 +577,7 @@ static int sync_trans(alpm_list_t *targets, int sync_only) continue; } if(pm_errno != PM_ERR_PKG_NOT_FOUND) { - fprintf(stderr, _("error: '%s': %s\n"), + pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerrorlast()); retval = 1; goto cleanup; @@ -594,26 +588,31 @@ static int sync_trans(alpm_list_t *targets, int sync_only) pmdb_t *db = alpm_list_getdata(j); grp = alpm_db_readgrp(db, targ); if(grp) { - alpm_list_t *k; + alpm_list_t *k, *pkgnames = NULL; found++; printf(_(":: group %s (including ignored packages):\n"), targ); /* remove dupe entries in case a package exists in multiple repos */ - const alpm_list_t *grppkgs = alpm_grp_get_pkgs(grp); + alpm_list_t *grppkgs = alpm_grp_get_pkgs(grp); alpm_list_t *pkgs = alpm_list_remove_dupes(grppkgs); - list_display(" ", pkgs); - if(yesno(_(":: Install whole content? [Y/n] "))) { - for(k = pkgs; k; k = alpm_list_next(k)) { + for(k = pkgs; k; k = alpm_list_next(k)) { + pkgnames = alpm_list_add(pkgnames, + (char*)alpm_pkg_get_name(k->data)); + } + list_display(" ", pkgnames); + if(yesno(1, _(":: Install whole content?"))) { + for(k = pkgnames; k; k = alpm_list_next(k)) { targets = alpm_list_add(targets, strdup(alpm_list_getdata(k))); } } else { - for(k = pkgs; k; k = alpm_list_next(k)) { + for(k = pkgnames; k; k = alpm_list_next(k)) { char *pkgname = alpm_list_getdata(k); - if(yesno(_(":: Install %s from group %s? [Y/n] "), pkgname, targ)) { + if(yesno(1, _(":: Install %s from group %s?"), pkgname, targ)) { targets = alpm_list_add(targets, strdup(pkgname)); } } } + alpm_list_free(pkgnames); alpm_list_free(pkgs); } } @@ -622,7 +621,9 @@ static int sync_trans(alpm_list_t *targets, int sync_only) alpm_list_t *prov = NULL; for(j = sync_dbs; j; j = alpm_list_next(j)) { pmdb_t *db = alpm_list_getdata(j); - prov = alpm_list_join(prov, alpm_db_whatprovides(db, targ)); + alpm_list_t *dblist = alpm_db_getpkgcache(db); + alpm_list_t *satisfiers = alpm_find_pkg_satisfiers(dblist, targ); + prov = alpm_list_join(prov, satisfiers); } if(prov != NULL) { if(alpm_list_count(prov) == 1) { @@ -634,7 +635,8 @@ static int sync_trans(alpm_list_t *targets, int sync_only) targets = alpm_list_add(targets, strdup(pname)); } else { alpm_list_t *k; - fprintf(stderr, _("error: several packages provide %s, please specify one :\n"), targ); + pm_fprintf(stderr, PM_LOG_ERROR, + _("several packages provide %s, please specify one :\n"), targ); for(k = prov; k; k = alpm_list_next(k)) { pmpkg_t *pkg = alpm_list_getdata(k); printf("%s ", alpm_pkg_get_name(pkg)); @@ -645,7 +647,8 @@ static int sync_trans(alpm_list_t *targets, int sync_only) goto cleanup; } } else { - fprintf(stderr, _("error: '%s': not found in sync db\n"), targ); + pm_fprintf(stderr, PM_LOG_ERROR, + _("'%s': not found in sync db\n"), targ); retval = 1; goto cleanup; } @@ -656,7 +659,7 @@ static int sync_trans(alpm_list_t *targets, int sync_only) /* Step 2: "compute" the transaction based on targets and flags */ if(alpm_trans_prepare(&data) == -1) { - fprintf(stderr, _("error: failed to prepare transaction (%s)\n"), + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), alpm_strerrorlast()); switch(pm_errno) { alpm_list_t *i; @@ -698,19 +701,9 @@ static int sync_trans(alpm_list_t *targets, int sync_only) printf("\n"); if(config->op_s_downloadonly) { - if(config->noconfirm) { - printf(_("Beginning download...\n")); - confirm = 1; - } else { - confirm = yesno(_("Proceed with download? [Y/n] ")); - } + confirm = yesno(1, _("Proceed with download?")); } else { - if(config->noconfirm) { - printf(_("Beginning upgrade process...\n")); - confirm = 1; - } else { - confirm = yesno(_("Proceed with installation? [Y/n] ")); - } + confirm = yesno(1, _("Proceed with installation?")); } if(!confirm) { goto cleanup; @@ -719,7 +712,7 @@ static int sync_trans(alpm_list_t *targets, int sync_only) /* Step 3: actually perform the installation */ if(alpm_trans_commit(&data) == -1) { - fprintf(stderr, _("error: failed to commit transaction (%s)\n"), + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"), alpm_strerrorlast()); switch(pm_errno) { alpm_list_t *i; @@ -741,9 +734,11 @@ static int sync_trans(alpm_list_t *targets, int sync_only) } } break; - case PM_ERR_PKG_CORRUPTED: + case PM_ERR_PKG_INVALID: + case PM_ERR_DLT_INVALID: for(i = data; i; i = alpm_list_next(i)) { - printf("%s", (char*)alpm_list_getdata(i)); + char *filename = alpm_list_getdata(i); + printf(_("%s is invalid or corrupted\n"), filename); } break; default: @@ -760,7 +755,7 @@ cleanup: if(data) { FREELIST(data); } - if(sync_trans_release() == -1) { + if(trans_release() == -1) { retval = 1; } @@ -770,20 +765,19 @@ cleanup: int pacman_sync(alpm_list_t *targets) { alpm_list_t *sync_dbs = NULL; - int sync_only = 0; /* clean the cache */ if(config->op_s_clean) { int ret = 0; - if(sync_trans_init(0) == -1) { + if(trans_init(PM_TRANS_TYPE_SYNC, 0) == -1) { return(1); } ret += sync_cleancache(config->op_s_clean); ret += sync_cleandb_all(); - if(sync_trans_release() == -1) { + if(trans_release() == -1) { ret++; } @@ -797,18 +791,11 @@ int pacman_sync(alpm_list_t *targets) return(1); } - if(config->op_s_search || config->group - || config->op_s_info || config->op_q_list) { - sync_only = 1; - } else if(targets == NULL && !(config->op_s_sync || config->op_s_upgrade)) { - /* don't proceed here unless we have an operation that doesn't require - * a target list */ - pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n")); - return(1); - } - - if(needs_transaction()) { - if(sync_trans(targets, sync_only) == 1) { + if(config->op_s_sync) { + /* grab a fresh package list */ + printf(_(":: Synchronizing package databases...\n")); + alpm_logaction("synchronizing package lists\n"); + if(!sync_synctree(config->op_s_sync, sync_dbs)) { return(1); } } @@ -833,7 +820,43 @@ int pacman_sync(alpm_list_t *targets) return(sync_list(sync_dbs, targets)); } - return(0); + if(targets == NULL) { + if(config->op_s_upgrade) { + /* proceed */ + } else if(config->op_s_sync) { + return(0); + } else { + /* don't proceed here unless we have an operation that doesn't require a + * target list */ + pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n")); + return(1); + } + } + + alpm_list_t *targs = alpm_list_strdup(targets); + if(!(config->flags & (PM_TRANS_FLAG_DOWNLOADONLY | PM_TRANS_FLAG_PRINTURIS))) { + /* check for newer versions of packages to be upgraded first */ + alpm_list_t *packages = syncfirst(); + if(packages) { + printf(_(":: The following packages should be upgraded first :\n")); + list_display(" ", packages); + if(yesno(1, _(":: Do you want to cancel the current operation\n" + ":: and upgrade these packages now?"))) { + FREELIST(targs); + targs = packages; + config->flags = 0; + config->op_s_upgrade = 0; + } else { + FREELIST(packages); + } + printf("\n"); + } + } + + int ret = sync_trans(targs); + FREELIST(targs); + + return(ret); } /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/add.c b/src/pacman/upgrade.c index fd40f005..c54b3ed7 100644 --- a/src/pacman/add.c +++ b/src/pacman/upgrade.c @@ -1,5 +1,5 @@ /* - * add.c + * upgrade.c * * Copyright (c) 2002-2007 by Judd Vinet <jvinet@zeroflux.org> * @@ -28,23 +28,9 @@ /* pacman */ #include "pacman.h" -#include "callback.h" #include "conf.h" #include "util.h" -/* Free the current transaction and print an error if unsuccessful */ -static int add_cleanup(void) -{ - int ret = alpm_trans_release(); - if(ret != 0) { - pm_printf(PM_LOG_ERROR, _("failed to release transaction (%s)\n"), - alpm_strerrorlast()); - ret = 1; - } - - return(ret); -} - /** * @brief Upgrade a specified list of packages. * @@ -54,23 +40,8 @@ static int add_cleanup(void) */ int pacman_upgrade(alpm_list_t *targets) { - /* this is basically just a remove-then-add process. pacman_add() will */ - /* handle it */ - config->upgrade = 1; - return(pacman_add(targets)); -} - -/** - * @brief Add a specified list of packages which cannot already be installed. - * - * @param targets a list of packages (as strings) to add - * - * @return 0 on success, 1 on failure - */ -int pacman_add(alpm_list_t *targets) -{ alpm_list_t *i, *data = NULL; - pmtranstype_t transtype = PM_TRANS_TYPE_ADD; + pmtranstype_t transtype = PM_TRANS_TYPE_UPGRADE; int retval = 0; if(targets == NULL) { @@ -93,20 +64,7 @@ int pacman_add(alpm_list_t *targets) } /* Step 1: create a new transaction */ - if(config->upgrade == 1) { - /* if upgrade flag was set, change this to an upgrade transaction */ - transtype = PM_TRANS_TYPE_UPGRADE; - } - - if(alpm_trans_init(transtype, config->flags, cb_trans_evt, - cb_trans_conv, cb_trans_progress) == -1) { - /* TODO: error messages should be in the front end, not the back */ - fprintf(stderr, _("error: %s\n"), alpm_strerrorlast()); - if(pm_errno == PM_ERR_HANDLE_LOCK) { - /* TODO this and the 2 other places should probably be on stderr */ - printf(_(" if you're sure a package manager is not already\n" - " running, you can remove %s.\n"), alpm_option_get_lockfile()); - } + if(trans_init(transtype, config->flags) == -1) { return(1); } @@ -115,9 +73,9 @@ int pacman_add(alpm_list_t *targets) for(i = targets; i; i = alpm_list_next(i)) { char *targ = alpm_list_getdata(i); if(alpm_trans_addtarget(targ) == -1) { - fprintf(stderr, _("error: '%s': %s\n"), + pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerrorlast()); - add_cleanup(); + trans_release(); return(1); } } @@ -125,7 +83,7 @@ int pacman_add(alpm_list_t *targets) /* Step 2: "compute" the transaction based on targets and flags */ /* TODO: No, compute nothing. This is stupid. */ if(alpm_trans_prepare(&data) == -1) { - fprintf(stderr, _("error: failed to prepare transaction (%s)\n"), + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), alpm_strerrorlast()); switch(pm_errno) { case PM_ERR_UNSATISFIED_DEPS: @@ -171,7 +129,7 @@ int pacman_add(alpm_list_t *targets) default: break; } - add_cleanup(); + trans_release(); FREELIST(data); return(1); } @@ -179,12 +137,15 @@ int pacman_add(alpm_list_t *targets) /* Step 3: perform the installation */ if(alpm_trans_commit(NULL) == -1) { - fprintf(stderr, _("error: failed to commit transaction (%s)\n"), alpm_strerrorlast()); - add_cleanup(); + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"), + alpm_strerrorlast()); + trans_release(); return(1); } - retval = add_cleanup(); + if(trans_release() == -1) { + retval = 1; + } return(retval); } diff --git a/src/pacman/util.c b/src/pacman/util.c index 0facfdd1..d7ac9e38 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -22,7 +22,6 @@ #include <sys/types.h> #include <sys/ioctl.h> #include <sys/time.h> -#include <sys/stat.h> #include <stdio.h> #include <stdlib.h> @@ -42,6 +41,33 @@ /* pacman */ #include "util.h" #include "conf.h" +#include "callback.h" + + +int trans_init(pmtranstype_t type, pmtransflag_t flags) +{ + if(alpm_trans_init(type, flags, cb_trans_evt, + cb_trans_conv, cb_trans_progress) == -1) { + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to init transaction (%s)\n"), + alpm_strerrorlast()); + if(pm_errno == PM_ERR_HANDLE_LOCK) { + fprintf(stderr, _(" if you're sure a package manager is not already\n" + " running, you can remove %s\n"), alpm_option_get_lockfile()); + } + return(-1); + } + return(0); +} + +int trans_release() +{ + if(alpm_trans_release() == -1) { + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to release transaction (%s)\n"), + alpm_strerrorlast()); + return(-1); + } + return(0); +} int needs_transaction() { @@ -94,33 +120,37 @@ int getcols() /* does the same thing as 'mkdir -p' */ int makepath(const char *path) { - char *orig, *str, *ptr; - char full[PATH_MAX+1] = ""; - mode_t oldmask; - - oldmask = umask(0000); + /* A bit of pointer hell here. Descriptions: + * orig - a copy of path so we can safely butcher it with strsep + * str - the current position in the path string (after the delimiter) + * ptr - the original position of str after calling strsep + * incr - incrementally generated path for use in access/mkdir call + */ + char *orig, *str, *ptr, *incr; + mode_t oldmask = umask(0000); + int ret = 0; orig = strdup(path); + incr = calloc(strlen(orig) + 1, sizeof(char)); str = orig; while((ptr = strsep(&str, "/"))) { if(strlen(ptr)) { - struct stat buf; - - /* TODO we should use strncat */ - strcat(full, "/"); - strcat(full, ptr); - if(stat(full, &buf)) { - if(mkdir(full, 0755)) { - free(orig); - umask(oldmask); - return(1); + /* we have another path component- append the newest component to + * existing string and create one more level of dir structure */ + strcat(incr, "/"); + strcat(incr, ptr); + if(access(incr, F_OK)) { + if(mkdir(incr, 0755)) { + ret = 1; + break; } } } } free(orig); + free(incr); umask(oldmask); - return(0); + return(ret); } /* does the same thing as 'rm -rf' */ @@ -234,6 +264,10 @@ void indentprint(const char *str, int indent) p = wcstr; cidx = indent; + if(!p) { + return; + } + while(*p) { if(*p == L' ') { const wchar_t *q, *next; @@ -457,32 +491,29 @@ void display_targets(const alpm_list_t *syncpkgs, pmdb_t *db_local) const alpm_list_t *i, *j; alpm_list_t *targets = NULL, *to_remove = NULL; /* TODO these are some messy variable names */ - unsigned long isize = 0, rsize = 0, dispsize = 0, dlsize = 0; + off_t isize = 0, rsize = 0, dispsize = 0, dlsize = 0; double mbisize = 0.0, mbrsize = 0.0, mbdispsize = 0.0, mbdlsize = 0.0; for(i = syncpkgs; i; i = alpm_list_next(i)) { pmsyncpkg_t *sync = alpm_list_getdata(i); pmpkg_t *pkg = alpm_sync_get_pkg(sync); - /* If this sync record is a replacement, the data member contains - * a list of packages to be removed due to the package that is being - * installed. */ - if(alpm_sync_get_type(sync) == PM_SYNC_TYPE_REPLACE) { - alpm_list_t *to_replace = alpm_sync_get_data(sync); + /* The removes member contains a list of packages to be removed + * due to the package that is being installed. */ + alpm_list_t *to_replace = alpm_sync_get_removes(sync); - for(j = to_replace; j; j = alpm_list_next(j)) { - pmpkg_t *rp = alpm_list_getdata(j); - const char *name = alpm_pkg_get_name(rp); + for(j = to_replace; j; j = alpm_list_next(j)) { + pmpkg_t *rp = alpm_list_getdata(j); + const char *name = alpm_pkg_get_name(rp); - if(!alpm_list_find_str(to_remove, name)) { - rsize += alpm_pkg_get_isize(rp); - to_remove = alpm_list_add(to_remove, strdup(name)); - } + if(!alpm_list_find_str(to_remove, name)) { + rsize += alpm_pkg_get_isize(rp); + to_remove = alpm_list_add(to_remove, strdup(name)); } } dispsize = alpm_pkg_get_size(pkg); - dlsize += alpm_pkg_download_size(pkg, db_local); + dlsize += alpm_pkg_download_size(pkg); isize += alpm_pkg_get_isize(pkg); /* print the package size with the output if ShowSize option set */ @@ -520,38 +551,50 @@ void display_targets(const alpm_list_t *syncpkgs, pmdb_t *db_local) printf("\n"); printf(_("Total Download Size: %.2f MB\n"), mbdlsize); - - /* TODO because all pkgs don't include isize, this is a crude hack */ - if(mbisize > mbdlsize) { - printf(_("Total Installed Size: %.2f MB\n"), mbisize); - } + printf(_("Total Installed Size: %.2f MB\n"), mbisize); FREELIST(targets); } /* presents a prompt and gets a Y/N answer */ -/* TODO there must be a better way */ -int yesno(char *fmt, ...) +int yesno(short preset, char *fmt, ...) { char response[32]; va_list args; + FILE *stream; if(config->noconfirm) { - return(1); + stream = stdout; + } else { + /* Use stderr so questions are always displayed when redirecting output */ + stream = stderr; } va_start(args, fmt); - /* Use stderr so questions are always displayed when redirecting output */ - vfprintf(stderr, fmt, args); + vfprintf(stream, fmt, args); va_end(args); + if(preset) { + fprintf(stream, " %s ", _("[Y/n]")); + } else { + fprintf(stream, " %s ", _("[y/N]")); + } + + if(config->noconfirm) { + fprintf(stream, "\n"); + return(preset); + } + if(fgets(response, 32, stdin)) { - if(strlen(response) != 0) { - strtrim(response); + strtrim(response); + if(strlen(response) == 0) { + return(preset); } - if(!strcasecmp(response, _("Y")) || !strcasecmp(response, _("YES")) || strlen(response) == 0) { + if(!strcasecmp(response, _("Y")) || !strcasecmp(response, _("YES"))) { return(1); + } else if (!strcasecmp(response, _("N")) || !strcasecmp(response, _("NO"))) { + return(0); } } return(0); diff --git a/src/pacman/util.h b/src/pacman/util.h index 0273512e..722e4ab6 100644 --- a/src/pacman/util.h +++ b/src/pacman/util.h @@ -36,6 +36,8 @@ /* update speed for the fill_progress based functions */ #define UPDATE_SPEED_SEC 0.2f +int trans_init(pmtranstype_t type, pmtransflag_t flags); +int trans_release(); int needs_transaction(); int getcols(); int makepath(const char *path); @@ -50,7 +52,7 @@ alpm_list_t *strsplit(const char *str, const char splitchar); void string_display(const char *title, const char *string); void list_display(const char *title, const alpm_list_t *list); void display_targets(const alpm_list_t *syncpkgs, pmdb_t *db_local); -int yesno(char *fmt, ...); +int yesno(short preset, char *fmt, ...); int pm_printf(pmloglevel_t level, const char *format, ...) __attribute__((format(printf,2,3))); int pm_fprintf(FILE *stream, pmloglevel_t level, const char *format, ...) __attribute__((format(printf,3,4))); int pm_vfprintf(FILE *stream, pmloglevel_t level, const char *format, va_list args) __attribute__((format(printf,3,0))); |