summaryrefslogtreecommitdiff
path: root/src/pacman
diff options
context:
space:
mode:
Diffstat (limited to 'src/pacman')
-rw-r--r--src/pacman/Makefile.am7
-rw-r--r--src/pacman/callback.c142
-rw-r--r--src/pacman/callback.h7
-rw-r--r--src/pacman/conf.c8
-rw-r--r--src/pacman/conf.h17
-rw-r--r--src/pacman/deptest.c46
-rw-r--r--src/pacman/package.c22
-rw-r--r--src/pacman/pacman.c136
-rw-r--r--src/pacman/pacman.h9
-rw-r--r--src/pacman/query.c69
-rw-r--r--src/pacman/remove.c47
-rw-r--r--src/pacman/sync.c383
-rw-r--r--src/pacman/upgrade.c (renamed from src/pacman/add.c)65
-rw-r--r--src/pacman/util.c131
-rw-r--r--src/pacman/util.h4
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)));