Switch pmgrp_t to dynamic allocation, general group cleanup
[pacman-ng.git] / src / pacman / sync.c
blob9e02341dd65dadacefbfc7140701b710828462b2
1 /*
2 * sync.c
4 * Copyright (c) 2002-2007 by Judd Vinet <jvinet@zeroflux.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "config.h"
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <limits.h>
26 #include <unistd.h>
27 #include <dirent.h>
28 #include <sys/stat.h>
30 #include <alpm.h>
31 #include <alpm_list.h>
32 #include <download.h> /* downloadLastErrString */
33 /* TODO remove above download.h inclusion once we abstract more, and also
34 * remove it from Makefile.am on the pacman side */
36 /* pacman */
37 #include "pacman.h"
38 #include "util.h"
39 #include "package.h"
40 #include "callback.h"
41 #include "conf.h"
43 extern pmdb_t *db_local;
45 /* if keep_used != 0, then the dirnames which match an used syncdb
46 * will be kept */
47 static int sync_cleandb(const char *dbpath, int keep_used) {
48 DIR *dir;
49 struct dirent *ent;
51 dir = opendir(dbpath);
52 if(dir == NULL) {
53 fprintf(stderr, _("error: could not access database directory\n"));
54 return(1);
57 rewinddir(dir);
58 /* step through the directory one file at a time */
59 while((ent = readdir(dir)) != NULL) {
60 char path[PATH_MAX];
61 struct stat buf;
62 alpm_list_t *syncdbs = NULL, *i;
63 int found = 0;
64 char *dname = ent->d_name;
66 if(!strcmp(dname, ".") || !strcmp(dname, "..")) {
67 continue;
69 /* skip the local and sync directories */
70 if(!strcmp(dname, "sync") || !strcmp(dname, "local")) {
71 continue;
74 /* build the full path */
75 snprintf(path, PATH_MAX, "%s%s", dbpath, ent->d_name);
76 /* skip entries that are not dirs (lock file, etc.) */
77 stat(path, &buf);
78 if(!S_ISDIR(buf.st_mode)) {
79 continue;
82 if(keep_used) {
83 syncdbs = alpm_option_get_syncdbs();
84 for(i = syncdbs; i && !found; i = alpm_list_next(i)) {
85 pmdb_t *db = alpm_list_getdata(i);
86 found = !strcmp(dname, alpm_db_get_name(db));
89 /* We have a directory that doesn't match any syncdb.
90 * Ask the user if he wants to remove it. */
91 if(!found) {
92 if(!yesno(1, _("Do you want to remove %s?"), path)) {
93 continue;
96 if(rmrf(path)) {
97 fprintf(stderr, _("error: could not remove repository directory\n"));
98 return(1);
103 return(0);
106 static int sync_cleandb_all(void) {
107 const char *dbpath = alpm_option_get_dbpath();
108 char newdbpath[PATH_MAX];
110 printf(_("Database directory: %s\n"), dbpath);
111 if(!yesno(1, _("Do you want to remove unused repositories?"))) {
112 return(0);
114 /* The sync dbs were previously put in dbpath/, but are now in dbpath/sync/,
115 * so we will clean everything in dbpath/ (except dbpath/local/ and dbpath/sync/,
116 * and only the unused sync dbs in dbpath/sync/ */
117 sync_cleandb(dbpath, 0);
119 sprintf(newdbpath, "%s%s", dbpath, "sync/");
120 sync_cleandb(newdbpath, 1);
122 printf(_("Database directory cleaned up\n"));
123 return(0);
126 static int sync_cleancache(int level)
128 /* TODO for now, just mess with the first cache directory */
129 alpm_list_t* cachedirs = alpm_option_get_cachedirs();
130 const char *cachedir = alpm_list_getdata(cachedirs);
132 if(level == 1) {
133 /* incomplete cleanup */
134 DIR *dir;
135 struct dirent *ent;
136 /* Open up each package and see if it should be deleted,
137 * depending on the clean method used */
138 printf(_("Cache directory: %s\n"), cachedir);
139 switch(config->cleanmethod) {
140 case PM_CLEAN_KEEPINST:
141 if(!yesno(1, _("Do you want to remove uninstalled packages from cache?"))) {
142 return(0);
144 break;
145 case PM_CLEAN_KEEPCUR:
146 if(!yesno(1, _("Do you want to remove outdated packages from cache?"))) {
147 return(0);
149 break;
150 default:
151 /* this should not happen : the config parsing doesn't set any other value */
152 return(1);
154 printf(_("removing old packages from cache... "));
156 dir = opendir(cachedir);
157 if(dir == NULL) {
158 fprintf(stderr, _("error: could not access cache directory\n"));
159 return(1);
162 rewinddir(dir);
163 /* step through the directory one file at a time */
164 while((ent = readdir(dir)) != NULL) {
165 char path[PATH_MAX];
166 int delete = 1;
167 pmpkg_t *localpkg = NULL, *pkg = NULL;
168 alpm_list_t *sync_dbs = alpm_option_get_syncdbs();
169 alpm_list_t *j;
171 if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) {
172 continue;
174 /* build the full filepath */
175 snprintf(path, PATH_MAX, "%s%s", cachedir, ent->d_name);
177 /* attempt to load the package, skip file on failures as we may have
178 * files here that aren't valid packages. we also don't need a full
179 * load of the package, just the metadata. */
180 if(alpm_pkg_load(path, 0, &localpkg) != 0 || localpkg == NULL) {
181 continue;
183 switch(config->cleanmethod) {
184 case PM_CLEAN_KEEPINST:
185 /* check if this package is in the local DB */
186 pkg = alpm_db_get_pkg(db_local, alpm_pkg_get_name(localpkg));
187 if(pkg != NULL && alpm_pkg_vercmp(alpm_pkg_get_version(localpkg),
188 alpm_pkg_get_version(pkg)) == 0) {
189 /* package was found in local DB and version matches, keep it */
190 delete = 0;
192 break;
193 case PM_CLEAN_KEEPCUR:
194 /* check if this package is in a sync DB */
195 for(j = sync_dbs; j && delete; j = alpm_list_next(j)) {
196 pmdb_t *db = alpm_list_getdata(j);
197 pkg = alpm_db_get_pkg(db, alpm_pkg_get_name(localpkg));
198 if(pkg != NULL && alpm_pkg_vercmp(alpm_pkg_get_version(localpkg),
199 alpm_pkg_get_version(pkg)) == 0) {
200 /* package was found in a sync DB and version matches, keep it */
201 delete = 0;
204 break;
205 default:
206 /* this should not happen : the config parsing doesn't set any other value */
207 delete = 0;
208 break;
210 /* free the local file package */
211 alpm_pkg_free(localpkg);
213 if(delete) {
214 unlink(path);
217 printf(_("done.\n"));
218 } else {
219 /* full cleanup */
220 printf(_("Cache directory: %s\n"), cachedir);
221 if(!yesno(0, _("Do you want to remove ALL packages from cache?"))) {
222 return(0);
224 printf(_("removing all packages from cache... "));
226 if(rmrf(cachedir)) {
227 fprintf(stderr, _("error: could not remove cache directory\n"));
228 return(1);
231 if(makepath(cachedir)) {
232 fprintf(stderr, _("error: could not create new cache directory\n"));
233 return(1);
235 printf(_("done.\n"));
238 return(0);
241 static int sync_trans_init(pmtransflag_t flags) {
242 if(alpm_trans_init(PM_TRANS_TYPE_SYNC, flags, cb_trans_evt,
243 cb_trans_conv, cb_trans_progress) == -1) {
244 fprintf(stderr, _("error: failed to init transaction (%s)\n"),
245 alpm_strerrorlast());
246 if(pm_errno == PM_ERR_HANDLE_LOCK) {
247 printf(_(" if you're sure a package manager is not already\n"
248 " running, you can remove %s.\n"), alpm_option_get_lockfile());
250 return(-1);
252 return(0);
255 static int sync_trans_release() {
256 if(alpm_trans_release() == -1) {
257 fprintf(stderr, _("error: failed to release transaction (%s)\n"),
258 alpm_strerrorlast());
259 return(-1);
261 return(0);
263 static int sync_synctree(int level, alpm_list_t *syncs)
265 alpm_list_t *i;
266 int success = 0, ret;
268 if(sync_trans_init(0) == -1) {
269 return(0);
272 for(i = syncs; i; i = alpm_list_next(i)) {
273 pmdb_t *db = alpm_list_getdata(i);
275 ret = alpm_db_update((level < 2 ? 0 : 1), db);
276 if(ret < 0) {
277 if(pm_errno == PM_ERR_DB_SYNC) {
278 /* use libdownload error */
279 /* TODO breaking abstraction barrier here?
280 * pacman -> libalpm -> libdownload
282 * Yes. This will be here until we add a nice pacman "pm_errstr" or
283 * something, OR add all libdownload error codes into the pm_error enum
285 fprintf(stderr, _("error: failed to synchronize %s: %s\n"),
286 alpm_db_get_name(db), downloadLastErrString);
287 } else {
288 fprintf(stderr, _("error: failed to update %s (%s)\n"),
289 alpm_db_get_name(db), alpm_strerrorlast());
291 } else if(ret == 1) {
292 printf(_(" %s is up to date\n"), alpm_db_get_name(db));
293 success++;
294 } else {
295 success++;
299 if(sync_trans_release() == -1) {
300 return(0);
302 /* We should always succeed if at least one DB was upgraded - we may possibly
303 * fail later with unresolved deps, but that should be rare, and would be
304 * expected
306 if(!success) {
307 fprintf(stderr, _("error: failed to synchronize any databases\n"));
309 return(success > 0);
312 /* search the sync dbs for a matching package */
313 static int sync_search(alpm_list_t *syncs, alpm_list_t *targets)
315 alpm_list_t *i, *j, *ret;
316 int freelist;
317 int found = 0;
319 for(i = syncs; i; i = alpm_list_next(i)) {
320 pmdb_t *db = alpm_list_getdata(i);
321 /* if we have a targets list, search for packages matching it */
322 if(targets) {
323 ret = alpm_db_search(db, targets);
324 freelist = 1;
325 } else {
326 ret = alpm_db_getpkgcache(db);
327 freelist = 0;
329 if(ret == NULL) {
330 continue;
331 } else {
332 found = 1;
334 for(j = ret; j; j = alpm_list_next(j)) {
335 /* print repo/name (group) info about each package in our list */
336 char *group = NULL;
337 alpm_list_t *grp;
338 pmpkg_t *pkg = alpm_list_getdata(j);
340 if (!config->quiet) {
341 printf("%s/%s %s", alpm_db_get_name(db), alpm_pkg_get_name(pkg),
342 alpm_pkg_get_version(pkg));
343 } else {
344 printf("%s", alpm_pkg_get_name(pkg));
347 /* print the package size with the output if ShowSize option set */
348 if(config->showsize) {
349 /* Convert byte size to MB */
350 double mbsize = alpm_pkg_get_size(pkg) / (1024.0 * 1024.0);
352 printf(" [%.2f MB]", mbsize);
355 if (!config->quiet) {
356 /* TODO package in multiple groups needs to be handled, do a loop */
357 if((grp = alpm_pkg_get_groups(pkg)) != NULL) {
358 group = alpm_list_getdata(grp);
359 printf(" (%s)", group);
362 /* we need a newline and initial indent first */
363 printf("\n ");
364 indentprint(alpm_pkg_get_desc(pkg), 4);
366 printf("\n");
368 /* we only want to free if the list was a search list */
369 if(freelist) {
370 alpm_list_free(ret);
374 return(!found);
377 static int sync_group(int level, alpm_list_t *syncs, alpm_list_t *targets)
379 alpm_list_t *i, *j, *k;
380 alpm_list_t *pkgnames = NULL;
382 if(targets) {
383 for(i = targets; i; i = alpm_list_next(i)) {
384 char *grpname = alpm_list_getdata(i);
385 for(j = syncs; j; j = alpm_list_next(j)) {
386 pmdb_t *db = alpm_list_getdata(j);
387 pmgrp_t *grp = alpm_db_readgrp(db, grpname);
389 if(grp) {
390 printf("%s\n", (char *)alpm_grp_get_name(grp));
391 /* get names of packages in group */
392 for(k = alpm_grp_get_pkgs(grp); k; k = alpm_list_next(k)) {
393 pkgnames = alpm_list_add(pkgnames,
394 (char*)alpm_pkg_get_name(k->data));
396 list_display(" ", pkgnames);
397 alpm_list_free(pkgnames);
401 } else {
402 for(i = syncs; i; i = alpm_list_next(i)) {
403 pmdb_t *db = alpm_list_getdata(i);
405 for(j = alpm_db_getgrpcache(db); j; j = alpm_list_next(j)) {
406 pmgrp_t *grp = alpm_list_getdata(j);
408 printf("%s\n", (char *)alpm_grp_get_name(grp));
409 if(grp && level > 1) {
410 for(k = alpm_grp_get_pkgs(grp); k; k = alpm_list_next(k)) {
411 pkgnames = alpm_list_add(pkgnames,
412 (char*)alpm_pkg_get_name(k->data));
414 list_display(" ", pkgnames);
415 alpm_list_free(pkgnames);
421 return(0);
424 static int sync_info(alpm_list_t *syncs, alpm_list_t *targets)
426 alpm_list_t *i, *j, *k;
427 int ret = 0;
429 if(targets) {
430 for(i = targets; i; i = alpm_list_next(i)) {
431 pmdb_t *db = NULL;
432 int foundpkg = 0;
434 char target[512]; /* TODO is this enough space? */
435 char *repo = NULL, *pkgstr = NULL;
437 strncpy(target, i->data, 512);
438 pkgstr = strchr(target, '/');
439 if(pkgstr) {
440 repo = target;
441 *pkgstr = '\0';
442 ++pkgstr;
444 for(j = syncs; j; j = alpm_list_next(j)) {
445 db = alpm_list_getdata(j);
446 if(strcmp(repo, alpm_db_get_name(db)) == 0) {
447 break;
449 db = NULL;
452 if(!db) {
453 fprintf(stderr, _("error: repository '%s' does not exist\n"), repo);
454 return(1);
457 for(k = alpm_db_getpkgcache(db); k; k = alpm_list_next(k)) {
458 pmpkg_t *pkg = alpm_list_getdata(k);
460 if(strcmp(alpm_pkg_get_name(pkg), pkgstr) == 0) {
461 dump_pkg_sync(pkg, alpm_db_get_name(db));
462 foundpkg = 1;
463 break;
467 if(!foundpkg) {
468 fprintf(stderr, _("error: package '%s' was not found in repository '%s'\n"), pkgstr, repo);
469 ret++;
471 } else {
472 pkgstr = target;
474 for(j = syncs; j; j = alpm_list_next(j)) {
475 pmdb_t *db = alpm_list_getdata(j);
477 for(k = alpm_db_getpkgcache(db); k; k = alpm_list_next(k)) {
478 pmpkg_t *pkg = alpm_list_getdata(k);
480 if(strcmp(alpm_pkg_get_name(pkg), pkgstr) == 0) {
481 dump_pkg_sync(pkg, alpm_db_get_name(db));
482 foundpkg = 1;
483 break;
487 if(!foundpkg) {
488 fprintf(stderr, _("error: package '%s' was not found\n"), pkgstr);
489 ret++;
493 } else {
494 for(i = syncs; i; i = alpm_list_next(i)) {
495 pmdb_t *db = alpm_list_getdata(i);
497 for(j = alpm_db_getpkgcache(db); j; j = alpm_list_next(j)) {
498 dump_pkg_sync(alpm_list_getdata(j), alpm_db_get_name(db));
503 return(ret);
506 static int sync_list(alpm_list_t *syncs, alpm_list_t *targets)
508 alpm_list_t *i, *j, *ls = NULL;
510 if(targets) {
511 for(i = targets; i; i = alpm_list_next(i)) {
512 const char *repo = alpm_list_getdata(i);
513 pmdb_t *db = NULL;
515 for(j = syncs; j; j = alpm_list_next(j)) {
516 pmdb_t *d = alpm_list_getdata(j);
518 if(strcmp(repo, alpm_db_get_name(d)) == 0) {
519 db = d;
520 break;
524 if(db == NULL) {
525 fprintf(stderr, _("error: repository \"%s\" was not found.\n"),repo);
526 alpm_list_free(ls);
527 return(1);
530 ls = alpm_list_add(ls, db);
532 } else {
533 ls = syncs;
536 for(i = ls; i; i = alpm_list_next(i)) {
537 pmdb_t *db = alpm_list_getdata(i);
539 for(j = alpm_db_getpkgcache(db); j; j = alpm_list_next(j)) {
540 pmpkg_t *pkg = alpm_list_getdata(j);
541 if (!config->quiet) {
542 printf("%s %s %s\n", alpm_db_get_name(db), alpm_pkg_get_name(pkg),
543 alpm_pkg_get_version(pkg));
544 } else {
545 printf("%s\n", alpm_pkg_get_name(pkg));
550 if(targets) {
551 alpm_list_free(ls);
554 return(0);
557 static int sync_trans(alpm_list_t *targets)
559 int retval = 0;
560 alpm_list_t *data = NULL;
561 alpm_list_t *sync_dbs = alpm_option_get_syncdbs();
563 /* Step 1: create a new transaction... */
564 if(sync_trans_init(config->flags) == -1) {
565 return(1);
568 if(config->op_s_upgrade) {
569 alpm_list_t *pkgs, *i;
570 printf(_(":: Starting full system upgrade...\n"));
571 alpm_logaction("starting full system upgrade\n");
572 if(alpm_trans_sysupgrade() == -1) {
573 fprintf(stderr, _("error: %s\n"), alpm_strerrorlast());
574 retval = 1;
575 goto cleanup;
578 if(!(alpm_trans_get_flags() & (PM_TRANS_FLAG_DOWNLOADONLY | PM_TRANS_FLAG_PRINTURIS))) {
579 /* check if pacman itself is one of the packages to upgrade.
580 * this can prevent some of the "syntax error" problems users can have
581 * when sysupgrade'ing with an older version of pacman.
583 pkgs = alpm_trans_get_pkgs();
584 for(i = pkgs; i; i = alpm_list_next(i)) {
585 pmsyncpkg_t *sync = alpm_list_getdata(i);
586 pmpkg_t *spkg = alpm_sync_get_pkg(sync);
587 /* TODO pacman name should probably not be hardcoded. In addition, we
588 * have problems on an -Syu if pacman has to pull in deps, so recommend
589 * an '-S pacman' operation */
590 if(strcmp("pacman", alpm_pkg_get_name(spkg)) == 0) {
591 printf("\n");
592 printf(_(":: pacman has detected a newer version of itself.\n"));
593 if(yesno(1, _(":: Do you want to cancel the current operation\n"
594 ":: and install the new pacman version now?"))) {
595 if(sync_trans_release() == -1) {
596 return(1);
598 if(sync_trans_init(0) == -1) {
599 return(1);
601 if(alpm_trans_addtarget("pacman") == -1) {
602 fprintf(stderr, _("error: pacman: %s\n"), alpm_strerrorlast());
603 return(1);
605 break;
610 } else {
611 alpm_list_t *i;
613 /* process targets */
614 for(i = targets; i; i = alpm_list_next(i)) {
615 char *targ = alpm_list_getdata(i);
616 if(alpm_trans_addtarget(targ) == -1) {
617 pmgrp_t *grp = NULL;
618 int found=0;
619 alpm_list_t *j;
621 if(pm_errno == PM_ERR_TRANS_DUP_TARGET) {
622 /* just ignore duplicate targets */
623 continue;
625 if(pm_errno != PM_ERR_PKG_NOT_FOUND) {
626 fprintf(stderr, _("error: '%s': %s\n"),
627 targ, alpm_strerrorlast());
628 retval = 1;
629 goto cleanup;
631 /* target not found: check if it's a group */
633 for(j = sync_dbs; j; j = alpm_list_next(j)) {
634 pmdb_t *db = alpm_list_getdata(j);
635 grp = alpm_db_readgrp(db, targ);
636 if(grp) {
637 alpm_list_t *k, *pkgnames = NULL;
639 found++;
640 printf(_(":: group %s (including ignored packages):\n"), targ);
641 /* remove dupe entries in case a package exists in multiple repos */
642 alpm_list_t *grppkgs = alpm_grp_get_pkgs(grp);
643 alpm_list_t *pkgs = alpm_list_remove_dupes(grppkgs);
644 for(k = pkgs; k; k = alpm_list_next(k)) {
645 pkgnames = alpm_list_add(pkgnames,
646 (char*)alpm_pkg_get_name(k->data));
648 list_display(" ", pkgnames);
649 if(yesno(1, _(":: Install whole content?"))) {
650 for(k = pkgnames; k; k = alpm_list_next(k)) {
651 targets = alpm_list_add(targets, strdup(alpm_list_getdata(k)));
653 } else {
654 for(k = pkgnames; k; k = alpm_list_next(k)) {
655 char *pkgname = alpm_list_getdata(k);
656 if(yesno(1, _(":: Install %s from group %s?"), pkgname, targ)) {
657 targets = alpm_list_add(targets, strdup(pkgname));
661 alpm_list_free(pkgnames);
662 alpm_list_free(pkgs);
665 if(!found) {
666 /* targ not found in sync db, searching for providers... */
667 alpm_list_t *prov = NULL;
668 for(j = sync_dbs; j; j = alpm_list_next(j)) {
669 pmdb_t *db = alpm_list_getdata(j);
670 prov = alpm_list_join(prov, alpm_db_whatprovides(db, targ));
672 if(prov != NULL) {
673 if(alpm_list_count(prov) == 1) {
674 const char *pname = NULL;
675 pmpkg_t *pkg = alpm_list_getdata(prov);
676 pname = alpm_pkg_get_name(pkg);
677 alpm_list_free(prov);
678 printf(_("Warning: %s provides %s\n"), pname, targ);
679 targets = alpm_list_add(targets, strdup(pname));
680 } else {
681 alpm_list_t *k;
682 fprintf(stderr, _("error: several packages provide %s, please specify one :\n"), targ);
683 for(k = prov; k; k = alpm_list_next(k)) {
684 pmpkg_t *pkg = alpm_list_getdata(k);
685 printf("%s ", alpm_pkg_get_name(pkg));
687 printf("\n");
688 alpm_list_free(prov);
689 retval = 1;
690 goto cleanup;
692 } else {
693 fprintf(stderr, _("error: '%s': not found in sync db\n"), targ);
694 retval = 1;
695 goto cleanup;
702 /* Step 2: "compute" the transaction based on targets and flags */
703 if(alpm_trans_prepare(&data) == -1) {
704 fprintf(stderr, _("error: failed to prepare transaction (%s)\n"),
705 alpm_strerrorlast());
706 switch(pm_errno) {
707 alpm_list_t *i;
708 case PM_ERR_UNSATISFIED_DEPS:
709 for(i = data; i; i = alpm_list_next(i)) {
710 pmdepmissing_t *miss = alpm_list_getdata(i);
711 pmdepend_t *dep = alpm_miss_get_dep(miss);
712 char *depstring = alpm_dep_get_string(dep);
713 printf(_(":: %s: requires %s\n"), alpm_miss_get_target(miss),
714 depstring);
715 free(depstring);
717 break;
718 case PM_ERR_CONFLICTING_DEPS:
719 for(i = data; i; i = alpm_list_next(i)) {
720 pmconflict_t *conflict = alpm_list_getdata(i);
721 printf(_(":: %s: conflicts with %s\n"),
722 alpm_conflict_get_package1(conflict), alpm_conflict_get_package2(conflict));
724 break;
725 default:
726 break;
728 retval = 1;
729 goto cleanup;
732 alpm_list_t *packages = alpm_trans_get_pkgs();
733 if(packages == NULL) {
734 /* nothing to do: just exit without complaining */
735 printf(_(" local database is up to date\n"));
736 goto cleanup;
739 if(!(alpm_trans_get_flags() & PM_TRANS_FLAG_PRINTURIS)) {
740 int confirm;
742 display_targets(packages, db_local);
743 printf("\n");
745 if(config->op_s_downloadonly) {
746 confirm = yesno(1, _("Proceed with download?"));
747 } else {
748 confirm = yesno(1, _("Proceed with installation?"));
750 if(!confirm) {
751 goto cleanup;
753 }/* else 'print uris' requested. We're done at this point */
755 /* Step 3: actually perform the installation */
756 if(alpm_trans_commit(&data) == -1) {
757 fprintf(stderr, _("error: failed to commit transaction (%s)\n"),
758 alpm_strerrorlast());
759 switch(pm_errno) {
760 alpm_list_t *i;
761 case PM_ERR_FILE_CONFLICTS:
762 for(i = data; i; i = alpm_list_next(i)) {
763 pmfileconflict_t *conflict = alpm_list_getdata(i);
764 switch(alpm_fileconflict_get_type(conflict)) {
765 case PM_FILECONFLICT_TARGET:
766 printf(_("%s exists in both '%s' and '%s'\n"),
767 alpm_fileconflict_get_file(conflict),
768 alpm_fileconflict_get_target(conflict),
769 alpm_fileconflict_get_ctarget(conflict));
770 break;
771 case PM_FILECONFLICT_FILESYSTEM:
772 printf(_("%s: %s exists in filesystem\n"),
773 alpm_fileconflict_get_target(conflict),
774 alpm_fileconflict_get_file(conflict));
775 break;
778 break;
779 case PM_ERR_PKG_INVALID:
780 case PM_ERR_DLT_INVALID:
781 for(i = data; i; i = alpm_list_next(i)) {
782 char *filename = alpm_list_getdata(i);
783 printf(_("%s is invalid or corrupted\n"), filename);
785 break;
786 default:
787 break;
789 /* TODO: stderr? */
790 printf(_("Errors occurred, no packages were upgraded.\n"));
791 retval = 1;
792 goto cleanup;
795 /* Step 4: release transaction resources */
796 cleanup:
797 if(data) {
798 FREELIST(data);
800 if(sync_trans_release() == -1) {
801 retval = 1;
804 return(retval);
807 int pacman_sync(alpm_list_t *targets)
809 alpm_list_t *sync_dbs = NULL;
811 /* clean the cache */
812 if(config->op_s_clean) {
813 int ret = 0;
815 if(sync_trans_init(0) == -1) {
816 return(1);
819 ret += sync_cleancache(config->op_s_clean);
820 ret += sync_cleandb_all();
822 if(sync_trans_release() == -1) {
823 ret++;
826 return(ret);
829 /* ensure we have at least one valid sync db set up */
830 sync_dbs = alpm_option_get_syncdbs();
831 if(sync_dbs == NULL || alpm_list_count(sync_dbs) == 0) {
832 pm_printf(PM_LOG_ERROR, _("no usable package repositories configured.\n"));
833 return(1);
836 if(targets == NULL && !(config->op_s_sync || config->op_s_upgrade
837 || config->op_s_search || config->group
838 || config->op_s_info || config->op_q_list)) {
839 /* don't proceed here unless we have an operation that doesn't require
840 * a target list */
841 pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n"));
842 return(1);
845 if(config->op_s_sync) {
846 /* grab a fresh package list */
847 printf(_(":: Synchronizing package databases...\n"));
848 alpm_logaction("synchronizing package lists\n");
849 if(!sync_synctree(config->op_s_sync, sync_dbs)) {
850 return(1);
852 config->op_s_sync = 0;
855 if(needs_transaction()) {
856 if(sync_trans(targets) == 1) {
857 return(1);
861 /* search for a package */
862 if(config->op_s_search) {
863 return(sync_search(sync_dbs, targets));
866 /* look for groups */
867 if(config->group) {
868 return(sync_group(config->group, sync_dbs, targets));
871 /* get package info */
872 if(config->op_s_info) {
873 return(sync_info(sync_dbs, targets));
876 /* get a listing of files in sync DBs */
877 if(config->op_q_list) {
878 return(sync_list(sync_dbs, targets));
881 return(0);
884 /* vim: set ts=2 sw=2 noet: */