[pacman-dev] [PATCH] Improve changelog handling

Allan McRae allan.mcrae at qimr.edu.au
Fri Dec 7 11:47:23 EST 2007


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 at 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 at 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








More information about the pacman-dev mailing list