remove.c

Go to the documentation of this file.
00001 /*
00002  *  remove.c
00003  *
00004  *  Copyright (c) 2002-2007 by Judd Vinet <jvinet@zeroflux.org>
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018  */
00019 
00020 #include "config.h"
00021 
00022 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include <string.h>
00025 
00026 #include <alpm.h>
00027 #include <alpm_list.h>
00028 
00029 /* pacman */
00030 #include "pacman.h"
00031 #include "util.h"
00032 #include "callback.h"
00033 #include "conf.h"
00034 
00035 extern pmdb_t *db_local;
00036 
00037 /* Free the current transaction and print an error if unsuccessful */
00038 static int remove_cleanup(void)
00039 {
00040     int ret = alpm_trans_release();
00041     if(ret != 0) {
00042         pm_printf(PM_LOG_ERROR, _("failed to release transaction (%s)\n"),
00043                 alpm_strerrorlast());
00044         ret = 1;
00045     }
00046 
00047     return(ret);
00048 }
00049 
00050 /**
00051  * @brief Remove a specified list of packages.
00052  *
00053  * @param targets a list of packages (as strings) to remove from the system
00054  *
00055  * @return 0 on success, 1 on failure
00056  */
00057 int pacman_remove(alpm_list_t *targets)
00058 {
00059     alpm_list_t *i, *data = NULL, *finaltargs = NULL;
00060     int retval = 0;
00061 
00062     if(targets == NULL) {
00063         pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n"));
00064         return(1);
00065     }
00066 
00067     /* If the target is a group, ask if its packages should be removed
00068      * (the library can't remove groups for now)
00069      */
00070     for(i = targets; i; i = alpm_list_next(i)) {
00071         pmgrp_t *grp = alpm_db_readgrp(db_local, alpm_list_getdata(i));
00072         if(grp) {
00073             int all;
00074             const alpm_list_t *p, *pkgnames = alpm_grp_get_pkgs(grp);
00075 
00076             printf(_(":: group %s:\n"), alpm_grp_get_name(grp));
00077             list_display("   ", pkgnames);
00078             all = yesno(_("    Remove whole content? [Y/n] "));
00079 
00080             for(p = pkgnames; p; p = alpm_list_next(p)) {
00081                 char *pkg = alpm_list_getdata(p);
00082                 if(all || yesno(_(":: Remove %s from group %s? [Y/n] "), pkg, (char *)alpm_list_getdata(i))) {
00083                     finaltargs = alpm_list_add(finaltargs, strdup(pkg));
00084                 }
00085             }
00086         } else {
00087             /* not a group, so add it to the final targets */
00088             finaltargs = alpm_list_add(finaltargs, strdup(alpm_list_getdata(i)));
00089         }
00090     }
00091 
00092     /* Step 1: create a new transaction */
00093     if(alpm_trans_init(PM_TRANS_TYPE_REMOVE, config->flags,
00094        cb_trans_evt, cb_trans_conv, cb_trans_progress) == -1) {
00095         fprintf(stderr, _("error: failed to init transaction (%s)\n"),
00096                 alpm_strerrorlast());
00097         if(pm_errno == PM_ERR_HANDLE_LOCK) {
00098             printf(_("  if you're sure a package manager is not already\n"
00099                      "  running, you can remove %s.\n"), alpm_option_get_lockfile());
00100         }
00101         FREELIST(finaltargs);
00102         return(1);
00103     }
00104 
00105     /* add targets to the created transaction */
00106     printf(_("loading package data... "));
00107     for(i = finaltargs; i; i = alpm_list_next(i)) {
00108         char *targ = alpm_list_getdata(i);
00109         if(alpm_trans_addtarget(targ) == -1) {
00110             printf("failed.\n");
00111             fprintf(stderr, _("error: failed to add target '%s' (%s)\n"), targ,
00112                     alpm_strerrorlast());
00113             remove_cleanup();
00114             FREELIST(finaltargs);
00115             return(1);
00116         }
00117     }
00118     printf(_("done.\n"));
00119 
00120     /* Step 2: prepare the transaction based on its type, targets and flags */
00121     if(alpm_trans_prepare(&data) == -1) {
00122         fprintf(stderr, _("error: failed to prepare transaction (%s)\n"),
00123                 alpm_strerrorlast());
00124         switch(pm_errno) {
00125             case PM_ERR_UNSATISFIED_DEPS:
00126                 for(i = data; i; i = alpm_list_next(i)) {
00127                     pmdepmissing_t *miss = alpm_list_getdata(i);
00128                     pmdepend_t *dep = alpm_miss_get_dep(miss);
00129                     char *depstring = alpm_dep_get_string(dep);
00130                     printf(_(":: %s: requires %s\n"), alpm_miss_get_target(miss),
00131                             depstring);
00132                     free(depstring);
00133                 }
00134                 FREELIST(data);
00135                 break;
00136             default:
00137                 break;
00138         }
00139         remove_cleanup();
00140         FREELIST(finaltargs);
00141         return(1);
00142     }
00143 
00144     /* Warn user in case of dangerous operation */
00145     if(config->flags & PM_TRANS_FLAG_RECURSE ||
00146        config->flags & PM_TRANS_FLAG_CASCADE) {
00147         /* list transaction targets */
00148         alpm_list_t *lst = NULL;
00149         /* create a new list of package names only */
00150         for(i = alpm_trans_get_pkgs(); i; i = alpm_list_next(i)) {
00151             pmpkg_t *pkg = alpm_list_getdata(i);
00152             lst = alpm_list_add(lst, strdup(alpm_pkg_get_name(pkg)));
00153         }
00154         printf("\n");
00155         list_display(_("Targets:"), lst);
00156         FREELIST(lst);
00157         /* get confirmation */
00158         if(yesno(_("\nDo you want to remove these packages? [Y/n] ")) == 0) {
00159             remove_cleanup();
00160             FREELIST(finaltargs);
00161             return(1);
00162         }
00163         printf("\n");
00164     }
00165 
00166     /* Step 3: actually perform the removal */
00167     if(alpm_trans_commit(NULL) == -1) {
00168         fprintf(stderr, _("error: failed to commit transaction (%s)\n"),
00169                 alpm_strerrorlast());
00170         remove_cleanup();
00171         FREELIST(finaltargs);
00172         return(1);
00173     }
00174 
00175     /* Step 4: release transaction resources */
00176     retval = remove_cleanup();
00177     FREELIST(finaltargs);
00178     return(retval);
00179 }
00180 
00181 /* vim: set ts=2 sw=2 noet: */

Generated on Mon Jan 14 23:53:40 2008 for libalpm by  doxygen 1.5.4