Hi, attached is a patch to fix bug 9395, against the current git tree for pacman, as described in an earlier email to this list. You may find a description of the changes I made in the Arch bug database for bug 9395. Please let me know if there are any questions.

Thank you, and best wishes,
Bryan

diff -rupN -x '*\.git*' pacman/doc/pacman.8.txt 
pacman-fixbug9395/doc/pacman.8.txt
--- pacman/doc/pacman.8.txt     2008-12-31 16:45:31.000000000 +1300
+++ pacman-fixbug9395/doc/pacman.8.txt  2008-12-31 17:52:33.000000000 +1300
@@ -152,6 +152,11 @@ Options
        If an install scriptlet exists, do not execute it. Do not use this
        unless you know what you are doing.
 
+*\--noignoreprompt*::
+       Do not prompt the user to ask for confirmation that packages listed in
+       IgnorePkg and IgnoreGroup really should be ignored; instead, assume
+       that they should be and silently ignore them.
+
 
 Query Options[[QO]]
 -------------------
diff -rupN -x '*\.git*' pacman/lib/libalpm/alpm.h 
pacman-fixbug9395/lib/libalpm/alpm.h
--- pacman/lib/libalpm/alpm.h   2008-12-31 16:45:31.000000000 +1300
+++ pacman-fixbug9395/lib/libalpm/alpm.h        2008-12-31 17:59:38.000000000 
+1300
@@ -377,7 +377,7 @@ typedef enum _pmtransconv_t {
        PM_TRANS_CONV_CONFLICT_PKG = 0x04,
        PM_TRANS_CONV_CORRUPTED_PKG = 0x08,
        PM_TRANS_CONV_LOCAL_NEWER = 0x10,
-       /* 0x20 flag can go here */
+    PM_TRANS_CONV_REMOVE_PKGS = 0x20,
        PM_TRANS_CONV_REMOVE_HOLDPKG = 0x40
 } pmtransconv_t;
 
diff -rupN -x '*\.git*' pacman/lib/libalpm/deps.c 
pacman-fixbug9395/lib/libalpm/deps.c
--- pacman/lib/libalpm/deps.c   2008-12-31 16:45:31.000000000 +1300
+++ pacman-fixbug9395/lib/libalpm/deps.c        2008-12-31 17:52:41.000000000 
+1300
@@ -546,17 +546,92 @@ pmpkg_t *_alpm_resolvedep(pmdepend_t *de
        return(NULL);
 }
 
+typedef struct __pkginfo_t
+{
+       /* The package for which this info is being kept */
+       pmpkg_t *pkg;
+       /* 0 if this package has been determined to be unresolvable, meaning 
that
+          it has dependencies that cannot be resolved, nonzero otherwise */
+       int unresolvable;
+       /* 0 if this package was not pulled, nonzero if this package was pulled 
*/
+       int pulled;
+       /* Packages that are immediately dependent on this package. */
+       alpm_list_t *dependents;
+} pkginfo_t;
+
+
+static pkginfo_t *_alpm_findinfo(alpm_list_t *list, pmpkg_t *pkg)
+{
+       alpm_list_t *i;
+
+       for (i = list; i; i = i->next) {
+               pkginfo_t *info = (pkginfo_t *) i->data;
+               if (info->pkg == pkg) {
+                       return info;
+               }
+       }
+
+       return NULL;
+}
+
+
+static void _alpm_mark_unresolvable(alpm_list_t *list, pkginfo_t *info)
+{
+       alpm_list_t *i;
+
+       if (info->unresolvable) {
+           return;
+       }
+
+       info->unresolvable = 1;
+
+       for (i = info->dependents; i; i = i->next) {
+               _alpm_mark_unresolvable(list, _alpm_findinfo(list, ((pmpkg_t *) 
i->data)));
+       }
+}
+
+static void _alpm_info_free(pkginfo_t *info)
+{
+       alpm_list_free(info->dependents);
+       free(info);
+}
+
+
+static int _alpm_is_needed(alpm_list_t *infolist, pkginfo_t *info)
+{
+       /* Obviously if it's already been marked unresolvable, it is not needed 
*/
+       if (info->unresolvable) {
+               return(0);
+       }
+       /* Now, if all of the top-level packages which depend on it are
+          unresolvable, then it is unneeded */
+       else {
+               alpm_list_t *i;
+               for (i = info->dependents; i; i = i->next) {
+                       if (!_alpm_is_needed(infolist, _alpm_findinfo(infolist, 
(pmpkg_t *) i->data))) {
+                           return(0);
+                       }
+               }
+               
+               return(1);
+       }
+}
+
+
 /* populates list with packages that need to be installed to satisfy all
  * dependencies of packages in list
  *
  * @param remove contains packages elected for removal
  */
-int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, alpm_list_t *list,
-                      alpm_list_t *remove, alpm_list_t **data)
+int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, alpm_list_t **list,
+                     alpm_list_t **pulled, alpm_list_t *remove, alpm_list_t 
**data)
 {
+       int ret = 0;
        alpm_list_t *i, *j;
        alpm_list_t *targ;
        alpm_list_t *deps = NULL;
+       alpm_list_t *info = NULL;
+       alpm_list_t *unresolvable = NULL;
 
        ALPM_LOG_FUNC;
 
@@ -565,8 +640,29 @@ int _alpm_resolvedeps(pmdb_t *local, alp
        }
 
        _alpm_log(PM_LOG_DEBUG, "started resolving dependencies\n");
-       for(i = list; i; i = i->next) {
+
+       /* Build up a list of pkginfo_t structures describing the root level
+          packages */
+       for(i = *list; i; i = i->next) {
+               pkginfo_t *thisinfo;
+               thisinfo = (pkginfo_t *) malloc(sizeof(pkginfo_t));
+               if (thisinfo == NULL) {
+                       pm_errno = PM_ERR_MEMORY;
+                       ret = -1;
+                       goto cleanup;
+               }
+               thisinfo->pkg = i->data;
+               thisinfo->unresolvable = 0;
+               thisinfo->pulled = 0;
+               thisinfo->dependents = NULL;
+               info = alpm_list_add(info, thisinfo);
+       }
+
+       /* Now resolve */
+       for(i = *list; i; i = i->next) {
                pmpkg_t *tpkg = i->data;
+               /* Find the info for tpkg */
+               pkginfo_t *tinfo = _alpm_findinfo(info, tpkg);
                targ = alpm_list_add(NULL, tpkg);
                deps = alpm_checkdeps(_alpm_db_get_pkgcache(local), 0, remove, 
targ);
                alpm_list_free(targ);
@@ -574,38 +670,122 @@ int _alpm_resolvedeps(pmdb_t *local, alp
                        pmdepmissing_t *miss = j->data;
                        pmdepend_t *missdep = alpm_miss_get_dep(miss);
                        /* check if one of the packages in list already 
satisfies this dependency */
-                       if(_alpm_find_dep_satisfier(list, missdep)) {
+                       pmpkg_t *spkg = _alpm_find_dep_satisfier(*list, 
missdep);
+                       if(spkg != NULL) {
+                               /* Check spkg to make sure that it was not 
unresolvable; if it is, mark tpkg as
+                                  unresolvable also */
+                               pkginfo_t *sinfo = _alpm_findinfo(info, spkg);
+                               if (sinfo->unresolvable) {
+                                       _alpm_mark_unresolvable(info, tinfo);
+                                       /* No need to do any further dependency
+                                          checking for tpkg, even if it has 
other
+                                          dependencies, tpkg will not be 
installed
+                                          because it is not resolvable */
+                                       break;
+                               }
+                               sinfo->dependents = 
alpm_list_add(sinfo->dependents, tpkg);
                                continue;
                        }
                        /* find a satisfier package in the given repositories */
-                       pmpkg_t *spkg = _alpm_resolvedep(missdep, dbs_sync, 
list, tpkg);
-                       if(!spkg) {
-                               pm_errno = PM_ERR_UNSATISFIED_DEPS;
-                               char *missdepstring = 
alpm_dep_get_string(missdep);
-                               _alpm_log(PM_LOG_ERROR, _("cannot resolve 
\"%s\", a dependency of \"%s\"\n"),
-                                                      missdepstring, 
tpkg->name);
-                               free(missdepstring);
-                               if(data) {
-                                       pmdepmissing_t *missd = 
_alpm_depmiss_new(miss->target,
-                                                                  
miss->depend, miss->causingpkg);
-                                       if(missd) {
-                                               *data = alpm_list_add(*data, 
missd);
-                                       }
-                               }
-                               alpm_list_free_inner(deps, 
(alpm_list_fn_free)_alpm_depmiss_free);
-                               alpm_list_free(deps);
-                               return(-1);
-                       }  else {
+                       spkg = _alpm_resolvedep(missdep, dbs_sync, *list, tpkg);
+                       if(spkg != NULL) {
                                _alpm_log(PM_LOG_DEBUG, "pulling dependency %s 
(needed by %s)\n",
                                          alpm_pkg_get_name(spkg), 
alpm_pkg_get_name(tpkg));
-                               list = alpm_list_add(list, spkg);
+                               *list = alpm_list_add(*list, spkg);
+                               pkginfo_t *sinfo;
+                               sinfo = (pkginfo_t *) malloc(sizeof(pkginfo_t));
+                               if (sinfo == NULL) {
+                                   pm_errno = PM_ERR_MEMORY;
+                                   ret = -1;
+                                   goto cleanup;
+                               }
+                               sinfo->pkg = spkg;
+                               sinfo->unresolvable = 0;
+                               sinfo->pulled = 1;
+                               sinfo->dependents = alpm_list_add(NULL, tpkg);
+                               info = alpm_list_add(info, sinfo);
+                       } else {
+                               /* tpkg is not resolvable, so mark it and all of
+                                  its dependents as such */
+                               _alpm_mark_unresolvable(info, tinfo);
                        }
                }
                alpm_list_free_inner(deps, 
(alpm_list_fn_free)_alpm_depmiss_free);
                alpm_list_free(deps);
+               deps = NULL;
+       }
+
+       /* Build up a list of unresolvable top-level packages, so that they
+          can be queried about */
+       for(i = info; i; i = i->next) {
+               pkginfo_t *info = (pkginfo_t *) i->data;
+               if (info->unresolvable && !info->pulled) {
+                       unresolvable = alpm_list_add(unresolvable, info->pkg);
+               }
+       }
+
+       /* If there were unresolvable packages, query the user to see if they
+          should be removed from the transaction */
+       if(unresolvable != NULL) {
+               int remove_unresolved = 0;
+               QUESTION(handle->trans, PM_TRANS_CONV_REMOVE_PKGS, 
unresolvable, NULL, NULL, &remove_unresolved);
+               if (remove_unresolved) {
+                       /* Need to remove all packages which are:
+                          - unresolvable, OR
+                          - are pulled elements whose entire list of top-level
+                            dependents are unresolvable */
+                       for (i = info; i; i = i->next) {
+                               pkginfo_t *thisinfo = (pkginfo_t *) i->data;
+                               if (!_alpm_is_needed(info, thisinfo)) {
+                                       *list = alpm_list_remove(*list, 
thisinfo->pkg, _alpm_pkg_cmp, NULL);
+                               }
+                       }
+               } else {
+                       alpm_list_free_inner(deps, 
(alpm_list_fn_free)_alpm_depmiss_free);
+                       alpm_list_free(deps);
+                       deps = NULL;
+                       pm_errno = PM_ERR_UNSATISFIED_DEPS;
+                       _alpm_log(PM_LOG_ERROR, _("cannot resolve dependencies 
for:\n"));
+                       for (i = unresolvable; i; i = i->next) {
+                               _alpm_log(PM_LOG_ERROR, _("\t%s\n"), 
alpm_pkg_get_name((pmpkg_t *) i->data));
+                               if (data) {
+                                       alpm_list_t *targ = alpm_list_add(NULL, 
i->data);
+                                       deps = 
alpm_checkdeps(_alpm_db_get_pkgcache(local), 0, remove, targ);
+                                       alpm_list_free(targ);
+                               }
+                       }
+                       for(i = deps; i; i = i->next) {
+                               pmdepmissing_t *miss = i->data;
+                               pmdepmissing_t *missd = 
_alpm_depmiss_new(miss->target, miss->depend, miss->causingpkg);
+                               if(missd) {
+                                       *data = alpm_list_add(*data, missd);
+                               }
+                       }
+                       ret = -1;
+               }
        }
+
+       /* Set pulled to be the last top-level item in the list */
+       *pulled = NULL;
+       for(i = *list; i; i = i->next) {
+               pkginfo_t *thisinfo = _alpm_findinfo(info, i->data);
+               if (thisinfo->pulled) {
+                       *pulled = i;
+                       break;
+               }
+       }
+
+ cleanup:
+       
+       alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_depmiss_free);
+       alpm_list_free(deps);
+       alpm_list_free_inner(info, (alpm_list_fn_free)_alpm_info_free);
+       alpm_list_free(info);
+       alpm_list_free(unresolvable);
+
        _alpm_log(PM_LOG_DEBUG, "finished resolving dependencies\n");
-       return(0);
+
+       return(ret);
 }
 
 /* Does pkg1 depend on pkg2, ie. does pkg2 satisfy a dependency of pkg1? */
diff -rupN -x '*\.git*' pacman/lib/libalpm/deps.h 
pacman-fixbug9395/lib/libalpm/deps.h
--- pacman/lib/libalpm/deps.h   2008-12-31 16:45:31.000000000 +1300
+++ pacman-fixbug9395/lib/libalpm/deps.h        2008-12-31 17:52:41.000000000 
+1300
@@ -48,8 +48,8 @@ void _alpm_depmiss_free(pmdepmissing_t *
 alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, int reverse);
 void _alpm_recursedeps(pmdb_t *db, alpm_list_t *targs, int include_explicit);
 pmpkg_t *_alpm_resolvedep(pmdepend_t *dep, alpm_list_t *dbs, alpm_list_t 
*excluding, pmpkg_t *tpkg);
-int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, alpm_list_t *list,
-                     alpm_list_t *remove, alpm_list_t **data);
+int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, alpm_list_t **list,
+                      alpm_list_t **pulled, alpm_list_t *remove, alpm_list_t 
**data);
 int _alpm_dep_edge(pmpkg_t *pkg1, pmpkg_t *pkg2);
 pmdepend_t *_alpm_splitdep(const char *depstring);
 pmpkg_t *_alpm_find_dep_satisfier(alpm_list_t *pkgs, pmdepend_t *dep);
diff -rupN -x '*\.git*' pacman/lib/libalpm/sync.c 
pacman-fixbug9395/lib/libalpm/sync.c
--- pacman/lib/libalpm/sync.c   2008-12-31 16:45:31.000000000 +1300
+++ pacman-fixbug9395/lib/libalpm/sync.c        2008-12-31 18:01:17.000000000 
+1300
@@ -417,9 +417,10 @@ int _alpm_sync_prepare(pmtrans_t *trans,
        }
 
        if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
-               /* store a pointer to the last original target so we can tell 
what was
-                * pulled by resolvedeps */
-               alpm_list_t *pulled = alpm_list_last(list);
+               /* resolvedeps returns a pointer to the first element of the
+                * list which is a pulled element, and all elements after that
+                * are pulled as well */
+               alpm_list_t *pulled;
                /* Resolve targets dependencies */
                EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_START, NULL, NULL);
                _alpm_log(PM_LOG_DEBUG, "resolving target's dependencies\n");
@@ -432,13 +433,13 @@ int _alpm_sync_prepare(pmtrans_t *trans,
                        }
                }
 
-               if(_alpm_resolvedeps(db_local, dbs_sync, list, remove, data) == 
-1) {
+               if(_alpm_resolvedeps(db_local, dbs_sync, &list, &pulled, 
remove, data) == -1) {
                        /* pm_errno is set by resolvedeps */
                        ret = -1;
                        goto cleanup;
                }
 
-               for(i = pulled->next; i; i = i->next) {
+               for(i = pulled; i; i = i->next) {
                        pmpkg_t *spkg = i->data;
                        pmsyncpkg_t *sync = 
_alpm_sync_new(PM_PKG_REASON_DEPEND, spkg, NULL);
                        if(sync == NULL) {
diff -rupN -x '*\.git*' pacman/src/pacman/callback.c 
pacman-fixbug9395/src/pacman/callback.c
--- pacman/src/pacman/callback.c        2008-12-31 16:45:31.000000000 +1300
+++ pacman-fixbug9395/src/pacman/callback.c     2008-12-31 18:04:16.000000000 
+1300
@@ -248,7 +248,10 @@ void cb_trans_conv(pmtransconv_t event, 
 {
        switch(event) {
                case PM_TRANS_CONV_INSTALL_IGNOREPKG:
-                       if(data2) {
+                       if(config->noignoreprompt) {
+                               *response = 0;
+                       }
+                       else if(data2) {
                                /* TODO we take this route based on data2 being 
not null? WTF */
                                *response = yesno(_(":: %s requires installing 
%s from IgnorePkg/IgnoreGroup. Install anyway?"),
                                                alpm_pkg_get_name(data2),
@@ -274,6 +277,31 @@ void cb_trans_conv(pmtransconv_t event, 
                                        (char *)data2,
                                        (char *)data2);
                        break;
+                case PM_TRANS_CONV_REMOVE_PKGS:
+                    {
+                        /* Allocate a buffer big enough to hold all of the
+                           package names */
+                        char *packagenames;
+                        alpm_list_t *unresolved = (alpm_list_t *) data1;
+                        alpm_list_t *i;
+                        int len = 1, /* for trailing \0 */ where = 0, count = 
0;
+                        for (i = unresolved; i; i = i->next) {
+                            count += 1;
+                            len += 3 /* for \t, comma, and \n */ +
+                                strlen(alpm_pkg_get_name(i->data));
+                        }
+                        packagenames = (char *) malloc(len);
+                        for (i = unresolved; i; i = i->next) {
+                            where += snprintf(&(packagenames[where]), len - 
where, "\t%s%s\n", 
+                                              alpm_pkg_get_name(i->data), 
(i->next) ? "," : "");
+                        }
+                        *response = yesno(_(":: the following package%s cannot 
be upgraded due to unresolvable "
+                                                                               
        "dependencies:\n%s\nDo you want to skip %s package%s for this 
upgrade?"),
+                                          (count > 1) ? "s" : "", 
packagenames, (count > 1) ? "these" : "this",
+                                          (count > 1) ? "s" : "");
+                        free(packagenames);
+                    }
+                    break;
                case PM_TRANS_CONV_LOCAL_NEWER:
                        if(!config->op_s_downloadonly) {
                                *response = yesno(_(":: %s-%s: local version is 
newer. Upgrade anyway?"),
diff -rupN -x '*\.git*' pacman/src/pacman/conf.c.rej 
pacman-fixbug9395/src/pacman/conf.c.rej
--- pacman/src/pacman/conf.c.rej        1970-01-01 12:00:00.000000000 +1200
+++ pacman-fixbug9395/src/pacman/conf.c.rej     2008-12-31 17:53:00.000000000 
+1300
@@ -0,0 +1,16 @@
+***************
+*** 48,53 ****
+       newconfig->dbpath = NULL;
+       newconfig->logfile = NULL;
+       newconfig->syncfirst = NULL;
+  
+       return(newconfig);
+  }
+--- 48,54 ----
+       newconfig->dbpath = NULL;
+       newconfig->logfile = NULL;
+       newconfig->syncfirst = NULL;
++         newconfig->noignoreprompt = 0;
+  
+       return(newconfig);
+  }
diff -rupN -x '*\.git*' pacman/src/pacman/conf.h 
pacman-fixbug9395/src/pacman/conf.h
--- pacman/src/pacman/conf.h    2008-12-31 16:45:31.000000000 +1300
+++ pacman-fixbug9395/src/pacman/conf.h 2008-12-31 18:04:47.000000000 +1300
@@ -69,6 +69,7 @@ typedef struct __config_t {
         * downloaded of the total download list */
        unsigned short totaldownload;
        unsigned short cleanmethod; /* select -Sc behavior */
+       unsigned short noignoreprompt; /* don't ask user to confirm ignored 
packages */
        alpm_list_t *syncfirst;
 } config_t;
 
diff -rupN -x '*\.git*' pacman/src/pacman/pacman.c 
pacman-fixbug9395/src/pacman/pacman.c
--- pacman/src/pacman/pacman.c  2008-12-31 16:45:31.000000000 +1300
+++ pacman-fixbug9395/src/pacman/pacman.c       2008-12-31 17:53:00.000000000 
+1300
@@ -137,15 +137,16 @@ static void usage(int op, const char * c
                                 "                       ignore a group upgrade 
(can be used more than once)\n"));
                        printf(_("  -q, --quiet          show less information 
for query and search\n"));
                }
-               printf(_("      --config <path>  set an alternate configuration 
file\n"));
-               printf(_("      --logfile <path> set an alternate log file\n"));
-               printf(_("      --noconfirm      do not ask for any 
confirmation\n"));
-               printf(_("      --noprogressbar  do not show a progress bar 
when downloading files\n"));
-               printf(_("      --noscriptlet    do not execute the install 
scriptlet if one exists\n"));
-               printf(_("  -v, --verbose        be verbose\n"));
-               printf(_("  -r, --root <path>    set an alternate installation 
root\n"));
-               printf(_("  -b, --dbpath <path>  set an alternate database 
location\n"));
-               printf(_("      --cachedir <dir> set an alternate package cache 
location\n"));
+               printf(_("      --config <path>   set an alternate 
configuration file\n"));
+               printf(_("      --logfile <path>  set an alternate log 
file\n"));
+               printf(_("      --noconfirm       do not ask for any 
confirmation\n"));
+               printf(_("      --noprogressbar   do not show a progress bar 
when downloading files\n"));
+               printf(_("      --noscriptlet     do not execute the install 
scriptlet if one exists\n"));
+               printf(_("      --noignoreprompt  don't prompt to confirm 
packages in IngorePkg and IgnoreGroup\n"));
+               printf(_("  -v, --verbose         be verbose\n"));
+               printf(_("  -r, --root <path>     set an alternate installation 
root\n"));
+               printf(_("  -b, --dbpath <path>   set an alternate database 
location\n"));
+               printf(_("      --cachedir <dir>  set an alternate package 
cache location\n"));
        }
 }
 
@@ -366,6 +367,7 @@ static int parseargs(int argc, char *arg
                {"debug",      optional_argument, 0, 1003},
                {"noprogressbar", no_argument,    0, 1004},
                {"noscriptlet", no_argument,      0, 1005},
+               {"noignoreprompt", no_argument,   0, 1006},
                {"cachedir",   required_argument, 0, 1007},
                {"asdeps",     no_argument,       0, 1008},
                {"logfile",    required_argument, 0, 1009},
@@ -422,6 +424,7 @@ static int parseargs(int argc, char *arg
                                break;
                        case 1004: config->noprogressbar = 1; break;
                        case 1005: config->flags |= PM_TRANS_FLAG_NOSCRIPTLET; 
break;
+                       case 1006: config->noignoreprompt = 1; break;
                        case 1007:
                                if(alpm_option_add_cachedir(optarg) != 0) {
                                        pm_printf(PM_LOG_ERROR, _("problem 
adding cachedir '%s' (%s)\n"),
@@ -680,6 +683,9 @@ static int _parseconfig(const char *file
                                } else if(strcmp(key, "TotalDownload") == 0) {
                                        config->totaldownload = 1;
                                        pm_printf(PM_LOG_DEBUG, "config: 
totaldownload\n");
+                               } else if(strcmp(key, "NoIgnorePrompt") == 0) {
+                                       config->noignoreprompt = 1;
+                                       pm_printf(PM_LOG_DEBUG, "config: 
noignoreprompt\n");
                                } else {
                                        pm_printf(PM_LOG_ERROR, _("config file 
%s, line %d: directive '%s' not recognized.\n"),
                                                        file, linenum, key);
_______________________________________________
pacman-dev mailing list
[email protected]
http://archlinux.org/mailman/listinfo/pacman-dev

Reply via email to