Skip to content

Commit

Permalink
Fix handling of unavailable and preferred packages.
Browse files Browse the repository at this point in the history
During some of the earlier rototilling, the package not available
message was no longer printed for unavailable packages due to changes in
the download code.  This is now fixed, and also differentiates correctly
between packages that are not available, and those that do not match the
requirements stated in preferred.conf.

Use separate functions for install and show-* commands, the former using
the preferred.conf logic, the latter using regular matches to match
local queries and other tools.  This also avoids "not preferred"
messages leaking into show-* output, they belong in trace/debug output.

Abstract away some of the logic that will help in future cleanups, and
improve the output messages.  Upgrades still do not support preferred
matches, this will be fixed in due course.
  • Loading branch information
Jonathan Perkin committed Sep 20, 2018
1 parent f8341b2 commit 9b6b39f
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 38 deletions.
13 changes: 6 additions & 7 deletions impact.c
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ pkg_impact(char **pkgargs, int *rc)
Plisthead *impacthead, *pdphead = NULL;
Pkglist *pimpact, *tmpimpact, *pdp;
char **ppkgargs, *pkgname;
int istty;
int istty, rv;
#ifndef DEBUG
char tmpicon;
#endif
Expand All @@ -369,12 +369,11 @@ pkg_impact(char **pkgargs, int *rc)
/* retreive impact list for all packages listed in the command line */
for (ppkgargs = pkgargs; *ppkgargs != NULL; ppkgargs++) {

/* check if this is a multiple-version package (apache, ...)
* and that the wanted package actually exists. Get pkgname
* from unique_pkg, full package format.
*/
if ((pkgname = unique_pkg(*ppkgargs, REMOTE_PKG)) == NULL) {
/* package is not available in the repository */
if ((rv = find_preferred_pkg(*ppkgargs, &pkgname)) != 0) {
if (pkgname == NULL)
fprintf(stderr, MSG_PKG_NOT_AVAIL, *ppkgargs);
else
fprintf(stderr, MSG_PKG_NOT_PREFERRED, *ppkgargs, pkgname);
*rc = EXIT_FAILURE;
continue;
}
Expand Down
3 changes: 1 addition & 2 deletions messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,7 @@
"there's more than one version available for this package.\n\
please re-run %s with a package name matching one of the following:\n"
#define MSG_PKG_NOT_AVAIL "%s is not available in the repository\n"
#define MSG_PKG_IS_PREFERRED "\rnot choosing %s, %s is preferred\n"
#define MSG_PKG_NOT_INSTALLABLE "\r\n%s is not installable\n"
#define MSG_PKG_NOT_PREFERRED "No %s package available that satisfies preferred match %s\n"
#define MSG_BROKEN_DEP "%s has no dependency in pkg_summary(5), while it's a reverse dependency for %s (missing package in repository ?). Default behaviour is to remove %s. "

/* pkglist.c */
Expand Down
83 changes: 64 additions & 19 deletions pkg_str.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,70 @@

#define GLOBCHARS "{<>[]?*"

/*
* Return list of potential candidates from a package match, or NULL if no
* valid matches are found.
*/
static Plistnumbered *
find_remote_pkgs(const char *pkgname)
{
const char *query;

query = exact_pkgfmt(pkgname) ? UNIQUE_EXACT_PKG : UNIQUE_PKG;

return rec_pkglist(query, REMOTE_PKG, pkgname);
}

/*
* Return best candidate for a remote package, taking into consideration any
* preferred.conf matches.
*
* A return value of -1 indicates no remote packages matched the request. A
* return value of 0 with a NULL result indicates that all remote packages
* failed to pass the preferred.conf requirements. Otherwise 0 is returned
* and result contains the best available package.
*/
int
find_preferred_pkg(const char *pkgname, char **result)
{
Plistnumbered *plist;
Pkglist *p, *pkg = NULL;

*result = NULL;

/* No matching packages available */
if ((plist = find_remote_pkgs(pkgname)) == NULL)
return -1;

/* Find best match */
SLIST_FOREACH(p, plist->P_Plisthead, next) {
/*
* Check that the candidate matches any potential
* preferred.conf restrictions, if not then skip.
*/
if (chk_preferred(p->full, result) != 0)
continue;

/* Save best match */
if (pkg == NULL)
pkg = p;
else if (dewey_cmp(p->version, DEWEY_GT, pkg->version))
pkg = p;
}

if (pkg != NULL) {
/* In case a previous version failed the match */
if (*result != NULL)
free(*result);
*result = xstrdup(pkg->full);
}

free_pkglist(&plist->P_Plisthead);
free(plist);

return (pkg == NULL) ? 1 : 0;
}

/**
* \fn unique_pkg
*
Expand All @@ -39,7 +103,6 @@
char *
unique_pkg(const char *pkgname, const char *dest)
{
uint8_t ispref = 0;
char *u_pkg = NULL;
Plistnumbered *plist;
Pkglist *best_match = NULL, *current;
Expand All @@ -53,19 +116,6 @@ unique_pkg(const char *pkgname, const char *dest)
return NULL;

SLIST_FOREACH(current, plist->P_Plisthead, next) {
/*
* there was a preferred.conf file and the current package
* matches one of the lines
*/
if (chk_preferred(current->full)) {
/*
* package is listed in preferred.conf but the
* version doesn't match requirement
*/
ispref = 1;
continue;
}

/* first result */
if (best_match == NULL)
best_match = current;
Expand All @@ -80,11 +130,6 @@ unique_pkg(const char *pkgname, const char *dest)
free_pkglist(&plist->P_Plisthead);
free(plist);

/* chosen package has no installation candidate */
if (u_pkg == NULL && !ispref)
printf(MSG_PKG_NOT_INSTALLABLE, pkgname);

/* u_pkg might be NULL if a version is preferred and not available */
return u_pkg;
}

Expand Down
3 changes: 2 additions & 1 deletion pkgin.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ uint64_t fs_room(const char *);
void clean_cache(void);
char *read_repos(void);
/* pkg_str.c */
int find_preferred_pkg(const char *, char **);
char *unique_pkg(const char *, const char *);
Pkglist *map_pkg_to_dep(Plisthead *, char *);
uint8_t non_trivial_glob(char *);
Expand Down Expand Up @@ -311,6 +312,6 @@ void pkgindb_stats(void);
/* preferred.c */
void load_preferred(void);
void free_preferred(void);
uint8_t chk_preferred(char *);
uint8_t chk_preferred(char *, char **);

#endif
27 changes: 18 additions & 9 deletions preferred.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,18 +105,27 @@ is_preferred(char *fullpkg)
return NULL;
}

/*
* Given a full package name in "pkg" (e.g. "foo-1.0"), look for any
* corresponding entries for "foo" in preferred.conf and if so check that
* any version requirements are satisfied.
*
* Return 0 if either there are no matches or the requirement is satisfied,
* otherwise return 1. If there is a match it is stored in *matchp.
*/
uint8_t
chk_preferred(char *match)
chk_preferred(char *pkg, char **matchp)
{
char *pref;

if ((pref = is_preferred(match)) != NULL && !pkg_match(pref, match)) {
/*
* package is listed in preferred.conf but the
* version doesn't match requirement
*/
printf(MSG_PKG_IS_PREFERRED, match, pref);
return 1;
if ((pref = is_preferred(pkg)) == NULL) {
/* No matches for pkg in preferred.conf */
*matchp = NULL;
return 0;
}
return 0;

if (*matchp == NULL)
*matchp = xstrdup(pref);

return (pkg_match(pref, pkg) == 0) ? 1 : 0;
}

0 comments on commit 9b6b39f

Please sign in to comment.