Rename public functions with grp in their name
[pacman-ng.git] / src / pacman / sync.c
blobce57d3cd709870b9939cd62a91a5b6ff8559145a
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, PM_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, PM_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, PM_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, PM_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, PM_PGP_VERIFY_NEVER, &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(PM_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(PM_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, PM_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, PM_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 int foundpkg = 0;
448 char target[512]; /* TODO is this enough space? */
449 char *repo = NULL, *pkgstr = NULL;
451 strncpy(target, i->data, 512);
452 pkgstr = strchr(target, '/');
453 if(pkgstr) {
454 alpm_db_t *db = NULL;
455 repo = target;
456 *pkgstr = '\0';
457 ++pkgstr;
459 for(j = syncs; j; j = alpm_list_next(j)) {
460 db = alpm_list_getdata(j);
461 if(strcmp(repo, alpm_db_get_name(db)) == 0) {
462 break;
464 db = NULL;
467 if(!db) {
468 pm_fprintf(stderr, PM_LOG_ERROR,
469 _("repository '%s' does not exist\n"), repo);
470 return 1;
473 for(k = alpm_db_get_pkgcache(db); k; k = alpm_list_next(k)) {
474 alpm_pkg_t *pkg = alpm_list_getdata(k);
476 if(strcmp(alpm_pkg_get_name(pkg), pkgstr) == 0) {
477 dump_pkg_full(pkg, PKG_FROM_SYNCDB, config->op_s_info > 1);
478 foundpkg = 1;
479 break;
483 if(!foundpkg) {
484 pm_fprintf(stderr, PM_LOG_ERROR,
485 _("package '%s' was not found in repository '%s'\n"), pkgstr, repo);
486 ret++;
488 } else {
489 pkgstr = target;
491 for(j = syncs; j; j = alpm_list_next(j)) {
492 alpm_db_t *db = alpm_list_getdata(j);
494 for(k = alpm_db_get_pkgcache(db); k; k = alpm_list_next(k)) {
495 alpm_pkg_t *pkg = alpm_list_getdata(k);
497 if(strcmp(alpm_pkg_get_name(pkg), pkgstr) == 0) {
498 dump_pkg_full(pkg, PKG_FROM_SYNCDB, config->op_s_info > 1);
499 foundpkg = 1;
500 break;
504 if(!foundpkg) {
505 pm_fprintf(stderr, PM_LOG_ERROR,
506 _("package '%s' was not found\n"), pkgstr);
507 ret++;
511 } else {
512 for(i = syncs; i; i = alpm_list_next(i)) {
513 alpm_db_t *db = alpm_list_getdata(i);
515 for(j = alpm_db_get_pkgcache(db); j; j = alpm_list_next(j)) {
516 alpm_pkg_t *pkg = alpm_list_getdata(j);
517 dump_pkg_full(pkg, PKG_FROM_SYNCDB, config->op_s_info > 1);
522 return ret;
525 static int sync_list(alpm_list_t *syncs, alpm_list_t *targets)
527 alpm_list_t *i, *j, *ls = NULL;
528 alpm_db_t *db_local = alpm_option_get_localdb(config->handle);
530 if(targets) {
531 for(i = targets; i; i = alpm_list_next(i)) {
532 const char *repo = alpm_list_getdata(i);
533 alpm_db_t *db = NULL;
535 for(j = syncs; j; j = alpm_list_next(j)) {
536 alpm_db_t *d = alpm_list_getdata(j);
538 if(strcmp(repo, alpm_db_get_name(d)) == 0) {
539 db = d;
540 break;
544 if(db == NULL) {
545 pm_fprintf(stderr, PM_LOG_ERROR,
546 _("repository \"%s\" was not found.\n"),repo);
547 alpm_list_free(ls);
548 return 1;
551 ls = alpm_list_add(ls, db);
553 } else {
554 ls = syncs;
557 for(i = ls; i; i = alpm_list_next(i)) {
558 alpm_db_t *db = alpm_list_getdata(i);
560 for(j = alpm_db_get_pkgcache(db); j; j = alpm_list_next(j)) {
561 alpm_pkg_t *pkg = alpm_list_getdata(j);
563 if(!config->quiet) {
564 printf("%s %s %s", alpm_db_get_name(db), alpm_pkg_get_name(pkg),
565 alpm_pkg_get_version(pkg));
566 print_installed(db_local, pkg);
567 printf("\n");
568 } else {
569 printf("%s\n", alpm_pkg_get_name(pkg));
574 if(targets) {
575 alpm_list_free(ls);
578 return 0;
581 static alpm_list_t *syncfirst(void) {
582 alpm_list_t *i, *res = NULL;
583 alpm_db_t *db_local = alpm_option_get_localdb(config->handle);
584 alpm_list_t *syncdbs = alpm_option_get_syncdbs(config->handle);
586 for(i = config->syncfirst; i; i = alpm_list_next(i)) {
587 char *pkgname = alpm_list_getdata(i);
588 alpm_pkg_t *pkg = alpm_db_get_pkg(db_local, pkgname);
589 if(pkg == NULL) {
590 continue;
593 if(alpm_sync_newversion(pkg, syncdbs)) {
594 res = alpm_list_add(res, strdup(pkgname));
598 return res;
601 static alpm_db_t *get_db(const char *dbname)
603 alpm_list_t *i;
604 for(i = alpm_option_get_syncdbs(config->handle); i; i = i->next) {
605 alpm_db_t *db = i->data;
606 if(strcmp(alpm_db_get_name(db), dbname) == 0) {
607 return db;
610 return NULL;
613 static int process_pkg(alpm_pkg_t *pkg)
615 int ret = alpm_add_pkg(config->handle, pkg);
617 if(ret == -1) {
618 enum _alpm_errno_t err = alpm_errno(config->handle);
619 if(err == PM_ERR_TRANS_DUP_TARGET
620 || err == PM_ERR_PKG_IGNORED) {
621 /* just skip duplicate or ignored targets */
622 pm_printf(PM_LOG_WARNING, _("skipping target: %s\n"), alpm_pkg_get_name(pkg));
623 return 0;
624 } else {
625 pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", alpm_pkg_get_name(pkg),
626 alpm_strerror(err));
627 return 1;
630 return 0;
633 static int process_group(alpm_list_t *dbs, char *group)
635 int ret = 0;
636 alpm_list_t *i;
637 alpm_list_t *pkgs = alpm_find_group_pkgs(dbs, group);
638 int count = alpm_list_count(pkgs);
640 if(!count) {
641 pm_fprintf(stderr, PM_LOG_ERROR, _("target not found: %s\n"), group);
642 return 1;
646 if(config->print == 0) {
647 printf(_(":: There are %d members in group %s:\n"), count,
648 group);
649 select_display(pkgs);
650 char *array = malloc(count);
651 multiselect_question(array, count);
652 int n = 0;
653 for(i = pkgs; i; i = alpm_list_next(i)) {
654 if(array[n++] == 0)
655 continue;
656 alpm_pkg_t *pkg = alpm_list_getdata(i);
658 if(process_pkg(pkg) == 1) {
659 ret = 1;
660 free(array);
661 goto cleanup;
664 } else {
665 for(i = pkgs; i; i = alpm_list_next(i)) {
666 alpm_pkg_t *pkg = alpm_list_getdata(i);
668 if(process_pkg(pkg) == 1) {
669 ret = 1;
670 goto cleanup;
674 cleanup:
675 alpm_list_free(pkgs);
676 return ret;
679 static int process_targname(alpm_list_t *dblist, char *targname)
681 alpm_pkg_t *pkg = alpm_find_dbs_satisfier(config->handle, dblist, targname);
683 /* #FS#23342 - skip ignored packages when user says no */
684 if(alpm_errno(config->handle) == PM_ERR_PKG_IGNORED) {
685 pm_printf(PM_LOG_WARNING, _("skipping target: %s\n"), targname);
686 /* TODO how to do this, we shouldn't be fucking with it from the frontend */
687 /* pm_errno = 0; */
688 return 0;
691 if(pkg) {
692 return process_pkg(pkg);
694 /* fallback on group */
695 return process_group(dblist, targname);
698 static int process_target(char *target)
700 /* process targets */
701 char *targstring = strdup(target);
702 char *targname = strchr(targstring, '/');
703 char *dbname = NULL;
704 int ret = 0;
705 alpm_list_t *dblist = NULL;
707 if(targname) {
708 alpm_db_t *db = NULL;
710 *targname = '\0';
711 targname++;
712 dbname = targstring;
713 db = get_db(dbname);
714 if(!db) {
715 pm_fprintf(stderr, PM_LOG_ERROR, _("database not found: %s\n"),
716 dbname);
717 ret = 1;
718 goto cleanup;
720 dblist = alpm_list_add(dblist, db);
721 ret = process_targname(dblist, targname);
722 alpm_list_free(dblist);
723 } else {
724 targname = targstring;
725 dblist = alpm_option_get_syncdbs(config->handle);
726 ret = process_targname(dblist, targname);
728 cleanup:
729 free(targstring);
730 return ret;
733 static int sync_trans(alpm_list_t *targets)
735 int retval = 0;
736 alpm_list_t *data = NULL;
737 alpm_list_t *packages = NULL;
738 alpm_list_t *i;
740 /* Step 1: create a new transaction... */
741 if(trans_init(config->flags) == -1) {
742 return 1;
745 /* process targets */
746 for(i = targets; i; i = alpm_list_next(i)) {
747 char *targ = alpm_list_getdata(i);
748 if(process_target(targ) == 1) {
749 retval = 1;
750 goto cleanup;
754 if(config->op_s_upgrade) {
755 printf(_(":: Starting full system upgrade...\n"));
756 alpm_logaction(config->handle, "starting full system upgrade\n");
757 if(alpm_sync_sysupgrade(config->handle, config->op_s_upgrade >= 2) == -1) {
758 pm_fprintf(stderr, PM_LOG_ERROR, "%s\n", alpm_strerror(alpm_errno(config->handle)));
759 retval = 1;
760 goto cleanup;
764 /* Step 2: "compute" the transaction based on targets and flags */
765 if(alpm_trans_prepare(config->handle, &data) == -1) {
766 enum _alpm_errno_t err = alpm_errno(config->handle);
767 pm_fprintf(stderr, PM_LOG_ERROR, _("failed to prepare transaction (%s)\n"),
768 alpm_strerror(err));
769 switch(err) {
770 case PM_ERR_PKG_INVALID_ARCH:
771 for(i = data; i; i = alpm_list_next(i)) {
772 char *pkg = alpm_list_getdata(i);
773 printf(_(":: package %s does not have a valid architecture\n"), pkg);
775 break;
776 case PM_ERR_UNSATISFIED_DEPS:
777 for(i = data; i; i = alpm_list_next(i)) {
778 alpm_depmissing_t *miss = alpm_list_getdata(i);
779 char *depstring = alpm_dep_compute_string(miss->depend);
780 printf(_(":: %s: requires %s\n"), miss->target, depstring);
781 free(depstring);
783 break;
784 case PM_ERR_CONFLICTING_DEPS:
785 for(i = data; i; i = alpm_list_next(i)) {
786 alpm_conflict_t *conflict = alpm_list_getdata(i);
787 /* only print reason if it contains new information */
788 if(strcmp(conflict->package1, conflict->reason) == 0 ||
789 strcmp(conflict->package2, conflict->reason) == 0) {
790 printf(_(":: %s and %s are in conflict\n"),
791 conflict->package1, conflict->package2);
792 } else {
793 printf(_(":: %s and %s are in conflict (%s)\n"),
794 conflict->package1, conflict->package2, conflict->reason);
797 break;
798 default:
799 break;
801 retval = 1;
802 goto cleanup;
805 packages = alpm_trans_get_add(config->handle);
806 if(packages == NULL) {
807 /* nothing to do: just exit without complaining */
808 printf(_(" there is nothing to do\n"));
809 goto cleanup;
812 /* Step 3: actually perform the operation */
813 if(config->print) {
814 print_packages(packages);
815 goto cleanup;
818 display_targets(alpm_trans_get_remove(config->handle), 0);
819 display_targets(alpm_trans_get_add(config->handle), 1);
820 printf("\n");
822 int confirm;
823 if(config->op_s_downloadonly) {
824 confirm = yesno(_("Proceed with download?"));
825 } else {
826 confirm = yesno(_("Proceed with installation?"));
828 if(!confirm) {
829 goto cleanup;
832 if(alpm_trans_commit(config->handle, &data) == -1) {
833 enum _alpm_errno_t err = alpm_errno(config->handle);
834 pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"),
835 alpm_strerror(err));
836 switch(err) {
837 case PM_ERR_FILE_CONFLICTS:
838 for(i = data; i; i = alpm_list_next(i)) {
839 alpm_fileconflict_t *conflict = alpm_list_getdata(i);
840 switch(conflict->type) {
841 case PM_FILECONFLICT_TARGET:
842 printf(_("%s exists in both '%s' and '%s'\n"),
843 conflict->file, conflict->target, conflict->ctarget);
844 break;
845 case PM_FILECONFLICT_FILESYSTEM:
846 printf(_("%s: %s exists in filesystem\n"),
847 conflict->target, conflict->file);
848 break;
851 break;
852 case PM_ERR_PKG_INVALID:
853 case PM_ERR_DLT_INVALID:
854 for(i = data; i; i = alpm_list_next(i)) {
855 char *filename = alpm_list_getdata(i);
856 printf(_("%s is invalid or corrupted\n"), filename);
858 break;
859 default:
860 break;
862 /* TODO: stderr? */
863 printf(_("Errors occurred, no packages were upgraded.\n"));
864 retval = 1;
865 goto cleanup;
868 /* Step 4: release transaction resources */
869 cleanup:
870 if(data) {
871 FREELIST(data);
873 if(trans_release() == -1) {
874 retval = 1;
877 return retval;
880 int pacman_sync(alpm_list_t *targets)
882 alpm_list_t *sync_dbs = NULL;
884 /* clean the cache */
885 if(config->op_s_clean) {
886 int ret = 0;
888 if(trans_init(0) == -1) {
889 return 1;
892 ret += sync_cleancache(config->op_s_clean);
893 printf("\n");
894 ret += sync_cleandb_all();
896 if(trans_release() == -1) {
897 ret++;
900 return ret;
903 /* ensure we have at least one valid sync db set up */
904 sync_dbs = alpm_option_get_syncdbs(config->handle);
905 if(sync_dbs == NULL) {
906 pm_printf(PM_LOG_ERROR, _("no usable package repositories configured.\n"));
907 return 1;
910 if(config->op_s_sync) {
911 /* grab a fresh package list */
912 printf(_(":: Synchronizing package databases...\n"));
913 alpm_logaction(config->handle, "synchronizing package lists\n");
914 if(!sync_synctree(config->op_s_sync, sync_dbs)) {
915 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(PM_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 & PM_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->op_s_upgrade = 0;
969 } else {
970 FREELIST(packages);
972 printf("\n");
973 } else {
974 pm_printf(PM_LOG_DEBUG, "skipping SyncFirst dialog\n");
975 FREELIST(packages);
980 int ret = sync_trans(targs);
981 FREELIST(targs);
983 return ret;
986 /* vim: set ts=2 sw=2 noet: */