Update translations from Transifex
[pacman-ng.git] / src / pacman / sync.c
blobea32a2649e6d30c0d1226abc7182a1701e18bf8b
1 /*
2 * sync.c
4 * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
5 * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "config.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <limits.h>
27 #include <unistd.h>
28 #include <dirent.h>
29 #include <sys/stat.h>
31 #include <alpm.h>
32 #include <alpm_list.h>
34 /* pacman */
35 #include "pacman.h"
36 #include "util.h"
37 #include "package.h"
38 #include "conf.h"
40 /* if keep_used != 0, then the db files which match an used syncdb
41 * will be kept */
42 static int sync_cleandb(const char *dbpath, int keep_used)
44 DIR *dir;
45 struct dirent *ent;
46 alpm_list_t *syncdbs;
48 dir = opendir(dbpath);
49 if(dir == NULL) {
50 pm_fprintf(stderr, ALPM_LOG_ERROR, _("could not access database directory\n"));
51 return 1;
54 syncdbs = alpm_option_get_syncdbs(config->handle);
56 rewinddir(dir);
57 /* step through the directory one file at a time */
58 while((ent = readdir(dir)) != NULL) {
59 char path[PATH_MAX];
60 struct stat buf;
61 int found = 0;
62 const char *dname = ent->d_name;
63 size_t len;
65 if(strcmp(dname, ".") == 0 || strcmp(dname, "..") == 0) {
66 continue;
68 /* skip the local and sync directories */
69 if(strcmp(dname, "sync") == 0 || strcmp(dname, "local") == 0) {
70 continue;
72 /* skip the db.lck file */
73 if(strcmp(dname, "db.lck") == 0) {
74 continue;
77 /* build the full path */
78 snprintf(path, PATH_MAX, "%s%s", dbpath, dname);
80 /* remove all non-skipped directories and non-database files */
81 stat(path, &buf);
82 len = strlen(path);
83 if(S_ISDIR(buf.st_mode) || strcmp(path + len - 3, ".db") != 0) {
84 if(rmrf(path)) {
85 pm_fprintf(stderr, ALPM_LOG_ERROR,
86 _("could not remove %s\n"), path);
87 closedir(dir);
88 return 1;
90 continue;
93 if(keep_used) {
94 alpm_list_t *i;
95 len = strlen(dname);
96 char *dbname = strndup(dname, len - 3);
97 for(i = syncdbs; i && !found; i = alpm_list_next(i)) {
98 alpm_db_t *db = alpm_list_getdata(i);
99 found = !strcmp(dbname, alpm_db_get_name(db));
101 free(dbname);
103 /* We have a database that doesn't match any syncdb.
104 * Ask the user if he wants to remove it. */
105 if(!found) {
106 if(!yesno(_("Do you want to remove %s?"), path)) {
107 continue;
110 if(rmrf(path)) {
111 pm_fprintf(stderr, ALPM_LOG_ERROR,
112 _("could not remove %s\n"), path);
113 closedir(dir);
114 return 1;
118 closedir(dir);
119 return 0;
122 static int sync_cleandb_all(void)
124 const char *dbpath;
125 char newdbpath[PATH_MAX];
126 int ret = 0;
128 dbpath = alpm_option_get_dbpath(config->handle);
129 printf(_("Database directory: %s\n"), dbpath);
130 if(!yesno(_("Do you want to remove unused repositories?"))) {
131 return 0;
133 /* The sync dbs were previously put in dbpath/ but are now in dbpath/sync/.
134 * We will clean everything in dbpath/ except local/, sync/ and db.lck, and
135 * only the unused sync dbs in dbpath/sync/ */
136 ret += sync_cleandb(dbpath, 0);
138 sprintf(newdbpath, "%s%s", dbpath, "sync/");
139 ret += sync_cleandb(newdbpath, 1);
141 printf(_("Database directory cleaned up\n"));
142 return ret;
145 static int sync_cleancache(int level)
147 alpm_list_t *i;
148 alpm_list_t *sync_dbs = alpm_option_get_syncdbs(config->handle);
149 alpm_db_t *db_local = alpm_option_get_localdb(config->handle);
150 alpm_list_t *cachedirs = alpm_option_get_cachedirs(config->handle);
151 int ret = 0;
153 for(i = cachedirs; i; i = alpm_list_next(i)) {
154 printf(_("Cache directory: %s\n"), (char *)alpm_list_getdata(i));
157 if(!config->cleanmethod) {
158 /* default to KeepInstalled if user did not specify */
159 config->cleanmethod = PM_CLEAN_KEEPINST;
162 if(level == 1) {
163 printf(_("Packages to keep:\n"));
164 if(config->cleanmethod & PM_CLEAN_KEEPINST) {
165 printf(_(" All locally installed packages\n"));
167 if(config->cleanmethod & PM_CLEAN_KEEPCUR) {
168 printf(_(" All current sync database packages\n"));
170 if(!yesno(_("Do you want to remove all other packages from cache?"))) {
171 return 0;
173 printf(_("removing old packages from cache...\n"));
174 } else {
175 if(!noyes(_("Do you want to remove ALL files from cache?"))) {
176 return 0;
178 printf(_("removing all files from cache...\n"));
181 for(i = cachedirs; i; i = alpm_list_next(i)) {
182 const char *cachedir = alpm_list_getdata(i);
183 DIR *dir = opendir(cachedir);
184 struct dirent *ent;
186 if(dir == NULL) {
187 pm_fprintf(stderr, ALPM_LOG_ERROR,
188 _("could not access cache directory %s\n"), cachedir);
189 ret++;
190 continue;
193 rewinddir(dir);
194 /* step through the directory one file at a time */
195 while((ent = readdir(dir)) != NULL) {
196 char path[PATH_MAX];
197 size_t pathlen;
198 int delete = 1;
199 alpm_pkg_t *localpkg = NULL, *pkg = NULL;
200 const char *local_name, *local_version;
202 if(strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
203 continue;
205 /* build the full filepath */
206 snprintf(path, PATH_MAX, "%s%s", cachedir, ent->d_name);
208 /* short circuit for removing all packages from cache */
209 if(level > 1) {
210 unlink(path);
211 continue;
214 /* we handle .sig files with packages, not separately */
215 pathlen = strlen(path);
216 if(strcmp(path + pathlen - 4, ".sig") == 0) {
217 continue;
220 /* attempt to load the package, prompt removal on failures as we may have
221 * files here that aren't valid packages. we also don't need a full
222 * load of the package, just the metadata. */
223 if(alpm_pkg_load(config->handle, path, 0, 0, &localpkg) != 0
224 || localpkg == NULL) {
225 if(yesno(_("File %s does not seem to be a valid package, remove it?"),
226 path)) {
227 if(localpkg) {
228 alpm_pkg_free(localpkg);
230 unlink(path);
232 continue;
234 local_name = alpm_pkg_get_name(localpkg);
235 local_version = alpm_pkg_get_version(localpkg);
237 if(config->cleanmethod & PM_CLEAN_KEEPINST) {
238 /* check if this package is in the local DB */
239 pkg = alpm_db_get_pkg(db_local, local_name);
240 if(pkg != NULL && alpm_pkg_vercmp(local_version,
241 alpm_pkg_get_version(pkg)) == 0) {
242 /* package was found in local DB and version matches, keep it */
243 pm_printf(ALPM_LOG_DEBUG, "pkg %s-%s found in local db\n",
244 local_name, local_version);
245 delete = 0;
248 if(config->cleanmethod & PM_CLEAN_KEEPCUR) {
249 alpm_list_t *j;
250 /* check if this package is in a sync DB */
251 for(j = sync_dbs; j && delete; j = alpm_list_next(j)) {
252 alpm_db_t *db = alpm_list_getdata(j);
253 pkg = alpm_db_get_pkg(db, local_name);
254 if(pkg != NULL && alpm_pkg_vercmp(local_version,
255 alpm_pkg_get_version(pkg)) == 0) {
256 /* package was found in a sync DB and version matches, keep it */
257 pm_printf(ALPM_LOG_DEBUG, "pkg %s-%s found in sync db\n",
258 local_name, local_version);
259 delete = 0;
263 /* free the local file package */
264 alpm_pkg_free(localpkg);
266 if(delete) {
267 unlink(path);
268 /* unlink a signature file if present too */
269 if(PATH_MAX - 5 >= pathlen) {
270 strcpy(path + pathlen, ".sig");
271 unlink(path);
275 closedir(dir);
278 return ret;
281 static int sync_synctree(int level, alpm_list_t *syncs)
283 alpm_list_t *i;
284 int success = 0, ret;
286 for(i = syncs; i; i = alpm_list_next(i)) {
287 alpm_db_t *db = alpm_list_getdata(i);
289 ret = alpm_db_update((level < 2 ? 0 : 1), db);
290 if(ret < 0) {
291 pm_fprintf(stderr, ALPM_LOG_ERROR, _("failed to update %s (%s)\n"),
292 alpm_db_get_name(db), alpm_strerror(alpm_errno(config->handle)));
293 } else if(ret == 1) {
294 printf(_(" %s is up to date\n"), alpm_db_get_name(db));
295 success++;
296 } else {
297 success++;
301 /* We should always succeed if at least one DB was upgraded - we may possibly
302 * fail later with unresolved deps, but that should be rare, and would be
303 * expected
305 if(!success) {
306 pm_fprintf(stderr, ALPM_LOG_ERROR, _("failed to synchronize any databases\n"));
308 return (success > 0);
311 static void print_installed(alpm_db_t *db_local, alpm_pkg_t *pkg)
313 const char *pkgname = alpm_pkg_get_name(pkg);
314 const char *pkgver = alpm_pkg_get_version(pkg);
315 alpm_pkg_t *lpkg = alpm_db_get_pkg(db_local, pkgname);
316 if(lpkg) {
317 const char *lpkgver = alpm_pkg_get_version(lpkg);
318 if(strcmp(lpkgver,pkgver) == 0) {
319 printf(" [%s]", _("installed"));
320 } else {
321 printf(" [%s: %s]", _("installed"), lpkgver);
326 /* search the sync dbs for a matching package */
327 static int sync_search(alpm_list_t *syncs, alpm_list_t *targets)
329 alpm_list_t *i, *j, *ret;
330 int freelist;
331 int found = 0;
332 alpm_db_t *db_local = alpm_option_get_localdb(config->handle);
334 for(i = syncs; i; i = alpm_list_next(i)) {
335 alpm_db_t *db = alpm_list_getdata(i);
336 /* if we have a targets list, search for packages matching it */
337 if(targets) {
338 ret = alpm_db_search(db, targets);
339 freelist = 1;
340 } else {
341 ret = alpm_db_get_pkgcache(db);
342 freelist = 0;
344 if(ret == NULL) {
345 continue;
346 } else {
347 found = 1;
349 for(j = ret; j; j = alpm_list_next(j)) {
350 alpm_list_t *grp;
351 alpm_pkg_t *pkg = alpm_list_getdata(j);
353 if(!config->quiet) {
354 printf("%s/%s %s", alpm_db_get_name(db), alpm_pkg_get_name(pkg),
355 alpm_pkg_get_version(pkg));
356 } else {
357 printf("%s", alpm_pkg_get_name(pkg));
360 if(!config->quiet) {
361 if((grp = alpm_pkg_get_groups(pkg)) != NULL) {
362 alpm_list_t *k;
363 printf(" (");
364 for(k = grp; k; k = alpm_list_next(k)) {
365 const char *group = alpm_list_getdata(k);
366 printf("%s", group);
367 if(alpm_list_next(k)) {
368 /* only print a spacer if there are more groups */
369 printf(" ");
372 printf(")");
375 print_installed(db_local, pkg);
377 /* we need a newline and initial indent first */
378 printf("\n ");
379 indentprint(alpm_pkg_get_desc(pkg), 4);
381 printf("\n");
383 /* we only want to free if the list was a search list */
384 if(freelist) {
385 alpm_list_free(ret);
389 return !found;
392 static int sync_group(int level, alpm_list_t *syncs, alpm_list_t *targets)
394 alpm_list_t *i, *j, *k;
396 if(targets) {
397 for(i = targets; i; i = alpm_list_next(i)) {
398 const char *grpname = alpm_list_getdata(i);
399 for(j = syncs; j; j = alpm_list_next(j)) {
400 alpm_db_t *db = alpm_list_getdata(j);
401 alpm_group_t *grp = alpm_db_readgroup(db, grpname);
403 if(grp) {
404 /* get names of packages in group */
405 for(k = grp->packages; k; k = alpm_list_next(k)) {
406 if(!config->quiet) {
407 printf("%s %s\n", grpname,
408 alpm_pkg_get_name(alpm_list_getdata(k)));
409 } else {
410 printf("%s\n", alpm_pkg_get_name(alpm_list_getdata(k)));
416 } else {
417 for(i = syncs; i; i = alpm_list_next(i)) {
418 alpm_db_t *db = alpm_list_getdata(i);
420 for(j = alpm_db_get_groupcache(db); j; j = alpm_list_next(j)) {
421 alpm_group_t *grp = alpm_list_getdata(j);
423 if(level > 1) {
424 for(k = grp->packages; k; k = alpm_list_next(k)) {
425 printf("%s %s\n", grp->name,
426 alpm_pkg_get_name(alpm_list_getdata(k)));
428 } else {
429 /* print grp names only, no package names */
430 printf("%s\n", grp->name);
436 return 0;
439 static int sync_info(alpm_list_t *syncs, alpm_list_t *targets)
441 alpm_list_t *i, *j, *k;
442 int ret = 0;
444 if(targets) {
445 for(i = targets; i; i = alpm_list_next(i)) {
446 const char *target = alpm_list_getdata(i);
447 char *name = strdup(target);
448 char *repo, *pkgstr;
449 int foundpkg = 0, founddb = 0;
451 pkgstr = strchr(name, '/');
452 if(pkgstr) {
453 repo = name;
454 *pkgstr = '\0';
455 ++pkgstr;
456 } else {
457 repo = NULL;
458 pkgstr = name;
461 for(j = syncs; j; j = alpm_list_next(j)) {
462 alpm_db_t *db = alpm_list_getdata(j);
463 if(repo && strcmp(repo, alpm_db_get_name(db)) != 0) {
464 continue;
466 founddb = 1;
468 for(k = alpm_db_get_pkgcache(db); k; k = alpm_list_next(k)) {
469 alpm_pkg_t *pkg = alpm_list_getdata(k);
471 if(strcmp(alpm_pkg_get_name(pkg), pkgstr) == 0) {
472 dump_pkg_full(pkg, PKG_FROM_SYNCDB, config->op_s_info > 1);
473 foundpkg = 1;
474 break;
479 if(!founddb) {
480 pm_fprintf(stderr, ALPM_LOG_ERROR,
481 _("repository '%s' does not exist\n"), repo);
482 ret++;
484 if(!foundpkg) {
485 pm_fprintf(stderr, ALPM_LOG_ERROR,
486 _("package '%s' was not found\n"), target);
487 ret++;
489 free(name);
491 } else {
492 for(i = syncs; i; i = alpm_list_next(i)) {
493 alpm_db_t *db = alpm_list_getdata(i);
495 for(j = alpm_db_get_pkgcache(db); j; j = alpm_list_next(j)) {
496 alpm_pkg_t *pkg = alpm_list_getdata(j);
497 dump_pkg_full(pkg, PKG_FROM_SYNCDB, config->op_s_info > 1);
502 return ret;
505 static int sync_list(alpm_list_t *syncs, alpm_list_t *targets)
507 alpm_list_t *i, *j, *ls = NULL;
508 alpm_db_t *db_local = alpm_option_get_localdb(config->handle);
510 if(targets) {
511 for(i = targets; i; i = alpm_list_next(i)) {
512 const char *repo = alpm_list_getdata(i);
513 alpm_db_t *db = NULL;
515 for(j = syncs; j; j = alpm_list_next(j)) {
516 alpm_db_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 pm_fprintf(stderr, ALPM_LOG_ERROR,
526 _("repository \"%s\" was not found.\n"),repo);
527 alpm_list_free(ls);
528 return 1;
531 ls = alpm_list_add(ls, db);
533 } else {
534 ls = syncs;
537 for(i = ls; i; i = alpm_list_next(i)) {
538 alpm_db_t *db = alpm_list_getdata(i);
540 for(j = alpm_db_get_pkgcache(db); j; j = alpm_list_next(j)) {
541 alpm_pkg_t *pkg = alpm_list_getdata(j);
543 if(!config->quiet) {
544 printf("%s %s %s", alpm_db_get_name(db), alpm_pkg_get_name(pkg),
545 alpm_pkg_get_version(pkg));
546 print_installed(db_local, pkg);
547 printf("\n");
548 } else {
549 printf("%s\n", alpm_pkg_get_name(pkg));
554 if(targets) {
555 alpm_list_free(ls);
558 return 0;
561 static alpm_list_t *syncfirst(void) {
562 alpm_list_t *i, *res = NULL;
563 alpm_db_t *db_local = alpm_option_get_localdb(config->handle);
564 alpm_list_t *syncdbs = alpm_option_get_syncdbs(config->handle);
566 for(i = config->syncfirst; i; i = alpm_list_next(i)) {
567 char *pkgname = alpm_list_getdata(i);
568 alpm_pkg_t *pkg = alpm_db_get_pkg(db_local, pkgname);
569 if(pkg == NULL) {
570 continue;
573 if(alpm_sync_newversion(pkg, syncdbs)) {
574 res = alpm_list_add(res, strdup(pkgname));
578 return res;
581 static alpm_db_t *get_db(const char *dbname)
583 alpm_list_t *i;
584 for(i = alpm_option_get_syncdbs(config->handle); i; i = i->next) {
585 alpm_db_t *db = i->data;
586 if(strcmp(alpm_db_get_name(db), dbname) == 0) {
587 return db;
590 return NULL;
593 static int process_pkg(alpm_pkg_t *pkg)
595 int ret = alpm_add_pkg(config->handle, pkg);
597 if(ret == -1) {
598 enum _alpm_errno_t err = alpm_errno(config->handle);
599 if(err == ALPM_ERR_TRANS_DUP_TARGET
600 || err == ALPM_ERR_PKG_IGNORED) {
601 /* just skip duplicate or ignored targets */
602 pm_printf(ALPM_LOG_WARNING, _("skipping target: %s\n"), alpm_pkg_get_name(pkg));
603 return 0;
604 } else {
605 pm_fprintf(stderr, ALPM_LOG_ERROR, "'%s': %s\n", alpm_pkg_get_name(pkg),
606 alpm_strerror(err));
607 return 1;
610 return 0;
613 static int process_group(alpm_list_t *dbs, const char *group)
615 int ret = 0;
616 alpm_list_t *i;
617 alpm_list_t *pkgs = alpm_find_group_pkgs(dbs, group);
618 int count = alpm_list_count(pkgs);
620 if(!count) {
621 pm_fprintf(stderr, ALPM_LOG_ERROR, _("target not found: %s\n"), group);
622 return 1;
626 if(config->print == 0) {
627 printf(_(":: There are %d members in group %s:\n"), count,
628 group);
629 select_display(pkgs);
630 char *array = malloc(count);
631 if(!array) {
632 ret = 1;
633 goto cleanup;
635 if(multiselect_question(array, count)) {
636 ret = 1;
637 free(array);
638 goto cleanup;
640 int n = 0;
641 for(i = pkgs; i; i = alpm_list_next(i)) {
642 if(array[n++] == 0)
643 continue;
644 alpm_pkg_t *pkg = alpm_list_getdata(i);
646 if(process_pkg(pkg) == 1) {
647 ret = 1;
648 free(array);
649 goto cleanup;
652 free(array);
653 } else {
654 for(i = pkgs; i; i = alpm_list_next(i)) {
655 alpm_pkg_t *pkg = alpm_list_getdata(i);
657 if(process_pkg(pkg) == 1) {
658 ret = 1;
659 goto cleanup;
663 cleanup:
664 alpm_list_free(pkgs);
665 return ret;
668 static int process_targname(alpm_list_t *dblist, const char *targname)
670 alpm_pkg_t *pkg = alpm_find_dbs_satisfier(config->handle, dblist, targname);
672 /* #FS#23342 - skip ignored packages when user says no */
673 if(alpm_errno(config->handle) == ALPM_ERR_PKG_IGNORED) {
674 pm_printf(ALPM_LOG_WARNING, _("skipping target: %s\n"), targname);
675 /* TODO how to do this, we shouldn't be fucking with it from the frontend */
676 /* pm_errno = 0; */
677 return 0;
680 if(pkg) {
681 return process_pkg(pkg);
683 /* fallback on group */
684 return process_group(dblist, targname);
687 static int process_target(const char *target)
689 /* process targets */
690 char *targstring = strdup(target);
691 char *targname = strchr(targstring, '/');
692 char *dbname = NULL;
693 int ret = 0;
694 alpm_list_t *dblist = NULL;
696 if(targname) {
697 alpm_db_t *db = NULL;
699 *targname = '\0';
700 targname++;
701 dbname = targstring;
702 db = get_db(dbname);
703 if(!db) {
704 pm_fprintf(stderr, ALPM_LOG_ERROR, _("database not found: %s\n"),
705 dbname);
706 ret = 1;
707 goto cleanup;
709 dblist = alpm_list_add(dblist, db);
710 ret = process_targname(dblist, targname);
711 alpm_list_free(dblist);
712 } else {
713 targname = targstring;
714 dblist = alpm_option_get_syncdbs(config->handle);
715 ret = process_targname(dblist, targname);
717 cleanup:
718 free(targstring);
719 return ret;
722 static int sync_trans(alpm_list_t *targets)
724 alpm_list_t *i;
726 /* Step 1: create a new transaction... */
727 if(trans_init(config->flags, 1) == -1) {
728 return 1;
731 /* process targets */
732 for(i = targets; i; i = alpm_list_next(i)) {
733 char *targ = alpm_list_getdata(i);
734 if(process_target(targ) == 1) {
735 trans_release();
736 return 1;
740 if(config->op_s_upgrade) {
741 printf(_(":: Starting full system upgrade...\n"));
742 alpm_logaction(config->handle, "starting full system upgrade\n");
743 if(alpm_sync_sysupgrade(config->handle, config->op_s_upgrade >= 2) == -1) {
744 pm_fprintf(stderr, ALPM_LOG_ERROR, "%s\n", alpm_strerror(alpm_errno(config->handle)));
745 trans_release();
746 return 1;
750 return sync_prepare_execute();
753 int sync_prepare_execute(void)
755 alpm_list_t *i, *packages, *data = NULL;
756 int retval = 0;
758 /* Step 2: "compute" the transaction based on targets and flags */
759 if(alpm_trans_prepare(config->handle, &data) == -1) {
760 enum _alpm_errno_t err = alpm_errno(config->handle);
761 pm_fprintf(stderr, ALPM_LOG_ERROR, _("failed to prepare transaction (%s)\n"),
762 alpm_strerror(err));
763 switch(err) {
764 case ALPM_ERR_PKG_INVALID_ARCH:
765 for(i = data; i; i = alpm_list_next(i)) {
766 char *pkg = alpm_list_getdata(i);
767 printf(_(":: package %s does not have a valid architecture\n"), pkg);
769 break;
770 case ALPM_ERR_UNSATISFIED_DEPS:
771 for(i = data; i; i = alpm_list_next(i)) {
772 alpm_depmissing_t *miss = alpm_list_getdata(i);
773 char *depstring = alpm_dep_compute_string(miss->depend);
774 printf(_(":: %s: requires %s\n"), miss->target, depstring);
775 free(depstring);
777 break;
778 case ALPM_ERR_CONFLICTING_DEPS:
779 for(i = data; i; i = alpm_list_next(i)) {
780 alpm_conflict_t *conflict = alpm_list_getdata(i);
781 /* only print reason if it contains new information */
782 if(conflict->reason->mod == ALPM_DEP_MOD_ANY) {
783 printf(_(":: %s and %s are in conflict\n"),
784 conflict->package1, conflict->package2);
785 } else {
786 char *reason = alpm_dep_compute_string(conflict->reason);
787 printf(_(":: %s and %s are in conflict (%s)\n"),
788 conflict->package1, conflict->package2, reason);
789 free(reason);
792 break;
793 default:
794 break;
796 retval = 1;
797 goto cleanup;
800 packages = alpm_trans_get_add(config->handle);
801 if(packages == NULL) {
802 /* nothing to do: just exit without complaining */
803 printf(_(" there is nothing to do\n"));
804 goto cleanup;
807 /* Step 3: actually perform the operation */
808 if(config->print) {
809 print_packages(packages);
810 goto cleanup;
813 display_targets(alpm_trans_get_remove(config->handle), 0);
814 display_targets(alpm_trans_get_add(config->handle), 1);
815 printf("\n");
817 int confirm;
818 if(config->op_s_downloadonly) {
819 confirm = yesno(_("Proceed with download?"));
820 } else {
821 confirm = yesno(_("Proceed with installation?"));
823 if(!confirm) {
824 goto cleanup;
827 if(alpm_trans_commit(config->handle, &data) == -1) {
828 enum _alpm_errno_t err = alpm_errno(config->handle);
829 pm_fprintf(stderr, ALPM_LOG_ERROR, _("failed to commit transaction (%s)\n"),
830 alpm_strerror(err));
831 switch(err) {
832 case ALPM_ERR_FILE_CONFLICTS:
833 for(i = data; i; i = alpm_list_next(i)) {
834 alpm_fileconflict_t *conflict = alpm_list_getdata(i);
835 switch(conflict->type) {
836 case ALPM_FILECONFLICT_TARGET:
837 printf(_("%s exists in both '%s' and '%s'\n"),
838 conflict->file, conflict->target, conflict->ctarget);
839 break;
840 case ALPM_FILECONFLICT_FILESYSTEM:
841 printf(_("%s: %s exists in filesystem\n"),
842 conflict->target, conflict->file);
843 break;
846 break;
847 case ALPM_ERR_PKG_INVALID:
848 case ALPM_ERR_PKG_INVALID_CHECKSUM:
849 case ALPM_ERR_PKG_INVALID_SIG:
850 case ALPM_ERR_DLT_INVALID:
851 for(i = data; i; i = alpm_list_next(i)) {
852 const char *filename = alpm_list_getdata(i);
853 printf(_("%s is invalid or corrupted\n"), filename);
855 break;
856 default:
857 break;
859 /* TODO: stderr? */
860 printf(_("Errors occurred, no packages were upgraded.\n"));
861 retval = 1;
862 goto cleanup;
865 /* Step 4: release transaction resources */
866 cleanup:
867 if(data) {
868 FREELIST(data);
870 if(trans_release() == -1) {
871 retval = 1;
874 return retval;
877 int pacman_sync(alpm_list_t *targets)
879 alpm_list_t *sync_dbs = NULL;
881 /* clean the cache */
882 if(config->op_s_clean) {
883 int ret = 0;
885 if(trans_init(0, 0) == -1) {
886 return 1;
889 ret += sync_cleancache(config->op_s_clean);
890 printf("\n");
891 ret += sync_cleandb_all();
893 if(trans_release() == -1) {
894 ret++;
897 return ret;
900 if(check_syncdbs(1, 0)) {
901 return 1;
904 sync_dbs = alpm_option_get_syncdbs(config->handle);
906 if(config->op_s_sync) {
907 /* grab a fresh package list */
908 printf(_(":: Synchronizing package databases...\n"));
909 alpm_logaction(config->handle, "synchronizing package lists\n");
910 if(!sync_synctree(config->op_s_sync, sync_dbs)) {
911 return 1;
915 if(check_syncdbs(1, 1)) {
916 return 1;
919 /* search for a package */
920 if(config->op_s_search) {
921 return sync_search(sync_dbs, targets);
924 /* look for groups */
925 if(config->group) {
926 return sync_group(config->group, sync_dbs, targets);
929 /* get package info */
930 if(config->op_s_info) {
931 return sync_info(sync_dbs, targets);
934 /* get a listing of files in sync DBs */
935 if(config->op_q_list) {
936 return sync_list(sync_dbs, targets);
939 if(targets == NULL) {
940 if(config->op_s_upgrade) {
941 /* proceed */
942 } else if(config->op_s_sync) {
943 return 0;
944 } else {
945 /* don't proceed here unless we have an operation that doesn't require a
946 * target list */
947 pm_printf(ALPM_LOG_ERROR, _("no targets specified (use -h for help)\n"));
948 return 1;
952 alpm_list_t *targs = alpm_list_strdup(targets);
953 if(!(config->flags & ALPM_TRANS_FLAG_DOWNLOADONLY) && !config->print) {
954 /* check for newer versions of packages to be upgraded first */
955 alpm_list_t *packages = syncfirst();
956 if(packages) {
957 /* Do not ask user if all the -S targets are SyncFirst packages, see FS#15810 */
958 alpm_list_t *tmp = NULL;
959 if(config->op_s_upgrade || (tmp = alpm_list_diff(targets, packages, (alpm_list_fn_cmp)strcmp))) {
960 alpm_list_free(tmp);
961 printf(_(":: The following packages should be upgraded first :\n"));
962 list_display(" ", packages);
963 if(yesno(_(":: Do you want to cancel the current operation\n"
964 ":: and upgrade these packages now?"))) {
965 FREELIST(targs);
966 targs = packages;
967 config->flags = 0;
968 config->flags |= ALPM_TRANS_FLAG_RECURSE;
969 config->flags |= ALPM_TRANS_FLAG_NEEDED;
970 config->op_s_upgrade = 0;
971 } else {
972 FREELIST(packages);
974 printf("\n");
975 } else {
976 pm_printf(ALPM_LOG_DEBUG, "skipping SyncFirst dialog\n");
977 FREELIST(packages);
982 int ret = sync_trans(targs);
983 FREELIST(targs);
985 return ret;
988 /* vim: set ts=2 sw=2 noet: */