diff options
64 files changed, 1480 insertions, 892 deletions
diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..fb151daf --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.py diff=python diff --git a/Makefile.am b/Makefile.am index ed9a34d3..2f5e7a7b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,7 +12,7 @@ EXTRA_DIST = HACKING # Sample makepkg prototype files pkgdatadir = ${datadir}/${PACKAGE} -dist_pkgdata_DATA = PKGBUILD.proto proto.install ChangeLog.proto +dist_pkgdata_DATA = PKGBUILD.proto PKGBUILD-split.proto proto.install ChangeLog.proto # run the pactest test suite and vercmp tests check-local: pactest src/pacman src/util diff --git a/PKGBUILD-split.proto b/PKGBUILD-split.proto new file mode 100644 index 00000000..35fb22b9 --- /dev/null +++ b/PKGBUILD-split.proto @@ -0,0 +1,55 @@ +# This is an example of a PKGBUILD for splitting packages. Use this as a +# start to creating your own, and remove these comments. For more information, +# see 'man PKGBUILD'. NOTE: Please fill out the license field for your package! +# If it is unknown, then please put 'unknown'. + +# Contributor: Your Name <youremail@domain.com> +pkgname=('pkg1' 'pkg2') +pkgver=VERSION +pkgrel=1 +pkgdesc="" +arch=() +url="" +license=('GPL') +groups=() +depends=() +makedepends=() +provides=() +conflicts=() +replaces=() +backup=() +options=() +install= +source=($pkgname-$pkgver.tar.gz) +noextract=() +md5sums=() #generate with 'makepkg -g' + +build() { + cd "$srcdir/$pkgname-$pkgver" + ./configure --prefix=/usr + make || return 1 +} + +package_pkg1() { + # options and directives that can be overridden + pkgdesc="" + license=() + groups=() + depends=() + optdepends=() + provides=() + conflicts=() + replaces=() + backup=() + options=() + install= + + make DESTDIR="$pkgdir/" install-pkg1 +} + +package_pkg2() { + # options and directives overrides + pkgdesc="" + + make DESTDIR="$pkgdir/" install-pkg2 +} diff --git a/configure.ac b/configure.ac index ee26f3bb..216cf760 100644 --- a/configure.ac +++ b/configure.ac @@ -88,9 +88,14 @@ AC_ARG_WITH(db-ext, AS_HELP_STRING([--with-db-ext=ext], [set the file extension used by the database]), [DBEXT=$withval], [DBEXT=.db.tar.gz]) -# Help line for libdownload/libfetch +# Help line for buildscript filename +AC_ARG_WITH(buildscript, + AS_HELP_STRING([--with-buildscript=name], [set the build script name used by makepkg]), + [BUILDSCRIPT=$withval], [BUILDSCRIPT=PKGBUILD]) + +# Help line for libfetch AC_ARG_ENABLE(internal-download, - AS_HELP_STRING([--disable-internal-download], [do not build with libdownload/libfetch support]), + AS_HELP_STRING([--disable-internal-download], [do not build with libfetch support]), [internaldownload=$enableval], [internaldownload=yes]) # Help line for documentation @@ -131,17 +136,14 @@ AM_GNU_GETTEXT_VERSION(0.13.1) AC_CHECK_LIB([archive], [archive_read_data], , AC_MSG_ERROR([libarchive is needed to compile pacman!])) -# Enable or disable usage of libdownload/libfetch -# - this is a nested check- first see if we need a library, if we do then -# check for libdownload first, then fallback to libfetch, then die -AC_MSG_CHECKING(whether to link with download library) +# Enable or disable usage of libfetch +AC_MSG_CHECKING(whether to link with libfetch) if test "x$internaldownload" = "xyes" ; then AC_MSG_RESULT(yes) AC_DEFINE([INTERNAL_DOWNLOAD], , [Use internal download library]) # Check for a download library if it was actually requested - AC_CHECK_LIB([download], [downloadParseURL], , - AC_CHECK_LIB([fetch], [fetchParseURL], , - AC_MSG_ERROR([libdownload or libfetch are needed to compile with internal download support])) ) + AC_CHECK_LIB([fetch], [fetchParseURL], , + AC_MSG_ERROR([libfetch is needed to compile with internal download support]) ) else AC_MSG_RESULT(no) fi @@ -188,7 +190,7 @@ case "${host_os}" in ;; darwin*) host_os_darwin=yes - SIZECMD="stat -f %z" + SIZECMD="/usr/bin/stat -f %z" ;; esac @@ -314,6 +316,9 @@ AC_DEFINE_UNQUOTED([SRCEXT], "$SRCEXT", [The file extension used by pacman sourc # Set database file extension AC_SUBST(DBEXT) AC_DEFINE_UNQUOTED([DBEXT], "$DBEXT", [The file extension used by pacman databases]) +# Set makepkg build script name +AC_SUBST(BUILDSCRIPT) +AC_DEFINE_UNQUOTED([BUILDSCRIPT], "$BUILDSCRIPT", [The build script name used by makepkg]) # Configuration files AC_CONFIG_FILES([ @@ -326,6 +331,7 @@ doc/Makefile etc/Makefile po/Makefile.in pactest/Makefile +pactest/tests/Makefile contrib/Makefile Makefile ]) @@ -361,6 +367,7 @@ ${PACKAGE_NAME}: package extension : ${PKGEXT} source pkg extension : ${SRCEXT} database extension : ${DBEXT} + build script name : ${BUILDSCRIPT} Compilation options: Run make in doc/ dir : ${wantdoc} diff --git a/contrib/pacdiff b/contrib/pacdiff index 64936491..5138d91c 100755 --- a/contrib/pacdiff +++ b/contrib/pacdiff @@ -1,5 +1,5 @@ -#!/bin/sh -# pacdiff : a simple pacnew/pacorig/pacsave updater for /etc/ +#!/bin/bash +# pacdiff : a simple pacnew/pacorig/pacsave updater # # Copyright (c) 2007 Aaron Griffin <aaronmgriffin@gmail.com> # @@ -17,29 +17,60 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -# Original http://phraktured.net/config/bin/pacdiff - diffprog=${DIFFPROG:-vimdiff} -for x in $(find /etc/ -name "*.pacnew" -o -name "*.pacorig" -o -name "*.pacsave") -do - echo "File: ${x%.pac*}" - chk="$(cmp $x ${x%.pac*})" - if [ -z "${chk}" ]; then - echo " Files are identical, removing..." - rm $x - else - echo -n " File differences found. (V)iew, (S)kip, (R)emove: [v/s/r] " - read c - c="$(echo $c| tr A-Z a-z)" #tolower - if [ "$c" = "r" ]; then - rm $x - elif [ "$c" = "s" ]; then - continue - else - [ "$c" = "n" -o "$c" = "N" ] || $diffprog $x ${x%.pac*} - echo -n " Remove file? [Y/n] " - read c - [ "$c" = "n" -o "$c" = "N" ] || rm $x - fi - fi -done +locate=0 + +usage() { + echo "pacdiff : a simple pacnew/pacorig/pacsave updater" + echo "Usage : pacdiff [-l]" + echo "The -l/--locate flag makes pacdiff use locate rather than find" +} + +cmd() { + if [ $locate -eq 1 ]; then + locate -0 -e -b \*.pacnew \*.pacorig \*.pacsave + else + find /etc/ \( -name \*.pacnew -o -name \*.pacorig -o -name \*.pacsave \) -print0 + fi +} + +if [ $# -gt 0 ]; then + case $1 in + -l|--locate) + locate=1;; + *) + usage; exit 0;; + esac +fi + +# see http://mywiki.wooledge.org/BashFAQ/020 +while IFS= read -u 3 -r -d '' pacfile; do + file="${pacfile%.pac*}" + echo "File: $file" + if [ ! -f "$file" ]; then + echo " $file does not exist" + rm -i "$pacfile" + continue + fi + check="$(cmp "$pacfile" "$file")" + if [ -z "${check}" ]; then + echo " Files are identical, removing..." + rm "$pacfile" + else + echo -n " File differences found. (V)iew, (S)kip, (R)emove: [v/s/r] " + while read c; do + case $c in + r|R) rm "$pacfile"; break ;; + v|V) + $diffprog "$pacfile" "$file" + rm -i "$pacfile"; break ;; + s|S) break ;; + *) echo -n " Invalid answer. Try again: [v/s/r] "; continue ;; + esac + done + fi +done 3< <(cmd) + +exit 0 + +# vim: set ts=2 sw=2 noet: diff --git a/doc/PKGBUILD.5.txt b/doc/PKGBUILD.5.txt index c1ad4df8..f8ed7f26 100644 --- a/doc/PKGBUILD.5.txt +++ b/doc/PKGBUILD.5.txt @@ -187,8 +187,8 @@ name. The syntax is: `$$source=('filename::url')$$` disable this option. *docs*;; - Save doc and info directories. If you wish to delete doc and - info directories, specify `!docs` in the array. + Save doc directories. If you wish to delete doc directories, + specify `!docs` in the array. *libtool*;; Leave libtool (.la) files in packages. Specify `!libtool` to @@ -198,7 +198,7 @@ name. The syntax is: `$$source=('filename::url')$$` Leave empty directories in packages. *zipman*;; - Compress man pages with gzip. + Compress man and info pages with gzip. *ccache*;; Allow the use of ccache during build. More useful in its negative @@ -256,6 +256,14 @@ If you create any variables of your own in the build function, it is recommended to use the bash `local` keyword to scope the variable to inside the build function. +package() Function +------------------ +An optional package() function can be specified in addition to the build() function. +This function is run immediately after the build() function. When specified in +combination with the fakeroot BUILDENV option in linkman:makepkg.conf[5], fakeroot +usage will be limited to running the packaging stage. The build() function will be +run as the user calling makepkg. + Install/Upgrade/Remove Scripting -------------------------------- Pacman has the ability to store and execute a package-specific script when it diff --git a/doc/makepkg.8.txt b/doc/makepkg.8.txt index 74285aaf..4bb37808 100644 --- a/doc/makepkg.8.txt +++ b/doc/makepkg.8.txt @@ -52,6 +52,9 @@ Options Removes all cached source files from the directory specified in `SRCDEST` in linkman:makepkg.conf[5]. +*--config* <`/path/to/config`>:: + Use an alternate config file instead of the `/etc/makepkg.conf` default; + *-d, \--nodeps*:: Do not perform any dependency checks. This will let you override and ignore any dependencies required. There is a good chance this option diff --git a/doc/makepkg.conf.5.txt b/doc/makepkg.conf.5.txt index 9fd52e64..04fe2bb7 100644 --- a/doc/makepkg.conf.5.txt +++ b/doc/makepkg.conf.5.txt @@ -61,6 +61,11 @@ Options **CXXFLAGS=**"cxxflags":: Flags used for the C++ compiler; see CFLAGS for more info. +**LDFLAGS=**"ldflags":: + Flags used for the linker. Several options may be specified with common + usage resembling ``-Wl,--hash-style=gnu''. Read ld(1) for more details on + available linker flags. + **MAKEFLAGS=**"makeflags":: This is often used to set the number of jobs used, for example, `-j2`. Other flags that make accepts can also be passed. @@ -98,7 +103,7 @@ Options running in the DistCC cluster. In addition, you will want to modify your `MAKEFLAGS`. -**OPTIONS=(**strip docs libtool emptydirs zipman**)**:: +**OPTIONS=(**strip !docs libtool emptydirs zipman**)**:: This array contains options that affect the default packaging. They are equivalent to options that can be placed in the PKGBUILD; the defaults are shown here. All options should always be left in the array; to enable or @@ -111,8 +116,9 @@ Options option. *docs*;; - Save doc and info directories. If you wish to delete doc and info - directories, specify `!docs` in the array. + Save doc directories. If you wish to delete doc directories, specify + `!docs` in the array. The directories affected are specified by the + `DOC_DIRS` variable. *libtool*;; Leave libtool (.la) files in packages. Specify `!libtool` to remove @@ -122,14 +128,26 @@ Options Leave empty directories in packages. *zipman*;; - Compress man pages with gzip. + Compress manual (man and info) pages with gzip. The directories + affected are specified by the `MAN_DIRS` variable. + + *purge*;; + Remove files specified by the `PURGE_TARGETS` variable from the + package. **INTEGRITY_CHECK=(**check1 ...**)**:: File integrity checks to use. Multiple checks may be specified; this affects both generation and checking. The current valid options are: `md5`, `sha1`, `sha256`, `sha384`, and `sha512`. -**DOC_DIRS=(**usr/{,share/}{info,doc} ...**)**:: +**MAN_DIRS=(**{usr{,/local}{,/share},opt/*}/{man,info} ...**)**:: + If `zipman` is specified in the OPTIONS array, this variable will + instruct makepkg where to look to compress manual (man and info) + pages. If you build packages that are located in opt/, you may need + to add the directory to this array. *NOTE:* Do not add the leading + slash to the directory name. + +**DOC_DIRS=(**usr/{,share/}{doc,gtk-doc} ...**)**:: If `!docs` is specified in the OPTIONS array, this variable will instruct makepkg where to look to remove docs. If you build packages that are located in opt/, you may need to add the directory to this @@ -142,6 +160,11 @@ Options to this array. *NOTE:* Do not add the leading slash to the directory name. +**PURGE_TARGETS=(**usr/{,share}/info/dir .podlist *.pod...**)**:: + If `purge` is specified in the OPTIONS array, this variable will + instruct makepkg which files to remove from the package. This is + useful for index files that are added by multiple packages. + **PKGDEST=**"/path/to/folder":: If this value is not set, packages will by default be placed in the current directory (location of the linkman:PKGBUILD[5]). Many people @@ -157,7 +180,7 @@ Options This value is used when querying a package to see who was the builder. It is recommended you change this to your name and email address. -*BUILDSCRIPT*, *PKGEXT*, *SRCEXT*, *DB_COMPRESSION*, *DB_CHECKSUMS*:: +*PKGEXT*, *SRCEXT*:: Do not touch these unless you know what you are doing. diff --git a/etc/Makefile.am b/etc/Makefile.am index b4f4972e..55c28c3b 100644 --- a/etc/Makefile.am +++ b/etc/Makefile.am @@ -20,9 +20,10 @@ edit = sed \ -e 's|@ROOTDIR[@]|$(ROOTDIR)|g' $(dist_sysconf_DATA): Makefile - rm -f $@ $@.tmp - $(edit) `test -f ./$@.in || echo $(srcdir)/`$@.in >$@.tmp - mv $@.tmp $@ + @echo ' ' GEN $@; + @rm -f $@ $@.tmp + @$(edit) `test -f ./$@.in || echo $(srcdir)/`$@.in >$@.tmp + @mv $@.tmp $@ makepkg.conf: $(srcdir)/makepkg.conf.in pacman.conf: $(srcdir)/pacman.conf.in diff --git a/etc/makepkg.conf.in b/etc/makepkg.conf.in index 0241a8ec..d8118676 100644 --- a/etc/makepkg.conf.in +++ b/etc/makepkg.conf.in @@ -31,6 +31,7 @@ CHOST="@CHOST@" # -mtune optimizes for an architecture, but builds for whole processor family CFLAGS="@CARCHFLAGS@-mtune=generic -O2 -pipe" CXXFLAGS="@CARCHFLAGS@-mtune=generic -O2 -pipe" +#LDFLAGS="" #-- Make Flags: change this for DistCC/SMP systems #MAKEFLAGS="-j2" @@ -58,23 +59,28 @@ BUILDENV=(fakeroot !distcc color !ccache !xdelta) # These are default values for the options=() settings ######################################################################### # -# Default: OPTIONS=(strip docs libtool emptydirs zipman) +# Default: OPTIONS=(strip docs libtool emptydirs zipman purge) # A negated option will do the opposite of the comments below. # -#-- strip: Strip symbols from binaries/libraries -#-- docs: Save doc and info directories +#-- strip: Strip symbols from binaries/libraries in STRIP_DIRS +#-- docs: Save doc directories specified by DOC_DIRS #-- libtool: Leave libtool (.la) files in packages #-- emptydirs: Leave empty directories in packages -#-- zipman: Compress manpages with gzip +#-- zipman: Compress manual (man and info) pages in MAN_DIRS with gzip +#-- purge: Remove files specified by PURGE_TARGETS # -OPTIONS=(strip docs libtool emptydirs zipman) +OPTIONS=(strip docs libtool emptydirs zipman purge) #-- File integrity checks to use. Valid: md5, sha1, sha256, sha384, sha512 INTEGRITY_CHECK=(md5) -#-- Info and doc directories to remove (if option set correctly above) -DOC_DIRS=(usr/{,share/}{info,doc,gtk-doc} opt/*/{info,doc,gtk-doc}) -#-- Directories to be searched for the strip option (if option set correctly above) +#-- Manual (man and info) directories to compress (if zipman is specified) +MAN_DIRS=({usr{,/local}{,/share},opt/*}/{man,info}) +#-- Doc directories to remove (if !docs is specified) +DOC_DIRS=(usr/{,share/}{doc,gtk-doc} opt/*/{doc,gtk-doc}) +#-- Directories to be searched for the strip option (if strip is specified) STRIP_DIRS=(bin lib sbin usr/{bin,lib,sbin,local/{bin,lib,sbin}} opt/*/{bin,lib,sbin}) +#-- Files to be removed from all packages (if purge is specified) +PURGE_TARGETS=(usr/{,share}/info/dir .packlist *.pod) ######################################################################### # PACKAGE OUTPUT @@ -90,16 +96,13 @@ STRIP_DIRS=(bin lib sbin usr/{bin,lib,sbin,local/{bin,lib,sbin}} opt/*/{bin,lib, #PACKAGER="John Doe <john@doe.com>" ######################################################################### -# BUILDSCRIPT/EXTENSION DEFAULTS +# EXTENSION DEFAULTS ######################################################################### # # WARNING: Do NOT modify these variables unless you know what you are # doing. # -BUILDSCRIPT='PKGBUILD' PKGEXT='@PKGEXT@' SRCEXT='@SRCEXT@' -DB_COMPRESSION='gz' -DB_CHECKSUMS=(md5) # vim: set ft=sh ts=2 sw=2 et: diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index 838f5a6d..6eb2085e 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -114,7 +114,7 @@ int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data) /* look for unsatisfied dependencies */ _alpm_log(PM_LOG_DEBUG, "looking for unsatisfied dependencies\n"); - lp = alpm_checkdeps(db, 1, NULL, trans->packages); + lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, NULL, trans->packages); if(lp != NULL) { if(data) { *data = lp; @@ -456,8 +456,8 @@ static int extract_single_file(struct archive *archive, return(1); } - hash_local = alpm_get_md5sum(filename); - hash_pkg = alpm_get_md5sum(checkfile); + hash_local = alpm_compute_md5sum(filename); + hash_pkg = alpm_compute_md5sum(checkfile); /* append the new md5 hash to it's respective entry * in newpkg's backup (it will be the new orginal) */ @@ -618,7 +618,7 @@ static int extract_single_file(struct archive *archive, } _alpm_log(PM_LOG_DEBUG, "appending backup entry for %s\n", filename); - hash = alpm_get_md5sum(filename); + hash = alpm_compute_md5sum(filename); MALLOC(backup, backup_len, RET_ERR(PM_ERR_MEMORY, -1)); sprintf(backup, "%s\t%s", oldbackup, hash); @@ -650,17 +650,18 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count, if(local) { is_upgrade = 1; - EVENT(trans, PM_TRANS_EVT_UPGRADE_START, newpkg, NULL); - _alpm_log(PM_LOG_DEBUG, "upgrading package %s-%s\n", - newpkg->name, newpkg->version); - /* we'll need to save some record for backup checks later */ oldpkg = _alpm_pkg_dup(local); /* make sure all infos are loaded because the database entry * will be removed soon */ _alpm_db_read(oldpkg->origin_data.db, oldpkg, INFRQ_ALL); + + EVENT(trans, PM_TRANS_EVT_UPGRADE_START, newpkg, oldpkg); + _alpm_log(PM_LOG_DEBUG, "upgrading package %s-%s\n", + newpkg->name, newpkg->version); + /* copy over the install reason */ - newpkg->reason = alpm_pkg_get_reason(local); + newpkg->reason = alpm_pkg_get_reason(oldpkg); /* pre_upgrade scriptlet */ if(alpm_pkg_has_scriptlet(newpkg) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 16b48a0a..3836d608 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -132,11 +132,6 @@ void alpm_option_add_ignorepkg(const char *pkg); void alpm_option_set_ignorepkgs(alpm_list_t *ignorepkgs); int alpm_option_remove_ignorepkg(const char *pkg); -alpm_list_t *alpm_option_get_holdpkgs(); -void alpm_option_add_holdpkg(const char *pkg); -void alpm_option_set_holdpkgs(alpm_list_t *holdpkgs); -int alpm_option_remove_holdpkg(const char *pkg); - alpm_list_t *alpm_option_get_ignoregrps(); void alpm_option_add_ignoregrp(const char *grp); void alpm_option_set_ignoregrps(alpm_list_t *ignoregrps); @@ -170,10 +165,10 @@ int alpm_db_setserver(pmdb_t *db, const char *url); int alpm_db_update(int level, pmdb_t *db); pmpkg_t *alpm_db_get_pkg(pmdb_t *db, const char *name); -alpm_list_t *alpm_db_getpkgcache(pmdb_t *db); +alpm_list_t *alpm_db_get_pkgcache(pmdb_t *db); pmgrp_t *alpm_db_readgrp(pmdb_t *db, const char *name); -alpm_list_t *alpm_db_getgrpcache(pmdb_t *db); +alpm_list_t *alpm_db_get_grpcache(pmdb_t *db); alpm_list_t *alpm_db_search(pmdb_t *db, const alpm_list_t* needles); /* @@ -218,6 +213,7 @@ alpm_list_t *alpm_pkg_get_deltas(pmpkg_t *pkg); alpm_list_t *alpm_pkg_get_replaces(pmpkg_t *pkg); alpm_list_t *alpm_pkg_get_files(pmpkg_t *pkg); alpm_list_t *alpm_pkg_get_backup(pmpkg_t *pkg); +pmdb_t *alpm_pkg_get_db(pmpkg_t *pkg); void *alpm_pkg_changelog_open(pmpkg_t *pkg); size_t alpm_pkg_changelog_read(void *ptr, size_t size, const pmpkg_t *pkg, const void *fp); @@ -253,8 +249,6 @@ alpm_list_t *alpm_grp_get_pkgs(const pmgrp_t *grp); pmpkg_t *alpm_sync_get_pkg(const pmsyncpkg_t *sync); alpm_list_t *alpm_sync_get_removes(const pmsyncpkg_t *sync); pmpkg_t *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync); -int alpm_sync_sysupgrade(pmdb_t *db_local, - alpm_list_t *dbs_sync, alpm_list_t **syncpkgs); /* * Transactions @@ -282,7 +276,7 @@ typedef enum _pmtransflag_t { PM_TRANS_FLAG_DOWNLOADONLY = 0x200, PM_TRANS_FLAG_NOSCRIPTLET = 0x400, PM_TRANS_FLAG_NOCONFLICTS = 0x800, - PM_TRANS_FLAG_PRINTURIS = 0x1000, + /* 0x1000 flag can go here */ PM_TRANS_FLAG_NEEDED = 0x2000, PM_TRANS_FLAG_ALLEXPLICIT = 0x4000, PM_TRANS_FLAG_UNNEEDED = 0x8000, @@ -364,10 +358,6 @@ typedef enum _pmtransevt_t { * A line of text is passed to the callback. */ PM_TRANS_EVT_SCRIPTLET_INFO, - /** Print URI. - * The database's URI and the package's filename are passed to the callback. - */ - PM_TRANS_EVT_PRINTURI, /** Files will be downloaded from a repository. * The repository's tree name is passed to the callback. */ @@ -382,8 +372,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_HOLDPKG = 0x40 + PM_TRANS_CONV_REMOVE_PKGS = 0x20, } pmtransconv_t; /* Transaction Progress */ @@ -431,7 +420,7 @@ typedef enum _pmdepmod_t { } pmdepmod_t; int alpm_depcmp(pmpkg_t *pkg, pmdepend_t *dep); -alpm_list_t *alpm_checkdeps(pmdb_t *db, int reversedeps, +alpm_list_t *alpm_checkdeps(alpm_list_t *pkglist, int reversedeps, alpm_list_t *remove, alpm_list_t *upgrade); alpm_list_t *alpm_deptest(pmdb_t *db, alpm_list_t *targets); @@ -439,7 +428,7 @@ const char *alpm_miss_get_target(const pmdepmissing_t *miss); pmdepend_t *alpm_miss_get_dep(pmdepmissing_t *miss); const char *alpm_miss_get_causingpkg(const pmdepmissing_t *miss); -alpm_list_t *alpm_checkdbconflicts(pmdb_t *db_local); +alpm_list_t *alpm_checkconflicts(alpm_list_t *pkglist); const char *alpm_conflict_get_package1(pmconflict_t *conflict); const char *alpm_conflict_get_package2(pmconflict_t *conflict); @@ -447,7 +436,7 @@ const char *alpm_conflict_get_package2(pmconflict_t *conflict); pmdepmod_t alpm_dep_get_mod(const pmdepend_t *dep); const char *alpm_dep_get_name(const pmdepend_t *dep); const char *alpm_dep_get_version(const pmdepend_t *dep); -char *alpm_dep_get_string(const pmdepend_t *dep); +char *alpm_dep_compute_string(const pmdepend_t *dep); /* * File conflicts @@ -468,7 +457,7 @@ const char *alpm_fileconflict_get_ctarget(pmfileconflict_t *conflict); */ /* checksums */ -char *alpm_get_md5sum(const char *name); +char *alpm_compute_md5sum(const char *name); /* * Errors @@ -527,11 +516,10 @@ enum _pmerrno_t { PM_ERR_INTERNAL_ERROR, PM_ERR_DB_SYNC, PM_ERR_RETRIEVE, - PM_ERR_PKG_HOLD, PM_ERR_INVALID_REGEX, /* External library errors */ PM_ERR_LIBARCHIVE, - PM_ERR_LIBDOWNLOAD, + PM_ERR_LIBFETCH, PM_ERR_EXTERNAL_DOWNLOAD }; diff --git a/lib/libalpm/be_files.c b/lib/libalpm/be_files.c index 31b23172..0765b8db 100644 --- a/lib/libalpm/be_files.c +++ b/lib/libalpm/be_files.c @@ -113,6 +113,26 @@ static int setlastupdate(const pmdb_t *db, time_t time) return(ret); } +static int checkdbdir(pmdb_t *db) +{ + struct stat buf; + char *path = db->path; + + if(stat(path, &buf) != 0) { + _alpm_log(PM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n", + path); + if(_alpm_makepath(path) != 0) { + RET_ERR(PM_ERR_SYSTEM, -1); + } + } else if(!S_ISDIR(buf.st_mode)) { + _alpm_log(PM_LOG_WARNING, "removing bogus database: %s\n", path); + if(unlink(path) != 0 || _alpm_makepath(path) != 0) { + RET_ERR(PM_ERR_SYSTEM, -1); + } + } + return(0); +} + /** Update a package database * @param force if true, then forces the update, otherwise update only in case * the database isn't up to date @@ -122,7 +142,6 @@ static int setlastupdate(const pmdb_t *db, time_t time) */ int SYMEXPORT alpm_db_update(int force, pmdb_t *db) { - alpm_list_t *lp; char *dbfile, *dbfilepath; time_t newmtime = 0, lastupdate = 0; const char *dbpath; @@ -176,14 +195,9 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db) return(-1); } else { /* remove the old dir */ - _alpm_log(PM_LOG_DEBUG, "flushing database %s\n", db->path); - for(lp = _alpm_db_get_pkgcache(db); lp; lp = lp->next) { - pmpkg_t *pkg = lp->data; - if(pkg && _alpm_db_remove(db, pkg) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not remove database entry %s%s\n"), - db->treename, pkg->name); - RET_ERR(PM_ERR_DB_REMOVE, -1); - } + if(_alpm_rmrf(db->path) != 0) { + _alpm_log(PM_LOG_ERROR, _("could not remove database %s\n"), db->treename); + RET_ERR(PM_ERR_DB_REMOVE, -1); } /* Cache needs to be rebuilt */ @@ -195,6 +209,7 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db) sprintf(dbfilepath, "%s%s" DBEXT, dbpath, db->treename); /* uncompress the sync database */ + checkdbdir(db); ret = _alpm_unpack(dbfilepath, db->path, NULL); if(ret) { free(dbfilepath); @@ -214,36 +229,6 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db) return(0); } -int _alpm_db_open(pmdb_t *db) -{ - ALPM_LOG_FUNC; - - if(db == NULL) { - RET_ERR(PM_ERR_DB_NULL, -1); - } - - _alpm_log(PM_LOG_DEBUG, "opening database from path '%s'\n", db->path); - db->handle = opendir(db->path); - if(db->handle == NULL) { - RET_ERR(PM_ERR_DB_OPEN, -1); - } - - return(0); -} - -void _alpm_db_close(pmdb_t *db) -{ - ALPM_LOG_FUNC; - - if(db == NULL) { - return; - } - - if(db->handle) { - closedir(db->handle); - db->handle = NULL; - } -} static int splitname(const char *target, pmpkg_t *pkg) { @@ -290,13 +275,17 @@ int _alpm_db_populate(pmdb_t *db) struct dirent *ent = NULL; struct stat sbuf; char path[PATH_MAX]; + DIR *dbdir; ALPM_LOG_FUNC; ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - rewinddir(db->handle); - while((ent = readdir(db->handle)) != NULL) { + dbdir = opendir(db->path); + if(dbdir == NULL) { + return(0); + } + while((ent = readdir(dbdir)) != NULL) { const char *name = ent->d_name; pmpkg_t *pkg; @@ -311,6 +300,7 @@ int _alpm_db_populate(pmdb_t *db) pkg = _alpm_pkg_new(); if(pkg == NULL) { + closedir(dbdir); return(-1); } /* split the db entry name */ @@ -336,6 +326,7 @@ int _alpm_db_populate(pmdb_t *db) count++; } + closedir(dbdir); db->pkgcache = alpm_list_msort(db->pkgcache, count, _alpm_pkg_cmp); return(count); } @@ -658,12 +649,16 @@ int _alpm_db_prepare(pmdb_t *db, pmpkg_t *info) int retval = 0; char *pkgpath = NULL; - oldmask = umask(0000); + if(checkdbdir(db) != 0) { + return(-1); + } + oldmask = umask(0000); pkgpath = get_pkgpath(db, info); if((retval = mkdir(pkgpath, 0755)) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not create directory %s: %s\n"), pkgpath, strerror(errno)); + _alpm_log(PM_LOG_ERROR, _("could not create directory %s: %s\n"), + pkgpath, strerror(errno)); } free(pkgpath); @@ -826,7 +821,7 @@ int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) if(info->depends) { fputs("%DEPENDS%\n", fp); for(lp = info->depends; lp; lp = lp->next) { - char *depstring = alpm_dep_get_string(lp->data); + char *depstring = alpm_dep_compute_string(lp->data); fprintf(fp, "%s\n", depstring); free(depstring); } diff --git a/lib/libalpm/cache.c b/lib/libalpm/cache.c index 10857792..8d18f3ee 100644 --- a/lib/libalpm/cache.c +++ b/lib/libalpm/cache.c @@ -54,6 +54,7 @@ int _alpm_db_load_pkgcache(pmdb_t *db) return(-1); } + db->pkgcache_loaded = 1; return(0); } @@ -61,7 +62,7 @@ void _alpm_db_free_pkgcache(pmdb_t *db) { ALPM_LOG_FUNC; - if(db == NULL || db->pkgcache == NULL) { + if(db == NULL || !db->pkgcache_loaded) { return; } @@ -71,10 +72,9 @@ void _alpm_db_free_pkgcache(pmdb_t *db) alpm_list_free_inner(db->pkgcache, (alpm_list_fn_free)_alpm_pkg_free); alpm_list_free(db->pkgcache); db->pkgcache = NULL; + db->pkgcache_loaded = 0; - if(db->grpcache) { - _alpm_db_free_grpcache(db); - } + _alpm_db_free_grpcache(db); } alpm_list_t *_alpm_db_get_pkgcache(pmdb_t *db) @@ -85,13 +85,13 @@ alpm_list_t *_alpm_db_get_pkgcache(pmdb_t *db) return(NULL); } - if(!db->pkgcache) { + if(!db->pkgcache_loaded) { _alpm_db_load_pkgcache(db); } /* hmmm, still NULL ?*/ if(!db->pkgcache) { - _alpm_log(PM_LOG_DEBUG, "error: pkgcache is NULL for db '%s'\n", db->treename); + _alpm_log(PM_LOG_DEBUG, "warning: pkgcache is NULL for db '%s'\n", db->treename); } return(db->pkgcache); @@ -104,7 +104,7 @@ int _alpm_db_add_pkgincache(pmdb_t *db, pmpkg_t *pkg) ALPM_LOG_FUNC; - if(db == NULL || pkg == NULL) { + if(db == NULL || !db->pkgcache_loaded || pkg == NULL) { return(-1); } @@ -139,7 +139,7 @@ int _alpm_db_remove_pkgfromcache(pmdb_t *db, pmpkg_t *pkg) ALPM_LOG_FUNC; - if(db == NULL || pkg == NULL) { + if(db == NULL || !db->pkgcache_loaded || pkg == NULL) { return(-1); } @@ -172,7 +172,7 @@ pmpkg_t *_alpm_db_get_pkgfromcache(pmdb_t *db, const char *target) alpm_list_t *pkgcache = _alpm_db_get_pkgcache(db); if(!pkgcache) { - _alpm_log(PM_LOG_DEBUG, "error: failed to get '%s' from NULL pkgcache\n", + _alpm_log(PM_LOG_DEBUG, "warning: failed to get '%s' from NULL pkgcache\n", target); return(NULL); } @@ -192,10 +192,6 @@ int _alpm_db_load_grpcache(pmdb_t *db) return(-1); } - if(db->pkgcache == NULL) { - _alpm_db_load_pkgcache(db); - } - _alpm_log(PM_LOG_DEBUG, "loading group cache for repository '%s'\n", db->treename); @@ -230,6 +226,7 @@ int _alpm_db_load_grpcache(pmdb_t *db) } } + db->grpcache_loaded = 1; return(0); } @@ -239,15 +236,19 @@ void _alpm_db_free_grpcache(pmdb_t *db) ALPM_LOG_FUNC; - if(db == NULL || db->grpcache == NULL) { + if(db == NULL || !db->grpcache_loaded) { return; } + _alpm_log(PM_LOG_DEBUG, "freeing group cache for repository '%s'\n", + db->treename); + for(lg = db->grpcache; lg; lg = lg->next) { _alpm_grp_free(lg->data); lg->data = NULL; } FREELIST(db->grpcache); + db->grpcache_loaded = 0; } alpm_list_t *_alpm_db_get_grpcache(pmdb_t *db) @@ -258,7 +259,7 @@ alpm_list_t *_alpm_db_get_grpcache(pmdb_t *db) return(NULL); } - if(db->grpcache == NULL) { + if(!db->grpcache_loaded) { _alpm_db_load_grpcache(db); } diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c index a044fc60..499e55a4 100644 --- a/lib/libalpm/conflict.c +++ b/lib/libalpm/conflict.c @@ -218,11 +218,11 @@ alpm_list_t *_alpm_outerconflicts(pmdb_t *db, alpm_list_t *packages) /** Check the package conflicts in a database * - * @param db_local the database to check + * @param pkglist the list of packages to check * @return an alpm_list_t of pmconflict_t */ -alpm_list_t SYMEXPORT *alpm_checkdbconflicts(pmdb_t *db_local) { - return(_alpm_innerconflicts(_alpm_db_get_pkgcache(db_local))); +alpm_list_t SYMEXPORT *alpm_checkconflicts(alpm_list_t *pkglist) { + return(_alpm_innerconflicts(pkglist)); } /* Returns a alpm_list_t* of file conflicts. diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c index 5632ffac..561967ce 100644 --- a/lib/libalpm/db.c +++ b/lib/libalpm/db.c @@ -85,9 +85,6 @@ static void _alpm_db_unregister(pmdb_t *db) return; } - _alpm_log(PM_LOG_DEBUG, "closing database '%s'\n", db->treename); - _alpm_db_close(db); - _alpm_log(PM_LOG_DEBUG, "unregistering database '%s'\n", db->treename); _alpm_db_free(db); } @@ -263,7 +260,7 @@ pmpkg_t SYMEXPORT *alpm_db_get_pkg(pmdb_t *db, const char *name) * @param db pointer to the package database to get the package from * @return the list of packages on success, NULL on error */ -alpm_list_t SYMEXPORT *alpm_db_getpkgcache(pmdb_t *db) +alpm_list_t SYMEXPORT *alpm_db_get_pkgcache(pmdb_t *db) { ALPM_LOG_FUNC; @@ -295,7 +292,7 @@ pmgrp_t SYMEXPORT *alpm_db_readgrp(pmdb_t *db, const char *name) * @param db pointer to the package database to get the group from * @return the list of groups on success, NULL on error */ -alpm_list_t SYMEXPORT *alpm_db_getgrpcache(pmdb_t *db) +alpm_list_t SYMEXPORT *alpm_db_get_grpcache(pmdb_t *db) { ALPM_LOG_FUNC; @@ -431,10 +428,8 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) pmdb_t *_alpm_db_register_local(void) { - struct stat buf; pmdb_t *db; const char *dbpath; - char path[PATH_MAX]; ALPM_LOG_FUNC; @@ -445,40 +440,23 @@ pmdb_t *_alpm_db_register_local(void) _alpm_log(PM_LOG_DEBUG, "registering local database\n"); - /* make sure the database directory exists */ dbpath = alpm_option_get_dbpath(); if(!dbpath) { _alpm_log(PM_LOG_ERROR, _("database path is undefined\n")); RET_ERR(PM_ERR_DB_OPEN, NULL); } - snprintf(path, PATH_MAX, "%slocal", dbpath); - /* TODO this is rediculous, we try to do this even if we can't */ - if(stat(path, &buf) != 0 || !S_ISDIR(buf.st_mode)) { - _alpm_log(PM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n", - path); - if(_alpm_makepath(path) != 0) { - RET_ERR(PM_ERR_SYSTEM, NULL); - } - } db = _alpm_db_new(dbpath, "local"); if(db == NULL) { RET_ERR(PM_ERR_DB_CREATE, NULL); } - _alpm_log(PM_LOG_DEBUG, "opening database '%s'\n", db->treename); - if(_alpm_db_open(db) == -1) { - _alpm_db_free(db); - RET_ERR(PM_ERR_DB_OPEN, NULL); - } - handle->db_local = db; return(db); } pmdb_t *_alpm_db_register_sync(const char *treename) { - struct stat buf; pmdb_t *db; const char *dbpath; char path[PATH_MAX]; @@ -496,25 +474,12 @@ pmdb_t *_alpm_db_register_sync(const char *treename) _alpm_log(PM_LOG_DEBUG, "registering sync database '%s'\n", treename); - /* make sure the database directory exists */ dbpath = alpm_option_get_dbpath(); if(!dbpath) { _alpm_log(PM_LOG_ERROR, _("database path is undefined\n")); RET_ERR(PM_ERR_DB_OPEN, NULL); } /* all sync DBs now reside in the sync/ subdir of the dbpath */ - snprintf(path, PATH_MAX, "%ssync/%s", dbpath, treename); - /* TODO this is rediculous, we try to do this even if we can't */ - if(stat(path, &buf) != 0 || !S_ISDIR(buf.st_mode)) { - _alpm_log(PM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n", - path); - if(_alpm_makepath(path) != 0) { - RET_ERR(PM_ERR_SYSTEM, NULL); - } - } - - /* Ensure the db gets the real path. */ - path[0] = '\0'; snprintf(path, PATH_MAX, "%ssync/", dbpath); db = _alpm_db_new(path, treename); @@ -522,12 +487,6 @@ pmdb_t *_alpm_db_register_sync(const char *treename) RET_ERR(PM_ERR_DB_CREATE, NULL); } - _alpm_log(PM_LOG_DEBUG, "opening database '%s'\n", db->treename); - if(_alpm_db_open(db) == -1) { - _alpm_db_free(db); - RET_ERR(PM_ERR_DB_OPEN, NULL); - } - handle->dbs_sync = alpm_list_add(handle->dbs_sync, db); return(db); } diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h index 25b90b5f..1af16355 100644 --- a/lib/libalpm/db.h +++ b/lib/libalpm/db.h @@ -41,8 +41,9 @@ typedef enum _pmdbinfrq_t { struct __pmdb_t { char *path; char *treename; - void *handle; + unsigned short pkgcache_loaded; alpm_list_t *pkgcache; + unsigned short grpcache_loaded; alpm_list_t *grpcache; alpm_list_t *servers; }; @@ -56,8 +57,6 @@ pmdb_t *_alpm_db_register_local(void); pmdb_t *_alpm_db_register_sync(const char *treename); /* be.c, backend specific calls */ -int _alpm_db_open(pmdb_t *db); -void _alpm_db_close(pmdb_t *db); int _alpm_db_populate(pmdb_t *db); int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq); int _alpm_db_prepare(pmdb_t *db, pmpkg_t *info); diff --git a/lib/libalpm/delta.c b/lib/libalpm/delta.c index 8dce7e3b..ff77501e 100644 --- a/lib/libalpm/delta.c +++ b/lib/libalpm/delta.c @@ -95,7 +95,7 @@ static alpm_list_t *delta_graph_init(alpm_list_t *deltas) /* determine whether the delta file already exists */ fpath = _alpm_filecache_find(vdelta->delta); - md5sum = alpm_get_md5sum(fpath); + md5sum = alpm_compute_md5sum(fpath); if(fpath && md5sum && strcmp(md5sum, vdelta->delta_md5) == 0) { vdelta->download_size = 0; } @@ -104,7 +104,7 @@ static alpm_list_t *delta_graph_init(alpm_list_t *deltas) /* determine whether a base 'from' file exists */ fpath = _alpm_filecache_find(vdelta->from); - md5sum = alpm_get_md5sum(fpath); + md5sum = alpm_compute_md5sum(fpath); if(fpath && md5sum && strcmp(md5sum, vdelta->from_md5) == 0) { v->weight = vdelta->download_size; } diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index c667daa2..694e5be5 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -229,13 +229,13 @@ alpm_list_t SYMEXPORT *alpm_deptest(pmdb_t *db, alpm_list_t *targets) /** Checks dependencies and returns missing ones in a list. * Dependencies can include versions with depmod operators. - * @param db pointer to the local package database + * @param pkglist the list of local packages * @param reversedeps handles the backward dependencies * @param remove an alpm_list_t* of packages to be removed * @param upgrade an alpm_list_t* of packages to be upgraded (remove-then-upgrade) * @return an alpm_list_t* of pmpkg_t* of missing_t pointers. */ -alpm_list_t SYMEXPORT *alpm_checkdeps(pmdb_t *db, int reversedeps, +alpm_list_t SYMEXPORT *alpm_checkdeps(alpm_list_t *pkglist, int reversedeps, alpm_list_t *remove, alpm_list_t *upgrade) { alpm_list_t *i, *j; @@ -245,12 +245,8 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(pmdb_t *db, int reversedeps, ALPM_LOG_FUNC; - if(db == NULL) { - return(NULL); - } - targets = alpm_list_join(alpm_list_copy(remove), alpm_list_copy(upgrade)); - for(i = _alpm_db_get_pkgcache(db); i; i = i->next) { + for(i = pkglist; i; i = i->next) { void *pkg = i->data; if(alpm_list_find(targets, pkg, _alpm_pkg_cmp)) { modified = alpm_list_add(modified, pkg); @@ -273,7 +269,7 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(pmdb_t *db, int reversedeps, if(!_alpm_find_dep_satisfier(upgrade, depend) && !_alpm_find_dep_satisfier(dblist, depend)) { /* Unsatisfied dependency in the upgrade list */ - char *missdepstring = alpm_dep_get_string(depend); + char *missdepstring = alpm_dep_compute_string(depend); _alpm_log(PM_LOG_DEBUG, "checkdeps: missing dependency '%s' for package '%s'\n", missdepstring, alpm_pkg_get_name(tp)); free(missdepstring); @@ -297,7 +293,7 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(pmdb_t *db, int reversedeps, if(causingpkg && !_alpm_find_dep_satisfier(upgrade, depend) && !_alpm_find_dep_satisfier(dblist, depend)) { - char *missdepstring = alpm_dep_get_string(depend); + char *missdepstring = alpm_dep_compute_string(depend); _alpm_log(PM_LOG_DEBUG, "checkdeps: transaction would break '%s' dependency of '%s'\n", missdepstring, alpm_pkg_get_name(lp)); free(missdepstring); @@ -508,8 +504,20 @@ void _alpm_recursedeps(pmdb_t *db, alpm_list_t *targs, int include_explicit) } } -/* helper function for resolvedeps: search for dep satisfier in dbs */ -pmpkg_t *_alpm_resolvedep(pmdepend_t *dep, alpm_list_t *dbs, alpm_list_t *excluding, pmpkg_t *tpkg) +/** + * helper function for resolvedeps: search for dep satisfier in dbs + * + * @param dep is the dependency to search for + * @param dbs are the databases to search + * @param excluding are the packages to exclude from the search + * @param prompt if true, will cause an unresolvable dependency to issue an + * interactive prompt asking whether the package should be removed from + * the transaction or the transaction aborted; if false, simply returns + * an error code without prompting + * @return the resolved package + **/ +pmpkg_t *_alpm_resolvedep(pmdepend_t *dep, alpm_list_t *dbs, + alpm_list_t *excluding, int prompt) { alpm_list_t *i, *j; /* 1. literals */ @@ -517,9 +525,11 @@ pmpkg_t *_alpm_resolvedep(pmdepend_t *dep, alpm_list_t *dbs, alpm_list_t *exclud pmpkg_t *pkg = _alpm_db_get_pkgfromcache(i->data, dep->name); if(pkg && alpm_depcmp(pkg, dep) && !_alpm_pkg_find(excluding, pkg->name)) { if(_alpm_pkg_should_ignore(pkg)) { - int install; - QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, - tpkg, NULL, &install); + int install = 0; + if (prompt) { + QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, + NULL, NULL, &install); + } if(!install) { continue; } @@ -534,9 +544,11 @@ pmpkg_t *_alpm_resolvedep(pmdepend_t *dep, alpm_list_t *dbs, alpm_list_t *exclud if(alpm_depcmp(pkg, dep) && strcmp(pkg->name, dep->name) && !_alpm_pkg_find(excluding, pkg->name)) { if(_alpm_pkg_should_ignore(pkg)) { - int install; - QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, - tpkg, NULL, &install); + int install = 0; + if (prompt) { + QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, + pkg, NULL, NULL, &install); + } if(!install) { continue; } @@ -550,17 +562,33 @@ pmpkg_t *_alpm_resolvedep(pmdepend_t *dep, alpm_list_t *dbs, alpm_list_t *exclud return(NULL); } -/* populates list with packages that need to be installed to satisfy all - * dependencies of packages in list +/* Computes resolvable dependencies for a given package and adds that package + * and those resolvable dependencies to a list. * - * @param remove contains packages elected for removal + * @param local is the local database + * @param dbs_sync are the sync databases + * @param pkg is the package to resolve + * @param packages is a pointer to a list of packages which will be + * searched first for any dependency packages needed to complete the + * resolve, and to which will be added any [pkg] and all of its + * dependencies not already on the list + * @param remove is the set of packages which will be removed in this + * transaction + * @param data returns the dependency which could not be satisfied in the + * event of an error + * @return 0 on success, with [pkg] and all of its dependencies not already on + * the [*packages] list added to that list, or -1 on failure due to an + * unresolvable dependency, in which case the [*packages] list will be + * unmodified by this function */ -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, pmpkg_t *pkg, + alpm_list_t **packages, alpm_list_t *remove, + alpm_list_t **data) { alpm_list_t *i, *j; alpm_list_t *targ; alpm_list_t *deps = NULL; + alpm_list_t *packages_copy; ALPM_LOG_FUNC; @@ -568,25 +596,36 @@ int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, alpm_list_t *list, return(-1); } + if(_alpm_pkg_find(*packages, pkg->name) != NULL) { + return(0); + } + + /* Create a copy of the packages list, so that it can be restored + on error */ + packages_copy = alpm_list_copy(*packages); + /* [pkg] has not already been resolved into the packages list, so put it + on that list */ + *packages = alpm_list_add(*packages, pkg); + _alpm_log(PM_LOG_DEBUG, "started resolving dependencies\n"); - for(i = list; i; i = i->next) { + for(i = alpm_list_last(*packages); i; i = i->next) { pmpkg_t *tpkg = i->data; targ = alpm_list_add(NULL, tpkg); - deps = alpm_checkdeps(local, 0, remove, targ); + deps = alpm_checkdeps(_alpm_db_get_pkgcache(local), 0, remove, targ); alpm_list_free(targ); for(j = deps; j; j = j->next) { 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)) { + /* check if one of the packages in the [*packages] list already satisfies this dependency */ + if(_alpm_find_dep_satisfier(*packages, missdep)) { continue; } /* find a satisfier package in the given repositories */ - pmpkg_t *spkg = _alpm_resolvedep(missdep, dbs_sync, list, tpkg); + pmpkg_t *spkg = _alpm_resolvedep(missdep, dbs_sync, *packages, 0); 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"), + char *missdepstring = alpm_dep_compute_string(missdep); + _alpm_log(PM_LOG_WARNING, _("cannot resolve \"%s\", a dependency of \"%s\"\n"), missdepstring, tpkg->name); free(missdepstring); if(data) { @@ -596,18 +635,21 @@ int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, alpm_list_t *list, *data = alpm_list_add(*data, missd); } } + alpm_list_free(*packages); + *packages = packages_copy; alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(deps); return(-1); } else { _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); + *packages = alpm_list_add(*packages, spkg); } } alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(deps); } + alpm_list_free(packages_copy); _alpm_log(PM_LOG_DEBUG, "finished resolving dependencies\n"); return(0); } @@ -689,7 +731,7 @@ const char SYMEXPORT *alpm_dep_get_version(const pmdepend_t *dep) * @param dep the depend to turn into a string * @return a string-formatted dependency with operator if necessary */ -char SYMEXPORT *alpm_dep_get_string(const pmdepend_t *dep) +char SYMEXPORT *alpm_dep_compute_string(const pmdepend_t *dep) { char *name, *opr, *ver, *str = NULL; size_t len; diff --git a/lib/libalpm/deps.h b/lib/libalpm/deps.h index 2f3c4502..eb1400bd 100644 --- a/lib/libalpm/deps.h +++ b/lib/libalpm/deps.h @@ -47,9 +47,9 @@ pmdepmissing_t *_alpm_depmiss_new(const char *target, pmdepend_t *dep, void _alpm_depmiss_free(pmdepmissing_t *miss); 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); +pmpkg_t *_alpm_resolvedep(pmdepend_t *dep, alpm_list_t *dbs, alpm_list_t *excluding, int prompt); +int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *pkg, + alpm_list_t **packages, 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 --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c index ca13652e..5b0a691f 100644 --- a/lib/libalpm/dload.c +++ b/lib/libalpm/dload.c @@ -24,6 +24,7 @@ #include <errno.h> #include <string.h> #include <unistd.h> +#include <signal.h> #include <limits.h> /* the following two are needed on BSD for libfetch */ #if defined(HAVE_SYS_SYSLIMITS_H) @@ -33,16 +34,8 @@ #include <sys/param.h> /* MAXHOSTNAMELEN */ #endif -#if defined(HAVE_LIBDOWNLOAD) -#include <download.h> -#elif defined(HAVE_LIBFETCH) +#if defined(INTERNAL_DOWNLOAD) #include <fetch.h> -#define downloadFreeURL fetchFreeURL -#define downloadLastErrCode fetchLastErrCode -#define downloadLastErrString fetchLastErrString -#define downloadParseURL fetchParseURL -#define downloadTimeout fetchTimeout -#define downloadXGet fetchXGet #endif /* libalpm */ @@ -86,7 +79,7 @@ static char *get_tempfile(const char *path, const char *filename) { static struct url *url_for_string(const char *url) { struct url *ret = NULL; - ret = downloadParseURL(url); + ret = fetchParseURL(url); if(!ret) { _alpm_log(PM_LOG_ERROR, _("url '%s' is invalid\n"), url); RET_ERR(PM_ERR_SERVER_BAD_URL, NULL); @@ -108,12 +101,14 @@ static struct url *url_for_string(const char *url) static int download_internal(const char *url, const char *localpath, time_t mtimeold, time_t *mtimenew) { - FILE *dlf, *localf = NULL; + fetchIO *dlf = NULL; + FILE *localf = NULL; struct url_stat ust; struct stat st; int chk_resume = 0, ret = 0; size_t dl_thisfile = 0, nread = 0; char *tempfile, *destfile, *filename; + struct sigaction new_action, old_action; struct url *fileurl = url_for_string(url); char buffer[PM_DLBUF_LEN]; @@ -148,23 +143,29 @@ static int download_internal(const char *url, const char *localpath, _alpm_log(PM_LOG_DEBUG, "FTP_PROXY: %s\n", getenv("FTP_PROXY")); _alpm_log(PM_LOG_DEBUG, "ftp_proxy: %s\n", getenv("ftp_proxy")); - /* libdownload does not reset the error code, reset it in - * the case of previous errors */ - downloadLastErrCode = 0; + /* libfetch does not reset the error code */ + fetchLastErrCode = 0; /* 10s timeout - TODO make a config option */ - downloadTimeout = 10000; + fetchTimeout = 10000; + + /* ignore any SIGPIPE signals- these may occur if our FTP socket dies or + * something along those lines. Store the old signal handler first. */ + new_action.sa_handler = SIG_IGN; + sigemptyset(&new_action.sa_mask); + sigaction(SIGPIPE, NULL, &old_action); + sigaction(SIGPIPE, &new_action, NULL); - dlf = downloadXGet(fileurl, &ust, (handle->nopassiveftp ? "" : "p")); + dlf = fetchXGet(fileurl, &ust, (handle->nopassiveftp ? "" : "p")); - if(downloadLastErrCode != 0 || dlf == NULL) { + if(fetchLastErrCode != 0 || dlf == NULL) { const char *host = _("disk"); if(strcmp(SCHEME_FILE, fileurl->scheme) != 0) { host = fileurl->host; } - pm_errno = PM_ERR_LIBDOWNLOAD; + pm_errno = PM_ERR_LIBFETCH; _alpm_log(PM_LOG_ERROR, _("failed retrieving file '%s' from %s : %s\n"), - filename, host, downloadLastErrString); + filename, host, fetchLastErrString); ret = -1; goto cleanup; } else { @@ -206,16 +207,8 @@ static int download_internal(const char *url, const char *localpath, handle->dlcb(filename, 0, ust.size); } - while((nread = fread(buffer, 1, PM_DLBUF_LEN, dlf)) > 0) { + while((nread = fetchIO_read(dlf, buffer, PM_DLBUF_LEN)) > 0) { size_t nwritten = 0; - if(ferror(dlf)) { - pm_errno = PM_ERR_LIBDOWNLOAD; - _alpm_log(PM_LOG_ERROR, _("error downloading '%s': %s\n"), - filename, downloadLastErrString); - ret = -1; - goto cleanup; - } - while(nwritten < nread) { nwritten += fwrite(buffer, 1, (nread - nwritten), localf); if(ferror(localf)) { @@ -231,27 +224,40 @@ static int download_internal(const char *url, const char *localpath, handle->dlcb(filename, dl_thisfile, ust.size); } } + + /* did the transfer complete normally? */ + if (ust.size != -1 && dl_thisfile < ust.size) { + pm_errno = PM_ERR_LIBFETCH; + _alpm_log(PM_LOG_ERROR, _("%s appears to be truncated: %jd/%jd bytes\n"), + filename, (intmax_t)dl_thisfile, (intmax_t)ust.size); + ret = -1; + goto cleanup; + } + /* probably safer to close the file descriptors now before renaming the file, * for example to make sure the buffers are flushed. */ fclose(localf); localf = NULL; - fclose(dlf); + fetchIO_close(dlf); dlf = NULL; rename(tempfile, destfile); ret = 0; cleanup: + /* restore any existing SIGPIPE signal handler */ + sigaction(SIGPIPE, &old_action, NULL); + FREE(tempfile); FREE(destfile); if(localf != NULL) { fclose(localf); } if(dlf != NULL) { - fclose(dlf); + fetchIO_close(dlf); } - downloadFreeURL(fileurl); + fetchFreeURL(fileurl); return(ret); } #endif diff --git a/lib/libalpm/error.c b/lib/libalpm/error.c index 05caf8ec..1f605806 100644 --- a/lib/libalpm/error.c +++ b/lib/libalpm/error.c @@ -30,11 +30,8 @@ #include <sys/param.h> /* MAXHOSTNAMELEN */ #endif -#if defined(HAVE_LIBDOWNLOAD) -#include <download.h> /* downloadLastErrString */ -#elif defined(HAVE_LIBFETCH) +#if defined(INTERNAL_DOWNLOAD) #include <fetch.h> /* fetchLastErrString */ -#define downloadLastErrString fetchLastErrString #endif /* libalpm */ @@ -143,9 +140,6 @@ const char SYMEXPORT *alpm_strerror(int err) return _("user aborted the operation"); case PM_ERR_INTERNAL_ERROR: return _("internal error"); - case PM_ERR_PKG_HOLD: - /* TODO wow this is not descriptive at all... what does this mean? */ - return _("not confirmed"); case PM_ERR_INVALID_REGEX: return _("invalid regular expression"); /* Errors from external libraries- our own wrapper error */ @@ -154,9 +148,9 @@ const char SYMEXPORT *alpm_strerror(int err) * requires the archive struct, so we can't. Just use a generic * error string instead. */ return _("libarchive error"); - case PM_ERR_LIBDOWNLOAD: + case PM_ERR_LIBFETCH: #if defined(INTERNAL_DOWNLOAD) - return downloadLastErrString; + return fetchLastErrString; #else /* obviously shouldn't get here... */ return _("download library error"); diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c index af1cc78b..813f4399 100644 --- a/lib/libalpm/handle.c +++ b/lib/libalpm/handle.c @@ -48,16 +48,7 @@ pmhandle_t *_alpm_handle_new() ALPM_LOG_FUNC; CALLOC(handle, 1, sizeof(pmhandle_t), RET_ERR(PM_ERR_MEMORY, NULL)); - handle->lckfd = -1; - handle->logstream = NULL; - - handle->root = NULL; - handle->dbpath = NULL; - handle->cachedirs = NULL; - handle->lockfile = NULL; - handle->logfile = NULL; - handle->usedelta = 0; return(handle); } @@ -92,7 +83,6 @@ void _alpm_handle_free(pmhandle_t *handle) FREELIST(handle->noupgrade); FREELIST(handle->noextract); FREELIST(handle->ignorepkg); - FREELIST(handle->holdpkg); FREELIST(handle->ignoregrp); FREE(handle); } @@ -205,15 +195,6 @@ alpm_list_t SYMEXPORT *alpm_option_get_ignorepkgs() return handle->ignorepkg; } -alpm_list_t SYMEXPORT *alpm_option_get_holdpkgs() -{ - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } - return handle->holdpkg; -} - alpm_list_t SYMEXPORT *alpm_option_get_ignoregrps() { if (handle == NULL) { @@ -516,28 +497,6 @@ int SYMEXPORT alpm_option_remove_ignorepkg(const char *pkg) return(0); } -void SYMEXPORT alpm_option_add_holdpkg(const char *pkg) -{ - handle->holdpkg = alpm_list_add(handle->holdpkg, strdup(pkg)); -} - -void SYMEXPORT alpm_option_set_holdpkgs(alpm_list_t *holdpkgs) -{ - if(handle->holdpkg) FREELIST(handle->holdpkg); - if(holdpkgs) handle->holdpkg = holdpkgs; -} - -int SYMEXPORT alpm_option_remove_holdpkg(const char *pkg) -{ - char *vdata = NULL; - handle->holdpkg = alpm_list_remove_str(handle->holdpkg, pkg, &vdata); - if(vdata != NULL) { - FREE(vdata); - return(1); - } - return(0); -} - void SYMEXPORT alpm_option_add_ignoregrp(const char *grp) { handle->ignoregrp = alpm_list_add(handle->ignoregrp, strdup(grp)); diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h index bec0a6f1..ad7666dc 100644 --- a/lib/libalpm/handle.h +++ b/lib/libalpm/handle.h @@ -52,7 +52,6 @@ typedef struct _pmhandle_t { alpm_list_t *noupgrade; /* List of packages NOT to be upgraded */ alpm_list_t *noextract; /* List of files NOT to extract */ alpm_list_t *ignorepkg; /* List of packages to ignore */ - alpm_list_t *holdpkg; /* List of packages which 'hold' pacman */ alpm_list_t *ignoregrp; /* List of groups to ignore */ /* options */ diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index a9f4b43d..ee0ff6f5 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -422,6 +422,15 @@ alpm_list_t SYMEXPORT *alpm_pkg_get_backup(pmpkg_t *pkg) return pkg->backup; } +pmdb_t SYMEXPORT *alpm_pkg_get_db(pmpkg_t *pkg) +{ + /* Sanity checks */ + ASSERT(pkg != NULL, return(NULL)); + ASSERT(pkg->origin == PKG_FROM_CACHE, return(NULL)); + + return(pkg->origin_data.db); +} + /** * Open a package changelog for reading. Similar to fopen in functionality, * except that the returned 'file stream' could really be from an archive diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c index 0bec5229..9dfff9c3 100644 --- a/lib/libalpm/remove.c +++ b/lib/libalpm/remove.c @@ -65,16 +65,6 @@ int _alpm_remove_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name) RET_ERR(PM_ERR_PKG_NOT_FOUND, -1); } - /* ignore holdpkgs on upgrade */ - if((trans == handle->trans) - && alpm_list_find_str(handle->holdpkg, info->name)) { - int resp = 0; - QUESTION(trans, PM_TRANS_CONV_REMOVE_HOLDPKG, info, NULL, NULL, &resp); - if(!resp) { - RET_ERR(PM_ERR_PKG_HOLD, -1); - } - } - _alpm_log(PM_LOG_DEBUG, "adding %s in the targets list\n", info->name); trans->packages = alpm_list_add(trans->packages, _alpm_pkg_dup(info)); @@ -104,7 +94,7 @@ static void remove_prepare_cascade(pmtrans_t *trans, pmdb_t *db, } alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(lp); - lp = alpm_checkdeps(db, 1, trans->packages, NULL); + lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->packages, NULL); } } @@ -134,7 +124,7 @@ static void remove_prepare_keep_needed(pmtrans_t *trans, pmdb_t *db, } alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(lp); - lp = alpm_checkdeps(db, 1, trans->packages, NULL); + lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->packages, NULL); } } @@ -161,7 +151,7 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data) EVENT(trans, PM_TRANS_EVT_CHECKDEPS_START, NULL, NULL); _alpm_log(PM_LOG_DEBUG, "looking for unsatisfied dependencies\n"); - lp = alpm_checkdeps(db, 1, trans->packages, NULL); + lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->packages, NULL); if(lp != NULL) { if(trans->flags & PM_TRANS_FLAG_CASCADE) { diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index 4a705b57..709a36dc 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -77,17 +77,12 @@ void _alpm_sync_free(pmsyncpkg_t *sync) /* Find recommended replacements for packages during a sync. */ -static int find_replacements(pmtrans_t *trans, pmdb_t *db_local, - alpm_list_t *dbs_sync, alpm_list_t **syncpkgs) +static int find_replacements(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync) { alpm_list_t *i, *j, *k; /* wow */ ALPM_LOG_FUNC; - if(syncpkgs == NULL) { - return(-1); - } - /* check for "recommended" package replacements */ _alpm_log(PM_LOG_DEBUG, "checking for package replacements\n"); for(i = dbs_sync; i; i = i->next) { @@ -113,13 +108,10 @@ static int find_replacements(pmtrans_t *trans, pmdb_t *db_local, alpm_pkg_get_name(lpkg), alpm_pkg_get_version(lpkg), alpm_pkg_get_name(spkg), alpm_pkg_get_version(spkg)); } else { - /* get confirmation for the replacement */ - if(trans) { - int doreplace = 0; - QUESTION(trans, PM_TRANS_CONV_REPLACE_PKG, lpkg, spkg, db->treename, &doreplace); - if(!doreplace) { - continue; - } + int doreplace = 0; + QUESTION(trans, PM_TRANS_CONV_REPLACE_PKG, lpkg, spkg, db->treename, &doreplace); + if(!doreplace) { + continue; } /* if confirmed, add this to the 'final' list, designating 'lpkg' as @@ -129,7 +121,7 @@ static int find_replacements(pmtrans_t *trans, pmdb_t *db_local, /* check if spkg->name is already in the packages list. */ /* TODO: same package name doesn't mean same package */ - sync = _alpm_sync_find(*syncpkgs, alpm_pkg_get_name(spkg)); + sync = _alpm_sync_find(trans->packages, alpm_pkg_get_name(spkg)); if(sync) { /* found it -- just append to the removes list */ sync->removes = alpm_list_add(sync->removes, lpkg); @@ -143,15 +135,12 @@ static int find_replacements(pmtrans_t *trans, pmdb_t *db_local, sync = _alpm_sync_new(alpm_pkg_get_reason(lpkg), spkg, NULL); if(sync == NULL) { pm_errno = PM_ERR_MEMORY; - alpm_list_free_inner(*syncpkgs, (alpm_list_fn_free)_alpm_sync_free); - alpm_list_free(*syncpkgs); - *syncpkgs = NULL; return(-1); } sync->removes = alpm_list_add(NULL, lpkg); _alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", alpm_pkg_get_name(spkg), alpm_pkg_get_version(spkg)); - *syncpkgs = alpm_list_add(*syncpkgs, sync); + trans->packages = alpm_list_add(trans->packages, sync); } _alpm_log(PM_LOG_DEBUG, "%s-%s elected for removal (to be replaced by %s-%s)\n", alpm_pkg_get_name(lpkg), alpm_pkg_get_version(lpkg), @@ -199,33 +188,19 @@ pmpkg_t SYMEXPORT *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync) return(NULL); } -/** Get a list of upgradable packages on the current system - * Adds out of date packages to *list. - * @arg list pointer to a list of pmsyncpkg_t. - */ -int SYMEXPORT alpm_sync_sysupgrade(pmdb_t *db_local, - alpm_list_t *dbs_sync, alpm_list_t **syncpkgs) -{ - return(_alpm_sync_sysupgrade(NULL, db_local, dbs_sync, syncpkgs)); -} - -int _alpm_sync_sysupgrade(pmtrans_t *trans, - pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **syncpkgs) +int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync) { alpm_list_t *i, *j, *replaced = NULL; ALPM_LOG_FUNC; - if(syncpkgs == NULL) { - return(-1); - } /* check for "recommended" package replacements */ - if(find_replacements(trans, db_local, dbs_sync, syncpkgs)) { + if(find_replacements(trans, db_local, dbs_sync)) { return(-1); } /* compute the to-be-replaced packages for efficiency */ - for(i = *syncpkgs; i; i = i->next) { + for(i = trans->packages; i; i = i->next) { pmsyncpkg_t *sync = i->data; for(j = sync->removes; j; j = j->next) { replaced = alpm_list_add(replaced, j->data); @@ -255,22 +230,19 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, } /* add the upgrade package to our pmsyncpkg_t list */ - if(_alpm_sync_find(*syncpkgs, alpm_pkg_get_name(spkg))) { + if(_alpm_sync_find(trans->packages, alpm_pkg_get_name(spkg))) { /* avoid duplicated targets */ continue; } /* we can set any reason here, it will be overridden by add_commit */ pmsyncpkg_t *sync = _alpm_sync_new(PM_PKG_REASON_EXPLICIT, spkg, NULL); if(sync == NULL) { - alpm_list_free_inner(*syncpkgs, (alpm_list_fn_free)_alpm_sync_free); - alpm_list_free(*syncpkgs); - *syncpkgs = NULL; alpm_list_free(replaced); return(-1); } _alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", alpm_pkg_get_name(spkg), alpm_pkg_get_version(spkg)); - *syncpkgs = alpm_list_add(*syncpkgs, sync); + trans->packages = alpm_list_add(trans->packages, sync); } } @@ -313,12 +285,12 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy RET_ERR(PM_ERR_PKG_REPO_NOT_FOUND, -1); } dep = _alpm_splitdep(targ); - spkg = _alpm_resolvedep(dep, dbs, NULL, NULL); + spkg = _alpm_resolvedep(dep, dbs, NULL, 1); _alpm_dep_free(dep); alpm_list_free(dbs); } else { dep = _alpm_splitdep(targline); - spkg = _alpm_resolvedep(dep, dbs_sync, NULL, NULL); + spkg = _alpm_resolvedep(dep, dbs_sync, NULL, 1); _alpm_dep_free(dep); } FREE(targline); @@ -427,6 +399,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync { alpm_list_t *deps = NULL; alpm_list_t *list = NULL, *remove = NULL; /* allow checkdeps usage with trans->packages */ + alpm_list_t *unresolvable = NULL; alpm_list_t *i, *j; int ret = 0; @@ -439,15 +412,13 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync *data = NULL; } - for(i = trans->packages; i; i = i->next) { - pmsyncpkg_t *sync = i->data; - list = alpm_list_add(list, sync->pkg); - } - - 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); + if(trans->flags & PM_TRANS_FLAG_NODEPS) { + for(i = trans->packages; i; i = i->next) { + pmsyncpkg_t *sync = i->data; + list = alpm_list_add(list, sync->pkg); + } + } else { + /* Build up list by repeatedly resolving each transaction package */ /* Resolve targets dependencies */ EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_START, NULL, NULL); _alpm_log(PM_LOG_DEBUG, "resolving target's dependencies\n"); @@ -460,14 +431,53 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync } } - if(_alpm_resolvedeps(db_local, dbs_sync, list, remove, data) == -1) { - /* pm_errno is set by resolvedeps */ - ret = -1; - goto cleanup; + /* Resolve packages in the transaction one at a time, in addtion + building up a list of packages which could not be resolved. */ + for(i = trans->packages; i; i = i->next) { + pmpkg_t *pkg = ((pmsyncpkg_t *) i->data)->pkg; + if(_alpm_resolvedeps(db_local, dbs_sync, pkg, &list, remove, data) == -1) { + unresolvable = alpm_list_add(unresolvable, pkg); + } + /* Else, [list] now additionally contains [pkg] and all of its + dependencies not already on the list */ } - for(i = pulled->next; i; i = i->next) { + /* If there were unresolvable top-level packages, prompt the user to + see if they'd like to ignore them rather than failing the sync */ + if(unresolvable != NULL) { + int remove_unresolvable = 0; + QUESTION(handle->trans, PM_TRANS_CONV_REMOVE_PKGS, unresolvable, + NULL, NULL, &remove_unresolvable); + if (remove_unresolvable) { + /* User wants to remove the unresolvable packages from the + transaction, so simply drop the unresolvable list. The + packages will be removed from the actual transaction when + the transaction packages are replaced with a + dependency-reordered list below */ + alpm_list_free(unresolvable); + unresolvable = NULL; + } + else { + /* pm_errno is set by resolvedeps */ + ret = -1; + goto cleanup; + } + } + + /* Add all packages which were "pulled" (i.e. weren't already in the + transaction) to the transaction in pmsyncpkg_t structures */ + for(i = list; i; i = i->next) { pmpkg_t *spkg = i->data; + for(j = trans->packages; j; j = j->next) { + if(_alpm_pkg_cmp(spkg, ((pmsyncpkg_t *) j->data)->pkg) == 0) { + spkg = NULL; + break; + } + } + if (spkg == NULL) { + continue; + } + pmsyncpkg_t *sync = _alpm_sync_new(PM_PKG_REASON_DEPEND, spkg, NULL); if(sync == NULL) { ret = -1; @@ -497,8 +507,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_DONE, NULL, NULL); } - /* We don't care about conflicts if we're just printing uris */ - if(!(trans->flags & (PM_TRANS_FLAG_NOCONFLICTS | PM_TRANS_FLAG_PRINTURIS))) { + if(!(trans->flags & PM_TRANS_FLAG_NOCONFLICTS)) { /* check for inter-conflicts and whatnot */ EVENT(trans, PM_TRANS_EVT_INTERCONFLICTS_START, NULL, NULL); @@ -631,7 +640,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync } _alpm_log(PM_LOG_DEBUG, "checking dependencies\n"); - deps = alpm_checkdeps(db_local, 1, remove, list); + deps = alpm_checkdeps(_alpm_db_get_pkgcache(db_local), 1, remove, list); if(deps) { pm_errno = PM_ERR_UNSATISFIED_DEPS; ret = -1; @@ -656,6 +665,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync cleanup: alpm_list_free(list); alpm_list_free(remove); + alpm_list_free(unresolvable); return(ret); } @@ -838,32 +848,27 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) fname = alpm_pkg_get_filename(spkg); ASSERT(fname != NULL, RET_ERR(PM_ERR_PKG_INVALID_NAME, -1)); - if(trans->flags & PM_TRANS_FLAG_PRINTURIS) { - EVENT(trans, PM_TRANS_EVT_PRINTURI, (char *)alpm_db_get_url(current), - (char *)fname); - } else { - if(spkg->download_size != 0) { - alpm_list_t *delta_path = spkg->delta_path; - if(delta_path) { - alpm_list_t *dlts = NULL; - - for(dlts = delta_path; dlts; dlts = dlts->next) { - pmdelta_t *d = dlts->data; - - if(d->download_size != 0) { - /* add the delta filename to the download list if - * it's not in the cache */ - files = alpm_list_add(files, strdup(d->delta)); - } - - /* keep a list of the delta files for md5sums */ - deltas = alpm_list_add(deltas, d); + if(spkg->download_size != 0) { + alpm_list_t *delta_path = spkg->delta_path; + if(delta_path) { + alpm_list_t *dlts = NULL; + + for(dlts = delta_path; dlts; dlts = dlts->next) { + pmdelta_t *d = dlts->data; + + if(d->download_size != 0) { + /* add the delta filename to the download list if + * it's not in the cache */ + files = alpm_list_add(files, strdup(d->delta)); } - } else { - /* not using deltas, so add the file to the download list */ - files = alpm_list_add(files, strdup(fname)); + /* keep a list of the delta files for md5sums */ + deltas = alpm_list_add(deltas, d); } + + } else { + /* not using deltas, so add the file to the download list */ + files = alpm_list_add(files, strdup(fname)); } } } @@ -880,9 +885,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) FREELIST(files); } } - if(trans->flags & PM_TRANS_FLAG_PRINTURIS) { - return(0); - } /* clear out value to let callback know we are done */ if(handle->totaldlcb) { diff --git a/lib/libalpm/sync.h b/lib/libalpm/sync.h index b71f0ef2..b6a4bbff 100644 --- a/lib/libalpm/sync.h +++ b/lib/libalpm/sync.h @@ -33,8 +33,7 @@ struct __pmsyncpkg_t { pmsyncpkg_t *_alpm_sync_new(pmpkgreason_t newreason, pmpkg_t *spkg, alpm_list_t *removes); void _alpm_sync_free(pmsyncpkg_t *data); -int _alpm_sync_sysupgrade(pmtrans_t *trans, - pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **syncpkgs); +int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync); int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, char *name); int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **data); diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c index acad84e8..4b831193 100644 --- a/lib/libalpm/trans.c +++ b/lib/libalpm/trans.c @@ -100,7 +100,7 @@ int SYMEXPORT alpm_trans_sysupgrade() ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); ASSERT(trans->type == PM_TRANS_TYPE_SYNC, RET_ERR(PM_ERR_TRANS_TYPE, -1)); - return(_alpm_trans_sysupgrade(trans)); + return(_alpm_sync_sysupgrade(trans, handle->db_local, handle->dbs_sync)); } /** Add a target to the transaction. @@ -226,15 +226,6 @@ pmtrans_t *_alpm_trans_new() ALPM_LOG_FUNC; CALLOC(trans, 1, sizeof(pmtrans_t), RET_ERR(PM_ERR_MEMORY, NULL)); - - trans->packages = NULL; - trans->skip_add = NULL; - trans->skip_remove = NULL; - trans->type = 0; - trans->flags = 0; - trans->cb_event = NULL; - trans->cb_conv = NULL; - trans->cb_progress = NULL; trans->state = STATE_IDLE; return(trans); @@ -280,17 +271,6 @@ int _alpm_trans_init(pmtrans_t *trans, pmtranstype_t type, pmtransflag_t flags, return(0); } -int _alpm_trans_sysupgrade(pmtrans_t *trans) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - - return(_alpm_sync_sysupgrade(trans, handle->db_local, handle->dbs_sync, - &(trans->packages))); -} - /** Add a target to the transaction. * @param trans the current transaction * @param target the name of the target to add diff --git a/lib/libalpm/trans.h b/lib/libalpm/trans.h index d74c3e90..48996573 100644 --- a/lib/libalpm/trans.h +++ b/lib/libalpm/trans.h @@ -71,7 +71,6 @@ void _alpm_trans_free(pmtrans_t *trans); int _alpm_trans_init(pmtrans_t *trans, pmtranstype_t type, pmtransflag_t flags, alpm_trans_cb_event event, alpm_trans_cb_conv conv, alpm_trans_cb_progress progress); -int _alpm_trans_sysupgrade(pmtrans_t *trans); int _alpm_trans_addtarget(pmtrans_t *trans, char *target); int _alpm_trans_prepare(pmtrans_t *trans, alpm_list_t **data); int _alpm_trans_commit(pmtrans_t *trans, alpm_list_t **data); diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index be465afa..75f6042d 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -242,7 +242,8 @@ char *_alpm_strreplace(const char *str, const char *needle, const char *replace) int _alpm_lckmk() { int fd; - char *dir, *ptr; + pid_t pid; + char *dir, *ptr, *spid = NULL; const char *file = alpm_option_get_lockfile(); /* create the dir of the lockfile first */ @@ -256,7 +257,17 @@ int _alpm_lckmk() while((fd = open(file, O_WRONLY | O_CREAT | O_EXCL, 0000)) == -1 && errno == EINTR); - return(fd > 0 ? fd : -1); + if(fd > 0) { + pid = getpid(); + size_t len = snprintf(spid, 0, "%ld\n", (long)pid) + 1; + spid = malloc(len); + snprintf(spid, len, "%ld\n", (long)pid); + while(write(fd, (void *)spid, len) == -1 && errno == EINTR); + fsync(fd); + free(spid); + return(fd); + } + return(-1); } /* Remove a lock file */ @@ -277,19 +288,21 @@ int _alpm_lckrm() * @param archive the archive to unpack * @param prefix where to extract the files * @param fn a file within the archive to unpack or NULL for all + * @return 0 on success, 1 on failure */ int _alpm_unpack(const char *archive, const char *prefix, const char *fn) { - int ret = 1; + int ret = 0; mode_t oldmask; struct archive *_archive; struct archive_entry *entry; - char expath[PATH_MAX]; + char cwd[PATH_MAX]; + int restore_cwd = 0; ALPM_LOG_FUNC; if((_archive = archive_read_new()) == NULL) - RET_ERR(PM_ERR_LIBARCHIVE, -1); + RET_ERR(PM_ERR_LIBARCHIVE, 1); archive_read_support_compression_all(_archive); archive_read_support_format_all(_archive); @@ -298,10 +311,25 @@ int _alpm_unpack(const char *archive, const char *prefix, const char *fn) ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { _alpm_log(PM_LOG_ERROR, _("could not open %s: %s\n"), archive, archive_error_string(_archive)); - RET_ERR(PM_ERR_PKG_OPEN, -1); + RET_ERR(PM_ERR_PKG_OPEN, 1); } oldmask = umask(0022); + + /* save the cwd so we can restore it later */ + if(getcwd(cwd, PATH_MAX) == NULL) { + _alpm_log(PM_LOG_ERROR, _("could not get current working directory\n")); + } else { + restore_cwd = 1; + } + + /* just in case our cwd was removed in the upgrade operation */ + if(chdir(prefix) != 0) { + _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), prefix, strerror(errno)); + ret = 1; + goto cleanup; + } + while(archive_read_next_header(_archive, &entry) == ARCHIVE_OK) { const struct stat *st; const char *entryname; /* the name of the file in the archive */ @@ -326,10 +354,6 @@ int _alpm_unpack(const char *archive, const char *prefix, const char *fn) } /* Extract the archive entry. */ - ret = 0; - snprintf(expath, PATH_MAX, "%s/%s", prefix, entryname); - archive_entry_set_pathname(entry, expath); - int readret = archive_read_extract(_archive, entry, 0); if(readret == ARCHIVE_WARN) { /* operation succeeded but a non-critical error was encountered */ @@ -350,6 +374,9 @@ int _alpm_unpack(const char *archive, const char *prefix, const char *fn) cleanup: umask(oldmask); archive_read_finish(_archive); + if(restore_cwd) { + chdir(cwd); + } return(ret); } @@ -539,7 +566,7 @@ int _alpm_lstat(const char *path, struct stat *buf) * @return the checksum on success, NULL on error * @addtogroup alpm_misc */ -char SYMEXPORT *alpm_get_md5sum(const char *filename) +char SYMEXPORT *alpm_compute_md5sum(const char *filename) { unsigned char output[16]; char *md5sum; @@ -573,7 +600,7 @@ int _alpm_test_md5sum(const char *filepath, const char *md5sum) char *md5sum2; int ret; - md5sum2 = alpm_get_md5sum(filepath); + md5sum2 = alpm_compute_md5sum(filepath); if(md5sum == NULL || md5sum2 == NULL) { ret = -1; diff --git a/pactest/Makefile.am b/pactest/Makefile.am index ce611f78..64f9a22e 100644 --- a/pactest/Makefile.am +++ b/pactest/Makefile.am @@ -1,3 +1,5 @@ +SUBDIRS = tests + check_SCRIPTS = \ pactest.py \ pmdb.py \ @@ -7,7 +9,6 @@ check_SCRIPTS = \ pmrule.py \ pmtest.py \ util.py \ - $(wildcard tests/*.py) \ vercmptest.sh noinst_SCRIPTS = $(check_SCRIPTS) diff --git a/pactest/README b/pactest/README index 5d4e47fc..8f97a17d 100644 --- a/pactest/README +++ b/pactest/README @@ -70,12 +70,12 @@ Usage pactest will run the suite of tests defined by the "--test" parameter. Example: - ./pactest.py --test=test/* + ./pactest.py --test tests/*.py -This example will run tests from the "test" directory. +This example will run all tests from the "tests" directory. Note: several "--test" options can be passed to pactest. -Use the ""help" option to get the full list of parameters: +Use the "help" option to get the full list of parameters: ./pactest.py --help @@ -103,15 +103,22 @@ Example: ------ A dictionary that holds the data used in the pacman configuration file. -It has 3 keys, each one of them pointing at a list of strings: - - noupgrade - - noextract - - ignorepkg +The following options are known to be useful in pactest tests; this list +is not necessarily complete: + - HoldPkg + - IgnorePkg + - IgnoreGroup + - SyncFirst + - NoExtract + - NoUpgrade + - XferCommand + +For documentation on these options, see the pacman.conf documentation. Examples: - self.option["noupgrade"] = ["etc/X11/xorg.conf", + self.option["NoUpgrade"] = ["etc/X11/xorg.conf", "etc/pacman.conf"] - self.option["noextract"] = ["etc/lilo.conf"] + self.option["NoExtract"] = ["etc/lilo.conf"] filesystem ---------- diff --git a/pactest/pmenv.py b/pactest/pmenv.py index e9d0b4c9..cc433dd0 100755 --- a/pactest/pmenv.py +++ b/pactest/pmenv.py @@ -71,9 +71,11 @@ class pmenv: t.generate() # Hack for mtimes consistency for i in t.rules: - if i.rule.find("MODIFIED") != -1: - time.sleep(1.5) - break + if i.rule.find("FILE_MODIFIED") != -1: + [test, arg] = i.rule.split("=") + for f in t.files: + if f.name == arg: + f.resettimes() t.run(self.pacman) diff --git a/pactest/pmfile.py b/pactest/pmfile.py index 21baf017..ab4aa2c7 100755 --- a/pactest/pmfile.py +++ b/pactest/pmfile.py @@ -56,6 +56,14 @@ class pmfile: return retval + def resettimes(self): + """ + """ + + filename = os.path.join(self.root, self.name) + os.utime(filename, (355, 355)) + self.mtime = getmtime(filename) + vprint("\tmtime reset (%s)" % self.name) if __name__ == "__main__": f = pmfile("/tmp", "foobar") diff --git a/pactest/tests/Makefile.am b/pactest/tests/Makefile.am new file mode 100644 index 00000000..b793687b --- /dev/null +++ b/pactest/tests/Makefile.am @@ -0,0 +1,27 @@ +CONFTESTS = $(patsubst %py.in,%py,$(wildcard *.py.in)) + +check_SCRIPTS = \ + $(wildcard *.py) \ + $(CONFTESTS) + +noinst_SCRIPTS = $(check_SCRIPTS) + +EXTRA_DIST = $(check_SCRIPTS) + +CLEANFILES = $(CONFTESTS) + +#### Taken from the autoconf scripts Makefile.am #### +edit = sed \ + -e 's|@LIBS[@]|$(LIBS)|g' \ + -e 's|@configure_input[@]|Generated from $@.in; do not edit by hand.|g' + + +$(CONFTESTS): Makefile + @echo ' ' GEN $@; + @rm -f $@ $@.tmp + @test -f $(srcdir)/$@.in && $(edit) $(srcdir)/$@.in >$@.tmp || true + @test -f $@.tmp || false + @chmod a-w $@.tmp + @mv $@.tmp $@ + +# vim:set ts=2 sw=2 noet: diff --git a/pactest/tests/ignore001.py b/pactest/tests/ignore001.py new file mode 100644 index 00000000..bb3fa59a --- /dev/null +++ b/pactest/tests/ignore001.py @@ -0,0 +1,17 @@ +self.description = "Sync with irrelevant ignored packages" + +package1 = pmpkg("package1") +self.addpkg2db("local", package1) + +package2 = pmpkg("package2") +self.addpkg2db("local", package2) + +package2up = pmpkg("package2", "2.0-1") +self.addpkg2db("sync", package2up) + +self.option["IgnorePkg"] = ["irrelavent"] +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=package1|1.0-1") +self.addrule("PKG_VERSION=package2|2.0-1") diff --git a/pactest/tests/ignore002.py b/pactest/tests/ignore002.py new file mode 100644 index 00000000..b2c5593a --- /dev/null +++ b/pactest/tests/ignore002.py @@ -0,0 +1,35 @@ +self.description = "Sync with relevant ignored packages" + +package1 = pmpkg("package1") +self.addpkg2db("local", package1) + +package2 = pmpkg("package2") +self.addpkg2db("local", package2) + +package3 = pmpkg("package3") +package3.depends = ["package2=1.0-1"] +self.addpkg2db("local", package3) + +package4 = pmpkg("package4") +package4.depends = ["package3=1.0-1"] +self.addpkg2db("local", package4) + +package2up = pmpkg("package2", "2.0-1") +self.addpkg2db("sync", package2up) + +package3up = pmpkg("package3", "2.0-1") +package3up.depends = ["package2=2.0-1"] +self.addpkg2db("sync", package3up) + +package4up = pmpkg("package4", "2.0-1") +package4up.depends = ["package3=2.0-1"] +self.addpkg2db("sync", package4up) + +self.option["IgnorePkg"] = ["package2"] +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=package1|1.0-1") +self.addrule("PKG_VERSION=package2|1.0-1") +self.addrule("PKG_VERSION=package3|1.0-1") +self.addrule("PKG_VERSION=package4|1.0-1") diff --git a/pactest/tests/ignore003.py b/pactest/tests/ignore003.py new file mode 100644 index 00000000..02b3c91c --- /dev/null +++ b/pactest/tests/ignore003.py @@ -0,0 +1,35 @@ +self.description = "Sync with relevant ignored packages and dependency loop" + +package1 = pmpkg("package1") +self.addpkg2db("local", package1) + +package2 = pmpkg("package2") +self.addpkg2db("local", package2) + +package3 = pmpkg("package3") +package3.depends = ["package2=1.0-1"] +self.addpkg2db("local", package3) + +package4 = pmpkg("package4") +package4.depends = ["package3=1.0-1"] +self.addpkg2db("local", package4) + +package2up = pmpkg("package2", "2.0-1") +self.addpkg2db("sync", package2up) + +package3up = pmpkg("package3", "2.0-1") +package3up.depends = ["package2=2.0-1", "package4=2.0-1"] +self.addpkg2db("sync", package3up) + +package4up = pmpkg("package4", "2.0-1") +package4up.depends = ["package3=2.0-1"] +self.addpkg2db("sync", package4up) + +self.option["IgnorePkg"] = ["package2"] +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=package1|1.0-1") +self.addrule("PKG_VERSION=package2|1.0-1") +self.addrule("PKG_VERSION=package3|1.0-1") +self.addrule("PKG_VERSION=package4|1.0-1") diff --git a/pactest/tests/ignore004.py b/pactest/tests/ignore004.py new file mode 100644 index 00000000..fff12f62 --- /dev/null +++ b/pactest/tests/ignore004.py @@ -0,0 +1,46 @@ +self.description = "Sync with ignore causing top-level to be ignored" + +packageA1 = pmpkg("packageA1") +packageA1.depends = ["packageA2=1.0-1", "packageA3=1.0-1"]; +self.addpkg2db("local", packageA1) + +packageA2 = pmpkg("packageA2") +packageA2.depends = ["packageA4=1.0-1", "packageA5=1.0-1"]; +self.addpkg2db("local", packageA2) + +packageA3 = pmpkg("packageA3") +self.addpkg2db("local", packageA3) + +packageA4 = pmpkg("packageA4") +self.addpkg2db("local", packageA4) + +packageA5 = pmpkg("packageA5") +self.addpkg2db("local", packageA5) + +packageA1up = pmpkg("packageA1", "2.0-1") +packageA1up.depends = ["packageA2=2.0-1", "packageA3=2.0-1"]; +self.addpkg2db("sync", packageA1up) + +packageA2up = pmpkg("packageA2", "2.0-1") +packageA2up.depends = ["packageA4=2.0-1", "packageA5=2.0-1"]; +self.addpkg2db("sync", packageA2up) + +packageA3up = pmpkg("packageA3", "2.0-1") +self.addpkg2db("sync", packageA3up) + +packageA4up = pmpkg("packageA4", "2.0-1") +self.addpkg2db("sync", packageA4up) + +packageA5up = pmpkg("packageA5", "2.0-1") +self.addpkg2db("sync", packageA5up) + + +self.option["IgnorePkg"] = ["packageA3"] +self.args = "-S packageA1" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=packageA1|1.0-1") +self.addrule("PKG_VERSION=packageA2|1.0-1") +self.addrule("PKG_VERSION=packageA3|1.0-1") +self.addrule("PKG_VERSION=packageA4|1.0-1") +self.addrule("PKG_VERSION=packageA5|1.0-1") diff --git a/pactest/tests/ignore005.py b/pactest/tests/ignore005.py new file mode 100644 index 00000000..1957ea4f --- /dev/null +++ b/pactest/tests/ignore005.py @@ -0,0 +1,46 @@ +self.description = "Sync with ignore causing top-level to be included" + +packageA1 = pmpkg("packageA1") +packageA1.depends = ["packageA2>=1.0-1", "packageA3=1.0-1"]; +self.addpkg2db("local", packageA1) + +packageA2 = pmpkg("packageA2") +packageA2.depends = ["packageA4=1.0-1", "packageA5=1.0-1"]; +self.addpkg2db("local", packageA2) + +packageA3 = pmpkg("packageA3") +self.addpkg2db("local", packageA3) + +packageA4 = pmpkg("packageA4") +self.addpkg2db("local", packageA4) + +packageA5 = pmpkg("packageA5") +self.addpkg2db("local", packageA5) + +packageA1up = pmpkg("packageA1", "2.0-1") +packageA1up.depends = ["packageA2>=2.0-1", "packageA3=2.0-1"]; +self.addpkg2db("sync", packageA1up) + +packageA2up = pmpkg("packageA2", "2.0-1") +packageA2up.depends = ["packageA4=2.0-1", "packageA5=2.0-1"]; +self.addpkg2db("sync", packageA2up) + +packageA3up = pmpkg("packageA3", "2.0-1") +self.addpkg2db("sync", packageA3up) + +packageA4up = pmpkg("packageA4", "2.0-1") +self.addpkg2db("sync", packageA4up) + +packageA5up = pmpkg("packageA5", "2.0-1") +self.addpkg2db("sync", packageA5up) + + +self.option["IgnorePkg"] = ["packageA3"] +self.args = "-S packageA1 packageA2" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=packageA1|1.0-1") +self.addrule("PKG_VERSION=packageA2|2.0-1") +self.addrule("PKG_VERSION=packageA3|1.0-1") +self.addrule("PKG_VERSION=packageA4|2.0-1") +self.addrule("PKG_VERSION=packageA5|2.0-1") diff --git a/pactest/tests/provision020.py b/pactest/tests/provision020.py index 7cb0a01b..c9c0ac36 100644 --- a/pactest/tests/provision020.py +++ b/pactest/tests/provision020.py @@ -10,6 +10,6 @@ self.addpkg2db("local", lp) self.args = "-S %s" % p.name -self.addrule("PACMAN_RETCODE=1") +self.addrule("PACMAN_RETCODE=0") self.addrule("!PKG_EXIST=pkg1") self.addrule("PKG_EXIST=pkg2") diff --git a/pactest/tests/provision022.py b/pactest/tests/provision022.py index 4883d428..190a8b66 100644 --- a/pactest/tests/provision022.py +++ b/pactest/tests/provision022.py @@ -10,6 +10,6 @@ self.addpkg2db("local", lp) self.args = "-S %s" % p.name -self.addrule("PACMAN_RETCODE=1") +self.addrule("PACMAN_RETCODE=0") self.addrule("!PKG_EXIST=pkg1") self.addrule("PKG_EXIST=pkg2") diff --git a/pactest/tests/remove030.py b/pactest/tests/remove030.py index 9e2b9da5..e975a4ba 100644 --- a/pactest/tests/remove030.py +++ b/pactest/tests/remove030.py @@ -7,7 +7,5 @@ self.option["HoldPkg"] = ["dummy"] self.args = "-R %s" % p1.name -self.addrule("PACMAN_RETCODE=0") -self.addrule("!PKG_EXIST=dummy") -self.addrule("!FILE_EXIST=etc/dummy.conf") -self.addrule("!FILE_PACSAVE=etc/dummy.conf") +self.addrule("PACMAN_RETCODE=1") +self.addrule("PKG_EXIST=dummy") diff --git a/pactest/tests/sync1008.py b/pactest/tests/sync1008.py index a6064597..90c61dfb 100644 --- a/pactest/tests/sync1008.py +++ b/pactest/tests/sync1008.py @@ -14,6 +14,6 @@ self.addpkg2db("sync1", sp3) self.args = "-S pkg" -self.addrule("PACMAN_RETCODE=1") +self.addrule("PACMAN_RETCODE=0") self.addrule("!PKG_EXIST=pkg") self.addrule("!PKG_EXIST=cpkg") diff --git a/pactest/tests/sync200.py b/pactest/tests/sync200.py.in index 9005bd3d..3c11f83f 100644 --- a/pactest/tests/sync200.py +++ b/pactest/tests/sync200.py.in @@ -1,5 +1,8 @@ self.description = "Synchronize the local database" +if not "download" in "@LIBS@": + self.option['XferCommand'] = ['/usr/bin/curl %u > %o'] + sp1 = pmpkg("spkg1", "1.0-1") sp1.depends = ["spkg2"] sp2 = pmpkg("spkg2", "2.0-1") diff --git a/pactest/tests/sync300.py b/pactest/tests/sync300.py index 31b520a8..36d6758a 100644 --- a/pactest/tests/sync300.py +++ b/pactest/tests/sync300.py @@ -9,6 +9,6 @@ self.addpkg2db("sync", sp2) self.args = "-S %s" % sp1.name -self.addrule("PACMAN_RETCODE=1") +self.addrule("PACMAN_RETCODE=0") self.addrule("!PKG_EXIST=pkg1") self.addrule("!PKG_EXIST=pkg2") diff --git a/pactest/util.py b/pactest/util.py index db9560fe..da6d44e3 100755 --- a/pactest/util.py +++ b/pactest/util.py @@ -18,7 +18,7 @@ import sys import os -import md5 +import hashlib import stat @@ -198,7 +198,7 @@ def getmd5sum(filename): print "file %s does not exist!" % filename return "" fd = open(filename, "rb") - checksum = md5.new() + checksum = hashlib.md5() while 1: block = fd.read(1048576) if not block: @@ -211,7 +211,7 @@ def getmd5sum(filename): def mkmd5sum(data): """ """ - checksum = md5.new() + checksum = hashlib.md5() checksum.update("%s\n" % data) digest = checksum.digest() return "%02x"*len(digest) % tuple(map(ord, digest)) @@ -33,7 +33,7 @@ msgstr "risoluzione delle dipendenze in corso...\n" #, c-format msgid "looking for inter-conflicts...\n" -msgstr "ricerca dei conflitti incrociati in corso...\n" +msgstr "ricerca di conflitti in corso...\n" #, c-format msgid "installing %s...\n" @@ -53,7 +53,7 @@ msgstr "controllo dell'integrità dei pacchetti in corso...\n" #, c-format msgid "checking delta integrity...\n" -msgstr "controllo dell'integrità di delta in corso...\n" +msgstr "controllo dell'integrità del delta in corso...\n" #, c-format msgid "applying deltas...\n" @@ -399,7 +399,8 @@ msgstr " -o, --owns <file> interroga il pacchetto che contiene il <file>\n" #, c-format msgid " -p, --file <package> query a package file instead of the database\n" msgstr "" -" -p, --file <package> interroga un file del pacchetto invece del database\n" +" -p, --file <pacchetto> interroga un file del pacchetto invece del " +"database\n" #, c-format msgid "" @@ -414,10 +415,8 @@ msgid " -t, --unrequired list all packages not required by any package\n" msgstr " -t, --unrequired elenca tutti i pacchetti non richiesti\n" #, c-format -msgid " -u, --upgrades list all packages that can be upgraded\n" -msgstr "" -" -u, --upgrades elenca tutti i pacchetti che possono essere " -"aggiornati\n" +msgid " -u, --upgrades list all outdated packages\n" +msgstr " -u, --upgrades elenca tutti i pacchetti non aggiornati\n" #, c-format msgid " -q, --quiet show less information for query and search\n" @@ -537,8 +536,9 @@ msgid "" " This program may be freely redistributed under\n" " the terms of the GNU General Public License.\n" msgstr "" -" This program may be freely redistributed under\n" -" the terms of the GNU General Public License.\n" +" Questo programma può essere liberamente " +"ridistribuito\n" +" sotto i termini della GNU General Public License.\n" #, c-format msgid "problem setting rootdir '%s' (%s)\n" @@ -650,14 +650,6 @@ msgid "group \"%s\" was not found\n" msgstr "il gruppo \"%s\" non è stato trovato\n" #, c-format -msgid "Checking for package upgrades... \n" -msgstr "Controllo degli aggiornamenti dei pacchetti in corso... \n" - -#, c-format -msgid "no upgrades found.\n" -msgstr "non ci sono aggiornamenti.\n" - -#, c-format msgid "no usable package repositories configured.\n" msgstr "non è stato configurato nessun repository di pacchetti valido.\n" @@ -671,7 +663,7 @@ msgstr "il pacchetto \"%s\" non è stato trovato\n" #, c-format msgid "%s not found, searching for group...\n" -msgstr "%s non è stato trovato. cerco per un gruppo...\n" +msgstr "%s non è stato trovato, ricerca in corso all'interno di un gruppo...\n" #, c-format msgid "'%s': not found in local db\n" @@ -923,6 +915,10 @@ msgid "Total Removed Size: %.2f MB\n" msgstr "Dimensione totale dei pacchetti da rimuovere: %.2f MB\n" #, c-format +msgid "New optional dependencies for %s\n" +msgstr "Nuove dipendenze opzionali di %s\n" + +#, c-format msgid "Optional dependencies for %s\n" msgstr "Dipendenze opzionali di %s\n" @@ -994,7 +990,7 @@ msgid "The download program %s is not installed." msgstr "Il programma %s per il download non è installato." msgid "Pacman returned a fatal error (%i): %s" -msgstr "Pacman ha ritornato un errore fatale (%i): %s" +msgstr "Pacman ha riportato un errore fatale (%i): %s" msgid "Installing missing dependencies..." msgstr "Installazione delle dipendenze mancanti in corso..." @@ -1035,18 +1031,15 @@ msgstr "Impossibile scaricare %s" msgid "Generating checksums for source files..." msgstr "Generazione dei checksum dei sorgenti in corso..." -msgid "Invalid integrity algorithm '%s' specified." -msgstr "L'algoritmo dell'integrità di '%s' specificato non è valido." - msgid "Cannot find openssl." msgstr "Impossibile trovare openssl." +msgid "Invalid integrity algorithm '%s' specified." +msgstr "L'algoritmo dell'integrità di '%s' specificato non è valido." + msgid "Unable to find source file %s to generate checksum." msgstr "Impossibile trovare il file sorgente di %s per generare il checksum." -msgid "Invalid integrity algorithm '%s' specified" -msgstr "L'algoritmo dell'integrità di '%s' specificato non è valido" - msgid "Validating source files with %s..." msgstr "Validazione dei file sorgenti con %s in corso..." @@ -1083,11 +1076,11 @@ msgstr "Compilazione interrotta." msgid "Tidying install..." msgstr "Rimozione dei dati superflui in corso..." -msgid "Removing info/doc files..." -msgstr "Rimozione dei file info/doc in corso..." +msgid "Removing doc files..." +msgstr "Rimozione dei file doc in corso..." -msgid "Compressing man pages..." -msgstr "Compressione delle pagine man in corso..." +msgid "Compressing man and info pages..." +msgstr "Compressione delle pagine man ed info in corso..." msgid "Stripping debugging symbols from binaries and libraries..." msgstr "Rimozione dei simboli di debug dai binari e dalle librerie in corso..." @@ -1122,6 +1115,9 @@ msgstr "Aggiunta del changelog del pacchetto in corso..." msgid "Compressing package..." msgstr "Compressione del pacchetto in corso..." +msgid "'%s' is not a valid archive extension." +msgstr "'%s' non è una valida estensione di un archivio." + msgid "Failed to create package file." msgstr "Impossibile creare il pacchetto." @@ -1206,6 +1202,9 @@ msgstr " -c, --clean Ripulisce i sorgenti dopo la compilazione" msgid " -C, --cleancache Clean up source files from the cache" msgstr " -C, --cleancache Elimina i sorgenti dalla cache" +msgid " --config <config> Use an alternate config file (instead of '%s')" +msgstr " --config <config> Usa un file di config alternativo (invece di '%s')" + msgid " -d, --nodeps Skip all dependency checks" msgstr " -d, --nodeps Ignora tutti i controlli sulle dipendenze" @@ -1322,8 +1321,8 @@ msgstr "La cache del sorgente è stata pulita." msgid "No files have been removed." msgstr "Non è stato rimosso nessun file." -msgid "Source destination must be defined in makepkg.conf." -msgstr "La destinazione del sorgente deve essere definita in makepkg.conf." +msgid "Source destination must be defined in %s." +msgstr "La destinazione del sorgente deve essere definita in %s." msgid "In addition, please run makepkg -C outside of your cache directory." msgstr "" @@ -1360,8 +1359,8 @@ msgid "ownership of the packaged files. Try using the fakeroot environment by" msgstr "" "di proprietà del pacchettizzatore. Prova ad usare l'ambiente di fakeroot," -msgid "placing 'fakeroot' in the BUILDENV array in makepkg.conf." -msgstr "posizionando 'fakeroot' nell'array BUILDENV in makepkg.conf." +msgid "placing 'fakeroot' in the BUILDENV array in %s." +msgstr "inserendo 'fakeroot' nell'array BUILDENV in %s." msgid "Do not use the '-F' option. This option is only for use by makepkg." msgstr "Non usare l'opzione '-F'. Questa opzione si usa solo con makepkg." @@ -1556,10 +1555,10 @@ msgid "Finished. Your pacman database has been optimized." msgstr "Terminato. Il database di pacman è stato ottimizzato." msgid "Usage: repo-add [-q] <path-to-db> <package> ...\\n" -msgstr "uso: repo-add [-q] <path-al-db> <nomepacchetto> ...\\n" +msgstr "uso: repo-add [-q] <path-del-db> <pacchetto> ...\\n" msgid "Usage: repo-remove [-q] <path-to-db> <packagename> ...\\n\\n" -msgstr "Uso: repo-remove [-q] <path-al-db> <nomepacchetto>...\\n\\n" +msgstr "Uso: repo-remove [-q] <path-del-db> <nomepacchetto>...\\n\\n" msgid "" "repo-add will update a package database by reading a package file." @@ -1630,9 +1629,6 @@ msgstr "Rimozione del pacchetto esistente '%s' in corso..." msgid "Either realpath or readlink are required by repo-add." msgstr "realpath o readlink sono richiesti da repo-add." -msgid "%s not found. Cannot continue." -msgstr "%s non è stato trovato. Impossibile continuare." - msgid "Cannot create temp directory for database building." msgstr "Impossibile creare la directory temp per creare il database." @@ -1672,8 +1668,8 @@ msgstr "Non è stato trovato nessun pacchetto corrispondente a '%s'." msgid "Creating updated database file '%s'" msgstr "Creazione di un database aggiornato di '%s'" -msgid "No compression set." -msgstr "Non è stata impostata nessuna compressione." +msgid "'%s' does not have a valid archive extension." +msgstr "'%s' non è una valida estensione di un archivio." msgid "All packages have been removed from the database. Deleting '%s'." msgstr "" diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 10e179e1..d6d9bb93 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -37,6 +37,7 @@ edit = sed \ -e 's|@PACKAGE_BUGREPORT[@]|$(PACKAGE_BUGREPORT)|g' \ -e 's|@PACKAGE_NAME[@]|$(PACKAGE_NAME)|g' \ -e 's|@DBEXT[@]|$(DBEXT)|g' \ + -e 's|@BUILDSCRIPT[@]|$(BUILDSCRIPT)|g' \ -e 's|@SIZECMD[@]|$(SIZECMD)|g' \ -e 's|@configure_input[@]|Generated from $@.in; do not edit by hand.|g' @@ -46,13 +47,14 @@ edit = sed \ # two 'test' lines- make sure we can handle both sh and py type scripts # third 'test' line- make sure one of the two checks succeeded $(OURSCRIPTS): Makefile - rm -f $@ $@.tmp - test -f $(srcdir)/$@.sh.in && $(edit) $(srcdir)/$@.sh.in >$@.tmp || true - test -f $(srcdir)/$@.py.in && $(edit) $(srcdir)/$@.py.in >$@.tmp || true - test -f $@.tmp || false - chmod +x $@.tmp - chmod a-w $@.tmp - mv $@.tmp $@ + @echo ' ' GEN $@; + @rm -f $@ $@.tmp + @test -f $(srcdir)/$@.sh.in && $(edit) $(srcdir)/$@.sh.in >$@.tmp || true + @test -f $(srcdir)/$@.py.in && $(edit) $(srcdir)/$@.py.in >$@.tmp || true + @test -f $@.tmp || false + @chmod +x $@.tmp + @chmod a-w $@.tmp + @mv $@.tmp $@ makepkg: $(srcdir)/makepkg.sh.in pacman-optimize: $(srcdir)/pacman-optimize.sh.in diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in index d05d2403..52e80d17 100644 --- a/scripts/makepkg.sh.in +++ b/scripts/makepkg.sh.in @@ -38,11 +38,16 @@ export COMMAND_MODE='legacy' myver='@PACKAGE_VERSION@' confdir='@sysconfdir@' +BUILDSCRIPT='@BUILDSCRIPT@' startdir="$PWD" srcdir="$startdir/src" pkgdir="$startdir/pkg" -known_options=('strip' 'docs' 'libtool' 'emptydirs' 'zipman' 'ccache' 'distcc' 'makeflags' 'force') -readonly -a known_options + +packaging_options=('strip' 'docs' 'libtool' 'emptydirs' 'zipman' 'purge') +other_options=('ccache' 'distcc' 'makeflags' 'force') +splitpkg_overrides=('pkgdesc' 'license' 'groups' 'depends' 'optdepends' 'provides' \ + 'conflicts' 'replaces' 'backup' 'options' 'install') +readonly -a packaging_options other_options splitpkg_overrides # Options ASROOT=0 @@ -62,6 +67,8 @@ LOGGING=0 SOURCEONLY=0 IGNOREARCH=0 HOLDVER=0 +PKGFUNC=0 +SPLITPKG=0 # Forces the pkgver of the current PKGBUILD. Used by the fakeroot call # when dealing with svn/cvs/etc PKGBUILDs. @@ -122,7 +129,7 @@ error() { # the fakeroot call, the error message will be printed by the main call. ## trap_exit() { - if [ "$INFAKEROOT" = "0" ]; then + if [ "$INFAKEROOT" -eq 0 ]; then echo error "$@" fi @@ -136,16 +143,16 @@ trap_exit() { clean_up() { local EXIT_CODE=$? - if [ "$INFAKEROOT" = "1" ]; then + if [ "$INFAKEROOT" -eq 1 ]; then # Don't clean up when leaving fakeroot, we're not done yet. return fi - if [ $EXIT_CODE -eq 0 -a "$CLEANUP" = "1" ]; then + if [ $EXIT_CODE -eq 0 -a "$CLEANUP" -eq 1 ]; then # If it's a clean exit and -c/--clean has been passed... msg "$(gettext "Cleaning up...")" rm -rf "$pkgdir" "$srcdir" - if [ "$pkgname" != "" ]; then + if [ -n "$pkgname" ]; then # Can't do this unless the BUILDSCRIPT has been sourced. rm -f "${pkgname}-${pkgver}-${pkgrel}-${CARCH}.log*" fi @@ -270,7 +277,7 @@ get_downloadclient() { local i for i in "${DLAGENTS[@]}"; do local handler=$(echo $i | sed 's|::.*||') - if [ "$proto" == "$handler" ]; then + if [ "$proto" = "$handler" ]; then agent=$(echo $i | sed 's|^.*::||') break fi @@ -278,7 +285,7 @@ get_downloadclient() { # if we didn't find an agent, return an error if [ -z "$agent" ]; then - error "$(gettext "There is no agent set up to handle %s URLs. Check %s.")" "$proto" "$confdir/makepkg.conf" + error "$(gettext "There is no agent set up to handle %s URLs. Check %s.")" "$proto" "$MAKEPKG_CONF" plain "$(gettext "Aborting...")" exit 1 # $E_CONFIG_ERROR fi @@ -346,16 +353,16 @@ handledeps() { local deplist="$*" - if [ "$DEP_BIN" = "0" ]; then + if [ "$DEP_BIN" -eq 0 ]; then return $R_DEPS_MISSING fi - if [ "$DEP_BIN" = "1" ]; then + if [ "$DEP_BIN" -eq 1 ]; then # install missing deps from binary packages (using pacman -S) msg "$(gettext "Installing missing dependencies...")" local ret=0 - if [ "$ASROOT" = 0 ]; then + if [ "$ASROOT" -eq 0 ]; then sudo pacman $PACMAN_OPTS -S --asdeps $deplist || ret=$? else pacman $PACMAN_OPTS -S --asdeps $deplist || ret=$? @@ -382,7 +389,7 @@ resolve_deps() { local R_DEPS_MISSING=1 local deplist="$(check_deps $*)" - if [ "$deplist" = "" ]; then + if [ -z "$deplist" ]; then return $R_DEPS_SATISFIED fi @@ -390,8 +397,8 @@ resolve_deps() { pkgdeps="$pkgdeps $deplist" # check deps again to make sure they were resolved deplist="$(check_deps $*)" - [ "$deplist" = "" ] && return $R_DEPS_SATISFIED - elif [ "$DEP_BIN" = "1" ]; then + [ -z "$deplist" ] && return $R_DEPS_SATISFIED + elif [ "$DEP_BIN" -eq 1 ]; then error "$(gettext "Failed to install all missing dependencies.")" fi @@ -407,8 +414,8 @@ resolve_deps() { # fix flyspray bug #5923 remove_deps() { # $pkgdeps is a GLOBAL variable, set by resolve_deps() - [ "$RMDEPS" = "0" ] && return - [ "$pkgdeps" = "" ] && return + [ "$RMDEPS" -eq 0 ] && return + [ -z "$pkgdeps" ] && return local dep depstrip deplist deplist="" @@ -419,7 +426,7 @@ remove_deps() { msg "Removing installed dependencies..." local ret=0 - if [ "$ASROOT" = "0" ]; then + if [ "$ASROOT" -eq 0 ]; then sudo pacman $PACMAN_OPTS -Rns $deplist || ret=$? else pacman $PACMAN_OPTS -Rns $deplist || ret=$? @@ -488,6 +495,11 @@ generate_checksums() { msg "$(gettext "Generating checksums for source files...")" plain "" + if [ ! $(type -p openssl) ]; then + error "$(gettext "Cannot find openssl.")" + exit 1 # $E_MISSING_PROGRAM + fi + local integ for integ in ${INTEGRITY_CHECK[@]}; do integ="$(echo $integ | tr '[:upper:]' '[:lower:]')" @@ -498,11 +510,6 @@ generate_checksums() { exit 1;; # $E_CONFIG_ERROR esac - if [ ! $(type -p openssl) ]; then - error "$(gettext "Cannot find openssl.")" - exit 1 # $E_MISSING_PROGRAM - fi - local ct=0 local numsrc=${#source[@]} echo -n "${integ}sums=(" @@ -540,24 +547,18 @@ generate_checksums() { } check_checksums() { - local integ - for integ in ${INTEGRITY_CHECK[@]}; do - integ="$(echo $integ | tr '[:upper:]' '[:lower:]')" - case "$integ" in - md5|sha1|sha256|sha384|sha512) : ;; - *) - error "$(gettext "Invalid integrity algorithm '%s' specified")" "$integ" - exit 1;; # $E_CONFIG_ERROR - esac - - if [ ! $(type -p openssl) ]; then - error "$(gettext "Cannot find openssl.")" - exit 1 # $E_MISSING_PROGRAM - fi + if [ ! $(type -p openssl) ]; then + error "$(gettext "Cannot find openssl.")" + exit 1 # $E_MISSING_PROGRAM + fi + local correlation=0 + local integ required + for integ in md5 sha1 sha256 sha384 sha512; do local integrity_sums=($(eval echo "\${${integ}sums[@]}")) if [ ${#integrity_sums[@]} -eq ${#source[@]} ]; then msg "$(gettext "Validating source files with %s...")" "${integ}sums" + correlation=1 local errors=0 local idx=0 local file @@ -591,10 +592,16 @@ check_checksums() { error "$(gettext "One or more files did not pass the validity check!")" exit 1 # TODO: error code fi - else - warning "$(gettext "Integrity checks (%s) are missing or incomplete.")" "$integ" + elif [ ${#integrity_sums[@]} -gt 0 ]; then + error "$(gettext "Integrity checks (%s) differ in size from the source array.")" "$integ" + exit 1 # TODO: error code fi done + + if [ $correlation -eq 0 ]; then + error "$(gettext "Integrity checks are missing.")" + exit 1 # TODO: error code + fi } extract_sources() { @@ -674,13 +681,13 @@ run_build() { cd "$srcdir" # ensure all necessary build variables are exported - export CFLAGS CXXFLAGS MAKEFLAGS CHOST + export CFLAGS CXXFLAGS MAKEFLAGS LDFLAGS CHOST # save our shell options so build() can't override what we need local shellopts=$(shopt -p) local ret=0 - if [ "$LOGGING" = "1" ]; then - BUILDLOG="${startdir}/${pkgname}-${pkgver}-${pkgrel}-${CARCH}.log" + if [ "$LOGGING" -eq 1 ]; then + BUILDLOG="${startdir}/${pkgname}-${pkgver}-${pkgrel}-${CARCH}-build.log" if [ -f "$BUILDLOG" ]; then local i=1 while true; do @@ -708,21 +715,88 @@ run_build() { fi } +run_package() { + if [ -z "$1" ]; then + pkgfunc="package" + nameofpkg="$pkgname" + else + pkgfunc="package_$1" + nameofpkg="$1" + fi + + # clear user-specified makeflags if requested + if [ "$(check_option makeflags)" = "n" ]; then + MAKEFLAGS="" + fi + + msg "$(gettext "Starting %s()...")" "$pkgfunc" + cd "$srcdir" + + # ensure all necessary build variables are exported + export CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST + + local ret=0 + if [ "$LOGGING" -eq 1 ]; then + BUILDLOG="${startdir}/${nameofpkg}-${pkgver}-${pkgrel}-${CARCH}-package.log" + if [ -f "$BUILDLOG" ]; then + local i=1 + while true; do + if [ -f "$BUILDLOG.$i" ]; then + i=$(($i +1)) + else + break + fi + done + mv "$BUILDLOG" "$BUILDLOG.$i" + fi + + # ensure overridden package variables suvrive tee with split packages + logpipe=$(mktemp -u "$startdir/logpipe.XXXXXXXX") + mknod "$logpipe" p + exec 3>&1 + tee "$BUILDLOG" < "$logpipe" & + exec 1>"$logpipe" 2>"$logpipe" + $pkgfunc 2>&1 || ret=$? + sync + exec 1>&3 2>&3 3>&- + rm "$logpipe" + else + $pkgfunc 2>&1 || ret=$? + fi + + if [ $ret -gt 0 ]; then + error "$(gettext "Packaging Failed.")" + plain "$(gettext "Aborting...")" + remove_deps + exit 2 # $E_BUILD_FAILED + fi +} + tidy_install() { cd "$pkgdir" msg "$(gettext "Tidying install...")" - if [ "$(check_option docs)" = "n" ]; then - msg2 "$(gettext "Removing info/doc files...")" - #fix flyspray bug #5021 + if [ "$(check_option docs)" = "n" -a -n "${DOC_DIRS[*]}" ]; then + msg2 "$(gettext "Removing doc files...")" rm -rf ${DOC_DIRS[@]} fi - if [ "$(check_option zipman)" = "y" ]; then - msg2 "$(gettext "Compressing man pages...")" - local manpage mandirs ext file link hardlinks hl - mandirs="usr/man usr/share/man usr/local/man usr/local/share/man opt/*/man" - find ${mandirs} -type f 2>/dev/null | + if [ "$(check_option purge)" = "y" -a -n "${PURGE_TARGETS[*]}" ]; then + msg2 "$(gettext "Purging other files...")" + local pt + for pt in "${PURGE_TARGETS[@]}"; do + if [ "${pt}" = "${pt//\/}" ]; then + find . -type f -name "${pt}" -exec rm -f -- '{}' \; + else + rm -f ${pt} + fi + done + fi + + if [ "$(check_option zipman)" = "y" -a -n "${MAN_DIRS[*]}" ]; then + msg2 "$(gettext "Compressing man and info pages...")" + local manpage ext file link hardlinks hl + find ${MAN_DIRS[@]} -type f 2>/dev/null | while read manpage ; do # check file still exists (potentially compressed with hard link) if [ -f ${manpage} ]; then @@ -730,7 +804,7 @@ tidy_install() { file="${manpage##*/}" if [ "$ext" != "gz" -a "$ext" != "bz2" ]; then # update symlinks to this manpage - find ${mandirs} -lname "$file" 2>/dev/null | + find ${MAN_DIRS[@]} -lname "$file" 2>/dev/null | while read link ; do rm -f "$link" ln -sf "${file}.gz" "${link}.gz" @@ -738,7 +812,7 @@ tidy_install() { # find hard links and remove them # the '|| true' part keeps the script from bailing if find returned an # error, such as when one of the man directories doesn't exist - hardlinks="$(find ${mandirs} \! -name "$file" -samefile "$manpage" 2>/dev/null)" || true + hardlinks="$(find ${MAN_DIRS[@]} \! -name "$file" -samefile "$manpage" 2>/dev/null)" || true for hl in ${hardlinks}; do rm -f "${hl}"; done @@ -754,15 +828,9 @@ tidy_install() { done fi - - if [ "$(check_option strip)" = "y" ]; then + if [ "$(check_option strip)" = "y" -a -n "${STRIP_DIRS[*]}" ]; then msg2 "$(gettext "Stripping debugging symbols from binaries and libraries...")" local binary - if [ -z "${STRIP_DIRS[*]}" ]; then - # fall back to default value - STRIP_DIRS=(bin lib sbin usr/{bin,lib,sbin,local/{bin,lib,sbin}} - opt/*/{bin,lib,sbin}) - fi find ${STRIP_DIRS[@]} -type f 2>/dev/null | while read binary ; do case "$(file -biz "$binary")" in *application/x-sharedlib*) # Libraries (.so) @@ -787,6 +855,12 @@ tidy_install() { } create_package() { + if [ -z "$1" ]; then + nameofpkg="$pkgname" + else + nameofpkg="$1" + fi + if [ ! -d "$pkgdir" ]; then error "$(gettext "Missing pkg/ directory.")" plain "$(gettext "Aborting...")" @@ -797,7 +871,7 @@ create_package() { msg "$(gettext "Creating package...")" local builddate=$(date -u "+%s") - if [ "$PACKAGER" != "" ]; then + if [ -n "$PACKAGER" ]; then local packager="$PACKAGER" else local packager="Unknown Packager" @@ -807,18 +881,18 @@ create_package() { # write the .PKGINFO file msg2 "$(gettext "Generating .PKGINFO file...")" echo "# Generated by makepkg $myver" >.PKGINFO - if [ "$INFAKEROOT" = "1" ]; then + if [ "$INFAKEROOT" -eq 1 ]; then echo "# using $(fakeroot -v)" >>.PKGINFO fi echo "# $(LC_ALL=C date -u)" >>.PKGINFO - echo "pkgname = $pkgname" >>.PKGINFO + echo "pkgname = $nameofpkg" >>.PKGINFO echo "pkgver = $pkgver-$pkgrel" >>.PKGINFO echo "pkgdesc = $pkgdesc" >>.PKGINFO echo "url = $url" >>.PKGINFO echo "builddate = $builddate" >>.PKGINFO echo "packager = $packager" >>.PKGINFO echo "size = $size" >>.PKGINFO - if [ "$CARCH" != "" ]; then + if [ -n "$CARCH" ]; then echo "arch = $CARCH" >>.PKGINFO fi if [ "$(check_option force)" = "y" ]; then @@ -850,10 +924,20 @@ create_package() { for it in "${backup[@]}"; do echo "backup = $it" >>.PKGINFO done + for it in "${packaging_options[@]}"; do + local ret="$(check_option $it)" + if [ "$ret" != "?" ]; then + if [ "$ret" = "y" ]; then + echo "makepkgopt = $it" >>.PKGINFO + else + echo "makepkgopt = !$it" >>.PKGINFO + fi + fi + done # TODO maybe remove this at some point # warn if license array is not present or empty - if [ "$license" = "" ]; then + if [ -z "$license" ]; then warning "$(gettext "Please add a license line to your %s!")" "$BUILDSCRIPT" plain "$(gettext "Example for GPL'ed software: license=('GPL').")" fi @@ -861,7 +945,7 @@ create_package() { local comp_files=".PKGINFO" # check for an install script - if [ "$install" != "" ]; then + if [ -n "$install" ]; then msg2 "$(gettext "Adding install script...")" cp "$startdir/$install" .INSTALL comp_files="$comp_files .INSTALL" @@ -877,13 +961,21 @@ create_package() { # tar it up msg2 "$(gettext "Compressing package...")" - local pkg_file="$PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" + local TAR_OPT + case "$PKGEXT" in + *tar.gz) TAR_OPT="z" ;; + *tar.bz2) TAR_OPT="j" ;; + *) warning "$(gettext "'%s' is not a valid archive extension.")" \ + "$PKGEXT" ;; + esac + + local pkg_file="$PKGDEST/${nameofpkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" # when fileglobbing, we want * in an empty directory to expand to # the null string rather than itself shopt -s nullglob - if ! bsdtar -czf "$pkg_file" $comp_files *; then + if ! bsdtar -c${TAR_OPT}f "$pkg_file" $comp_files *; then error "$(gettext "Failed to create package file.")" exit 1 # TODO: error code fi @@ -923,7 +1015,7 @@ create_xdelta() { rm -f "$pkginfo" - if [ "$base_file" != "" ]; then + if [ -n "$base_file" ]; then msg "$(gettext "Making delta from version %s...")" "$latest_version" local delta_file="$PKGDEST/$pkgname-${latest_version}_to_$pkgver-$pkgrel-$CARCH.delta" local ret=0 @@ -956,7 +1048,7 @@ create_xdelta() { create_srcpackage() { cd "$startdir" - if [ "$SOURCEONLY" = "2" ]; then + if [ "$SOURCEONLY" -eq 2 ]; then # get back to our src directory so we can begin with sources mkdir -p "$srcdir" cd "$srcdir" @@ -972,7 +1064,7 @@ create_srcpackage() { msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT" ln -s "${startdir}/${BUILDSCRIPT}" "${srclinks}/${pkgname}/" - if [ "$install" != "" ]; then + if [ -n "$install" ]; then if [ -f $install ]; then msg2 "$(gettext "Adding install script...")" ln -s "${startdir}/$install" "${srclinks}/${pkgname}/" @@ -992,18 +1084,26 @@ create_srcpackage() { if [ -f "$netfile" ]; then msg2 "$(gettext "Adding %s...")" "$netfile" ln -s "${startdir}/$netfile" "${srclinks}/${pkgname}" - elif [ "$SOURCEONLY" = "2" -a -f "$SRCDEST/$file" ]; then + elif [ "$SOURCEONLY" -eq 2 -a -f "$SRCDEST/$file" ]; then msg2 "$(gettext "Adding %s...")" "$file" ln -s "$SRCDEST/$file" "${srclinks}/${pkgname}/" fi done + local TAR_OPT + case "$SRCEXT" in + *tar.gz) TAR_OPT="z" ;; + *tar.bz2) TAR_OPT="j" ;; + *) warning "$(gettext "'%s' is not a valid archive extension.")" \ + "$SRCEXT" ;; + esac + local pkg_file="$PKGDEST/${pkgname}-${pkgver}-${pkgrel}${SRCEXT}" # tar it up msg2 "$(gettext "Compressing source package...")" cd "${srclinks}" - if ! bsdtar -czLf "$pkg_file" ${pkgname}; then + if ! bsdtar -c${TAR_OPT}Lf "$pkg_file" ${pkgname}; then error "$(gettext "Failed to create source package file.")" exit 1 # TODO: error code fi @@ -1012,9 +1112,9 @@ create_srcpackage() { } install_package() { - [ "$INSTALL" = "0" ] && return + [ "$INSTALL" -eq 0 ] && return msg "$(gettext "Installing package ${pkgname} with pacman -U...")" - if [ "$ASROOT" = "0" ]; then + if [ "$ASROOT" -eq 0 ]; then sudo pacman $PACMAN_OPTS -U $PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT} || exit $? else pacman $PACMAN_OPTS -U $PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT} || exit $? @@ -1024,10 +1124,14 @@ install_package() { devel_check() { newpkgver="" # Only update pkgver if --holdver is not set - if [ "$HOLDVER" = "1" ]; then + if [ "$HOLDVER" -eq 1 ]; then + return + fi + # Cannot update pkgver/pkgrel if reading PKGBUILD from pipe + if [ ! -f "./$BUILDSCRIPT" ]; then return fi - if [ "$FORCE_VER" = "" ]; then + if [ -z "$FORCE_VER" ]; then # Check if this is a svn/cvs/etc PKGBUILD; set $newpkgver if so. # This will only be used on the first call to makepkg; subsequent # calls to makepkg via fakeroot will explicitly pass the version @@ -1070,7 +1174,7 @@ devel_check() { cd ../../ fi - if [ "$newpkgver" != "" ]; then + if [ -n "$newpkgver" ]; then msg2 "$(gettext "Version found: %s")" "$newpkgver" fi @@ -1090,15 +1194,35 @@ devel_update() { # ... # _foo=pkgver # - if [ "$newpkgver" != "" ]; then + if [ -n "$newpkgver" ]; then if [ "$newpkgver" != "$pkgver" ]; then - sed -i "s/^pkgver=[^ ]*/pkgver=$newpkgver/" "./$BUILDSCRIPT" - sed -i "s/^pkgrel=[^ ]*/pkgrel=1/" "./$BUILDSCRIPT" - source "$BUILDSCRIPT" + if [ -f "./$BUILDSCRIPT" ]; then + sed -i "s/^pkgver=[^ ]*/pkgver=$newpkgver/" "./$BUILDSCRIPT" + sed -i "s/^pkgrel=[^ ]*/pkgrel=1/" "./$BUILDSCRIPT" + source "$BUILDSCRIPT" + fi fi fi } +backup_package_variables() { + for var in ${splitpkg_overrides[@]}; do + indirect="${var}_backup" + eval "${indirect}=\"${!var}\"" + done +} + +restore_package_variables() { + for var in ${splitpkg_overrides[@]}; do + indirect="${var}_backup" + if [ -n "${!indirect}" ]; then + eval "${var}=\"${!indirect}\"" + else + unset ${var} + fi + done +} + # getopt like parser parse_options() { local short_options=$1; shift; @@ -1195,6 +1319,7 @@ usage() { printf "$(gettext " -A, --ignorearch Ignore incomplete arch field in %s")\n" "$BUILDSCRIPT" echo "$(gettext " -c, --clean Clean up work files after build")" echo "$(gettext " -C, --cleancache Clean up source files from the cache")" + printf "$(gettext " --config <config> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf" echo "$(gettext " -d, --nodeps Skip all dependency checks")" echo "$(gettext " -e, --noextract Do not extract source files (use existing src/ dir)")" echo "$(gettext " -f, --force Overwrite existing package")" @@ -1242,36 +1367,12 @@ fi ARGLIST=$@ -#preserve environment variables -_PKGDEST=${PKGDEST} -_SRCDEST=${SRCDEST} - -# Source makepkg.conf; fail if it is not found -if [ -r "$confdir/makepkg.conf" ]; then - source "$confdir/makepkg.conf" -else - error "$(gettext "%s not found.")" "$confdir/makepkg.conf" - plain "$(gettext "Aborting...")" - exit 1 # $E_CONFIG_ERROR -fi - -# Source user-specific makepkg.conf overrides -if [ -r ~/.makepkg.conf ]; then - source ~/.makepkg.conf -fi - -# override settings with an environment variable for batch processing -PKGDEST=${_PKGDEST:-$PKGDEST} -PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined -SRCDEST=${_SRCDEST:-$SRCDEST} -SRCDEST=${SRCDEST:-$startdir} #default to $startdir if undefined - # Parse Command Line Options. OPT_SHORT="AbcCdefFghiLmop:rRsV" OPT_LONG="allsource,asroot,ignorearch,builddeps,clean,cleancache,nodeps" OPT_LONG="$OPT_LONG,noextract,force,forcever:,geninteg,help,holdver" OPT_LONG="$OPT_LONG,install,log,nocolor,nobuild,rmdeps,repackage,source" -OPT_LONG="$OPT_LONG,syncdeps,version" +OPT_LONG="$OPT_LONG,syncdeps,version,config:" # Pacman Options OPT_LONG="$OPT_LONG,noconfirm,noprogressbar" OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@" || echo 'PARSE_OPTIONS FAILED')" @@ -1294,6 +1395,7 @@ while true; do -A|--ignorearch) IGNOREARCH=1 ;; -c|--clean) CLEANUP=1 ;; -C|--cleancache) CLEANCACHE=1 ;; + --config) shift; MAKEPKG_CONF=$1 ;; -d|--nodeps) NODEPS=1 ;; -e|--noextract) NOEXTRACT=1 ;; -f|--force) FORCE=1 ;; @@ -1321,13 +1423,41 @@ while true; do shift done -if [ "$HOLDVER" = "1" -a "$FORCE_VER" != "" ]; then +#preserve environment variables +_PKGDEST=${PKGDEST} +_SRCDEST=${SRCDEST} + +# default config is makepkg.conf +MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf} + +# Source the config file; fail if it is not found +if [ -r "$MAKEPKG_CONF" ]; then + source "$MAKEPKG_CONF" +else + error "$(gettext "%s not found.")" "$MAKEPKG_CONF" + plain "$(gettext "Aborting...")" + exit 1 # $E_CONFIG_ERROR +fi + +# Source user-specific makepkg.conf overrides +if [ -r ~/.makepkg.conf ]; then + source ~/.makepkg.conf +fi + +# override settings with an environment variable for batch processing +PKGDEST=${_PKGDEST:-$PKGDEST} +PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined +SRCDEST=${_SRCDEST:-$SRCDEST} +SRCDEST=${SRCDEST:-$startdir} #default to $startdir if undefined + + +if [ "$HOLDVER" -eq 1 -a -n "$FORCE_VER" ]; then # The '\\0' is here to prevent gettext from thinking --holdver is an option error "$(gettext "\\0--holdver and --forcever cannot both be specified" )" exit 1 fi -if [ "$CLEANCACHE" = "1" ]; then +if [ "$CLEANCACHE" -eq 1 ]; then #fix flyspray feature request #5223 if [ -n "$SRCDEST" -a "$SRCDEST" != "$startdir" ]; then msg "$(gettext "Cleaning up ALL files from %s.")" "$SRCDEST" @@ -1352,25 +1482,25 @@ if [ "$CLEANCACHE" = "1" ]; then fi else # $SRCDEST is $startdir, two possibilities - error "$(gettext "Source destination must be defined in makepkg.conf.")" + error "$(gettext "Source destination must be defined in %s.")" "$MAKEPKG_CONF" plain "$(gettext "In addition, please run makepkg -C outside of your cache directory.")" exit 1 fi fi if [ -z "$BUILDSCRIPT" ]; then - error "$(gettext "BUILDSCRIPT is undefined! Ensure you have updated %s.")" "$confdir/makepkg.conf" + error "$(gettext "BUILDSCRIPT is undefined! Ensure you have updated %s.")" "$MAKEPKG_CONF" exit 1 fi -if [ "$INFAKEROOT" = "0" ]; then - if [ $EUID -eq 0 -a "$ASROOT" = "0" ]; then +if [ "$INFAKEROOT" -eq 0 ]; then + if [ $EUID -eq 0 -a "$ASROOT" -eq 0 ]; then # Warn those who like to live dangerously. error "$(gettext "Running makepkg as root is a BAD idea and can cause")" plain "$(gettext "permanent, catastrophic damage to your system. If you")" plain "$(gettext "wish to run as root, please use the --asroot option.")" exit 1 # $E_USER_ABORT - elif [ $EUID -gt 0 -a "$ASROOT" = "1" ]; then + elif [ $EUID -gt 0 -a "$ASROOT" -eq 1 ]; then # Warn those who try to use the --asroot option when they are not root error "$(gettext "The --asroot option is meant for the root user only.")" plain "$(gettext "Please rerun makepkg without the --asroot flag.")" @@ -1378,25 +1508,25 @@ if [ "$INFAKEROOT" = "0" ]; then elif [ "$(check_buildenv fakeroot)" = "y" -a $EUID -gt 0 ]; then if [ ! $(type -p fakeroot) ]; then error "$(gettext "Fakeroot must be installed if using the 'fakeroot' option")" - plain "$(gettext "in the BUILDENV array in %s.")" "$confdir/makepkg.conf" + plain "$(gettext "in the BUILDENV array in %s.")" "$MAKEPKG_CONF" exit 1 fi elif [ $EUID -gt 0 ]; then warning "$(gettext "Running makepkg as an unprivileged user will result in non-root")" plain "$(gettext "ownership of the packaged files. Try using the fakeroot environment by")" - plain "$(gettext "placing 'fakeroot' in the BUILDENV array in makepkg.conf.")" + plain "$(gettext "placing 'fakeroot' in the BUILDENV array in %s.")" "$MAKEPKG_CONF" sleep 1 fi else - if [ "$FAKEROOTKEY" = "" ]; then + if [ -z "$FAKEROOTKEY" ]; then error "$(gettext "Do not use the '-F' option. This option is only for use by makepkg.")" exit 1 # TODO: error code fi fi # check for sudo if we will need it during makepkg execution -if [ "$ASROOT" = "0" -a \( "$DEP_BIN" = "1" \ - -o "$RMDEPS" = "1" -o "$INSTALL" = "1" \) ]; then +if [ "$ASROOT" -eq 0 \ + -a \( "$DEP_BIN" -eq 1 -o "$RMDEPS" -eq 1 -o "$INSTALL" -eq 1 \) ]; then if [ ! "$(type -p sudo)" ]; then error "$(gettext "Cannot find the sudo binary! Is sudo installed?")" plain "$(gettext "Missing dependencies cannot be installed or removed as a normal user")" @@ -1410,13 +1540,24 @@ unset replaces depends conflicts backup source install build makedepends unset optdepends options noextract if [ ! -f "$BUILDSCRIPT" ]; then - error "$(gettext "%s does not exist.")" "$BUILDSCRIPT" - exit 1 + if [ -t 0 ]; then + error "$(gettext "%s does not exist.")" "$BUILDSCRIPT" + exit 1 + else + # PKGBUILD passed through a pipe + BUILDSCRIPT=/dev/stdin + fi +else + crlftest=$(file $BUILDSCRIPT | grep -F 'CRLF' || true) + if [ -n "$crlftest" ]; then + error "$(gettext "%s contains CRLF characters and cannot be sourced.")" "$BUILDSCRIPT" + exit 1 + fi fi source "$BUILDSCRIPT" -if [ "$GENINTEG" = "1" ]; then +if [ "$GENINTEG" -eq 1 ]; then mkdir -p "$srcdir" cd "$srcdir" download_sources @@ -1424,6 +1565,14 @@ if [ "$GENINTEG" = "1" ]; then exit 0 # $E_OK fi +if [ "$(type -t package)" = "function" ]; then + PKGFUNC=1 +fi + +if [ "${#pkgname[@]}" -gt "1" ]; then + SPLITPKG=1 +fi + # check for no-no's in the build script if [ -z "$pkgname" ]; then error "$(gettext "%s is not allowed to be empty.")" "pkgname" @@ -1451,15 +1600,11 @@ if [ "$arch" = 'any' ]; then fi if ! in_array $CARCH ${arch[@]}; then - if [ "$IGNOREARCH" = "0" ]; then + if [ "$IGNOREARCH" -eq 0 ]; then error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgname" "$CARCH" plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT" plain "$(gettext "such as arch=('%s').")" "$CARCH" exit 1 - else - warning "$(gettext "%s is not available for the '%s' architecture.")" "$pkgname" "$CARCH" - plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT" - plain "$(gettext "such as arch=('%s').")" "$CARCH" fi fi @@ -1480,7 +1625,7 @@ valid_options=1 for opt in ${options[@]}; do known=0 # check if option matches a known option or its inverse - for kopt in ${known_options[@]}; do + for kopt in ${packaging_options[@]} ${other_options[@]}; do if [ "${opt}" = "${kopt}" -o "${opt}" = "!${kopt}" ]; then known=1 fi @@ -1503,8 +1648,8 @@ devel_check devel_update if [ -f "$PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" \ - -a "$FORCE" = "0" -a "$SOURCEONLY" = "0" -a "$NOBUILD" = "0" ]; then - if [ "$INSTALL" = "1" ]; then + -a "$FORCE" -eq 0 -a "$SOURCEONLY" -eq 0 -a "$NOBUILD" -eq 0 ]; then + if [ "$INSTALL" -eq 1 ]; then warning "$(gettext "A package has already been built, installing existing package...")" install_package exit $? @@ -1515,31 +1660,40 @@ if [ -f "$PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" \ fi # Run the bare minimum in fakeroot -# fix flyspray bug 6208 -- using makepkg with fakeroot gives an error -if [ "$INFAKEROOT" = "1" ]; then - if [ "$REPKG" = "1" ]; then - warning "$(gettext "Skipping build.")" +if [ "$INFAKEROOT" -eq 1 ]; then + if [ "$SPLITPKG" -eq 0 ]; then + if [ "$PKGFUNC" -eq 0 ]; then + if [ "$REPKG" -eq 0 ]; then + run_build + fi + else + run_package + tidy_install + fi + create_package else - run_build - tidy_install + for pkg in ${pkgname[@]}; do + pkgdir="$pkgdir/$pkg" + mkdir -p "$pkgdir" + backup_package_variables + run_package $pkg + tidy_install + create_package $pkg + restore_package_variables + pkgdir="${pkgdir%/*}" + done fi - create_package - msg "$(gettext "Leaving fakeroot environment.")" exit 0 # $E_OK fi msg "$(gettext "Making package: %s")" "$pkgname $pkgver-$pkgrel $CARCH ($(date))" -if [ $EUID -eq 0 ]; then - warning "$(gettext "Running makepkg as root...")" -fi - # if we are creating a source-only package, go no further -if [ "$SOURCEONLY" != "0" ]; then +if [ "$SOURCEONLY" -ne 0 ]; then if [ -f "$PKGDEST/${pkgname}-${pkgver}-${pkgrel}${SRCEXT}" \ - -a "$FORCE" = "0" ]; then + -a "$FORCE" -eq 0 ]; then error "$(gettext "A package has already been built. (use -f to overwrite)")" exit 1 fi @@ -1549,11 +1703,11 @@ if [ "$SOURCEONLY" != "0" ]; then fi # fix flyspray bug #5973 -if [ "$NODEPS" = "1" -o "$NOBUILD" = "1" -o "$REPKG" = "1" ]; then - if [ "$NODEPS" = "1" ]; then +if [ "$NODEPS" -eq 1 -o "$NOBUILD" -eq 1 -o "$REPKG" -eq 1 ]; then + # no warning message needed for nobuild, repkg + if [ "$NODEPS" -eq 1 ]; then warning "$(gettext "Skipping dependency checks.")" fi - # skip printing a warning message for the others: nobuild, repkg elif [ $(type -p pacman) ]; then unset pkgdeps # Set by resolve_deps() and used by remove_deps() deperr=0 @@ -1579,16 +1733,19 @@ umask 0022 mkdir -p "$srcdir" cd "$srcdir" -if [ "$NOEXTRACT" = "1" -o "$REPKG" = "1" ]; then +if [ "$NOEXTRACT" -eq 1 ]; then warning "$(gettext "Skipping source retrieval -- using existing src/ tree")" warning "$(gettext "Skipping source integrity checks -- using existing src/ tree")" warning "$(gettext "Skipping source extraction -- using existing src/ tree")" - if [ "$NOEXTRACT" = "1" -a "$(ls "$srcdir" 2>/dev/null)" = "" ]; then + if [ "$NOEXTRACT" -eq 1 -a -z "$(ls "$srcdir" 2>/dev/null)" ]; then error "$(gettext "The source directory is empty, there is nothing to build!")" plain "$(gettext "Aborting...")" exit 1 - elif [ "$REPKG" = "1" -a \( ! -d "$pkgdir" -o "$(ls "$pkgdir" 2>/dev/null)" = "" \) ]; then + fi +elif [ "$REPKG" -eq 1 ]; then + if [ "$PKGFUNC" -eq 0 -a "$SPLITPKG" -eq 0 \ + -a \( ! -d "$pkgdir" -o -z "$(ls "$pkgdir" 2>/dev/null)" \) ]; then error "$(gettext "The package directory is empty, there is nothing to repackage!")" plain "$(gettext "Aborting...")" exit 1 @@ -1599,33 +1756,55 @@ else extract_sources fi -if [ "$NOBUILD" = "1" ]; then +if [ "$NOBUILD" -eq 1 ]; then msg "$(gettext "Sources are ready.")" exit 0 #E_OK else # check for existing pkg directory; don't remove if we are repackaging - if [ -d "$pkgdir" -a "$REPKG" = "0" ]; then + if [ -d "$pkgdir" \ + -a \( "$REPKG" -eq 0 -o "$PKGFUNC" -eq 1 -o "$SPLITPKG" -eq 1 \) ]; then msg "$(gettext "Removing existing pkg/ directory...")" rm -rf "$pkgdir" fi mkdir -p "$pkgdir" cd "$startdir" + # if we are root or if fakeroot is not enabled, then we don't use it if [ "$(check_buildenv fakeroot)" != "y" -o $EUID -eq 0 ]; then - # if we are root or if fakeroot is not enabled, then we don't use it - if [ "$REPKG" = "1" ]; then - warning "$(gettext "Skipping build.")" + if [ "$REPKG" -eq 0 ]; then + devel_update + run_build + fi + if [ "$SPLITPKG" -eq 0 ]; then + if [ "$PKGFUNC" -eq 1 ]; then + run_package + tidy_install + elif [ "$REPKG" -eq 0 ]; then + tidy_install + fi + create_package else + for pkg in ${pkgname[@]}; do + pkgdir="$pkgdir/$pkg" + mkdir -p "$pkgdir" + backup_package_variables + run_package $pkg + tidy_install + create_package $pkg + restore_package_variables + pkgdir="${pkgdir%/*}" + done + fi + else + if [ "$REPKG" -eq 0 -a \( "$PKGFUNC" -eq 1 -o "$SPLITPKG" -eq 1 \) ]; then devel_update run_build - tidy_install + cd "$startdir" fi - create_package - else msg "$(gettext "Entering fakeroot environment...")" - if [ "$newpkgver" != "" ]; then + if [ -n "$newpkgver" ]; then fakeroot -- $0 --forcever $newpkgver -F $ARGLIST || exit $? else fakeroot -- $0 -F $ARGLIST || exit $? diff --git a/scripts/repo-add.sh.in b/scripts/repo-add.sh.in index 32e3a301..c6d25aac 100644 --- a/scripts/repo-add.sh.in +++ b/scripts/repo-add.sh.in @@ -34,7 +34,6 @@ REPO_DB_FILE="" umask 0022 msg() { - [ $QUIET -ne 0 ] && return local mesg=$1; shift printf "==> ${mesg}\n" "$@" >&1 } @@ -68,8 +67,8 @@ repo-remove will update a package database by removing the package name\n\ specified on the command line from the given repo database. Multiple\n\ packages to remove can be specified on the command line.\n\n")" printf "$(gettext "\ -The -q/--quiet flag to either program will force silent running except\n\ -in the case of warnings or errors.\n\n")" +Use the -q/--quiet flag to minimize output to basic messages, warnings,\n\ +and errors\n\n")" echo "$(gettext "Example: repo-add /path/to/repo.db.tar.gz pacman-3.0.0.pkg.tar.gz")" echo "$(gettext "Example: repo-remove /path/to/repo.db.tar.gz kernel26")" } @@ -83,15 +82,6 @@ This is free software; see the source for copying conditions.\n\ There is NO WARRANTY, to the extent permitted by law.\n")" } -# test if a file is a repository DB -test_repo_db_file () { - if bsdtar -tf "$REPO_DB_FILE" | grep -q "/desc"; then - return 0 # YES - else - return 1 # NO - fi -} - # write a list entry # arg1 - Entry name # arg2 - List @@ -107,8 +97,8 @@ write_list_entry() { # arg1 - path to delta db_write_delta() { - # blank out all variables and set deltafile to absolute path - local deltafile=$($realpath "$1") + # blank out all variables + local deltafile="$1" local filename=$(basename "$deltafile") local deltavars pkgname fromver tover arch csize md5sum @@ -138,12 +128,12 @@ db_write_delta() # arg1 - path to package db_write_entry() { - # blank out all variables and set pkgfile to an absolute path - local pkgfile=$($realpath "$1") + # blank out all variables + local pkgfile="$1" local pkgname pkgver pkgdesc url builddate packager csize size \ group depend backup license replaces provides conflict force \ _groups _depends _backups _licenses _replaces _provides _conflicts \ - startdir optdepend _optdepends + startdir optdepend _optdepends md5sum local OLDIFS="$IFS" # IFS (field separator) is only the newline character @@ -172,22 +162,22 @@ db_write_entry() IFS=$OLDIFS - # get compressed size of package + # get md5sum and compressed size of package + md5sum="$(openssl dgst -md5 "$pkgfile" | awk '{print $NF}')" csize=$(@SIZECMD@ "$pkgfile") - startdir=$(pwd) - pushd "$gstmpdir" 2>&1 >/dev/null - # ensure $pkgname and $pkgver variables were found if [ -z "$pkgname" -o -z "$pkgver" ]; then error "$(gettext "Invalid package file '%s'.")" "$pkgfile" - popd 2>&1 >/dev/null return 1 fi # remove an existing entry if it exists, ignore failures db_remove_entry "$pkgname" + startdir=$(pwd) + pushd "$gstmpdir" 2>&1 >/dev/null + # create package directory mkdir "$pkgname-$pkgver" cd "$pkgname-$pkgver" @@ -204,7 +194,7 @@ db_write_entry() # compute checksums msg2 "$(gettext "Computing md5 checksums...")" - echo -e "%MD5SUM%\n$(openssl dgst -md5 "$pkgfile" | awk '{print $NF}')\n" >>desc + echo -e "%MD5SUM%\n$md5sum\n" >>desc [ -n "$url" ] && echo -e "%URL%\n$url\n" >>desc write_list_entry "LICENSE" "$_licenses" "desc" @@ -222,6 +212,7 @@ db_write_entry() write_list_entry "OPTDEPENDS" "$_optdepends" "depends" # create deltas entry if there are delta files + # Xav : why should deltas be in $startdir? for delta in $startdir/$pkgname-*-*_to_*-*-$arch.delta; do # This for loop also pulls in all files that start with the current package # name and are followed by a -whatever. For instance, running this loop for @@ -247,11 +238,15 @@ db_write_entry() # add the final newline [ -f "deltas" ] && echo -e "" >>deltas + popd 2>&1 >/dev/null + # preserve the modification time - touch -r "$pkgfile" desc depends - [ -f "deltas" ] && touch -r "$pkgfile" deltas + # Xav : what for? + pkgdir="$gstmpdir/$pkgname-$pkgver" + touch -r "$pkgfile" "$pkgdir/desc" "$pkgdir/depends" + [ -f "$pkgdir/deltas" ] && touch -r "$pkgfile" "$pkgdir/deltas" - popd 2>&1 >/dev/null + return 0 } # end db_write_entry # remove existing entries from the DB @@ -298,28 +293,6 @@ if [ $# -lt 2 ]; then exit 1 fi -# check for and store the name of a realpath-like program -if [ $(type -t realpath) ]; then - realpath='realpath' -elif [ $(type -t readlink) ]; then - realpath='readlink -f' -else - error "$(gettext "Either realpath or readlink are required by repo-add.")" - exit 1 # $E_MISSING_PROGRAM -fi - -# source system and user makepkg.conf -if [ -r "$confdir/makepkg.conf" ]; then - source "$confdir/makepkg.conf" -else - error "$(gettext "%s not found. Cannot continue.")" "$confdir/makepkg.conf" - exit 1 # $E_CONFIG_ERROR -fi - -if [ -r ~/.makepkg.conf ]; then - source ~/.makepkg.conf -fi - # main routine gstmpdir=$(mktemp -d /tmp/repo-tools.XXXXXXXXXX) || (\ error "$(gettext "Cannot create temp directory for database building.")"; \ @@ -341,10 +314,9 @@ for arg in "$@"; do elif [ "$arg" == "--quiet" -o "$arg" == "-q" ]; then QUIET=1 elif [ -z "$REPO_DB_FILE" ]; then - # store absolute path to repo DB - REPO_DB_FILE=$($realpath "$arg") + REPO_DB_FILE="$arg" if [ -f "$REPO_DB_FILE" ]; then - if ! test_repo_db_file $cmd; then + if ! (bsdtar -tf "$REPO_DB_FILE" | grep -q "/desc"); then error "$(gettext "Repository file '%s' is not a proper pacman database.")" "$REPO_DB_FILE" exit 1 fi @@ -384,26 +356,27 @@ done # if all operations were a success, re-zip database if [ $success -eq 1 ]; then msg "$(gettext "Creating updated database file '%s'")" "$REPO_DB_FILE" - pushd "$gstmpdir" 2>&1 >/dev/null - if [ -n "$(ls)" ]; then - [ -f "${REPO_DB_FILE}.old" ] && rm "${REPO_DB_FILE}.old" - [ -f "$REPO_DB_FILE" ] && mv "$REPO_DB_FILE" "${REPO_DB_FILE}.old" + case "$REPO_DB_FILE" in + *tar.gz) TAR_OPT="z" ;; + *tar.bz2) TAR_OPT="j" ;; + *) warning "$(gettext "'%s' does not have a valid archive extension.")" \ + "$REPO_DB_FILE" ;; + esac - case "$DB_COMPRESSION" in - gz) TAR_OPT="z" ;; - bz2) TAR_OPT="j" ;; - *) warning "$(gettext "No compression set.")" ;; - esac + filename=$(basename "$REPO_DB_FILE") - bsdtar -c${TAR_OPT}f "$REPO_DB_FILE" * + pushd "$gstmpdir" 2>&1 >/dev/null + if [ -n "$(ls)" ]; then + bsdtar -c${TAR_OPT}f "$filename" * else - # we should only end up with an empty db after a remove of the last package in the database + # the database will be moved to .old below, and there will be no new one to replace it error "$(gettext "All packages have been removed from the database. Deleting '%s'.")" "$REPO_DB_FILE" - rm "$REPO_DB_FILE" fi - popd 2>&1 >/dev/null + + [ -f "$REPO_DB_FILE" ] && mv -f "$REPO_DB_FILE" "${REPO_DB_FILE}.old" + [ -f "$gstmpdir/$filename" ] && mv "$gstmpdir/$filename" "$REPO_DB_FILE" else msg "$(gettext "No packages modified, nothing to do.")" fi diff --git a/src/pacman/callback.c b/src/pacman/callback.c index 6f41df7c..e1cad20f 100644 --- a/src/pacman/callback.c +++ b/src/pacman/callback.c @@ -201,7 +201,7 @@ void cb_trans_evt(pmtransevt_t event, void *data1, void *data2) (char *)alpm_pkg_get_name(data1), (char *)alpm_pkg_get_version(data2), (char *)alpm_pkg_get_version(data1)); - display_optdepends(data1); + display_new_optdepends(data2,data1); break; case PM_TRANS_EVT_INTEGRITY_START: printf(_("checking package integrity...\n")); @@ -224,9 +224,6 @@ void cb_trans_evt(pmtransevt_t event, void *data1, void *data2) case PM_TRANS_EVT_SCRIPTLET_INFO: printf("%s", (char*)data1); break; - case PM_TRANS_EVT_PRINTURI: - printf("%s/%s\n", (char*)data1, (char*)data2); - break; case PM_TRANS_EVT_RETRIEVE_START: printf(_(":: Retrieving packages from %s...\n"), (char*)data1); break; @@ -251,35 +248,40 @@ void cb_trans_conv(pmtransconv_t event, void *data1, void *data2, { switch(event) { case PM_TRANS_CONV_INSTALL_IGNOREPKG: - if(data2) { - /* TODO we take this route based on data2 being not null? WTF */ - *response = yesno(1, _(":: %s requires installing %s from IgnorePkg/IgnoreGroup. Install anyway?"), - alpm_pkg_get_name(data2), - alpm_pkg_get_name(data1)); - } else { - *response = yesno(1, _(":: %s is in IgnorePkg/IgnoreGroup. Install anyway?"), - alpm_pkg_get_name(data1)); - } - break; - case PM_TRANS_CONV_REMOVE_HOLDPKG: - *response = yesno(1, _(":: %s is designated as a HoldPkg. Remove anyway?"), - alpm_pkg_get_name(data1)); + *response = yesno(_(":: %s is in IgnorePkg/IgnoreGroup. Install anyway?"), + alpm_pkg_get_name(data1)); break; case PM_TRANS_CONV_REPLACE_PKG: - *response = yesno(1, _(":: Replace %s with %s/%s?"), + *response = yesno(_(":: Replace %s with %s/%s?"), alpm_pkg_get_name(data1), (char *)data3, alpm_pkg_get_name(data2)); break; case PM_TRANS_CONV_CONFLICT_PKG: - *response = yesno(1, _(":: %s conflicts with %s. Remove %s?"), + *response = yesno(_(":: %s conflicts with %s. Remove %s?"), (char *)data1, (char *)data2, (char *)data2); break; + case PM_TRANS_CONV_REMOVE_PKGS: + { + alpm_list_t *unresolved = (alpm_list_t *) data1; + alpm_list_t *namelist = NULL, *i; + for (i = unresolved; i; i = i->next) { + namelist = alpm_list_add(namelist, + (char *)alpm_pkg_get_name(i->data)); + } + printf(":: the following package(s) cannot be upgraded due to " + "unresolvable dependencies:\n"); + list_display(" ", namelist); + *response = yesno(_("\nDo you want to skip the above " + "package(s) for this upgrade?")); + alpm_list_free(namelist); + } + break; case PM_TRANS_CONV_LOCAL_NEWER: if(!config->op_s_downloadonly) { - *response = yesno(1, _(":: %s-%s: local version is newer. Upgrade anyway?"), + *response = yesno(_(":: %s-%s: local version is newer. Upgrade anyway?"), alpm_pkg_get_name(data1), alpm_pkg_get_version(data1)); } else { @@ -287,7 +289,7 @@ void cb_trans_conv(pmtransconv_t event, void *data1, void *data2, } break; case PM_TRANS_CONV_CORRUPTED_PKG: - *response = yesno(1, _(":: File %s is corrupted. Do you want to delete it?"), + *response = yesno(_(":: File %s is corrupted. Do you want to delete it?"), (char *)data1); break; } diff --git a/src/pacman/conf.c b/src/pacman/conf.c index 48c927bf..ca5cd123 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -44,10 +44,6 @@ config_t *config_new(void) newconfig->logmask = PM_LOG_ERROR | PM_LOG_WARNING; /* CONFFILE is defined at compile-time */ newconfig->configfile = strdup(CONFFILE); - newconfig->rootdir = NULL; - newconfig->dbpath = NULL; - newconfig->logfile = NULL; - newconfig->syncfirst = NULL; return(newconfig); } @@ -58,6 +54,7 @@ int config_free(config_t *oldconfig) return(-1); } + FREELIST(oldconfig->holdpkg); FREELIST(oldconfig->syncfirst); free(oldconfig->configfile); free(oldconfig->rootdir); diff --git a/src/pacman/conf.h b/src/pacman/conf.h index 9d2318df..466d9832 100644 --- a/src/pacman/conf.h +++ b/src/pacman/conf.h @@ -57,6 +57,7 @@ typedef struct __config_t { unsigned short op_s_sync; unsigned short op_s_search; unsigned short op_s_upgrade; + unsigned short op_s_printuris; unsigned short group; pmtransflag_t flags; @@ -68,6 +69,7 @@ typedef struct __config_t { * downloaded of the total download list */ unsigned short totaldownload; unsigned short cleanmethod; /* select -Sc behavior */ + alpm_list_t *holdpkg; alpm_list_t *syncfirst; } config_t; diff --git a/src/pacman/package.c b/src/pacman/package.c index 71be2d8c..b23c577f 100644 --- a/src/pacman/package.c +++ b/src/pacman/package.c @@ -79,7 +79,7 @@ void dump_pkg_full(pmpkg_t *pkg, int level) /* turn depends list into a text list */ for(i = alpm_pkg_get_depends(pkg); i; i = alpm_list_next(i)) { pmdepend_t *dep = (pmdepend_t*)alpm_list_getdata(i); - depstrings = alpm_list_add(depstrings, alpm_dep_get_string(dep)); + depstrings = alpm_list_add(depstrings, alpm_dep_compute_string(dep)); } if(level>0) { @@ -176,7 +176,7 @@ void dump_pkg_backups(pmpkg_t *pkg) snprintf(path, PATH_MAX-1, "%s%s", root, str); /* if we find the file, calculate checksums, otherwise it is missing */ if(access(path, R_OK) == 0) { - char *md5sum = alpm_get_md5sum(path); + char *md5sum = alpm_compute_md5sum(path); if(md5sum == NULL) { pm_fprintf(stderr, PM_LOG_ERROR, diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index c7db3b48..59916d62 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -113,7 +113,7 @@ static void usage(int op, const char * const myname) printf(_(" -p, --file <package> query a package file instead of the database\n")); printf(_(" -s, --search <regex> search locally-installed packages for matching strings\n")); printf(_(" -t, --unrequired list all packages not required by any package\n")); - printf(_(" -u, --upgrades list all packages that can be upgraded\n")); + printf(_(" -u, --upgrades list all outdated packages\n")); printf(_(" -q, --quiet show less information for query and search\n")); } else if(op == PM_OP_SYNC) { printf("%s: %s {-S --sync} [%s] [%s]\n", str_usg, myname, str_opt, str_pkg); @@ -478,7 +478,8 @@ static int parseargs(int argc, char *argv[]) case 'o': config->op_q_owns = 1; break; case 'p': config->op_q_isfile = 1; - config->flags |= PM_TRANS_FLAG_PRINTURIS; + config->op_s_printuris = 1; + config->flags |= PM_TRANS_FLAG_NOCONFLICTS; break; case 'q': config->quiet = 1; @@ -539,6 +540,11 @@ static int parseargs(int argc, char *argv[]) } /* helper for being used with setrepeatingoption */ +static void option_add_holdpkg(const char *name) { + config->holdpkg = alpm_list_add(config->holdpkg, strdup(name)); +} + +/* helper for being used with setrepeatingoption */ static void option_add_syncfirst(const char *name) { config->syncfirst = alpm_list_add(config->syncfirst, strdup(name)); } @@ -701,7 +707,7 @@ static int _parseconfig(const char *file, const char *givensection, } else if(strcmp(key, "IgnoreGroup") == 0) { setrepeatingoption(ptr, "IgnoreGroup", alpm_option_add_ignoregrp); } else if(strcmp(key, "HoldPkg") == 0) { - setrepeatingoption(ptr, "HoldPkg", alpm_option_add_holdpkg); + setrepeatingoption(ptr, "HoldPkg", option_add_holdpkg); } else if(strcmp(key, "SyncFirst") == 0) { setrepeatingoption(ptr, "SyncFirst", option_add_syncfirst); } else if(strcmp(key, "DBPath") == 0) { diff --git a/src/pacman/query.c b/src/pacman/query.c index d899539f..0d48638f 100644 --- a/src/pacman/query.c +++ b/src/pacman/query.c @@ -103,7 +103,7 @@ static int query_fileowner(alpm_list_t *targets) root = alpm_option_get_root(); - for(i = alpm_db_getpkgcache(db_local); i && !found; i = alpm_list_next(i)) { + for(i = alpm_db_get_pkgcache(db_local); i && !found; i = alpm_list_next(i)) { pmpkg_t *info = alpm_list_getdata(i); for(j = alpm_pkg_get_files(info); j && !found; j = alpm_list_next(j)) { @@ -154,7 +154,7 @@ static int query_search(alpm_list_t *targets) searchlist = alpm_db_search(db_local, targets); freelist = 1; } else { - searchlist = alpm_db_getpkgcache(db_local); + searchlist = alpm_db_get_pkgcache(db_local); freelist = 0; } if(searchlist == NULL) { @@ -215,7 +215,7 @@ static int query_group(alpm_list_t *targets) char *grpname = NULL; int ret = 0; if(targets == NULL) { - for(j = alpm_db_getgrpcache(db_local); j; j = alpm_list_next(j)) { + for(j = alpm_db_get_grpcache(db_local); j; j = alpm_list_next(j)) { pmgrp_t *grp = alpm_list_getdata(j); const alpm_list_t *p, *packages; const char *grpname; @@ -251,24 +251,6 @@ static int query_group(alpm_list_t *targets) return ret; } -static int query_upgrades(void) -{ - alpm_list_t *syncpkgs = NULL; - printf(_("Checking for package upgrades... \n")); - - alpm_list_t *syncdbs = alpm_option_get_syncdbs(); - if(alpm_sync_sysupgrade(db_local, syncdbs, &syncpkgs) == -1) { - return(-1); - } - if(syncpkgs) { - display_synctargets(syncpkgs); - return(0); - } - - printf(_("no upgrades found.\n")); - return(1); -} - static int is_foreign(pmpkg_t *pkg) { const char *pkgname = alpm_pkg_get_name(pkg); @@ -320,6 +302,10 @@ static int filter(pmpkg_t *pkg) if(config->op_q_unrequired && !is_unrequired(pkg)) { return(0); } + /* check if this pkg is outdated */ + if(config->op_q_upgrade && (alpm_sync_newversion(pkg, alpm_option_get_syncdbs()) == NULL)) { + return(0); + } return(1); } @@ -361,12 +347,6 @@ int pacman_query(alpm_list_t *targets) return(ret); } - /* check for package upgrades */ - if(config->op_q_upgrade) { - ret = query_upgrades(); - return(ret); - } - /* looking for groups */ if(config->group) { ret = query_group(targets); @@ -391,7 +371,7 @@ int pacman_query(alpm_list_t *targets) return(1); } - for(i = alpm_db_getpkgcache(db_local); i; i = alpm_list_next(i)) { + for(i = alpm_db_get_pkgcache(db_local); i; i = alpm_list_next(i)) { pmpkg_t *pkg = alpm_list_getdata(i); if(filter(pkg)) { display(pkg); diff --git a/src/pacman/remove.c b/src/pacman/remove.c index f091fa4d..11bc157f 100644 --- a/src/pacman/remove.c +++ b/src/pacman/remove.c @@ -75,10 +75,10 @@ int pacman_remove(alpm_list_t *targets) } printf(_(":: group %s:\n"), targ); list_display(" ", pkgnames); - int all = yesno(1, _(" Remove whole content?")); + int all = yesno(_(" Remove whole content?")); for(p = pkgnames; p; p = alpm_list_next(p)) { char *pkgn = alpm_list_getdata(p); - if(all || yesno(1, _(":: Remove %s from group %s?"), pkgn, targ)) { + if(all || yesno(_(":: Remove %s from group %s?"), pkgn, targ)) { if(alpm_trans_addtarget(pkgn) == -1) { pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerrorlast()); @@ -107,7 +107,7 @@ int pacman_remove(alpm_list_t *targets) for(i = data; i; i = alpm_list_next(i)) { pmdepmissing_t *miss = alpm_list_getdata(i); pmdepend_t *dep = alpm_miss_get_dep(miss); - char *depstring = alpm_dep_get_string(dep); + char *depstring = alpm_dep_compute_string(dep); printf(_(":: %s: requires %s\n"), alpm_miss_get_target(miss), depstring); free(depstring); @@ -121,6 +121,21 @@ int pacman_remove(alpm_list_t *targets) goto cleanup; } + /* Search for holdpkg in target list */ + int holdpkg = 0; + for(i = alpm_trans_get_pkgs(); i; i = alpm_list_next(i)) { + pmpkg_t *pkg = alpm_list_getdata(i); + if(alpm_list_find_str(config->holdpkg, alpm_pkg_get_name(pkg))) { + pm_printf(PM_LOG_WARNING, _("%s is designated as a HoldPkg.\n"), + alpm_pkg_get_name(pkg)); + holdpkg = 1; + } + } + if(holdpkg && (noyes(_("HoldPkg was found in target list. Do you want to continue?")) == 0)) { + retval = 1; + goto cleanup; + } + /* Warn user in case of dangerous operation */ if(config->flags & PM_TRANS_FLAG_RECURSE || config->flags & PM_TRANS_FLAG_CASCADE) { @@ -131,7 +146,7 @@ int pacman_remove(alpm_list_t *targets) printf("\n"); /* get confirmation */ - if(yesno(1, _("Do you want to remove these packages?")) == 0) { + if(yesno(_("Do you want to remove these packages?")) == 0) { retval = 1; goto cleanup; } diff --git a/src/pacman/sync.c b/src/pacman/sync.c index 00e477af..d8a63481 100644 --- a/src/pacman/sync.c +++ b/src/pacman/sync.c @@ -85,7 +85,7 @@ static int sync_cleandb(const char *dbpath, int keep_used) { /* We have a directory that doesn't match any syncdb. * Ask the user if he wants to remove it. */ if(!found) { - if(!yesno(1, _("Do you want to remove %s?"), path)) { + if(!yesno(_("Do you want to remove %s?"), path)) { continue; } @@ -105,7 +105,7 @@ static int sync_cleandb_all(void) { char newdbpath[PATH_MAX]; printf(_("Database directory: %s\n"), dbpath); - if(!yesno(1, _("Do you want to remove unused repositories?"))) { + if(!yesno(_("Do you want to remove unused repositories?"))) { return(0); } /* The sync dbs were previously put in dbpath/, but are now in dbpath/sync/, @@ -135,12 +135,12 @@ static int sync_cleancache(int level) printf(_("Cache directory: %s\n"), cachedir); switch(config->cleanmethod) { case PM_CLEAN_KEEPINST: - if(!yesno(1, _("Do you want to remove uninstalled packages from cache?"))) { + if(!yesno(_("Do you want to remove uninstalled packages from cache?"))) { return(0); } break; case PM_CLEAN_KEEPCUR: - if(!yesno(1, _("Do you want to remove outdated packages from cache?"))) { + if(!yesno(_("Do you want to remove outdated packages from cache?"))) { return(0); } break; @@ -215,7 +215,7 @@ static int sync_cleancache(int level) } else { /* full cleanup */ printf(_("Cache directory: %s\n"), cachedir); - if(!yesno(0, _("Do you want to remove ALL packages from cache?"))) { + if(!noyes(_("Do you want to remove ALL packages from cache?"))) { return(0); } printf(_("removing all packages from cache... ")); @@ -286,7 +286,7 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t *targets) ret = alpm_db_search(db, targets); freelist = 1; } else { - ret = alpm_db_getpkgcache(db); + ret = alpm_db_get_pkgcache(db); freelist = 0; } if(ret == NULL) { @@ -371,7 +371,7 @@ static int sync_group(int level, alpm_list_t *syncs, alpm_list_t *targets) for(i = syncs; i; i = alpm_list_next(i)) { pmdb_t *db = alpm_list_getdata(i); - for(j = alpm_db_getgrpcache(db); j; j = alpm_list_next(j)) { + for(j = alpm_db_get_grpcache(db); j; j = alpm_list_next(j)) { pmgrp_t *grp = alpm_list_getdata(j); const char *grpname = alpm_grp_get_name(grp); @@ -425,7 +425,7 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) return(1); } - for(k = alpm_db_getpkgcache(db); k; k = alpm_list_next(k)) { + for(k = alpm_db_get_pkgcache(db); k; k = alpm_list_next(k)) { pmpkg_t *pkg = alpm_list_getdata(k); if(strcmp(alpm_pkg_get_name(pkg), pkgstr) == 0) { @@ -446,7 +446,7 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) for(j = syncs; j; j = alpm_list_next(j)) { pmdb_t *db = alpm_list_getdata(j); - for(k = alpm_db_getpkgcache(db); k; k = alpm_list_next(k)) { + for(k = alpm_db_get_pkgcache(db); k; k = alpm_list_next(k)) { pmpkg_t *pkg = alpm_list_getdata(k); if(strcmp(alpm_pkg_get_name(pkg), pkgstr) == 0) { @@ -467,7 +467,7 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) for(i = syncs; i; i = alpm_list_next(i)) { pmdb_t *db = alpm_list_getdata(i); - for(j = alpm_db_getpkgcache(db); j; j = alpm_list_next(j)) { + for(j = alpm_db_get_pkgcache(db); j; j = alpm_list_next(j)) { dump_pkg_sync(alpm_list_getdata(j), alpm_db_get_name(db)); } } @@ -510,7 +510,7 @@ static int sync_list(alpm_list_t *syncs, alpm_list_t *targets) for(i = ls; i; i = alpm_list_next(i)) { pmdb_t *db = alpm_list_getdata(i); - for(j = alpm_db_getpkgcache(db); j; j = alpm_list_next(j)) { + for(j = alpm_db_get_pkgcache(db); j; j = alpm_list_next(j)) { pmpkg_t *pkg = alpm_list_getdata(j); if (!config->quiet) { printf("%s %s %s\n", alpm_db_get_name(db), alpm_pkg_get_name(pkg), @@ -605,14 +605,14 @@ static int sync_trans(alpm_list_t *targets) (char*)alpm_pkg_get_name(k->data)); } list_display(" ", pkgnames); - if(yesno(1, _(":: Install whole content?"))) { + if(yesno(_(":: Install whole content?"))) { for(k = pkgnames; k; k = alpm_list_next(k)) { targets = alpm_list_add(targets, strdup(alpm_list_getdata(k))); } } else { for(k = pkgnames; k; k = alpm_list_next(k)) { char *pkgname = alpm_list_getdata(k); - if(yesno(1, _(":: Install %s from group %s?"), pkgname, targ)) { + if(yesno(_(":: Install %s from group %s?"), pkgname, targ)) { targets = alpm_list_add(targets, strdup(pkgname)); } } @@ -640,7 +640,7 @@ static int sync_trans(alpm_list_t *targets) for(i = data; i; i = alpm_list_next(i)) { pmdepmissing_t *miss = alpm_list_getdata(i); pmdepend_t *dep = alpm_miss_get_dep(miss); - char *depstring = alpm_dep_get_string(dep); + char *depstring = alpm_dep_compute_string(dep); printf(_(":: %s: requires %s\n"), alpm_miss_get_target(miss), depstring); free(depstring); @@ -667,23 +667,32 @@ static int sync_trans(alpm_list_t *targets) goto cleanup; } - if(!(alpm_trans_get_flags() & PM_TRANS_FLAG_PRINTURIS)) { - int confirm; + /* Step 3: actually perform the operation */ + if(config->op_s_printuris) { + /* print uris */ + alpm_list_t *i; + for(i = packages; i; i = alpm_list_next(i)) { + pmpkg_t *pkg = alpm_sync_get_pkg((pmsyncpkg_t *)alpm_list_getdata(i)); + pmdb_t *db = alpm_pkg_get_db(pkg); + printf("%s/%s\n", alpm_db_get_url(db), alpm_pkg_get_filename(pkg)); + } + /* we are done */ + goto cleanup; + } - display_synctargets(packages); - printf("\n"); + display_synctargets(packages); + printf("\n"); - if(config->op_s_downloadonly) { - confirm = yesno(1, _("Proceed with download?")); - } else { - confirm = yesno(1, _("Proceed with installation?")); - } - if(!confirm) { - goto cleanup; - } - }/* else 'print uris' requested. We're done at this point */ + int confirm; + if(config->op_s_downloadonly) { + confirm = yesno(_("Proceed with download?")); + } else { + confirm = yesno(_("Proceed with installation?")); + } + if(!confirm) { + goto cleanup; + } - /* Step 3: actually perform the installation */ if(alpm_trans_commit(&data) == -1) { pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"), alpm_strerrorlast()); @@ -740,7 +749,7 @@ int pacman_sync(alpm_list_t *targets) alpm_list_t *sync_dbs = NULL; /* Display only errors with -Sp and -Sw operations */ - if(config->flags & (PM_TRANS_FLAG_DOWNLOADONLY | PM_TRANS_FLAG_PRINTURIS)) { + if((config->flags & PM_TRANS_FLAG_DOWNLOADONLY) || config->op_s_printuris) { config->logmask &= ~PM_LOG_WARNING; } @@ -812,13 +821,13 @@ int pacman_sync(alpm_list_t *targets) } alpm_list_t *targs = alpm_list_strdup(targets); - if(!(config->flags & (PM_TRANS_FLAG_DOWNLOADONLY | PM_TRANS_FLAG_PRINTURIS))) { + if(!(config->flags & PM_TRANS_FLAG_DOWNLOADONLY) && !config->op_s_printuris) { /* check for newer versions of packages to be upgraded first */ alpm_list_t *packages = syncfirst(); if(packages) { printf(_(":: The following packages should be upgraded first :\n")); list_display(" ", packages); - if(yesno(1, _(":: Do you want to cancel the current operation\n" + if(yesno(_(":: Do you want to cancel the current operation\n" ":: and upgrade these packages now?"))) { FREELIST(targs); targs = packages; diff --git a/src/pacman/upgrade.c b/src/pacman/upgrade.c index c54b3ed7..2c996883 100644 --- a/src/pacman/upgrade.c +++ b/src/pacman/upgrade.c @@ -90,7 +90,7 @@ int pacman_upgrade(alpm_list_t *targets) for(i = data; i; i = alpm_list_next(i)) { pmdepmissing_t *miss = alpm_list_getdata(i); pmdepend_t *dep = alpm_miss_get_dep(miss); - char *depstring = alpm_dep_get_string(dep); + char *depstring = alpm_dep_compute_string(dep); /* TODO indicate if the error was a virtual package or not: * :: %s: requires %s, provided by %s diff --git a/src/pacman/util.c b/src/pacman/util.c index 8cfa675a..b80b09ad 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -610,6 +610,25 @@ void display_synctargets(const alpm_list_t *syncpkgs) alpm_list_free(rpkglist); } +/* Helper function for comparing strings using the + * alpm "compare func" signature */ +int str_cmp(const void *s1, const void *s2) +{ + return(strcmp(s1, s2)); +} + +void display_new_optdepends(pmpkg_t *oldpkg, pmpkg_t *newpkg) +{ + alpm_list_t *old = alpm_pkg_get_optdepends(oldpkg); + alpm_list_t *new = alpm_pkg_get_optdepends(newpkg); + alpm_list_t *optdeps = alpm_list_diff(new,old,str_cmp); + if(optdeps) { + printf(_("New optional dependencies for %s\n"), alpm_pkg_get_name(newpkg)); + list_display_linebreak(" ", optdeps); + } + alpm_list_free(optdeps); +} + void display_optdepends(pmpkg_t *pkg) { alpm_list_t *optdeps = alpm_pkg_get_optdepends(pkg); @@ -620,10 +639,9 @@ void display_optdepends(pmpkg_t *pkg) } /* presents a prompt and gets a Y/N answer */ -int yesno(short preset, char *fmt, ...) +static int question(short preset, char *fmt, va_list args) { char response[32]; - va_list args; FILE *stream; if(config->noconfirm) { @@ -633,9 +651,7 @@ int yesno(short preset, char *fmt, ...) stream = stderr; } - va_start(args, fmt); vfprintf(stream, fmt, args); - va_end(args); if(preset) { fprintf(stream, " %s ", _("[Y/n]")); @@ -663,6 +679,30 @@ int yesno(short preset, char *fmt, ...) return(0); } +int yesno(char *fmt, ...) +{ + int ret; + va_list args; + + va_start(args, fmt); + ret = question(1, fmt, args); + va_end(args); + + return(ret); +} + +int noyes(char *fmt, ...) +{ + int ret; + va_list args; + + va_start(args, fmt); + ret = question(0, fmt, args); + va_end(args); + + return(ret); +} + int pm_printf(pmloglevel_t level, const char *format, ...) { int ret; diff --git a/src/pacman/util.h b/src/pacman/util.h index 5eeec8d2..64168587 100644 --- a/src/pacman/util.h +++ b/src/pacman/util.h @@ -54,8 +54,10 @@ void list_display(const char *title, const alpm_list_t *list); void list_display_linebreak(const char *title, const alpm_list_t *list); void display_targets(const alpm_list_t *pkgs, int install); void display_synctargets(const alpm_list_t *syncpkgs); +void display_new_optdepends(pmpkg_t *oldpkg, pmpkg_t *newpkg); void display_optdepends(pmpkg_t *pkg); -int yesno(short preset, char *fmt, ...); +int yesno(char *fmt, ...); +int noyes(char *fmt, ...); int pm_printf(pmloglevel_t level, const char *format, ...) __attribute__((format(printf,2,3))); int pm_fprintf(FILE *stream, pmloglevel_t level, const char *format, ...) __attribute__((format(printf,3,4))); int pm_vfprintf(FILE *stream, pmloglevel_t level, const char *format, va_list args) __attribute__((format(printf,3,0))); diff --git a/src/util/testdb.c b/src/util/testdb.c index 87bfcf96..cbff5784 100644 --- a/src/util/testdb.c +++ b/src/util/testdb.c @@ -56,7 +56,7 @@ void output_cb(pmloglevel_t level, char *fmt, va_list args) } } -static int db_test(char *dbpath) +static int db_test(char *dbpath, int local) { struct dirent *ent; char path[PATH_MAX]; @@ -70,7 +70,8 @@ static int db_test(char *dbpath) } while ((ent = readdir(dir)) != NULL) { - if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { + if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") + || ent->d_name[0] == '.') { continue; } /* check for desc, depends, and files */ @@ -84,36 +85,133 @@ static int db_test(char *dbpath) printf("%s: dependency file is missing\n", ent->d_name); ret++; } - snprintf(path, PATH_MAX, "%s/%s/files", dbpath, ent->d_name); - if(access(path, F_OK)) { - printf("%s: file list is missing\n", ent->d_name); - ret++; + if(local) { + snprintf(path, PATH_MAX, "%s/%s/files", dbpath, ent->d_name); + if(access(path, F_OK)) { + printf("%s: file list is missing\n", ent->d_name); + ret++; + } } } return(ret); } -int main(int argc, char **argv) +int checkdeps(alpm_list_t *pkglist) { - int retval = 0; /* default = false */ - pmdb_t *db = NULL; - char *dbpath; - char localdbpath[PATH_MAX]; - alpm_list_t *i; + alpm_list_t *data, *i; + int ret = 0; + /* check dependencies */ + data = alpm_checkdeps(pkglist, 0, NULL, pkglist); + for(i = data; i; i = alpm_list_next(i)) { + pmdepmissing_t *miss = alpm_list_getdata(i); + pmdepend_t *dep = alpm_miss_get_dep(miss); + char *depstring = alpm_dep_compute_string(dep); + printf("missing dependency for %s : %s\n", alpm_miss_get_target(miss), + depstring); + free(depstring); + ret++; + } + return(ret); +} - if(argc == 1) { - dbpath = DBPATH; - } else if(argc == 3 && strcmp(argv[1], "-b") == 0) { - dbpath = argv[2]; - } else { - fprintf(stderr, "usage: %s -b <pacman db>\n", BASENAME); - return(1); +int checkconflicts(alpm_list_t *pkglist) +{ + alpm_list_t *data, *i; + int ret = 0; + /* check conflicts */ + data = alpm_checkconflicts(pkglist); + for(i = data; i; i = i->next) { + pmconflict_t *conflict = alpm_list_getdata(i); + printf("%s conflicts with %s\n", alpm_conflict_get_package1(conflict), + alpm_conflict_get_package2(conflict)); + ret++; } + return(ret); +} + +int check_localdb(char *dbpath) { + char localdbpath[PATH_MAX]; + int ret = 0; + pmdb_t *db = NULL; + alpm_list_t *pkglist; snprintf(localdbpath, PATH_MAX, "%s/local", dbpath); - retval = db_test(localdbpath); - if(retval) { - return(retval); + ret = db_test(localdbpath, 1); + if(ret) { + return(ret); + } + + db = alpm_db_register_local(); + if(db == NULL) { + fprintf(stderr, "error: could not register 'local' database (%s)\n", + alpm_strerrorlast()); + cleanup(EXIT_FAILURE); + } + pkglist = alpm_db_get_pkgcache(db); + ret += checkdeps(pkglist); + ret += checkconflicts(pkglist); + return(ret); +} + +int check_syncdbs(char *dbpath, alpm_list_t *dbnames) { + char syncdbpath[PATH_MAX]; + int ret = 0; + pmdb_t *db = NULL; + alpm_list_t *i, *pkglist, *syncpkglist = NULL; + + for(i = dbnames; i; i = alpm_list_next(i)) { + char *dbname = alpm_list_getdata(i); + snprintf(syncdbpath, PATH_MAX, "%s/sync/%s", dbpath, dbname); + ret = db_test(syncdbpath, 0); + if(ret) { + return(ret); + } + db = alpm_db_register_sync(dbname); + if(db == NULL) { + fprintf(stderr, "error: could not register sync database (%s)\n", + alpm_strerrorlast()); + cleanup(EXIT_FAILURE); + } + pkglist = alpm_db_get_pkgcache(db); + syncpkglist = alpm_list_join(syncpkglist, alpm_list_copy(pkglist)); + } + ret += checkdeps(syncpkglist); + alpm_list_free(syncpkglist); + + alpm_db_unregister_all(); + return(ret); +} + +void usage() { + fprintf(stderr, "usage:\n"); + fprintf(stderr, + "\t%s [-b <pacman db>] : check the local database\n", BASENAME); + fprintf(stderr, + "\t%s [-b <pacman db>] core extra ... : check the listed sync databases\n", BASENAME); + exit(1); +} + +int main(int argc, char **argv) +{ + int ret = 0; + char *dbpath = DBPATH; + int a = 1; + alpm_list_t *dbnames = NULL; + + while(a < argc) { + if(strcmp(argv[a], "-b") == 0) { + if(++a < argc) { + dbpath = argv[a]; + } else { + usage(); + } + } else if(strcmp(argv[a], "-h") == 0 || + strcmp(argv[a], "--help") == 0 ) { + usage(); + } else { + dbnames = alpm_list_add(dbnames, argv[a]); + } + a++; } if(alpm_initialize() == -1) { @@ -126,34 +224,15 @@ int main(int argc, char **argv) alpm_option_set_dbpath(dbpath); - db = alpm_db_register_local(); - if(db == NULL) { - fprintf(stderr, "error: could not register 'local' database (%s)\n", - alpm_strerrorlast()); - cleanup(EXIT_FAILURE); - } - - /* check dependencies */ - alpm_list_t *data; - data = alpm_checkdeps(db, 0, NULL, alpm_db_getpkgcache(db)); - for(i = data; i; i = alpm_list_next(i)) { - pmdepmissing_t *miss = alpm_list_getdata(i); - pmdepend_t *dep = alpm_miss_get_dep(miss); - char *depstring = alpm_dep_get_string(dep); - printf("missing dependency for %s : %s\n", alpm_miss_get_target(miss), - depstring); - free(depstring); - } - - /* check conflicts */ - data = alpm_checkdbconflicts(db); - for(i = data; i; i = i->next) { - pmconflict_t *conflict = alpm_list_getdata(i); - printf("%s conflicts with %s\n", alpm_conflict_get_package1(conflict), - alpm_conflict_get_package2(conflict)); + if(!dbnames) { + printf("Checking the integrity of the local database in %s\n",dbpath); + ret = check_localdb(dbpath); + } else { + printf("Checking the integrity of the sync databases in %s\n",dbpath); + ret = check_syncdbs(dbpath,dbnames); } - cleanup(retval); + cleanup(ret); } /* vim: set ts=2 sw=2 noet: */ |