And a new --print-format option to configure the output.

This implements FS#14208

Signed-off-by: Xavier Chantry <[email protected]>
---
 contrib/bash_completion |    9 +++-
 contrib/zsh_completion  |    1 +
 doc/pacman.8.txt        |   11 ++++
 src/pacman/conf.c       |    1 +
 src/pacman/conf.h       |    3 +-
 src/pacman/pacman.c     |   24 +++++++--
 src/pacman/remove.c     |    6 ++
 src/pacman/sync.c       |   24 ++-------
 src/pacman/upgrade.c    |    8 +++-
 src/pacman/util.c       |  120 +++++++++++++++++++++++++++++++++++++++++++----
 src/pacman/util.h       |    1 +
 11 files changed, 171 insertions(+), 37 deletions(-)

diff --git a/contrib/bash_completion b/contrib/bash_completion
index 65135cf..8fd62d6 100644
--- a/contrib/bash_completion
+++ b/contrib/bash_completion
@@ -167,7 +167,7 @@ _pacman ()
           groups) mod="${mod}g" ;;
           info) mod="${mod}i" ;;
           list) mod="${mod}l" ;;
-          print-uris) mod="${mod}p" ;;
+          print) mod="${mod}p" ;;
           search) mod="${mod}s" ;;
           sysupgrade) mod="${mod}u" ;;
           upgrades) mod="${mod}u" ;;
@@ -231,6 +231,8 @@ _pacman ()
           -v --verbose \
           -r --root \
           -b --dbpath \
+          -p --print \
+          --print-format \
           --cachedir \
           ' -- $cur ) )
         return 0
@@ -252,6 +254,8 @@ _pacman ()
           -v --verbose \
           -r --root \
           -b --dbpath \
+          -p --print \
+          --print-format \
           --cachedir \
           ' -- $cur ) )
         return 0
@@ -267,7 +271,6 @@ _pacman ()
           -h --help \
           -i --info \
           -l --list \
-          -p --print-uris \
           -s --search \
           -u --sysupgrade \
           -w --downloadonly \
@@ -283,6 +286,8 @@ _pacman ()
           -v --verbose \
           -r --root \
           -b --dbpath \
+          -p --print \
+          --print-format \
           --cachedir \
           ' -- $cur ) )
         return 0
diff --git a/contrib/zsh_completion b/contrib/zsh_completion
index 2f43d9b..2ecef35 100644
--- a/contrib/zsh_completion
+++ b/contrib/zsh_completion
@@ -26,6 +26,7 @@ _pacman_opts_common=(
        '--noconfirm[Do not ask for confirmation]'
        '--noprogressbar[Do not show a progress bar when downloading files]'
        '--noscriptlet[Do not execute the install scriptlet if one exists]'
+       '--print[Only print the targets instead of performing the operation]'
 )
 
 # options for passing to _arguments: options for --upgrade commands
diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt
index a534e05..e38b909 100644
--- a/doc/pacman.8.txt
+++ b/doc/pacman.8.txt
@@ -169,6 +169,17 @@ Options
 *\--arch* <'arch'>::
        Specify an alternate architecture.
 
+*\--print*::
+       Only print the targets instead of performing the actual operation (sync,
+       remove or upgrade).  Use '\--print-format' to specify how targets are
+       displayed.
+
+*\--print-format* <'format'>::
+       Specify a printf-like format to control the output of the '\--print'
+       operation.  The possible are attributes are : %n for pkgname, %v for 
pkgver, %l
+       for location, %r for repo and %s for size. The default format string is 
"%l",
+       which displays url with '-S', filename with '-U' and pkgname-pkgver 
with '-R'.
+
 Query Options[[QO]]
 -------------------
 *-c, \--changelog*::
diff --git a/src/pacman/conf.c b/src/pacman/conf.c
index 92c6f4e..a8da49c 100644
--- a/src/pacman/conf.c
+++ b/src/pacman/conf.c
@@ -62,6 +62,7 @@ int config_free(config_t *oldconfig)
        free(oldconfig->dbpath);
        free(oldconfig->logfile);
        free(oldconfig->xfercommand);
+       free(oldconfig->print_format);
        free(oldconfig);
        oldconfig = NULL;
 
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index 2d3de98..192f80f 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -31,6 +31,8 @@ typedef struct __config_t {
        unsigned short noconfirm;
        unsigned short noprogressbar;
        unsigned short logmask;
+       unsigned short print;
+       char *print_format;
        /* unfortunately, we have to keep track of paths both here and in the 
library
         * because they can come from both the command line or config file, and 
we
         * need to ensure we get the order of preference right. */
@@ -59,7 +61,6 @@ typedef struct __config_t {
        unsigned short op_s_sync;
        unsigned short op_s_search;
        unsigned short op_s_upgrade;
-       unsigned short op_s_printuris;
 
        unsigned short group;
        pmtransflag_t flags;
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index 3747208..929f745 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -128,7 +128,6 @@ static void usage(int op, const char * const myname)
                        printf(_("  -g, --groups         view all members of a 
package group\n"));
                        printf(_("  -i, --info           view package 
information\n"));
                        printf(_("  -l, --list <repo>    view a list of 
packages in a repo\n"));
-                       printf(_("  -p, --print-uris     print out URIs for 
given packages and their dependencies\n"));
                        printf(_("  -s, --search <regex> search remote 
repositories for matching strings\n"));
                        printf(_("  -u, --sysupgrade     upgrade all outdated 
packages (-uu enables downgrade)\n"));
                        printf(_("  -w, --downloadonly   download packages but 
do not install/upgrade anything\n"));
@@ -139,6 +138,9 @@ static void usage(int op, const char * const myname)
                                 "                       ignore a group upgrade 
(can be used more than once)\n"));
                        printf(_("  -q, --quiet          show less information 
for query and search\n"));
                }
+               printf(_("      --print          only print the targets instead 
of performing the operation\n"));
+               printf(_("      --print-format <string>\n"
+                                                "                       
specify how the targets should be printed\n"));
                printf(_("      --config <path>  set an alternate configuration 
file\n"));
                printf(_("      --logfile <path> set an alternate log file\n"));
                printf(_("      --noconfirm      do not ask for any 
confirmation\n"));
@@ -366,7 +368,7 @@ static int parseargs(int argc, char *argv[])
                {"nosave",     no_argument,       0, 'n'},
                {"owns",       no_argument,       0, 'o'},
                {"file",       no_argument,       0, 'p'},
-               {"print-uris", no_argument,       0, 'p'},
+               {"print",      no_argument,       0, 'p'},
                {"quiet",      no_argument,       0, 'q'},
                {"root",       required_argument, 0, 'r'},
                {"recursive",  no_argument,       0, 's'},
@@ -391,6 +393,7 @@ static int parseargs(int argc, char *argv[])
                {"needed",     no_argument,       0, 1011},
                {"asexplicit",     no_argument,   0, 1012},
                {"arch",       required_argument, 0, 1013},
+               {"print-format", required_argument, 0, 1014},
                {0, 0, 0, 0}
        };
 
@@ -468,6 +471,9 @@ static int parseargs(int argc, char *argv[])
                        case 1013:
                                setarch(optarg);
                                break;
+                       case 1014:
+                               config->print_format = strdup(optarg);
+                               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;
@@ -503,9 +509,7 @@ static int parseargs(int argc, char *argv[])
                        case 'o': config->op_q_owns = 1; break;
                        case 'p':
                                config->op_q_isfile = 1;
-                               config->op_s_printuris = 1;
-                               config->flags |= PM_TRANS_FLAG_NOCONFLICTS;
-                               config->flags |= PM_TRANS_FLAG_NOLOCK;
+                               config->print = 1;
                                break;
                        case 'q':
                                config->quiet = 1;
@@ -1075,6 +1079,16 @@ int main(int argc, char *argv[])
                alpm_option_set_totaldlcb(cb_dl_total);
        }
 
+       /* set up the print operations */
+       if(config->print) {
+               config->noconfirm = 1;
+               config->flags |= PM_TRANS_FLAG_NOCONFLICTS;
+               config->flags |= PM_TRANS_FLAG_NOLOCK;
+               /* Display only errors */
+               config->logmask &= ~PM_LOG_WARNING;
+       }
+
+
 #if defined(HAVE_GETEUID) && !defined(CYGWIN)
        /* check if we have sufficient permission for the requested operation */
        if(myuid > 0 && needs_root()) {
diff --git a/src/pacman/remove.c b/src/pacman/remove.c
index b5119fa..06503d3 100644
--- a/src/pacman/remove.c
+++ b/src/pacman/remove.c
@@ -159,6 +159,12 @@ int pacman_remove(alpm_list_t *targets)
        }
 
        /* Step 3: actually perform the removal */
+       if(config->print) { /* --print */
+               print_packages(alpm_trans_get_pkgs());
+               /* we are done */
+               goto cleanup;
+       }
+
        if(alpm_trans_commit(NULL) == -1) {
                pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit 
transaction (%s)\n"),
                        alpm_strerrorlast());
diff --git a/src/pacman/sync.c b/src/pacman/sync.c
index 896d028..30638bb 100644
--- a/src/pacman/sync.c
+++ b/src/pacman/sync.c
@@ -697,22 +697,8 @@ static int sync_trans(alpm_list_t *targets)
        }
 
        /* Step 3: actually perform the operation */
-       if(config->op_s_printuris) {
-               /* print uris */
-               alpm_list_t *i;
-               for(i = packages; i; i = alpm_list_next(i)) {
-                       pmpkg_t *pkg = alpm_list_getdata(i);
-                       pmdb_t *db = alpm_pkg_get_db(pkg);
-                       const char *dburl = alpm_db_get_url(db);
-                       if(dburl) {
-                               printf("%s/%s\n", dburl, 
alpm_pkg_get_filename(pkg));
-                       } else {
-                               /* can't use WARNING here, we don't show 
warnings in -Sp... */
-                               pm_fprintf(stderr, PM_LOG_ERROR, _("no database 
for package: %s\n"),
-                                               alpm_pkg_get_name(pkg));
-                       }
-
-               }
+       if(config->print) {
+               print_packages(packages);
                /* we are done */
                goto cleanup;
        }
@@ -785,8 +771,8 @@ int pacman_sync(alpm_list_t *targets)
 {
        alpm_list_t *sync_dbs = NULL;
 
-       /* Display only errors with -Sp and -Sw operations */
-       if((config->flags & PM_TRANS_FLAG_DOWNLOADONLY) || 
config->op_s_printuris) {
+       /* Display only errors with -Sw operations */
+       if(config->flags & PM_TRANS_FLAG_DOWNLOADONLY) {
                config->logmask &= ~PM_LOG_WARNING;
        }
 
@@ -859,7 +845,7 @@ int pacman_sync(alpm_list_t *targets)
        }
 
        alpm_list_t *targs = alpm_list_strdup(targets);
-       if(!(config->flags & PM_TRANS_FLAG_DOWNLOADONLY) && 
!config->op_s_printuris) {
+       if(!(config->flags & PM_TRANS_FLAG_DOWNLOADONLY) && !config->print) {
                /* check for newer versions of packages to be upgraded first */
                alpm_list_t *packages = syncfirst();
                if(packages) {
diff --git a/src/pacman/upgrade.c b/src/pacman/upgrade.c
index e769118..8269b3d 100644
--- a/src/pacman/upgrade.c
+++ b/src/pacman/upgrade.c
@@ -70,7 +70,6 @@ int pacman_upgrade(alpm_list_t *targets)
        }
 
        /* add targets to the created transaction */
-       printf(_("loading package data...\n"));
        for(i = targets; i; i = alpm_list_next(i)) {
                char *targ = alpm_list_getdata(i);
                if(alpm_trans_addtarget(targ) == -1) {
@@ -143,6 +142,13 @@ int pacman_upgrade(alpm_list_t *targets)
        alpm_list_free(data);
 
        /* Step 3: perform the installation */
+       if(config->print) { /* --print */
+               print_packages(alpm_trans_get_pkgs());
+               /* we are done */
+               trans_release();
+               return(0);
+       }
+
        if(alpm_trans_commit(NULL) == -1) {
                pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit 
transaction (%s)\n"),
                        alpm_strerrorlast());
diff --git a/src/pacman/util.c b/src/pacman/util.c
index a02b43c..8558302 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -47,8 +47,15 @@
 
 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) {
+       int ret;
+       if(config->print) {
+               ret = alpm_trans_init(type, flags, NULL, NULL, NULL);
+       } else {
+               ret = alpm_trans_init(type, flags, cb_trans_evt, cb_trans_conv,
+                               cb_trans_progress);
+       }
+
+       if(ret == -1) {
                pm_fprintf(stderr, PM_LOG_ERROR, _("failed to init transaction 
(%s)\n"),
                                alpm_strerrorlast());
                if(pm_errno == PM_ERR_HANDLE_LOCK) {
@@ -72,13 +79,16 @@ int trans_release(void)
 
 int needs_root(void)
 {
-       if(config->op == PM_OP_UPGRADE || config->op == PM_OP_REMOVE || /* -U, 
-R */
-          (config->op == PM_OP_SYNC && (config->op_s_clean || 
config->op_s_sync || /* -Sc, -Sy */
-             (!config->group && !config->op_s_info && !config->op_q_list /* 
all other -S combinations, where */
-               && !config->op_s_search && !config->op_s_printuris)))) {  /* 
-g, -i, -l, -s, -p is not set */
-               return(1);
-       } else {
-               return(0);
+       switch(config->op) {
+               case PM_OP_UPGRADE:
+               case PM_OP_REMOVE:
+                       return(!config->print);
+               case PM_OP_SYNC:
+                       return(config->op_s_clean || config->op_s_sync ||
+                                       (!config->group && !config->op_s_info 
&& !config->op_q_list &&
+                                        !config->op_s_search && 
!config->print));
+               default:
+                       return(0);
        }
 }
 
@@ -607,6 +617,98 @@ void display_synctargets(const alpm_list_t *syncpkgs)
        alpm_list_free(rpkglist);
 }
 
+off_t pkg_get_size(pmpkg_t *pkg)
+{
+       switch(config->op) {
+               case PM_OP_SYNC:
+                       return(alpm_pkg_download_size(pkg));
+               case PM_OP_UPGRADE:
+                       return(alpm_pkg_get_size(pkg));
+               default:
+                       return(alpm_pkg_get_isize(pkg));
+       }
+}
+
+char *pkg_get_location(pmpkg_t *pkg)
+{
+       pmdb_t *db;
+       const char *dburl;
+       char *string;
+       switch(config->op) {
+               case PM_OP_SYNC:
+                       db = alpm_pkg_get_db(pkg);
+                       dburl = alpm_db_get_url(db);
+                       if(dburl) {
+                               char *pkgurl = NULL;
+                               asprintf(&pkgurl, "%s/%s", dburl, 
alpm_pkg_get_filename(pkg));
+                               return(pkgurl);
+                       }
+               case PM_OP_UPGRADE:
+                       return(strdup(alpm_pkg_get_filename(pkg)));
+               default:
+                       string = NULL;
+                       asprintf(&string, "%s-%s", alpm_pkg_get_name(pkg), 
alpm_pkg_get_version(pkg));
+                       return(string);
+       }
+}
+
+void print_packages(const alpm_list_t *packages)
+{
+       const alpm_list_t *i;
+       if(!config->print_format) {
+               config->print_format = strdup("%l");
+       }
+       for(i = packages; i; i = alpm_list_next(i)) {
+               pmpkg_t *pkg = alpm_list_getdata(i);
+               char *string = strdup(config->print_format);
+               char *temp = string;
+               /* %n : pkgname */
+               if(strstr(temp,"%n")) {
+                       string = strreplace(temp, "%n", alpm_pkg_get_name(pkg));
+                       free(temp);
+                       temp = string;
+               }
+               /* %v : pkgver */
+               if(strstr(temp,"%v")) {
+                       string = strreplace(temp, "%v", 
alpm_pkg_get_version(pkg));
+                       free(temp);
+                       temp = string;
+               }
+               /* %l : location */
+               if(strstr(temp,"%l")) {
+                       char *pkgloc = pkg_get_location(pkg);
+                       string = strreplace(temp, "%l", pkgloc);
+                       free(pkgloc);
+                       free(temp);
+                       temp = string;
+               }
+               /* %r : repo */
+               if(strstr(temp,"%r")) {
+                       const char *repo = "local";
+                       pmdb_t *db = alpm_pkg_get_db(pkg);
+                       if(db) {
+                               repo = alpm_db_get_name(db);
+                       }
+                       string = strreplace(temp, "%r", repo);
+                       free(temp);
+                       temp = string;
+               }
+               /* %s : size */
+               if(strstr(temp,"%s")) {
+                       char *size;
+                       double mbsize = 0.0;
+                       mbsize = pkg_get_size(pkg) / (1024.0 * 1024.0);
+                       asprintf(&size, "%.2f", mbsize);
+                       string = strreplace(temp, "%s", size);
+                       free(size);
+                       free(temp);
+                       temp = string;
+               }
+               printf("%s\n",string);
+               free(string);
+       }
+}
+
 /* Helper function for comparing strings using the
  * alpm "compare func" signature */
 int str_cmp(const void *s1, const void *s2)
diff --git a/src/pacman/util.h b/src/pacman/util.h
index 1282422..25a8168 100644
--- a/src/pacman/util.h
+++ b/src/pacman/util.h
@@ -57,6 +57,7 @@ void display_targets(const alpm_list_t *pkgs, int install);
 void display_synctargets(const alpm_list_t *syncpkgs);
 void display_new_optdepends(pmpkg_t *oldpkg, pmpkg_t *newpkg);
 void display_optdepends(pmpkg_t *pkg);
+void print_packages(const alpm_list_t *packages);
 int yesno(char *fmt, ...);
 int noyes(char *fmt, ...);
 int pm_printf(pmloglevel_t level, const char *format, ...) 
__attribute__((format(printf,2,3)));
-- 
1.6.4.2


Reply via email to