Line data Source code
1 : /*-
2 : * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
3 : * Copyright (c) 2013 Matthew Seaman <matthew@FreeBSD.org>
4 : * Copyright (c) 2012-2013 Bryan Drewery <bdrewery@FreeBSD.org>
5 : * All rights reserved.
6 : *
7 : * Redistribution and use in source and binary forms, with or without
8 : * modification, are permitted provided that the following conditions
9 : * are met:
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer
12 : * in this position and unchanged.
13 : * 2. Redistributions in binary form must reproduce the above copyright
14 : * notice, this list of conditions and the following disclaimer in the
15 : * documentation and/or other materials provided with the distribution.
16 : *
17 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
18 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 : * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
21 : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 : */
28 :
29 : #include <err.h>
30 : #include <getopt.h>
31 : #include <stdio.h>
32 : #include <sysexits.h>
33 : #include <unistd.h>
34 :
35 : #include <pkg.h>
36 :
37 : #include "pkgcli.h"
38 :
39 : void
40 0 : usage_upgrade(void)
41 : {
42 0 : fprintf(stderr, "Usage: pkg upgrade [-fInFqUy] [-r reponame] [-Cgix] <pkg-name> ...\n\n");
43 0 : fprintf(stderr, "For more information see 'pkg help upgrade'.\n");
44 0 : }
45 :
46 : int
47 3 : exec_upgrade(int argc, char **argv)
48 : {
49 3 : struct pkgdb *db = NULL;
50 3 : struct pkg_jobs *jobs = NULL;
51 3 : const char *reponame = NULL;
52 : int retcode;
53 : int updcode;
54 : int ch;
55 3 : int lock_type = PKGDB_LOCK_ADVISORY;
56 3 : match_t match = MATCH_EXACT;
57 3 : int done = 0;
58 3 : bool rc = true;
59 3 : pkg_flags f = PKG_FLAG_NONE | PKG_FLAG_PKG_VERSION_TEST;
60 :
61 3 : struct option longopts[] = {
62 : { "case-sensitive", no_argument, NULL, 'C' },
63 : { "force", no_argument, NULL, 'f' },
64 : { "fetch-only", no_argument, NULL, 'F' },
65 : { "glob", no_argument, NULL, 'g' },
66 : { "case-insensitive", no_argument, NULL, 'i' },
67 : { "no-install-scripts", no_argument, NULL, 'I' },
68 : { "dry-run", no_argument, NULL, 'n' },
69 : { "quiet", no_argument, NULL, 'q' },
70 : { "repository", required_argument, NULL, 'r' },
71 : { "no-repo-update", no_argument, NULL, 'U' },
72 : { "regex", no_argument, NULL, 'x' },
73 : { "yes", no_argument, NULL, 'y' },
74 : { NULL, 0, NULL, 0 },
75 : };
76 :
77 3 : nbactions = nbdone = 0;
78 :
79 10 : while ((ch = getopt_long(argc, argv, "+CfFgiInqr:Uxy", longopts, NULL)) != -1) {
80 4 : switch (ch) {
81 : case 'C':
82 0 : pkgdb_set_case_sensitivity(true);
83 0 : break;
84 : case 'f':
85 0 : f |= PKG_FLAG_FORCE;
86 0 : break;
87 : case 'F':
88 0 : f |= PKG_FLAG_SKIP_INSTALL;
89 0 : lock_type = PKGDB_LOCK_READONLY;
90 0 : break;
91 : case 'g':
92 0 : match = MATCH_GLOB;
93 0 : break;
94 : case 'i':
95 0 : pkgdb_set_case_sensitivity(false);
96 0 : break;
97 : case 'I':
98 0 : f |= PKG_FLAG_NOSCRIPT;
99 0 : break;
100 : case 'n':
101 2 : f |= PKG_FLAG_DRY_RUN;
102 2 : lock_type = PKGDB_LOCK_READONLY;
103 2 : dry_run = true;
104 2 : break;
105 : case 'q':
106 0 : quiet = true;
107 0 : break;
108 : case 'r':
109 0 : reponame = optarg;
110 0 : break;
111 : case 'U':
112 0 : auto_update = false;
113 0 : break;
114 : case 'x':
115 0 : match = MATCH_REGEX;
116 0 : break;
117 : case 'y':
118 2 : yes = true;
119 2 : break;
120 : default:
121 0 : usage_upgrade();
122 0 : return (EX_USAGE);
123 : /* NOTREACHED */
124 : }
125 : }
126 3 : argc -= optind;
127 3 : argv += optind;
128 :
129 3 : if (dry_run && !auto_update)
130 0 : retcode = pkgdb_access(PKGDB_MODE_READ,
131 : PKGDB_DB_LOCAL|PKGDB_DB_REPO);
132 : else
133 3 : retcode = pkgdb_access(PKGDB_MODE_READ |
134 : PKGDB_MODE_WRITE |
135 : PKGDB_MODE_CREATE,
136 : PKGDB_DB_LOCAL|PKGDB_DB_REPO);
137 3 : if (retcode == EPKG_ENOACCESS && dry_run) {
138 0 : auto_update = false;
139 0 : retcode = pkgdb_access(PKGDB_MODE_READ,
140 : PKGDB_DB_LOCAL|PKGDB_DB_REPO);
141 : }
142 :
143 3 : if (retcode == EPKG_ENOACCESS) {
144 0 : warnx("Insufficient privilege to upgrade packages");
145 0 : return (EX_NOPERM);
146 3 : } else if (retcode != EPKG_OK)
147 0 : return (EX_IOERR);
148 : else
149 3 : retcode = EX_SOFTWARE;
150 :
151 : /* first update the remote repositories if needed */
152 3 : if (auto_update &&
153 : (updcode = pkgcli_update(false, false, reponame)) != EPKG_OK)
154 0 : return (updcode);
155 :
156 3 : if (pkgdb_open_all(&db, PKGDB_REMOTE, reponame) != EPKG_OK)
157 0 : return (EX_IOERR);
158 :
159 3 : if (pkgdb_obtain_lock(db, lock_type) != EPKG_OK) {
160 0 : pkgdb_close(db);
161 0 : warnx("Cannot get an advisory lock on a database, it is locked by another process");
162 0 : return (EX_TEMPFAIL);
163 : }
164 :
165 3 : if (pkg_jobs_new(&jobs, PKG_JOBS_UPGRADE, db) != EPKG_OK)
166 0 : goto cleanup;
167 :
168 3 : if (reponame != NULL && pkg_jobs_set_repository(jobs, reponame) != EPKG_OK)
169 0 : goto cleanup;
170 :
171 3 : pkg_jobs_set_flags(jobs, f);
172 :
173 3 : if (argc > 0)
174 0 : if (pkg_jobs_add(jobs, match, argv, argc) == EPKG_FATAL)
175 0 : goto cleanup;
176 :
177 3 : if (pkg_jobs_solve(jobs) != EPKG_OK)
178 0 : goto cleanup;
179 :
180 6 : while ((nbactions = pkg_jobs_count(jobs)) > 0) {
181 : /* print a summary before applying the jobs */
182 3 : rc = yes;
183 3 : if (!quiet || dry_run) {
184 3 : print_jobs_summary(jobs,
185 : "The following %d package(s) will be affected (of %d checked):\n\n",
186 : nbactions, pkg_jobs_total(jobs));
187 :
188 3 : if (!dry_run)
189 1 : rc = query_yesno(false, "\nProceed with this "
190 : "action? ");
191 : else
192 2 : rc = false;
193 : }
194 :
195 3 : if (rc) {
196 1 : retcode = pkg_jobs_apply(jobs);
197 1 : done = 1;
198 1 : if (retcode == EPKG_CONFLICT) {
199 0 : printf("Conflicts with the existing packages "
200 : "have been found.\nOne more solver "
201 : "iteration is needed to resolve them.\n");
202 0 : continue;
203 : }
204 1 : else if (retcode != EPKG_OK)
205 0 : goto cleanup;
206 : }
207 :
208 3 : if (messages != NULL) {
209 0 : sbuf_finish(messages);
210 0 : printf("%s", sbuf_data(messages));
211 : }
212 3 : break;
213 : }
214 :
215 3 : if (done == 0 && rc)
216 0 : printf("Your packages are up to date.\n");
217 :
218 3 : retcode = EX_OK;
219 :
220 : cleanup:
221 3 : pkg_jobs_free(jobs);
222 3 : pkgdb_release_lock(db, lock_type);
223 3 : pkgdb_close(db);
224 :
225 3 : if (!dry_run)
226 1 : pkg_cache_full_clean();
227 :
228 3 : if (!rc && newpkgversion)
229 0 : newpkgversion = false;
230 :
231 3 : return (retcode);
232 : }
|