My goal was to replicate the tree output format from gentoo's equery tool. No support for differentiating output based on file types (symlink, FIFO etc). Signed-off-by: Bill Kolokithas <kolokithas.b@gmail.com> --- src/pacman/package.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/pacman/package.h | 1 + src/pacman/pacman.c | 2 +- src/pacman/query.c | 4 ++- 4 files changed, 84 insertions(+), 2 deletions(-) diff --git a/src/pacman/package.c b/src/pacman/package.c index 1485889..949755a 100644 --- a/src/pacman/package.c +++ b/src/pacman/package.c @@ -334,6 +334,85 @@ void dump_pkg_files(alpm_pkg_t *pkg, int quiet) fflush(stdout); } +/* Count character occurrences in a string + */ +static int count_char(char *s, char c) +{ + int count = 0; + + for (; *s; s++) + if (*s == c) + count++; + + return count; +} + +/* List all files contained in a package in a tree format + */ +void dump_pkg_file_tree(alpm_pkg_t *pkg) +{ + const char *pkgname, *root, *prefix; + const alpm_file_t *file; + alpm_filelist_t *pkgfiles; + char *basename, filename[512], pool[128]; + int len, isDir, num_spaces, dirdepth; + size_t i; + + /* Fill our pool with spaces */ + memset(pool, ' ', sizeof(pool)); + pkgname = alpm_pkg_get_name(pkg); + pkgfiles = alpm_pkg_get_files(pkg); + root = alpm_option_get_root(config->handle); + + printf("%s%s:%s\n", config->colstr.title, pkgname, config->colstr.nocolor); + + for(i = 0; i < pkgfiles->count; i++) { + /* Duplicate the file name because we will alter it */ + file = pkgfiles->files + i; + strncpy(filename, file->name, sizeof(filename)); + /* Ensure string is always terminated */ + filename[512 - 1] = '\0'; + + prefix = "/"; + len = strlen(filename); + isDir = filename[len - 1] == '/'; + dirdepth = count_char(filename, '/'); + + /* Indent accordingly */ + num_spaces = 1; + if(dirdepth == 2) { + num_spaces = 3; + } else if(dirdepth > 2) { + num_spaces = 3 * (dirdepth - 1); + } + + /* Cut the trailing '/' so we can find the one before it */ + if(isDir) { + filename[len - 1] = '\0'; + } else { + /* Extra padding for files */ + num_spaces += 3; + } + + /* If no '/' is found, then it means we are on the top level so, we prepend the root */ + basename = strrchr(filename, '/'); + if(!basename) { + basename = filename; + prefix = root; + } else { + /* Skip the starting '/' char */ + basename++; + } + + if(isDir) { + printf("%.*s%s> %s%s%s\n", num_spaces, pool, config->colstr.title, prefix, basename, config->colstr.nocolor); + } else { + printf("%.*s%s+%s %s\n", num_spaces, pool, config->colstr.title, config->colstr.nocolor, basename); + } + } + fflush(stdout); +} + /* Display the changelog of a package */ void dump_pkg_changelog(alpm_pkg_t *pkg) diff --git a/src/pacman/package.h b/src/pacman/package.h index 65eea87..58d58b5 100644 --- a/src/pacman/package.h +++ b/src/pacman/package.h @@ -26,6 +26,7 @@ void dump_pkg_full(alpm_pkg_t *pkg, int extra); void dump_pkg_backups(alpm_pkg_t *pkg); void dump_pkg_files(alpm_pkg_t *pkg, int quiet); +void dump_pkg_file_tree(alpm_pkg_t *pkg); void dump_pkg_changelog(alpm_pkg_t *pkg); void print_installed(alpm_db_t *db_local, alpm_pkg_t *pkg); diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index e5d16fc..60e0f0d 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -525,7 +525,7 @@ static int parsearg_query(int opt) break; case OP_LIST: case 'l': - config->op_q_list = 1; + (config->op_q_list)++; break; case OP_FOREIGN: case 'm': diff --git a/src/pacman/query.c b/src/pacman/query.c index 8814307..d1a11d5 100644 --- a/src/pacman/query.c +++ b/src/pacman/query.c @@ -301,8 +301,10 @@ static int display(alpm_pkg_t *pkg) dump_pkg_full(pkg, config->op_q_info > 1); } } - if(config->op_q_list) { + if(config->op_q_list == 1) { dump_pkg_files(pkg, config->quiet); + } else if(config->op_q_list > 1) { + dump_pkg_file_tree(pkg); } if(config->op_q_changelog) { dump_pkg_changelog(pkg); -- 1.8.4.2