On 10/25/15 at 05:07pm, Florian Pritz wrote:
Signed-off-by: Florian Pritz <bluewind@xinu.at> ---
v2: - Always output paths without leading slash
doc/pacman.8.txt | 4 ++++ src/pacman/conf.h | 2 ++ src/pacman/files.c | 69 ++++++++++++++++++++++++++++++++++++++--------------- src/pacman/pacman.c | 6 +++++ 4 files changed, 62 insertions(+), 19 deletions(-)
diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt index 38b8bb7..1f11cf3 100644 --- a/doc/pacman.8.txt +++ b/doc/pacman.8.txt @@ -477,6 +477,10 @@ The '--list', '--search' and '--owns' options are exclusive and can not be combi *-o <file>, \--owns<file>*:: Search for packages that own a particular file.
+*--machinereadable*:: + Use a machine readable output format for '--list', '--search' and + '--owns'. The format is 'repository/pkgname pkgver path'.
Spaces are not really reliable field separators. Every single field being printed is allowed to contain spaces by alpm/pacman.
Handling Config Files[[HCF]] ---------------------------- diff --git a/src/pacman/conf.h b/src/pacman/conf.h index 3fff900..1760b07 100644 --- a/src/pacman/conf.h +++ b/src/pacman/conf.h @@ -89,6 +89,7 @@ typedef struct __config_t { unsigned short op_s_upgrade;
unsigned short op_f_regex; + unsigned short op_f_machinereadable;
unsigned short group; unsigned short noask; @@ -190,6 +191,7 @@ enum { OP_RECURSIVE, OP_SEARCH, OP_REGEX, + OP_MACHINEREADABLE, OP_UNREQUIRED, OP_UPGRADES, OP_SYSUPGRADE, diff --git a/src/pacman/files.c b/src/pacman/files.c index 31ce9e0..b21503a 100644 --- a/src/pacman/files.c +++ b/src/pacman/files.c @@ -27,6 +27,14 @@ #include "conf.h" #include "package.h"
+static void dump_pkg_machinereadable(alpm_db_t *db, alpm_pkg_t *pkg) { + alpm_filelist_t *pkgfiles = alpm_pkg_get_files(pkg); + for(size_t filenum = 0; filenum < pkgfiles->count; filenum++) { + const alpm_file_t *file = pkgfiles->files + filenum; + printf("%s/%s %s %s\n", alpm_db_get_name(db), alpm_pkg_get_name(pkg), + alpm_pkg_get_version(pkg), file->name); + } +}
static int files_fileowner(alpm_list_t *syncs, alpm_list_t *targets) { int ret = 0; @@ -59,13 +67,17 @@ static int files_fileowner(alpm_list_t *syncs, alpm_list_t *targets) { alpm_filelist_t *files = alpm_pkg_get_files(pkg);
if(alpm_filelist_contains(files, f)) { - - if(!config->quiet) { - printf(_("%s is owned by %s/%s %s\n"), f, - alpm_db_get_name(repo), alpm_pkg_get_name(pkg), - alpm_pkg_get_version(pkg)); + if(config->op_f_machinereadable) { + printf("%s/%s %s %s\n", alpm_db_get_name(repo), alpm_pkg_get_name(pkg), + alpm_pkg_get_version(pkg), f); } else { - printf("%s/%s\n", alpm_db_get_name(repo), alpm_pkg_get_name(pkg)); + if(!config->quiet) { + printf(_("%s is owned by %s/%s %s\n"), f, + alpm_db_get_name(repo), alpm_pkg_get_name(pkg), + alpm_pkg_get_version(pkg)); + } else { + printf("%s/%s\n", alpm_db_get_name(repo), alpm_pkg_get_name(pkg)); + }
No need to nest this if, make it part of the outer conditional.
}
found = 1; @@ -137,19 +149,28 @@ static int files_search(alpm_list_t *syncs, alpm_list_t *targets, int regex) { }
if(match != NULL) { - if(config->quiet) { - printf("%s/%s\n", alpm_db_get_name(repo), alpm_pkg_get_name(pkg)); - } else { + if(config->op_f_machinereadable) { alpm_list_t *ml; - printf("%s%s/%s%s %s%s%s\n", colstr->repo, alpm_db_get_name(repo), - colstr->title, alpm_pkg_get_name(pkg), - colstr->version, alpm_pkg_get_version(pkg), colstr->nocolor); - for(ml = match; ml; ml = alpm_list_next(ml)) { - c = ml->data; - printf(" %s\n", c); + char *filename = ml->data; + printf("%s/%s %s %s\n", alpm_db_get_name(repo), alpm_pkg_get_name(pkg), + alpm_pkg_get_version(pkg), filename); + } + } else { + if(config->quiet) { + printf("%s/%s\n", alpm_db_get_name(repo), alpm_pkg_get_name(pkg)); + } else { + alpm_list_t *ml; + printf("%s%s/%s%s %s%s%s\n", colstr->repo, alpm_db_get_name(repo), + colstr->title, alpm_pkg_get_name(pkg), + colstr->version, alpm_pkg_get_version(pkg), colstr->nocolor); + + for(ml = match; ml; ml = alpm_list_next(ml)) { + c = ml->data; + printf(" %s\n", c); + } + FREELIST(match); }
Same for this one.
- FREELIST(match);
match needs to be free'd any time it's not NULL, this needs to be moved to the outer block.
} } } @@ -222,8 +243,14 @@ static int files_list(alpm_list_t *syncs, alpm_list_t *targets) {
if((pkg = alpm_db_get_pkg(db, targ)) != NULL) { found = 1; - dump_file_list(pkg); - break; + if(config->op_f_machinereadable) { + dump_pkg_machinereadable(db, pkg); + // list all repos if not asked for a specific one
I don't like having the machine readable format printing a different set of packages than the normal format.
+ continue;
Unnecessary continue.
+ } else { + dump_file_list(pkg); + break; + } } } if(!found) { @@ -240,7 +267,11 @@ static int files_list(alpm_list_t *syncs, alpm_list_t *targets) {
for(j = alpm_db_get_pkgcache(db); j; j = alpm_list_next(j)) { alpm_pkg_t *pkg = j->data; - dump_file_list(pkg); + if(config->op_f_machinereadable) { + dump_pkg_machinereadable(db, pkg); + } else { + dump_file_list(pkg); + } } } } diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index c680067..0bb1b39 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -181,6 +181,8 @@ static void usage(int op, const char * const myname) addlist(_(" -x, --regex enable searching using regular expressions\n")); addlist(_(" -y, --refresh download fresh package databases from the server\n" " (-yy to force a refresh even if up to date)\n")); + addlist(_(" --machinereadable\n" + " produce machine-readable output\n")); } switch(op) { case PM_OP_SYNC: @@ -792,6 +794,9 @@ static int parsearg_files(int opt) case 'x': config->op_f_regex = 1; break; + case OP_MACHINEREADABLE: + config->op_f_machinereadable = 1; + break; case OP_QUIET: case 'q': config->quiet = 1; @@ -941,6 +946,7 @@ static int parseargs(int argc, char *argv[]) {"recursive", no_argument, 0, OP_RECURSIVE}, {"search", no_argument, 0, OP_SEARCH}, {"regex", no_argument, 0, OP_REGEX}, + {"machinereadable", no_argument, 0, OP_MACHINEREADABLE}, {"unrequired", no_argument, 0, OP_UNREQUIRED}, {"upgrades", no_argument, 0, OP_UPGRADES}, {"sysupgrade", no_argument, 0, OP_SYSUPGRADE}, -- 2.6.2