[pacman-dev] [PATCH] Add CheckNewVersion option.

Dan McGee dpmcgee at gmail.com
Mon Feb 18 01:33:35 EST 2008


On Feb 17, 2008 9:12 AM, Chantry Xavier <shiningxc at gmail.com> wrote:
> This patch offers a way to fix FS#9228.
> By putting "CheckNewVersion = pacman" in pacman.conf, the version check will
> happen before the transaction really starts, and before any replacements is
> made.
> Otherwise, no version check is done.
>
> The sync301 pactest was updated to use this CheckNewVersion option.
>
> Example session with CheckNewVersion = pacman, and a newer pacman version
> available :
> $ pacman -Su (or pacman -S <any targets>)
> :: the following packages should be upgraded first :
>     pacman
> :: Do you want to cancel the current operation
> :: and upgrade these packages now? [Y/n]
>
> resolving dependencies...
> looking for inter-conflicts...
>
> Targets: pacman-x.y.z-t
>
> Total Download Size:    x.xx MB
> Total Installed Size:   x.xx MB
>
> Proceed with installation? [Y/n] n
>
> As Nagy previously noted, doing this check on any -S operations might look
> intrusive, but it can be required.
> For example, the case where you want to install a package with versioned
> provisions, using a pacman version which didn't support that feature yet
> (and there is already a newer pacman in sync db supporting it).

Hmm, so say I put glibc in my CheckNewVersion option list, and I am
not running the version in the sync DB. If I were to do this:
pacman -S mpd

I would be prompted to upgrade glibc? This seems a bit overreaching,
as this is exactly what I did today on my server box. :) I would
prefer it only be invoked on a --sysupgrade operation. But you do have
a valid point.

I'm also not sure about "CheckNewVersion" from a naming standpoint.
Maybe something more like "UpgradeFirst" or something? We check for a
new version of every package, so the name seems a bit misleading.


> Signed-off-by: Chantry Xavier <shiningxc at gmail.com>
> ---
>  doc/pacman.conf.5.txt    |    6 +++
>  pactest/pmtest.py        |    3 +-
>  pactest/tests/sync301.py |    4 ++-
>  src/pacman/conf.c        |    2 +
>  src/pacman/conf.h        |    1 +
>  src/pacman/pacman.c      |    8 ++++
>  src/pacman/sync.c        |   81 ++++++++++++++++++++++------------------------
>  7 files changed, 61 insertions(+), 44 deletions(-)
>
> diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt
> index e8f7454..c48ec68 100644
> --- a/doc/pacman.conf.5.txt
> +++ b/doc/pacman.conf.5.txt
> @@ -80,6 +80,12 @@ Options
>         Instructs pacman to ignore any upgrades for this package when performing
>         a '\--sysupgrade'.
>
> +*CheckNewVersion =* package ...::
> +       Instructs pacman to check for newer version of these packages before any
> +       '-S' or '-Su' operation. The user will then have the choice to either cancel
> +       the current operation and install these packages or go on with the current
> +       operation. This could typically be done for pacman itself.
> +
>  *IgnoreGroup =* group ...::
>         Instructs pacman to ignore any upgrades for all packages in this
>         group when performing a '\--sysupgrade'.
> diff --git a/pactest/pmtest.py b/pactest/pmtest.py
> index d54d7ba..9b45384 100755
> --- a/pactest/pmtest.py
> +++ b/pactest/pmtest.py
> @@ -83,7 +83,8 @@ class pmtest:
>              "noupgrade": [],
>              "ignorepkg": [],
>              "ignoregroup": [],
> -            "noextract": []
> +            "noextract": [],
> +            "checknewversion": [],
>          }
>
>          # Test rules
> diff --git a/pactest/tests/sync301.py b/pactest/tests/sync301.py
> index e8526b9..cde08c6 100644
> --- a/pactest/tests/sync301.py
> +++ b/pactest/tests/sync301.py
> @@ -16,10 +16,12 @@ self.addpkg2db("local", lp)
>  lp1 = pmpkg("pkg1", "1.0-1")
>  self.addpkg2db("local", lp1)
>
> +self.option["checknewversion"] = ["pacman"]
> +
>  self.args = "-Su"
>
>  self.addrule("PACMAN_RETCODE=0")
>  self.addrule("PKG_EXIST=pacman")
>  self.addrule("PKG_VERSION=pacman|1.0-2")
> +self.addrule("PKG_VERSION=pkg1|1.0-1")
>  self.addrule("PKG_EXIST=dep")
> -self.addrule("PKG_REQUIREDBY=dep|pacman")
> diff --git a/src/pacman/conf.c b/src/pacman/conf.c
> index bf3a462..72c1408 100644
> --- a/src/pacman/conf.c
> +++ b/src/pacman/conf.c
> @@ -45,6 +45,7 @@ config_t *config_new(void)
>         newconfig->rootdir = NULL;
>         newconfig->dbpath = NULL;
>         newconfig->logfile = NULL;
> +       newconfig->checknewversion = NULL;
>
>         return(newconfig);
>  }
> @@ -55,6 +56,7 @@ int config_free(config_t *oldconfig)
>                 return(-1);
>         }
>
> +       FREELIST(oldconfig->checknewversion);
>         free(oldconfig->configfile);
>         free(oldconfig->rootdir);
>         free(oldconfig->dbpath);
> diff --git a/src/pacman/conf.h b/src/pacman/conf.h
> index f804f56..2bbfb10 100644
> --- a/src/pacman/conf.h
> +++ b/src/pacman/conf.h
> @@ -70,6 +70,7 @@ typedef struct __config_t {
>         unsigned short totaldownload; /* When downloading, display the amount
>                                          downloaded, rate, ETA, and percent
>                                          downloaded of the total download list */
> +       alpm_list_t *checknewversion;
>  } config_t;
>
>  /* Operations */
> diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
> index f185320..31af78d 100644
> --- a/src/pacman/pacman.c
> +++ b/src/pacman/pacman.c
> @@ -515,6 +515,11 @@ static int parseargs(int argc, char *argv[])
>         return(0);
>  }
>
> +/* helper for being used with setrepeatingoption */
> +void option_add_checknewversion(const char *name) {
> +       config->checknewversion = alpm_list_add(config->checknewversion, strdup(name));
> +}
> +
>  /** Add repeating options such as NoExtract, NoUpgrade, etc to libalpm
>   * settings. Refactored out of the parseconfig code since all of them did
>   * the exact same thing and duplicated code.
> @@ -675,6 +680,9 @@ static int _parseconfig(const char *file, const char *givensection,
>                                         } else if(strcmp(key, "HoldPkg") == 0
>                                                         || strcmp(upperkey, "HOLDPKG") == 0) {
>                                                 setrepeatingoption(ptr, "HoldPkg", alpm_option_add_holdpkg);
> +                                       } else if(strcmp(key, "CheckNewVersion") == 0
> +                                                       || strcmp(upperkey, "CHECKNEWVERSION") == 0) {
> +                                               setrepeatingoption(ptr, "CheckNewVersion", option_add_checknewversion);
>                                         } else if(strcmp(key, "DBPath") == 0 || strcmp(upperkey, "DBPATH") == 0) {
>                                                 /* don't overwrite a path specified on the command line */
>                                                 if(!config->dbpath) {
> diff --git a/src/pacman/sync.c b/src/pacman/sync.c
> index bb2a8bb..66bd598 100644
> --- a/src/pacman/sync.c
> +++ b/src/pacman/sync.c
> @@ -488,6 +488,24 @@ static int sync_list(alpm_list_t *syncs, alpm_list_t *targets)
>         return(0);
>  }
>
> +static alpm_list_t *checknewversion() {
> +       alpm_list_t *i, *res = NULL;
> +
> +       for(i = config->checknewversion; i; i = alpm_list_next(i)) {
> +               char *pkgname = alpm_list_getdata(i);
> +               pmpkg_t *pkg = alpm_db_get_pkg(alpm_option_get_localdb(), pkgname);
> +               if(pkg == NULL) {
> +                       continue;
> +               }
> +
> +               if(alpm_sync_newversion(pkg, alpm_option_get_syncdbs())) {
> +                       res = alpm_list_add(res, strdup(pkgname));
> +               }
> +       }
> +
> +       return(res);
> +}
> +
>  static int sync_trans(alpm_list_t *targets)
>  {
>         int retval = 0;
> @@ -507,7 +525,6 @@ static int sync_trans(alpm_list_t *targets)
>         }
>
>         if(config->op_s_upgrade) {
> -               alpm_list_t *pkgs, *i;
>                 printf(_(":: Starting full system upgrade...\n"));
>                 alpm_logaction("starting full system upgrade\n");
>                 if(alpm_trans_sysupgrade() == -1) {
> @@ -515,46 +532,6 @@ static int sync_trans(alpm_list_t *targets)
>                         retval = 1;
>                         goto cleanup;
>                 }
> -
> -               if(!(alpm_trans_get_flags() & (PM_TRANS_FLAG_DOWNLOADONLY | PM_TRANS_FLAG_PRINTURIS))) {
> -                       /* check if pacman itself is one of the packages to upgrade.
> -                        * this can prevent some of the "syntax error" problems users can have
> -                        * when sysupgrade'ing with an older version of pacman.
> -                        */
> -                       pkgs = alpm_trans_get_pkgs();
> -                       for(i = pkgs; i; i = alpm_list_next(i)) {
> -                               pmsyncpkg_t *sync = alpm_list_getdata(i);
> -                               pmpkg_t *spkg = alpm_sync_get_pkg(sync);
> -                               /* TODO pacman name should probably not be hardcoded. In addition, we
> -                                * have problems on an -Syu if pacman has to pull in deps, so recommend
> -                                * an '-S pacman' operation */
> -                               if(strcmp("pacman", alpm_pkg_get_name(spkg)) == 0) {
> -                                       printf("\n");
> -                                       printf(_(":: pacman has detected a newer version of itself.\n"));
> -                                       if(yesno(_(":: Do you want to cancel the current operation\n"
> -                                                  ":: and install the new pacman version now? [Y/n] "))) {
> -                                               if(alpm_trans_release() == -1) {
> -                                                       fprintf(stderr, _("error: failed to release transaction (%s)\n"),
> -                                                           alpm_strerrorlast());
> -                                                       retval = 1;
> -                                                       goto cleanup;
> -                                               }
> -                                               if(alpm_trans_init(PM_TRANS_TYPE_SYNC, config->flags,
> -                                                  cb_trans_evt, cb_trans_conv, cb_trans_progress) == -1) {
> -                                                       fprintf(stderr, _("error: failed to init transaction (%s)\n"),
> -                                                           alpm_strerrorlast());
> -                                                       return(1);
> -                                               }
> -                                               if(alpm_trans_addtarget("pacman") == -1) {
> -                                                       fprintf(stderr, _("error: pacman: %s\n"), alpm_strerrorlast());
> -                                                       retval = 1;
> -                                                       goto cleanup;
> -                                               }
> -                                               break;
> -                                       }
> -                               }
> -                       }
> -               }
Oh so much cleaner now. :)

>         } else {
>                 alpm_list_t *i;
>
> @@ -795,7 +772,27 @@ int pacman_sync(alpm_list_t *targets)
>         }
>
>         if(needs_transaction()) {
> -               if(sync_trans(targets) == 1) {
> +               alpm_list_t *targs = alpm_list_strdup(targets);
> +               if(!(config->flags & (PM_TRANS_FLAG_DOWNLOADONLY | PM_TRANS_FLAG_PRINTURIS))) {

Presumably could just add a check for config->op_s_upgrade here. I
just don't know that it makes sense to honor this variable for all -S
ops and not just -Su.

> +                       /* check for newer packages version */
> +                       alpm_list_t *newversion = checknewversion();
> +                       if(newversion) {
> +                               printf(_(":: the following packages should be upgraded first :\n"));
> +                               list_display("   ", newversion);
> +                               if(yesno(_(":: Do you want to cancel the current operation\n"
> +                                                               ":: and upgrade these packages now? [Y/n] "))) {
> +                                       FREELIST(targs);
> +                                       targs = newversion;
> +                                       config->flags = 0;
> +                                       config->op_s_upgrade = 0;
> +                               }
> +                               printf("\n");
> +                       }
> +               }
> +
> +               int ret = sync_trans(targs);
> +               FREELIST(targs);
> +               if(ret == 1) {
>                         return(1);
>                 }
>         }
> --
> 1.5.4




More information about the pacman-dev mailing list