Hi all, Below is a patch that tries to improve the handling of changelog dumping. Now changelogs should also get dumped when using "pacman -Qcp <file>" syntax as well as "pacman -Qc <pkg>" (See http://bugs.archlinux.org/task/7321) This is my first patch to the pacman/libalpm code base so it probably needs lots of checking. I stared at the code for a couple of hours before I started but I am probably using some libalpm functions wrongly. I would pay particular attention to the entirely new "alpm_pkg_get_changelog" function in libalpm/package.c. The code builds cleanly but I can't test much more than that at the moment due to my testing box having what I think is RAM issues leaving me only my work laptop... Cheers, Allan From 47affca982ec2d449bd6d96846172052dbdd3da6 Mon Sep 17 00:00:00 2001 From: Allan McRae <mcrae_allan@hotmail.com> Date: Sat, 8 Dec 2007 02:35:00 +1000 Subject: [PATCH] Improve changelog handling Allows dumping of changelog for both installed packages and from package files (See FS#7321). Moves querying of changelog file in alpm backend. Signed-off-by: Allan McRae <mcrae_allan@hotmail.com> --- lib/libalpm/alpm.h | 1 + lib/libalpm/package.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ src/pacman/package.c | 33 ++++++++++------------ src/pacman/package.h | 2 +- src/pacman/query.c | 9 +----- 5 files changed, 89 insertions(+), 27 deletions(-) diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 1e18ad9..7f6c9eb 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -216,6 +216,7 @@ alpm_list_t *alpm_pkg_get_deltas(pmpkg_t *pkg); alpm_list_t *alpm_pkg_get_replaces(pmpkg_t *pkg); alpm_list_t *alpm_pkg_get_files(pmpkg_t *pkg); alpm_list_t *alpm_pkg_get_backup(pmpkg_t *pkg); +alpm_list_t *alpm_pkg_get_changelog(pmpkg_t *pkg); unsigned short alpm_pkg_has_scriptlet(pmpkg_t *pkg); unsigned long alpm_pkg_download_size(pmpkg_t *newpkg, pmdb_t *db_local); diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index 172456d..bbdb95d 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -491,6 +491,77 @@ alpm_list_t SYMEXPORT *alpm_pkg_get_backup(pmpkg_t *pkg) return pkg->backup; } +alpm_list_t SYMEXPORT *alpm_pkg_get_changelog(pmpkg_t *pkg) +{ + ALPM_LOG_FUNC; + + /* Sanity checks */ + ASSERT(handle != NULL, return(NULL)); + ASSERT(pkg != NULL, return(NULL)); + + int ret = ARCHIVE_OK; + alpm_list_t *cl = NULL; + char clfile[PATH_MAX]; + char *tmpfile = NULL; + struct archive *archive; + struct archive_entry *entry; + int fd = -1; + char line[PATH_MAX]; + + if(pkg->origin == PKG_FROM_CACHE) { + snprintf(clfile, PATH_MAX, "%s/%s/%s-%s/changelog", + alpm_option_get_dbpath(), + alpm_db_get_name(alpm_db_register_local()), + alpm_pkg_get_name(pkg), + alpm_pkg_get_version(pkg)); + } else if(pkg->origin == PKG_FROM_FILE) { + const char *pkgfile = pkg->origin_data.file; + + if((archive = archive_read_new()) == NULL) { + RET_ERR(PM_ERR_LIBARCHIVE_ERROR, NULL); + } + + archive_read_support_compression_all(archive); + archive_read_support_format_all(archive); + + if (archive_read_open_filename(archive, pkgfile, + ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { + RET_ERR(PM_ERR_PKG_OPEN, NULL); + } + + while((ret = archive_read_next_header(archive, &entry)) == ARCHIVE_OK) { + const char *entry_name = archive_entry_pathname(entry); + + if(strcmp(entry_name, ".CHANGELOG") == 0) { + tmpfile = strdup("/tmp/alpm_XXXXXX"); + fd = mkstemp(tmpfile); + archive_read_data_into_fd(archive, fd); + break; + } + } + snprintf(clfile, PATH_MAX, "%s", tmpfile); + } + + FILE* fp = fopen(clfile, "r"); + if(fp == NULL){ + return cl; + } + + while(!feof(fp)) { + fgets(line, (int)PATH_MAX, fp); + cl = alpm_list_add(cl, strdup(line)); + } + fclose(fp); + + if(pkg->origin == PKG_FROM_FILE) { + unlink(tmpfile); + FREE(tmpfile); + close(fd); + } + + return cl; +} + unsigned short SYMEXPORT alpm_pkg_has_scriptlet(pmpkg_t *pkg) { ALPM_LOG_FUNC; diff --git a/src/pacman/package.c b/src/pacman/package.c index ac3f820..00c3535 100644 --- a/src/pacman/package.c +++ b/src/pacman/package.c @@ -232,29 +232,26 @@ void dump_pkg_files(pmpkg_t *pkg) fflush(stdout); } -/* Display the changelog of an installed package +/* Display the changelog of a package */ -void dump_pkg_changelog(char *clfile, const char *pkgname) +void dump_pkg_changelog(pmpkg_t *pkg) { - FILE* fp = NULL; - char line[PATH_MAX+1]; - - if((fp = fopen(clfile, "r")) == NULL) - { - fprintf(stderr, _("error: no changelog available for '%s'.\n"), pkgname); + alpm_list_t *changelog = NULL; + alpm_list_t *i; + char line[PATH_MAX]; + + changelog = alpm_pkg_get_changelog(pkg); + if(changelog == NULL) { + fprintf(stderr, _("error: no changelog available for '%s'.\n"), alpm_pkg_get_name(pkg)); return; - } - else - { - while(!feof(fp)) - { - fgets(line, (int)PATH_MAX, fp); - printf("%s", line); - line[0] = '\0'; + } else { + for(i = changelog; i; i = alpm_list_next(i)) { + snprintf(line, PATH_MAX-1, "%s", (char*)alpm_list_getdata(i)); + fprintf(stdout, "%s\n", line); } - fclose(fp); - return; } + + FREELIST(changelog); } /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/package.h b/src/pacman/package.h index 0e4bb0f..7dfc054 100644 --- a/src/pacman/package.h +++ b/src/pacman/package.h @@ -28,7 +28,7 @@ void dump_pkg_sync(pmpkg_t *pkg, const char *treename); void dump_pkg_backups(pmpkg_t *pkg); void dump_pkg_files(pmpkg_t *pkg); -void dump_pkg_changelog(char *clfile, const char *pkgname); +void dump_pkg_changelog(pmpkg_t *pkg); #endif /* _PM_PACKAGE_H */ diff --git a/src/pacman/query.c b/src/pacman/query.c index 8a8765b..1307077 100644 --- a/src/pacman/query.c +++ b/src/pacman/query.c @@ -312,14 +312,7 @@ static void display(pmpkg_t *pkg) dump_pkg_files(pkg); } if(config->op_q_changelog) { - char changelog[PATH_MAX]; - /* TODO should be done in the backend- no raw DB stuff up front */ - snprintf(changelog, PATH_MAX, "%s/%s/%s-%s/changelog", - alpm_option_get_dbpath(), - alpm_db_get_name(db_local), - alpm_pkg_get_name(pkg), - alpm_pkg_get_version(pkg)); - dump_pkg_changelog(changelog, alpm_pkg_get_name(pkg)); + dump_pkg_changelog(pkg); } if(!config->op_q_info && !config->op_q_list && !config->op_q_changelog) { if (!config->quiet) { -- 1.5.3.7