add.c

Go to the documentation of this file.
00001 /*
00002  *  add.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 "callback.h"
00032 #include "conf.h"
00033 #include "util.h"
00034 
00035 /* Free the current transaction and print an error if unsuccessful */
00036 static int add_cleanup(void)
00037 {
00038     int ret = alpm_trans_release();
00039     if(ret != 0) {
00040         pm_printf(PM_LOG_ERROR, _("failed to release transaction (%s)\n"),
00041                 alpm_strerrorlast());
00042         ret = 1;
00043     }
00044 
00045     return(ret);
00046 }
00047 
00048 /**
00049  * @brief Upgrade a specified list of packages.
00050  *
00051  * @param targets a list of packages (as strings) to upgrade
00052  *
00053  * @return 0 on success, 1 on failure
00054  */
00055 int pacman_upgrade(alpm_list_t *targets)
00056 {
00057     /* this is basically just a remove-then-add process. pacman_add() will */
00058     /* handle it */
00059     config->upgrade = 1;
00060     return(pacman_add(targets));
00061 }
00062 
00063 /**
00064  * @brief Add a specified list of packages which cannot already be installed.
00065  *
00066  * @param targets a list of packages (as strings) to add
00067  *
00068  * @return 0 on success, 1 on failure
00069  */
00070 int pacman_add(alpm_list_t *targets)
00071 {
00072     alpm_list_t *i, *data = NULL;
00073     pmtranstype_t transtype = PM_TRANS_TYPE_ADD;
00074     int retval = 0;
00075 
00076     if(targets == NULL) {
00077         pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n"));
00078         return(1);
00079     }
00080 
00081     /* Check for URL targets and process them
00082      */
00083     for(i = targets; i; i = alpm_list_next(i)) {
00084         if(strstr(i->data, "://")) {
00085             char *str = alpm_fetch_pkgurl(i->data);
00086             if(str == NULL) {
00087                 return(1);
00088             } else {
00089                 free(i->data);
00090                 i->data = str;
00091             }
00092         }
00093     }
00094 
00095     /* Step 1: create a new transaction */
00096     if(config->upgrade == 1) {
00097         /* if upgrade flag was set, change this to an upgrade transaction */
00098         transtype = PM_TRANS_TYPE_UPGRADE;
00099     }
00100 
00101     if(alpm_trans_init(transtype, config->flags, cb_trans_evt,
00102        cb_trans_conv, cb_trans_progress) == -1) {
00103         /* TODO: error messages should be in the front end, not the back */
00104         fprintf(stderr, _("error: %s\n"), alpm_strerrorlast());
00105         if(pm_errno == PM_ERR_HANDLE_LOCK) {
00106             /* TODO this and the 2 other places should probably be on stderr */
00107             printf(_("  if you're sure a package manager is not already\n"
00108                      "  running, you can remove %s.\n"), alpm_option_get_lockfile());
00109         }
00110         return(1);
00111     }
00112 
00113     /* add targets to the created transaction */
00114     printf(_("loading package data... "));
00115     for(i = targets; i; i = alpm_list_next(i)) {
00116         char *targ = alpm_list_getdata(i);
00117         if(alpm_trans_addtarget(targ) == -1) {
00118             fprintf(stderr, _("error: failed to add target '%s' (%s)"), targ,
00119                     alpm_strerrorlast());
00120             add_cleanup();
00121             return(1);
00122         }
00123     }
00124     printf(_("done.\n"));
00125 
00126     /* Step 2: "compute" the transaction based on targets and flags */
00127     /* TODO: No, compute nothing. This is stupid. */
00128     if(alpm_trans_prepare(&data) == -1) {
00129         fprintf(stderr, _("error: failed to prepare transaction (%s)\n"),
00130                 alpm_strerrorlast());
00131         switch(pm_errno) {
00132             case PM_ERR_UNSATISFIED_DEPS:
00133                 for(i = data; i; i = alpm_list_next(i)) {
00134                     pmdepmissing_t *miss = alpm_list_getdata(i);
00135                     pmdepend_t *dep = alpm_miss_get_dep(miss);
00136                     char *depstring = alpm_dep_get_string(dep);
00137 
00138                     /* TODO indicate if the error was a virtual package or not:
00139                      *      :: %s: requires %s, provided by %s
00140                      */
00141                     printf(_(":: %s: requires %s\n"), alpm_miss_get_target(miss),
00142                             depstring);
00143                     free(depstring);
00144                 }
00145                 break;
00146             case PM_ERR_CONFLICTING_DEPS:
00147                 for(i = data; i; i = alpm_list_next(i)) {
00148                     pmconflict_t *conflict = alpm_list_getdata(i);
00149                     printf(_(":: %s: conflicts with %s"),
00150                         alpm_conflict_get_package1(conflict), alpm_conflict_get_package2(conflict));
00151                 }
00152                 break;
00153             case PM_ERR_FILE_CONFLICTS:
00154                 for(i = data; i; i = alpm_list_next(i)) {
00155                     pmfileconflict_t *conflict = alpm_list_getdata(i);
00156                     switch(alpm_fileconflict_get_type(conflict)) {
00157                         case PM_FILECONFLICT_TARGET:
00158                             printf(_("%s exists in both '%s' and '%s'\n"),
00159                                     alpm_fileconflict_get_file(conflict),
00160                                     alpm_fileconflict_get_target(conflict),
00161                                     alpm_fileconflict_get_ctarget(conflict));
00162                         break;
00163                         case PM_FILECONFLICT_FILESYSTEM:
00164                             printf(_("%s: %s exists in filesystem\n"),
00165                                     alpm_fileconflict_get_target(conflict),
00166                                     alpm_fileconflict_get_file(conflict));
00167                         break;
00168                     }
00169                 }
00170                 printf(_("\nerrors occurred, no packages were upgraded.\n"));
00171                 break;
00172             default:
00173                 break;
00174         }
00175         add_cleanup();
00176         FREELIST(data);
00177         return(1);
00178     }
00179     alpm_list_free(data);
00180 
00181     /* Step 3: perform the installation */
00182     if(alpm_trans_commit(NULL) == -1) {
00183         fprintf(stderr, _("error: failed to commit transaction (%s)\n"), alpm_strerrorlast());
00184         add_cleanup();
00185         return(1);
00186     }
00187 
00188     retval = add_cleanup();
00189     return(retval);
00190 }
00191 
00192 /* vim: set ts=2 sw=2 noet: */

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