Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Merge branch 'upgrade-rework'
Vsevolod Stakhov committed 12 years ago
commit e495c6fe02896b73e382fc25afb142a5047374d6
parent 0773d4a
5 files changed +180 -105
modified docs/pkg-install.8
@@ -15,7 +15,7 @@
.\"     @(#)pkg.8
.\" $FreeBSD$
.\"
-
.Dd April 18, 2014
+
.Dd May 05, 2014
.Dt PKG-INSTALL 8
.Os
.Sh NAME
@@ -26,13 +26,13 @@
.Op Fl AfIMnFqRUy
.Op Fl r Ar reponame
.Op Fl Cgix
-
.Ar pkg-origin ...
+
.Ar <pkg-origin|pkg-name|pkg-name-version> ...
.Sh DESCRIPTION
.Nm
is used for installation of packages from a package repository or
local archives.
Multiple package names can be specified on the command line, either
-
explicitly or by matching against package names in the repository
+
explicitly or by matching against package names (or origins) in the repository
catalogues using shell globbing or regular expressions.
.Pp
.Nm
modified docs/pkg-upgrade.8
@@ -15,7 +15,7 @@
.\"     @(#)pkg.8
.\" $FreeBSD$
.\"
-
.Dd April 18, 2014
+
.Dd May 05, 2014
.Dt PKG-UPGRADE 8
.Os
.Sh NAME
@@ -25,14 +25,26 @@
.Nm
.Op Fl fInFqUy
.Op Fl r Ar reponame
+
.Op Fl Cgix
+
.Op Ar <pkg-origin|pkg-name|pkg-name-version> ...
.Sh DESCRIPTION
.Nm
is used for upgrading packaged software distributions.
.Pp
.Nm
-
compares the versions of all of the packages installed on the system
+
compares the versions of all or specific packages installed on the system
to what is available in the configured package repositories.
Any out-of-date packages are added to a work list for processing.
+
The difference to 
+
.Xr pkg-install 8
+
is that
+
.Nm
+
tries to upgrade dependencies of packages matched as well while
+
.Xr pkg-install 8
+
is more conservative during dependencies upgrade. Moreover,
+
.Nm
+
cannot install new packages, so a caller should ensure that patterns specified
+
as arguments have installed candidates for matching.
If the
.Fl f
(force) flag is given, all installed packages are added to the work
@@ -136,6 +148,26 @@ status from
.Pa repo.conf .
.It Fl y
Assume yes when asked for confirmation before package installation.
+
.It Fl C
+
Make the standard or the regular expression
+
.Fl ( x )
+
matching against
+
.Ar pkg-name
+
case sensitive.
+
.It Fl f
+
Force the reinstallation of the package if already installed.
+
.It Fl g
+
Treat the package names as shell glob patterns.
+
.It Fl i
+
Make the standard or the regular expression
+
.Fl ( x )
+
matching against
+
.Ar pkg-name
+
case insensitive.
+
This is the default, unless modified by setting
+
.Ev CASE_SENSITIVE_MATCH
+
to true in
+
.Pa pkg.conf .
.El
.Sh ENVIRONMENT
The following environment variables affect the execution of
modified libpkg/pkg_jobs.c
@@ -1019,6 +1019,29 @@ find_remote_pkg(struct pkg_jobs *j, const char *pattern,
}

static int
+
pkg_jobs_check_local_pkg(struct pkg_jobs *j, struct job_pattern *jp)
+
{
+
	struct pkgdb_it *it;
+
	struct pkg *pkg = NULL;
+
	int rc = EPKG_OK;
+

+
	it = pkgdb_query(j->db, jp->pattern, jp->match);
+
	if (it != NULL) {
+
		if (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC) != EPKG_OK)
+
			rc = EPKG_FATAL;
+
		else
+
			pkg_free(pkg);
+

+
		pkgdb_it_free(it);
+
	}
+
	else {
+
		rc = EPKG_FATAL;
+
	}
+

+
	return (rc);
+
}
+

+
static int
pkg_jobs_find_remote_pattern(struct pkg_jobs *j, struct job_pattern *jp,
		bool *got_local)
{
@@ -1026,8 +1049,21 @@ pkg_jobs_find_remote_pattern(struct pkg_jobs *j, struct job_pattern *jp,
	struct pkg *pkg = NULL;
	struct pkg_manifest_key *keys = NULL;
	struct pkg_job_universe_item *unit;
+
	struct job_pattern jfp;
+
	const char *pkgname;

	if (!jp->is_file) {
+
		if (j->type == PKG_JOBS_UPGRADE) {
+
			/*
+
			 * For upgrade patterns we must ensure that a local package is
+
			 * installed as well.
+
			 */
+
			if (pkg_jobs_check_local_pkg (j, jp) != EPKG_OK) {
+
				pkg_emit_error("%s is not installed, therefore upgrade is impossible",
+
						jp->pattern);
+
				return (EPKG_FATAL);
+
			}
+
		}
		rc = find_remote_pkg(j, jp->pattern, jp->match, true, true, true);
		*got_local = false;
	}
@@ -1036,6 +1072,17 @@ pkg_jobs_find_remote_pattern(struct pkg_jobs *j, struct job_pattern *jp,
		if (pkg_open(&pkg, jp->path, keys, PKG_OPEN_MANIFEST_ONLY) != EPKG_OK)
			rc = EPKG_FATAL;
		else {
+
			if (j->type == PKG_JOBS_UPGRADE) {
+
				pkg_get(pkg, PKG_NAME, &pkgname);
+
				jfp.match = MATCH_EXACT;
+
				jfp.pattern = __DECONST(char *, pkgname);
+
				if (pkg_jobs_check_local_pkg (j, &jfp) != EPKG_OK) {
+
					pkg_emit_error("%s is not installed, therefore upgrade is impossible",
+
							jfp.pattern);
+
					pkg_manifest_keys_free(keys);
+
					return (EPKG_FATAL);
+
				}
+
			}
			pkg->type = PKG_FILE;
			rc = pkg_jobs_process_remote_pkg(j, pkg, true,
					j->flags & PKG_FLAG_FORCE, false, &unit, true);
@@ -1632,12 +1679,14 @@ jobs_solve_autoremove(struct pkg_jobs *j)
}

static int
-
jobs_solve_upgrade(struct pkg_jobs *j)
+
jobs_solve_install_upgrade(struct pkg_jobs *j)
{
	struct pkg *pkg = NULL;
	struct pkgdb_it *it;
	char *origin;
-
	bool automatic;
+
	bool automatic, got_local;
+
	struct job_pattern *jp, *jtmp;
+
	struct pkg_job_request *req, *rtmp;
	unsigned flags = PKG_LOAD_BASIC|PKG_LOAD_OPTIONS|PKG_LOAD_DEPS|
			PKG_LOAD_SHLIBS_REQUIRED|PKG_LOAD_ANNOTATIONS|PKG_LOAD_CONFLICTS;

@@ -1647,73 +1696,44 @@ jobs_solve_upgrade(struct pkg_jobs *j)
			goto order;
		}

-
	if (j->solved == 0) {
-
		if ((it = pkgdb_query(j->db, NULL, MATCH_ALL)) == NULL)
-
			return (EPKG_FATAL);
-

-
		while (pkgdb_it_next(it, &pkg, flags) == EPKG_OK) {
-
			/* TODO: use repository priority here */
-
			pkg_jobs_add_universe(j, pkg, true, false, NULL);
-
			pkg_get(pkg, PKG_ORIGIN, &origin, PKG_AUTOMATIC, &automatic);
-
			/* Do not test we ignore what doesn't exists remotely */
-
			find_remote_pkg(j, origin, MATCH_EXACT, false, true, !automatic);
-
			pkg = NULL;
-
		}
-
		pkgdb_it_free(it);
-
	}
-
	else {
-
		/*
-
		 * If we have tried to solve request, then we just want to re-add all
-
		 * request packages to the universe to find out any potential conflicts
-
		 */
-
		struct pkg_job_request *req, *rtmp;
-
		HASH_ITER(hh, j->request_add, req, rtmp) {
-
			pkg_jobs_add_universe(j, req->item->pkg, true, false, NULL);
-
		}
-
	}
-

-
	if (pkg_conflicts_request_resolve(j) != EPKG_OK) {
-
		pkg_emit_error("Cannot resolve conflicts in a request");
+
	if (j->patterns == NULL && j->type == PKG_JOBS_INSTALL) {
+
		pkg_emit_error("no patterns are specified for install job");
		return (EPKG_FATAL);
	}

-
	pkg_jobs_propagate_automatic(j);
-

-
order:
-

-
	j->solved ++;
-

-
	return (EPKG_OK);
-
}
-

-
static int
-
jobs_solve_install(struct pkg_jobs *j)
-
{
-
	struct job_pattern *jp, *jtmp;
-
	struct pkg_job_request *req, *rtmp;
-
	bool got_local;
-

-
	if ((j->flags & PKG_FLAG_PKG_VERSION_TEST) == PKG_FLAG_PKG_VERSION_TEST) {
-
		if (new_pkg_version(j)) {
-
			pkg_emit_newpkgversion();
-
			goto order;
-
		}
-
	}
-

	if (j->solved == 0) {
-
		HASH_ITER(hh, j->patterns, jp, jtmp) {
-
			if (pkg_jobs_find_remote_pattern(j, jp, &got_local) == EPKG_FATAL) {
-
				pkg_emit_error("No packages matching '%s' have been found in the "
-
						"repositories", jp->pattern);
+
		if (j->patterns == NULL) {
+
			if ((it = pkgdb_query(j->db, NULL, MATCH_ALL)) == NULL)
				return (EPKG_FATAL);
+

+
			while (pkgdb_it_next(it, &pkg, flags) == EPKG_OK) {
+
				/* TODO: use repository priority here */
+
				pkg_jobs_add_universe(j, pkg, true, false, NULL);
+
				pkg_get(pkg, PKG_ORIGIN, &origin, PKG_AUTOMATIC, &automatic);
+
				/* Do not test we ignore what doesn't exists remotely */
+
				find_remote_pkg(j, origin, MATCH_EXACT, false, true, !automatic);
+
				pkg = NULL;
			}
+
			pkgdb_it_free(it);
		}
-
		if (got_local) {
-
			/*
-
			 * Need to iterate request one more time to recurse depends
-
			 */
-
			HASH_ITER(hh, j->request_add, req, rtmp) {
-
				pkg_jobs_add_universe(j, req->item->pkg, true, true, NULL);
+
		else {
+
			HASH_ITER(hh, j->patterns, jp, jtmp) {
+
				if (pkg_jobs_find_remote_pattern(j, jp, &got_local) == EPKG_FATAL) {
+
					pkg_emit_error("No packages available to %s matching '%s' "
+
							"have been found in the "
+
							"repositories",
+
							(j->type == PKG_JOBS_UPGRADE) ? "upgrade" : "install",
+
							jp->pattern);
+
					return (EPKG_FATAL);
+
				}
+
			}
+
			if (got_local) {
+
				/*
+
				 * Need to iterate request one more time to recurse depends
+
				 */
+
				HASH_ITER(hh, j->request_add, req, rtmp) {
+
					pkg_jobs_add_universe(j, req->item->pkg, true, true, NULL);
+
				}
			}
		}
	}
@@ -1802,10 +1822,8 @@ pkg_jobs_solve(struct pkg_jobs *j)
		ret = jobs_solve_deinstall(j);
		break;
	case PKG_JOBS_UPGRADE:
-
		ret = jobs_solve_upgrade(j);
-
		break;
	case PKG_JOBS_INSTALL:
-
		ret = jobs_solve_install(j);
+
		ret = jobs_solve_install_upgrade(j);
		break;
	case PKG_JOBS_FETCH:
		ret = jobs_solve_fetch(j);
@@ -1854,7 +1872,7 @@ pkg_jobs_solve(struct pkg_jobs *j)
						j->solved = 0;
					}
					else {
-
						ret = pkg_solve_sat_to_jobs(problem, j);
+
						ret = pkg_solve_sat_to_jobs(problem);
					}
				}
			}
modified libpkg/pkg_solve.c
@@ -76,6 +76,7 @@ struct pkg_solve_rule {
};

struct pkg_solve_problem {
+
	struct pkg_jobs *j;
	unsigned int rules_count;
	struct pkg_solve_rule *rules;
	struct pkg_solve_variable *variables_by_origin;
@@ -321,16 +322,24 @@ pkg_solve_test_guess(struct pkg_solve_problem *problem, struct pkg_solve_variabl
 * Set initial guess based on a variable passed
 */
static bool
-
pkg_solve_initial_guess(struct pkg_solve_variable *var)
+
pkg_solve_initial_guess(struct pkg_solve_problem *problem,
+
		struct pkg_solve_variable *var)
{
-
	if (var->unit->pkg->type == PKG_INSTALLED) {
-
		/* For local packages assume true if we have no upgrade */
-
		if (var->unit->next == NULL && var->unit->prev == var->unit)
-
			return (true);
+
	if (problem->j->type == PKG_JOBS_UPGRADE) {
+
		if (var->unit->pkg->type == PKG_INSTALLED) {
+
			/* For local packages assume true if we have no upgrade */
+
			if (var->unit->next == NULL && var->unit->prev == var->unit)
+
				return (true);
+
		}
+
		else {
+
			/* For remote packages we return true if they are upgrades for local ones */
+
			if (var->unit->next != NULL || var->unit->prev != var->unit)
+
				return (true);
+
		}
	}
	else {
-
		/* For remote packages we return true if they are upgrades for local ones */
-
		if (var->unit->next != NULL || var->unit->prev != var->unit)
+
		/* For all non-upgrade jobs be more conservative */
+
		if (var->unit->pkg->type == PKG_INSTALLED)
			return (true);
	}

@@ -399,8 +408,7 @@ pkg_solve_sat_problem(struct pkg_solve_problem *problem)
			assert (var == elt->var);

			if (elt->guess == -1)
-
				/* Guess true for installed packages and false otherwise */
-
				var->guess = pkg_solve_initial_guess(var);
+
				var->guess = pkg_solve_initial_guess(problem, var);
			else
				/* For analyzed variables we can only inverse previous guess */
				var->guess = !elt->guess;
@@ -549,12 +557,13 @@ pkg_solve_problem_free(struct pkg_solve_problem *problem)
}

static int
-
pkg_solve_add_universe_variable(struct pkg_jobs *j,
-
		struct pkg_solve_problem *problem, const char *origin, struct pkg_solve_variable **var)
+
pkg_solve_add_universe_variable(struct pkg_solve_problem *problem,
+
		const char *origin, struct pkg_solve_variable **var)
{
	struct pkg_job_universe_item *unit, *cur;
	struct pkg_solve_variable *nvar, *tvar = NULL, *found;
	const char *digest;
+
	struct pkg_jobs *j = problem->j;

	HASH_FIND_STR(j->universe, origin, unit);
	/* If there is no package in universe, refuse continue */
@@ -640,7 +649,7 @@ pkg_solve_add_var_rules (struct pkg_solve_variable *var,
} while (0)

static int
-
pkg_solve_handle_provide (struct pkg_jobs *j, struct pkg_solve_problem *problem,
+
pkg_solve_handle_provide (struct pkg_solve_problem *problem,
		struct pkg_job_provide *pr, struct pkg_solve_rule *rule, int *cnt)
{
	struct pkg_solve_item *it = NULL;
@@ -661,7 +670,8 @@ pkg_solve_handle_provide (struct pkg_jobs *j, struct pkg_solve_problem *problem,
		HASH_FIND(hd, problem->variables_by_digest, digest,
				strlen(digest), var);
		if (var == NULL) {
-
			if (pkg_solve_add_universe_variable(j, problem, origin, &var) != EPKG_OK)
+
			if (pkg_solve_add_universe_variable(problem, origin,
+
					&var) != EPKG_OK)
				continue;
		}
		/* Check if we have the specified require provided by this package */
@@ -682,7 +692,7 @@ pkg_solve_handle_provide (struct pkg_jobs *j, struct pkg_solve_problem *problem,
}

static int
-
pkg_solve_add_pkg_rule(struct pkg_jobs *j, struct pkg_solve_problem *problem,
+
pkg_solve_add_pkg_rule(struct pkg_solve_problem *problem,
		struct pkg_solve_variable *pvar, bool conflicting)
{
	struct pkg_dep *dep, *dtmp;
@@ -694,6 +704,7 @@ pkg_solve_add_pkg_rule(struct pkg_jobs *j, struct pkg_solve_problem *problem,
	struct pkg_shlib *shlib = NULL;
	struct pkg_job_provide *pr, *prhead;
	int cnt;
+
	struct pkg_jobs *j = problem->j;

	const char *origin;

@@ -708,7 +719,7 @@ pkg_solve_add_pkg_rule(struct pkg_jobs *j, struct pkg_solve_problem *problem,
			origin = pkg_dep_get(dep, PKG_DEP_ORIGIN);
			HASH_FIND(ho, problem->variables_by_origin, origin, strlen(origin), var);
			if (var == NULL) {
-
				if (pkg_solve_add_universe_variable(j, problem, origin, &var) != EPKG_OK)
+
				if (pkg_solve_add_universe_variable(problem, origin, &var) != EPKG_OK)
					continue;
			}
			/* Dependency rule: (!A | B) */
@@ -749,7 +760,7 @@ pkg_solve_add_pkg_rule(struct pkg_jobs *j, struct pkg_solve_problem *problem,
			origin = pkg_conflict_origin(conflict);
			HASH_FIND(ho, problem->variables_by_origin, origin, strlen(origin), var);
			if (var == NULL) {
-
				if (pkg_solve_add_universe_variable(j, problem, origin, &var) != EPKG_OK)
+
				if (pkg_solve_add_universe_variable(problem, origin, &var) != EPKG_OK)
					continue;
			}
			/* Return the origin to the package's origin and not conflict */
@@ -826,7 +837,7 @@ pkg_solve_add_pkg_rule(struct pkg_jobs *j, struct pkg_solve_problem *problem,
					/* B1 | B2 | ... */
					cnt = 1;
					LL_FOREACH(prhead, pr) {
-
						if (pkg_solve_handle_provide (j, problem, pr, rule,
+
						if (pkg_solve_handle_provide (problem, pr, rule,
								&cnt) != EPKG_OK)
							goto err;
					}
@@ -906,8 +917,7 @@ err:
}

static int
-
pkg_solve_add_universe_item(struct pkg_jobs *j,
-
		struct pkg_job_universe_item *un,
+
pkg_solve_add_universe_item(struct pkg_job_universe_item *un,
		struct pkg_solve_problem *problem)
{
	struct pkg_job_universe_item *ucur;
@@ -944,7 +954,7 @@ pkg_solve_add_universe_item(struct pkg_jobs *j,
	}
	HASH_FIND(ho, problem->variables_by_origin, origin, strlen(origin), var);
	/* Now `var' contains a variables chain related to this origin */
-
	if (pkg_solve_add_pkg_rule(j, problem, var, true) == EPKG_FATAL)
+
	if (pkg_solve_add_pkg_rule(problem, var, true) == EPKG_FATAL)
		return (EPKG_FATAL);

	return (EPKG_OK);
@@ -968,6 +978,8 @@ pkg_solve_jobs_to_sat(struct pkg_jobs *j)
		return (NULL);
	}

+
	problem->j = j;
+

	/* Add requests */
	HASH_ITER(hh, j->request_add, jreq, jtmp) {
		if (jreq->skip)
@@ -977,7 +989,7 @@ pkg_solve_jobs_to_sat(struct pkg_jobs *j)
		it = NULL;
		var = NULL;

-
		if (pkg_solve_add_universe_item(j, jreq->item, problem) == EPKG_FATAL)
+
		if (pkg_solve_add_universe_item(jreq->item, problem) == EPKG_FATAL)
			goto err;

		pkg_get(jreq->item->pkg, PKG_DIGEST, &digest);
@@ -1013,7 +1025,7 @@ pkg_solve_jobs_to_sat(struct pkg_jobs *j)
		it = NULL;
		var = NULL;

-
		if (pkg_solve_add_universe_item(j, jreq->item, problem) == EPKG_FATAL)
+
		if (pkg_solve_add_universe_item(jreq->item, problem) == EPKG_FATAL)
			goto err;

		pkg_get(jreq->item->pkg, PKG_DIGEST, &digest);
@@ -1051,7 +1063,7 @@ pkg_solve_jobs_to_sat(struct pkg_jobs *j)
		var = NULL;

		/* Add corresponding variables */
-
		if (pkg_solve_add_universe_item(j, un, problem) == EPKG_FATAL)
+
		if (pkg_solve_add_universe_item(un, problem) == EPKG_FATAL)
			goto err;
	}

@@ -1109,11 +1121,12 @@ pkg_solve_dimacs_export(struct pkg_solve_problem *problem, FILE *f)

static void
pkg_solve_insert_res_job (struct pkg_solve_variable *var,
-
		struct pkg_solve_problem *problem, struct pkg_jobs *j)
+
		struct pkg_solve_problem *problem)
{
	struct pkg_solved *res;
	struct pkg_solve_variable *cur_var, *del_var = NULL, *add_var = NULL;
	int seen_add = 0, seen_del = 0;
+
	struct pkg_jobs *j = problem->j;

	LL_FOREACH(var, cur_var) {
		if (cur_var->to_install && cur_var->unit->pkg->type != PKG_INSTALLED) {
@@ -1168,7 +1181,7 @@ pkg_solve_insert_res_job (struct pkg_solve_variable *var,
}

int
-
pkg_solve_sat_to_jobs(struct pkg_solve_problem *problem, struct pkg_jobs *j)
+
pkg_solve_sat_to_jobs(struct pkg_solve_problem *problem)
{
	struct pkg_solve_variable *var, *vtmp;

@@ -1177,7 +1190,7 @@ pkg_solve_sat_to_jobs(struct pkg_solve_problem *problem, struct pkg_jobs *j)
			return (EPKG_FATAL);

		pkg_debug(4, "solver: check variable with origin %s", var->origin);
-
		pkg_solve_insert_res_job(var, problem, j);
+
		pkg_solve_insert_res_job(var, problem);
	}

	return (EPKG_OK);
@@ -1255,7 +1268,7 @@ pkg_solve_parse_sat_output(FILE *f, struct pkg_solve_problem *problem, struct pk
	}

	if (done)
-
		ret = pkg_solve_sat_to_jobs(problem, j);
+
		ret = pkg_solve_sat_to_jobs(problem);
	else {
		pkg_emit_error("cannot parse sat solver output");
		ret = EPKG_FATAL;
modified src/upgrade.c
@@ -38,7 +38,7 @@
void
usage_upgrade(void)
{
-
	fprintf(stderr, "Usage: pkg upgrade [-fInFqUy] [-r reponame]\n\n");
+
	fprintf(stderr, "Usage: pkg upgrade [-fInFqUy] [-r reponame] [-Cgix] <pkg-name> ...\n\n");
	fprintf(stderr, "For more information see 'pkg help upgrade'.\n");
}

@@ -52,6 +52,7 @@ exec_upgrade(int argc, char **argv)
	int updcode;
	int ch;
	int lock_type = PKGDB_LOCK_ADVISORY;
+
	match_t match = MATCH_EXACT;
	bool yes = true, yes_arg = false;
	bool dry_run = false;
	bool auto_update;
@@ -62,7 +63,7 @@ exec_upgrade(int argc, char **argv)
	yes_arg = pkg_object_bool(pkg_config_get("ASSUME_ALWAYS_YES"));
	auto_update = pkg_object_bool(pkg_config_get("REPO_AUTOUPDATE"));

-
	while ((ch = getopt(argc, argv, "fInqFr:Uy")) != -1) {
+
	while ((ch = getopt(argc, argv, "fInqFr:UyCgix")) != -1) {
		switch (ch) {
		case 'f':
			f |= PKG_FLAG_FORCE;
@@ -70,6 +71,15 @@ exec_upgrade(int argc, char **argv)
		case 'I':
			f |= PKG_FLAG_NOSCRIPT;
			break;
+
		case 'C':
+
			pkgdb_set_case_sensitivity(true);
+
			break;
+
		case 'g':
+
			match = MATCH_GLOB;
+
			break;
+
		case 'i':
+
			pkgdb_set_case_sensitivity(false);
+
			break;
		case 'U':
			auto_update = false;
			break;
@@ -88,6 +98,9 @@ exec_upgrade(int argc, char **argv)
		case 'r':
			reponame = optarg;
			break;
+
		case 'x':
+
			match = MATCH_REGEX;
+
			break;
		case 'y':
			yes_arg = true;
			break;
@@ -100,11 +113,6 @@ exec_upgrade(int argc, char **argv)
	argc -= optind;
	argv += optind;

-
	if (argc != 0) {
-
		usage_upgrade();
-
		return (EX_USAGE);
-
	}
-

	if (dry_run && !auto_update)
		retcode = pkgdb_access(PKGDB_MODE_READ,
				       PKGDB_DB_LOCAL|PKGDB_DB_REPO);
@@ -149,6 +157,10 @@ exec_upgrade(int argc, char **argv)

	pkg_jobs_set_flags(jobs, f);

+
	if (argc > 0)
+
		if (pkg_jobs_add(jobs, match, argv, argc) == EPKG_FATAL)
+
				goto cleanup;
+

	if (pkg_jobs_solve(jobs) != EPKG_OK)
		goto cleanup;