poldek: poldek/pkgu.c, poldek/pkgu.h, poldek/libpoldek.sym, poldek/cli/desc...
mis
mis at pld-linux.org
Sat May 24 20:19:12 CEST 2008
Author: mis Date: Sat May 24 18:19:12 2008 GMT
Module: poldek Tag: HEAD
---- Log message:
- packge changelogs are stored in repo index
- desc -L displays changelog
- ls -S (and "lls" alias) lists upgradeable packages with potential security fixes
- code cleanups
---- Files affected:
poldek/poldek:
pkgu.c (1.36 -> 1.37) , pkgu.h (1.12 -> 1.13) , libpoldek.sym (1.35 -> 1.36)
poldek/poldek/cli:
desc.c (1.33 -> 1.34) , ls.c (1.26 -> 1.27)
poldek/poldek/conf:
cli.conf (1.2 -> 1.3)
---- Diffs:
================================================================
Index: poldek/poldek/pkgu.c
diff -u poldek/poldek/pkgu.c:1.36 poldek/poldek/pkgu.c:1.37
--- poldek/poldek/pkgu.c:1.36 Thu May 8 22:35:47 2008
+++ poldek/poldek/pkgu.c Sat May 24 20:19:07 2008
@@ -52,6 +52,7 @@
char *buildhost;
char *distro;
char *sourcerpm;
+ char *changelog;
tn_hash *_ht;
tn_array *_langs;
@@ -281,6 +282,365 @@
return t;
}
+
+struct changelog_ent {
+ time_t ts;
+ char *info; /* rev, author */
+ char message[0];
+};
+
+int changelog_ent_cmp(struct changelog_ent *e1, struct changelog_ent *e2)
+{
+ return e1->ts - e2->ts;
+}
+
+static time_t parse_datetime(const char *str)
+{
+ struct tm tm;
+ time_t ts = 0;
+ int n;
+ char c;
+
+ n = sscanf(str, "%d%c%d%c%d %d:%d:%d", &tm.tm_year, &c, &tm.tm_mon, &c,
+ &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
+ if (n != 8)
+ return 0;
+
+ tm.tm_mon -= 1;
+ tm.tm_year -= 1900;
+
+ if ((ts = mktime(&tm)) == -1)
+ ts = 0;
+
+ return ts;
+}
+
+/* remove header; add '*'s; replace "Revision REV" with "rREV" */
+static
+char *prepare_pld_changelog(tn_alloc *na, const char *changelog, time_t since)
+{
+ struct changelog_ent *ent = NULL;
+ char *entmark = "Revision", *prepared_log;
+ int i, started, max_MESSAGE = 1024, len;
+ tn_array *entries, *lines;
+ tn_buf *logmsg;
+
+ lines = n_str_etokl_ext(changelog, "\n", "", "", '\\');
+
+
+ len = strlen(entmark);
+ entries = n_array_new(8, NULL, (tn_fn_cmp)changelog_ent_cmp);
+ logmsg = n_buf_new(1024);
+ started = 0;
+
+ for (i = 0; i < n_array_size(lines); i++) {
+ char *line = n_array_nth(lines, i);
+
+ if (strncmp(line, entmark, len) == 0)
+ started = 1;
+
+ if (!started)
+ continue;
+
+ if (strncmp(line, entmark, len) == 0) {
+ char *tstr, *rev, info[80];
+ time_t ts;
+ int n;
+
+ if (ent != NULL) {
+ n_snprintf(ent->message, max_MESSAGE, "%s", n_buf_ptr(logmsg));
+ n_buf_clean(logmsg);
+ n_array_push(entries, ent);
+ ent = NULL;
+ }
+
+ //Revision REV YYYY-MM-DD HH:MM:SS rest
+ rev = line + len + 1; /* skip Revision */
+ while (*rev && isspace(*rev))
+ rev++;
+
+ tstr = strchr(rev, ' ');
+ if (tstr) {
+ *tstr = '\0';
+ tstr++;
+ while (*tstr && isspace(*tstr))
+ tstr++;
+ }
+
+ if (rev && tstr) {
+ ts = parse_datetime(tstr);
+ if (ts == 0)
+ continue;
+
+ if (ts < since)
+ break;
+ }
+
+ n = n_snprintf(info, sizeof(info), "* r%s %s", rev, tstr);
+
+ ent = n_malloc(sizeof(*ent) + max_MESSAGE);
+ memset(ent, 0, sizeof(*ent));
+ ent->info = n_strdupl(info, n);
+ ent->message[0] = '\0';
+ continue;
+ }
+
+ if (ent)
+ n_buf_printf(logmsg, "%s\n", line);
+ }
+
+ if (ent != NULL) {
+ n_snprintf(ent->message, max_MESSAGE, "%s", n_buf_ptr(logmsg));
+ n_array_push(entries, ent);
+ }
+
+ n_array_free(lines);
+ n_buf_clean(logmsg);
+
+ /* shift && free entries cause ents are simply malloc()ed here */
+ while (n_array_size(entries)) {
+ ent = n_array_shift(entries);
+ n_buf_printf(logmsg, "%s\n", ent->info);
+ n_buf_printf(logmsg, "%s\n", ent->message);
+ }
+ n_array_free(entries);
+
+ prepared_log = na_strdup(na, n_buf_ptr(logmsg), n_buf_size(logmsg));
+ n_buf_free(logmsg);
+
+ return prepared_log;
+}
+
+static tn_array *parse_changelog(tn_alloc *na, tn_array *lines)
+{
+ struct changelog_ent *ent = NULL;
+ int i, max_MESSAGE = 1024;
+ tn_array *entries;
+ tn_buf *logmsg;
+
+ entries = n_array_new(8, NULL, (tn_fn_cmp)changelog_ent_cmp);
+ logmsg = n_buf_new(1024);
+
+ for (i = 0; i < n_array_size(lines); i++) {
+ char *line = n_array_nth(lines, i);
+
+ if (*line == '*') {
+ char *ts;
+
+ if (ent != NULL) {
+ n_snprintf(ent->message, max_MESSAGE, "%s", n_buf_ptr(logmsg));
+ n_buf_clean(logmsg);
+ n_array_push(entries, ent);
+ ent = NULL;
+ }
+
+ ent = na->na_malloc(na, sizeof(*ent) + max_MESSAGE);
+ memset(ent, 0, sizeof(*ent));
+ ent->info = na_strdup(na, line, strlen(line));
+ ent->message[0] = '\0';
+
+ //* [rREV] YYYY-MM-DD HH:MM:SS rest
+ ts = strchr(line, ' ');
+ while (*ts && isspace(*ts))
+ ts++;
+
+ if (ts && *ts == 'r')
+ ts = strchr(ts, ' ');
+
+ if (ts) {
+ while (*ts && isspace(*ts))
+ ts++;
+
+ if (ts)
+ ent->ts = parse_datetime(ts);
+ }
+ continue;
+ }
+ if (ent)
+ n_buf_printf(logmsg, "%s\n", line);
+ }
+
+ if (ent != NULL) {
+ n_snprintf(ent->message, max_MESSAGE, "%s", n_buf_ptr(logmsg));
+ n_array_push(entries, ent);
+ }
+ n_buf_free(logmsg);
+
+ return entries;
+}
+
+static tn_array *get_parsed_changelog(struct pkguinf *inf, time_t since)
+{
+ tn_array *lines, *entries;
+ const char *changelog;
+
+ if ((changelog = pkguinf_get(inf, PKGUINF_CHANGELOG)) == NULL)
+ return NULL;
+
+ lines = n_str_etokl_ext(changelog, "\n", "", "", '\\');
+ entries = parse_changelog(inf->_na, lines);
+ n_array_free(lines);
+
+ if (since) {
+ tn_array *tmp = n_array_clone(entries);
+ int i;
+
+ for (i=0; i<n_array_size(entries); i++) {
+ struct changelog_ent *ent = n_array_nth(entries, i);
+ if (ent->ts > since)
+ n_array_push(tmp, ent);
+ }
+ n_array_free(entries);
+ entries = tmp;
+ }
+
+ return entries;
+}
+
+int pkguinf_changelog_with_security_fixes(struct pkguinf *inf, time_t since)
+{
+ tn_array *entries;
+ int yes = 0, i;
+
+ n_assert(since);
+ if ((entries = get_parsed_changelog(inf, since)) == NULL)
+ return 0;
+
+ for (i=0; i < n_array_size(entries); i++) {
+ struct changelog_ent *ent = n_array_nth(entries, i);
+ const char *m = ent->message;
+
+ if (strstr(m, "CVE-2") || strstr(m, "CVE-19") || strstr(m, "ecurity")) {
+ yes = 1;
+ break;
+ }
+ }
+ n_array_free(entries);
+ return yes;
+}
+
+const char *pkguinf_get_changelog(struct pkguinf *inf, time_t since)
+{
+ tn_array *entries;
+ tn_buf *nbuf;
+ char *changelog = NULL;
+ int i;
+
+ if (!since)
+ return pkguinf_get(inf, PKGUINF_CHANGELOG);
+
+ if ((entries = get_parsed_changelog(inf, since)) == NULL)
+ return pkguinf_get(inf, PKGUINF_CHANGELOG);
+
+ nbuf = n_buf_new(1024 * 4);
+ for (i=0; i < n_array_size(entries); i++) {
+ struct changelog_ent *ent = n_array_nth(entries, i);
+ n_buf_printf(nbuf, "%s\n", ent->info);
+ n_buf_printf(nbuf, "%s\n", ent->message);
+ }
+ n_array_free(entries);
+
+ changelog = na_strdup(inf->_na, n_buf_ptr(nbuf), n_buf_size(nbuf));
+ n_buf_free(nbuf);
+ return changelog;
+}
+
+static char *do_load_changelog_from_rpmhdr(tn_alloc *na, void *hdr)
+{
+ struct rpmhdr_ent e_name, e_time, e_text;
+ char **names = NULL, **texts = NULL, *changelog = NULL;
+ uint32_t *times = NULL;
+ tn_buf *nbuf = NULL;
+ time_t since;
+ int i;
+
+ since = time(NULL) - 3600 * 24 * 356; /* skip entries older than year */
+
+ if (!pm_rpmhdr_ent_get(&e_name, hdr, RPMTAG_CHANGELOGNAME))
+ return NULL;
+
+ if (!pm_rpmhdr_ent_get(&e_time, hdr, RPMTAG_CHANGELOGTIME)) {
+ pm_rpmhdr_ent_free(&e_name);
+ return NULL;
+ }
+
+ if (!pm_rpmhdr_ent_get(&e_text, hdr, RPMTAG_CHANGELOGTEXT)) {
+ pm_rpmhdr_ent_free(&e_name);
+ pm_rpmhdr_ent_free(&e_time);
+ return NULL;
+ }
+
+ names = pm_rpmhdr_ent_as_strarr(&e_name);
+ times = pm_rpmhdr_ent_as_intarr(&e_time);
+ texts = pm_rpmhdr_ent_as_strarr(&e_text);
+
+ if (e_name.cnt == 1 && strstr(names[0], "PLD")) {
+ changelog = prepare_pld_changelog(na, texts[0], since);
+ goto l_end;
+ }
+
+ nbuf = n_buf_new(1024);
+ for (i=0; i < e_name.cnt; i++) {
+ char ts[32];
+
+ if ((time_t)times[i] < since)
+ break;
+
+ strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S", gmtime((time_t*)×[i]));
+
+ n_buf_printf(nbuf, "* %s %s\n", ts, names[i]);
+ n_buf_printf(nbuf, "%s\n\n", texts[i]);
+ }
+
+ changelog = na_strdup(na, n_buf_ptr(nbuf), n_buf_size(nbuf));
+ n_buf_free(nbuf);
+
+ l_end:
+ pm_rpmhdr_ent_free(&e_name);
+ pm_rpmhdr_ent_free(&e_time);
+ pm_rpmhdr_ent_free(&e_text);
+
+ return changelog;
+}
+
+static
+char *load_changelog_from_rpmhdr(tn_alloc *na, void *hdr, const char *sourcerpm)
+{
+ const char *name, *version, *release;
+ char nvr[512], *changelog = NULL;
+ uint32_t epoch, n;
+
+ pm_rpmhdr_nevr(hdr, &name, &epoch, &version, &release, NULL, NULL);
+ if (name == NULL || version == NULL || release == NULL)
+ return NULL;
+
+ n = n_snprintf(nvr, sizeof(nvr), "%s-%s-%s.", name, version, release);
+
+ /* "main" package */
+ if (sourcerpm == NULL || strncmp(sourcerpm, nvr, n) == 0) {
+ changelog = do_load_changelog_from_rpmhdr(na, hdr);
+
+ } else { /* subpackage */
+ char ts[32], *mainame, *p;
+ time_t now = time(NULL);
+
+ strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S", gmtime(&now));
+ n_strdupap(sourcerpm, &mainame);
+
+ if ((p = strrchr(mainame, '.'))) { /* cut off .src.rpm */
+ *p = '\0';
+ if ((p = strrchr(mainame, '.')))
+ *p = '\0';
+ }
+
+ changelog = na->na_malloc(na, 512);
+ n_snprintf(changelog, 512,
+ "* %s poldek at pld-linux.org\n- see %s's log\n", ts, mainame);
+ }
+
+ return changelog;
+}
+
struct pkguinf *pkguinf_ldrpmhdr(tn_alloc *na, void *hdr)
{
char **langs, **summs, **descrs;
@@ -350,7 +710,8 @@
pkgu->distro = cp_tag(pkgu->_na, h, RPMTAG_DISTRIBUTION);
pkgu->buildhost = cp_tag(pkgu->_na, h, RPMTAG_BUILDHOST);
pkgu->sourcerpm = cp_tag(pkgu->_na, h, RPMTAG_SOURCERPM);
-
+ pkgu->changelog = load_changelog_from_rpmhdr(pkgu->_na, h, pkgu->sourcerpm);
+
return pkgu;
}
@@ -364,104 +725,57 @@
return pkgu->_langs;
}
-#define PKGUINF_TAG_LANG 'L'
#define PKGUINF_TAG_ENDCMN 'E'
tn_buf *pkguinf_store(const struct pkguinf *pkgu, tn_buf *nbuf,
const char *lang)
{
struct pkguinf_i18n *inf;
+ struct member {
+ char tag;
+ char *value;
+ } members[] = {
+ { PKGUINF_LICENSE, pkgu->license },
+ { PKGUINF_URL, pkgu->url },
+ { PKGUINF_VENDOR, pkgu->vendor },
+ { PKGUINF_BUILDHOST, pkgu->buildhost },
+ { PKGUINF_DISTRO, pkgu->distro },
+ { PKGUINF_SOURCERPM, pkgu->sourcerpm },
+ { PKGUINF_CHANGELOG, pkgu->changelog },
+ { 0, NULL }
+ };
- if (lang && strcmp(lang, "C") == 0) {
- if (pkgu->license) {
- n_buf_putc(nbuf, PKGUINF_LICENSE);
- n_buf_putc(nbuf, '\0');
- n_buf_puts(nbuf, pkgu->license);
- n_buf_putc(nbuf, '\0');
- }
-
- if (pkgu->url) {
- n_buf_putc(nbuf, PKGUINF_URL);
- n_buf_putc(nbuf, '\0');
- n_buf_puts(nbuf, pkgu->url);
- n_buf_putc(nbuf, '\0');
- }
-
- if (pkgu->vendor) {
- n_buf_putc(nbuf, PKGUINF_VENDOR);
- n_buf_putc(nbuf, '\0');
- n_buf_puts(nbuf, pkgu->vendor);
- n_buf_putc(nbuf, '\0');
- }
-
- if (pkgu->buildhost) {
- n_buf_putc(nbuf, PKGUINF_BUILDHOST);
- n_buf_putc(nbuf, '\0');
- n_buf_puts(nbuf, pkgu->buildhost);
- n_buf_putc(nbuf, '\0');
- }
-
- if (pkgu->distro) {
- n_buf_putc(nbuf, PKGUINF_DISTRO);
- n_buf_putc(nbuf, '\0');
- n_buf_puts(nbuf, pkgu->distro);
- n_buf_putc(nbuf, '\0');
- }
-
- if (pkgu->sourcerpm) {
-
- n_buf_putc(nbuf, PKGUINF_SOURCERPM);
- n_buf_putc(nbuf, '\0');
- n_buf_puts(nbuf, pkgu->sourcerpm);
- n_buf_putc(nbuf, '\0');
- }
-
- n_buf_putc(nbuf, PKGUINF_TAG_ENDCMN);
- n_buf_putc(nbuf, '\0');
- }
-
-
n_assert(lang);
- if (lang != NULL) {
- if ((inf = n_hash_get(pkgu->_ht, lang))) {
- n_buf_putc(nbuf, PKGUINF_SUMMARY);
- n_buf_putc(nbuf, '\0');
- n_buf_puts(nbuf, inf->summary);
- n_buf_putc(nbuf, '\0');
+ if (n_str_eq(lang, "C")) {
+
+ int i = 0;
+ while (members[i].tag) {
+ struct member m = members[i++];
+ if (m.value == NULL)
+ continue;
- n_buf_putc(nbuf, PKGUINF_DESCRIPTION);
+ n_buf_putc(nbuf, m.tag);
n_buf_putc(nbuf, '\0');
- n_buf_puts(nbuf, inf->description);
+ n_buf_puts(nbuf, m.value);
n_buf_putc(nbuf, '\0');
}
- } else {
- int i;
- tn_array *langs = n_hash_keys(pkgu->_ht);
-
- n_assert(0);
-
- for (i=0; i < n_array_size(langs); i++) {
- char *lang = n_array_nth(langs, i);
- n_buf_putc(nbuf, PKGUINF_TAG_LANG);
- n_buf_putc(nbuf, '\0');
- n_buf_puts(nbuf, lang);
- n_buf_putc(nbuf, '\0');
+ n_buf_putc(nbuf, PKGUINF_TAG_ENDCMN);
+ n_buf_putc(nbuf, '\0');
+ }
+
+ if ((inf = n_hash_get(pkgu->_ht, lang))) {
+ n_buf_putc(nbuf, PKGUINF_SUMMARY);
+ n_buf_putc(nbuf, '\0');
+ n_buf_puts(nbuf, inf->summary);
+ n_buf_putc(nbuf, '\0');
- if ((inf = n_hash_get(pkgu->_ht, lang))) {
- n_buf_putc(nbuf, PKGUINF_SUMMARY);
- n_buf_putc(nbuf, '\0');
- n_buf_puts(nbuf, inf->summary);
- n_buf_putc(nbuf, '\0');
-
- n_buf_putc(nbuf, PKGUINF_DESCRIPTION);
- n_buf_putc(nbuf, '\0');
- n_buf_puts(nbuf, inf->description);
- n_buf_putc(nbuf, '\0');
- }
- }
+ n_buf_putc(nbuf, PKGUINF_DESCRIPTION);
+ n_buf_putc(nbuf, '\0');
+ n_buf_puts(nbuf, inf->description);
+ n_buf_putc(nbuf, '\0');
}
-
+
return nbuf;
}
@@ -509,6 +823,10 @@
set_member(pkgu, &pkgu->sourcerpm, val, len);
break;
+ case PKGUINF_CHANGELOG:
+ set_member(pkgu, &pkgu->changelog, val, len);
+ break;
+
default:
/* skip unknown tag */
;
@@ -578,6 +896,9 @@
case PKGUINF_SOURCERPM:
return pkgu->sourcerpm;
+
+ case PKGUINF_CHANGELOG:
+ return pkgu->changelog;
case PKGUINF_SUMMARY:
val = (char**)&pkgu->_summary;
================================================================
Index: poldek/poldek/pkgu.h
diff -u poldek/poldek/pkgu.h:1.12 poldek/poldek/pkgu.h:1.13
--- poldek/poldek/pkgu.h:1.12 Thu May 8 22:35:47 2008
+++ poldek/poldek/pkgu.h Sat May 24 20:19:07 2008
@@ -15,6 +15,7 @@
#define PKGUINF_BUILDHOST 'b'
#define PKGUINF_DISTRO 'D'
#define PKGUINF_SOURCERPM 'S'
+#define PKGUINF_CHANGELOG 'C'
struct pkguinf;
@@ -27,6 +28,8 @@
int pkguinf_set(struct pkguinf *pkgu, int tag, const char *val,
const char *lang);
+const char *pkguinf_get_changelog(struct pkguinf *inf, time_t since);
+int pkguinf_changelog_with_security_fixes(struct pkguinf *inf, time_t since);
tn_array *pkguinf_langs(struct pkguinf *pkgu);
================================================================
Index: poldek/poldek/libpoldek.sym
diff -u poldek/poldek/libpoldek.sym:1.35 poldek/poldek/libpoldek.sym:1.36
--- poldek/poldek/libpoldek.sym:1.35 Thu May 8 21:00:18 2008
+++ poldek/poldek/libpoldek.sym Sat May 24 20:19:07 2008
@@ -170,6 +170,8 @@
pkgscore_match_init
pkguinf_free
pkguinf_get
+pkguinf_get_changelog
+pkguinf_changelog_with_security_fixes
pkguinf_langs
pkguinf_link
pkguinf_new
================================================================
Index: poldek/poldek/cli/desc.c
diff -u poldek/poldek/cli/desc.c:1.33 poldek/poldek/cli/desc.c:1.34
--- poldek/poldek/cli/desc.c:1.33 Thu May 8 22:35:47 2008
+++ poldek/poldek/cli/desc.c Sat May 24 20:19:07 2008
@@ -56,6 +56,7 @@
#define OPT_DESC_DESCR (1 << 6)
#define OPT_DESC_FL (1 << 7)
#define OPT_DESC_FL_LONGFMT (1 << 8)
+#define OPT_DESC_CHANGELOG (1 << 9)
<<Diff was trimmed, longer than 597 lines>>
---- CVS-web:
http://cvs.pld-linux.org/cgi-bin/cvsweb.cgi/poldek/poldek/pkgu.c?r1=1.36&r2=1.37&f=u
http://cvs.pld-linux.org/cgi-bin/cvsweb.cgi/poldek/poldek/pkgu.h?r1=1.12&r2=1.13&f=u
http://cvs.pld-linux.org/cgi-bin/cvsweb.cgi/poldek/poldek/libpoldek.sym?r1=1.35&r2=1.36&f=u
http://cvs.pld-linux.org/cgi-bin/cvsweb.cgi/poldek/poldek/cli/desc.c?r1=1.33&r2=1.34&f=u
http://cvs.pld-linux.org/cgi-bin/cvsweb.cgi/poldek/poldek/cli/ls.c?r1=1.26&r2=1.27&f=u
http://cvs.pld-linux.org/cgi-bin/cvsweb.cgi/poldek/poldek/conf/cli.conf?r1=1.2&r2=1.3&f=u
More information about the pld-cvs-commit
mailing list