[pacman-dev] [PATCH 1/2] Allow alpm_depend_t to have a description
This is the first step in parsing and handling optdepends. There is no behavior change introduced in this commit; however, depends that contain a ": " string will now be parsed as having a description and it will be stored in the depend structure. Later patches will utilize this new field as appropriate. This is heavily based on the work of Benedikt, who did something similar but introduced a new type for this rather than only a new field to the existing type. Heavily-influenced-by: Benedikt Morbach <benedikt.morbach@googlemail.com> Signed-off-by: Dan McGee <dan@archlinux.org> --- lib/libalpm/alpm.h | 1 + lib/libalpm/deps.c | 44 +++++++++++++++++++++++++++++++------------- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 5f587d3..8a418dc 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -136,6 +136,7 @@ typedef struct __alpm_trans_t alpm_trans_t; typedef struct _alpm_depend_t { char *name; char *version; + char *desc; unsigned long name_hash; alpm_depmod_t mod; } alpm_depend_t; diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index eda0648..6069f5e 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -39,6 +39,7 @@ void _alpm_dep_free(alpm_depend_t *dep) { FREE(dep->name); FREE(dep->version); + FREE(dep->desc); FREE(dep); } @@ -409,7 +410,7 @@ int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) alpm_depend_t *_alpm_splitdep(const char *depstring) { alpm_depend_t *depend; - const char *ptr, *version; + const char *ptr, *version, *desc; size_t deplen; if(depstring == NULL) { @@ -417,7 +418,17 @@ alpm_depend_t *_alpm_splitdep(const char *depstring) } MALLOC(depend, sizeof(alpm_depend_t), return NULL); - deplen = strlen(depstring); + + /* Note the extra space in ": " to avoid matching the epoch */ + if((desc = strstr(depstring, ": ")) != NULL) { + STRDUP(depend->desc, desc + 2, return NULL); + deplen = desc - depstring; + } else { + /* no description- point desc at NULL at end of string for later use */ + depend->desc = NULL; + deplen = strlen(depstring); + desc = depstring + deplen; + } /* Find a version comparator if one exists. If it does, set the type and * increment the ptr accordingly so we can copy the right strings. */ @@ -442,21 +453,18 @@ alpm_depend_t *_alpm_splitdep(const char *depstring) depend->mod = ALPM_DEP_MOD_EQ; version = ptr + 1; } else { - /* no version specified, leave ptr NULL and set version to NULL */ + /* no version specified, set ptr to end of string and version to NULL */ + ptr = depstring + deplen; depend->mod = ALPM_DEP_MOD_ANY; depend->version = NULL; version = NULL; } /* copy the right parts to the right places */ - if(ptr) { - STRNDUP(depend->name, depstring, ptr - depstring, return NULL); - } else { - STRDUP(depend->name, depstring, return NULL); - } + STRNDUP(depend->name, depstring, ptr - depstring, return NULL); depend->name_hash = _alpm_hash_sdbm(depend->name); if(version) { - STRDUP(depend->version, version, return NULL); + STRNDUP(depend->version, version, desc - version, return NULL); } return depend; @@ -468,8 +476,9 @@ alpm_depend_t *_alpm_dep_dup(const alpm_depend_t *dep) CALLOC(newdep, 1, sizeof(alpm_depend_t), return NULL); STRDUP(newdep->name, dep->name, return NULL); - newdep->name_hash = dep->name_hash; STRDUP(newdep->version, dep->version, return NULL); + STRDUP(newdep->desc, dep->desc, return NULL); + newdep->name_hash = dep->name_hash; newdep->mod = dep->mod; return newdep; @@ -792,7 +801,7 @@ int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs, */ char SYMEXPORT *alpm_dep_compute_string(const alpm_depend_t *dep) { - const char *name, *opr, *ver; + const char *name, *opr, *ver, *desc_delim, *desc; char *str; size_t len; @@ -834,12 +843,21 @@ char SYMEXPORT *alpm_dep_compute_string(const alpm_depend_t *dep) ver = ""; } + if(dep->desc) { + desc_delim = ": "; + desc = dep->desc; + } else { + desc_delim = ""; + desc = ""; + } + /* we can always compute len and print the string like this because opr * and ver will be empty when ALPM_DEP_MOD_ANY is the depend type. the * reassignments above also ensure we do not do a strlen(NULL). */ - len = strlen(name) + strlen(opr) + strlen(ver) + 1; + len = strlen(name) + strlen(opr) + strlen(ver) + + strlen(desc_delim) + strlen(desc) + 1; MALLOC(str, len, return NULL); - snprintf(str, len, "%s%s%s", name, opr, ver); + snprintf(str, len, "%s%s%s%s%s", name, opr, ver, desc_delim, desc); return str; } -- 1.7.9.3
From: Benedikt Morbach <benedikt.morbach@googlemail.com> No new behaviour introduced, everything should work exactly as before. Dan: refactored to use the single alpm_depend_t structure. Signed-off-by: Benedikt Morbach <benedikt.morbach@googlemail.com> Signed-off-by: Dan McGee <dan@archlinux.org> --- lib/libalpm/alpm.h | 2 +- lib/libalpm/be_local.c | 6 ++-- lib/libalpm/be_package.c | 5 +-- lib/libalpm/be_sync.c | 2 +- lib/libalpm/package.c | 4 +-- src/pacman/package.c | 18 +++++++++-- src/pacman/util.c | 79 +++++++++++++++++++++++++++++++++++++++------- 7 files changed, 94 insertions(+), 22 deletions(-) diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 8a418dc..a6b7c78 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -820,7 +820,7 @@ alpm_list_t *alpm_pkg_get_depends(alpm_pkg_t *pkg); /** Returns the list of package optional dependencies. * @param pkg a pointer to package - * @return a reference to an internal list of strings. + * @return a reference to an internal list of alpm_depend_t structures. */ alpm_list_t *alpm_pkg_get_optdepends(alpm_pkg_t *pkg); diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c index 20b7895..0d423fa 100644 --- a/lib/libalpm/be_local.c +++ b/lib/libalpm/be_local.c @@ -611,7 +611,7 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) } else if(strcmp(line, "%DEPENDS%") == 0) { READ_AND_SPLITDEP(info->depends); } else if(strcmp(line, "%OPTDEPENDS%") == 0) { - READ_AND_STORE_ALL(info->optdepends); + READ_AND_SPLITDEP(info->optdepends); } else if(strcmp(line, "%CONFLICTS%") == 0) { READ_AND_SPLITDEP(info->conflicts); } else if(strcmp(line, "%PROVIDES%") == 0) { @@ -829,7 +829,9 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq if(info->optdepends) { fputs("%OPTDEPENDS%\n", fp); for(lp = info->optdepends; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); + char *optstring = alpm_dep_compute_string(lp->data); + fprintf(fp, "%s\n", optstring); + free(optstring); } fprintf(fp, "\n"); } diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c index 4008195..c076f61 100644 --- a/lib/libalpm/be_package.c +++ b/lib/libalpm/be_package.c @@ -36,7 +36,7 @@ #include "log.h" #include "handle.h" #include "package.h" -#include "deps.h" /* _alpm_splitdep */ +#include "deps.h" struct package_changelog { struct archive *archive; @@ -214,7 +214,8 @@ static int parse_descfile(alpm_handle_t *handle, struct archive *a, alpm_pkg_t * alpm_depend_t *dep = _alpm_splitdep(ptr); newpkg->depends = alpm_list_add(newpkg->depends, dep); } else if(strcmp(key, "optdepend") == 0) { - newpkg->optdepends = alpm_list_add(newpkg->optdepends, strdup(ptr)); + alpm_depend_t *optdep = _alpm_splitdep(ptr); + newpkg->optdepends = alpm_list_add(newpkg->optdepends, optdep); } else if(strcmp(key, "conflict") == 0) { alpm_depend_t *conflict = _alpm_splitdep(ptr); newpkg->conflicts = alpm_list_add(newpkg->conflicts, conflict); diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c index b7b2acd..c403203 100644 --- a/lib/libalpm/be_sync.c +++ b/lib/libalpm/be_sync.c @@ -566,7 +566,7 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive, } else if(strcmp(line, "%DEPENDS%") == 0) { READ_AND_SPLITDEP(pkg->depends); } else if(strcmp(line, "%OPTDEPENDS%") == 0) { - READ_AND_STORE_ALL(pkg->optdepends); + READ_AND_SPLITDEP(pkg->optdepends); } else if(strcmp(line, "%CONFLICTS%") == 0) { READ_AND_SPLITDEP(pkg->conflicts); } else if(strcmp(line, "%PROVIDES%") == 0) { diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index f66c307..5b07563 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -522,7 +522,7 @@ int _alpm_pkg_dup(alpm_pkg_t *pkg, alpm_pkg_t **new_ptr) newpkg->backup = alpm_list_add(newpkg->backup, _alpm_backup_dup(i->data)); } newpkg->depends = list_depdup(pkg->depends); - newpkg->optdepends = alpm_list_strdup(pkg->optdepends); + newpkg->optdepends = list_depdup(pkg->optdepends); newpkg->conflicts = list_depdup(pkg->conflicts); newpkg->provides = list_depdup(pkg->provides); for(i = pkg->deltas; i; i = i->next) { @@ -597,7 +597,7 @@ void _alpm_pkg_free(alpm_pkg_t *pkg) alpm_list_free_inner(pkg->backup, (alpm_list_fn_free)_alpm_backup_free); alpm_list_free(pkg->backup); free_deplist(pkg->depends); - FREELIST(pkg->optdepends); + free_deplist(pkg->optdepends); free_deplist(pkg->conflicts); free_deplist(pkg->provides); alpm_list_free_inner(pkg->deltas, (alpm_list_fn_free)_alpm_delta_free); diff --git a/src/pacman/package.c b/src/pacman/package.c index bef91e2..54c035c 100644 --- a/src/pacman/package.c +++ b/src/pacman/package.c @@ -38,7 +38,6 @@ /** Turn a depends list into a text list. * @param deps a list with items of type alpm_depend_t - * @return a string list, must be freed */ static void deplist_display(const char *title, alpm_list_t *deps) @@ -52,6 +51,21 @@ static void deplist_display(const char *title, FREELIST(text); } +/** Turn a optdepends list into a text list. + * @param optdeps a list with items of type alpm_optdepend_t + */ +static void optdeplist_display(const char *title, + alpm_list_t *optdeps) +{ + alpm_list_t *i, *text = NULL; + for(i = optdeps; i; i = alpm_list_next(i)) { + alpm_depend_t *optdep = i->data; + text = alpm_list_add(text, alpm_dep_compute_string(optdep)); + } + list_display_linebreak(title, text); + FREELIST(text); +} + /** * Display the details of a package. * Extra information entails 'required by' info for sync packages and backup @@ -111,7 +125,7 @@ void dump_pkg_full(alpm_pkg_t *pkg, int extra) list_display(_("Groups :"), alpm_pkg_get_groups(pkg)); deplist_display(_("Provides :"), alpm_pkg_get_provides(pkg)); deplist_display(_("Depends On :"), alpm_pkg_get_depends(pkg)); - list_display_linebreak(_("Optional Deps :"), alpm_pkg_get_optdepends(pkg)); + optdeplist_display(_("Optional Deps :"), alpm_pkg_get_optdepends(pkg)); if(extra || from == PKG_FROM_LOCALDB) { list_display(_("Required By :"), requiredby); } diff --git a/src/pacman/util.c b/src/pacman/util.c index 1d9049e..7be3dc5 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -1151,32 +1151,87 @@ void print_packages(const alpm_list_t *packages) } } -/* Helper function for comparing strings using the - * alpm "compare func" signature */ -int str_cmp(const void *s1, const void *s2) +/** + * Helper function for comparing depends using the alpm "compare func" + * signature. The function descends through the structure in the following + * comparison order: name, modifier (e.g., '>', '='), version, description. + * @param d1 the first depend structure + * @param d2 the second depend structure + * @return -1, 0, or 1 if first is <, ==, or > second + */ +static int depend_cmp(const void *d1, const void *d2) { - return strcmp(s1, s2); + const alpm_depend_t *dep1 = d1; + const alpm_depend_t *dep2 = d2; + int ret; + + ret = strcmp(dep1->name, dep2->name); + if(ret == 0) { + ret = dep1->mod - dep2->mod; + } + if(ret == 0) { + if(dep1->version && dep2->version) { + ret = strcmp(dep1->version, dep2->version); + } else if(!dep1->version && dep2->version) { + ret = -1; + } else if(dep1->version && !dep2->version) { + ret = 1; + } + } + if(ret == 0) { + if(dep1->desc && dep2->desc) { + ret = strcmp(dep1->desc, dep2->desc); + } else if(!dep1->desc && dep2->desc) { + ret = -1; + } else if(dep1->desc && !dep2->desc) { + ret = 1; + } + } + + return ret; } void display_new_optdepends(alpm_pkg_t *oldpkg, alpm_pkg_t *newpkg) { - alpm_list_t *old = alpm_pkg_get_optdepends(oldpkg); - alpm_list_t *new = alpm_pkg_get_optdepends(newpkg); - alpm_list_t *optdeps = alpm_list_diff(new,old,str_cmp); - if(optdeps) { + alpm_list_t *i, *old, *new, *optdeps, *optstrings = NULL; + + old = alpm_pkg_get_optdepends(oldpkg); + new = alpm_pkg_get_optdepends(newpkg); + optdeps = alpm_list_diff(new, old, depend_cmp); + + /* turn optdepends list into a text list */ + for(i = optdeps; i; i = alpm_list_next(i)) { + alpm_depend_t *optdep = i->data; + optstrings = alpm_list_add(optstrings, alpm_dep_compute_string(optdep)); + } + + if(optstrings) { printf(_("New optional dependencies for %s\n"), alpm_pkg_get_name(newpkg)); - list_display_linebreak(" ", optdeps); + list_display_linebreak(" ", optstrings); } + alpm_list_free(optdeps); + FREELIST(optstrings); } void display_optdepends(alpm_pkg_t *pkg) { - alpm_list_t *optdeps = alpm_pkg_get_optdepends(pkg); - if(optdeps) { + alpm_list_t *i, *optdeps, *optstrings = NULL; + + optdeps = alpm_pkg_get_optdepends(pkg); + + /* turn optdepends list into a text list */ + for(i = optdeps; i; i = alpm_list_next(i)) { + alpm_depend_t *optdep = i->data; + optstrings = alpm_list_add(optstrings, alpm_dep_compute_string(optdep)); + } + + if(optstrings) { printf(_("Optional dependencies for %s\n"), alpm_pkg_get_name(pkg)); - list_display_linebreak(" ", optdeps); + list_display_linebreak(" ", optstrings); } + + FREELIST(optstrings); } static void display_repo_list(const char *dbname, alpm_list_t *list) -- 1.7.9.3
participants (1)
-
Dan McGee