diff options
96 files changed, 5000 insertions, 2363 deletions
@@ -133,6 +133,19 @@ For pacman: #include "anythingelse.h" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +GDB and Valgrind Usage +~~~~~~~~~~~~~~~~~~~~~~ + +When using GDB or valgrind on pacman, you will want to run it on the actual +binary rather than the shell script wrapper produced by libtool. The actual +binary lives at `src/pacman/.libs/lt-pacman`, and will exist after running +`./src/pacman/pacman` at least once. + +For example, to run valgrind: + + ./src/pacman/pacman + valgrind --leak-check=full -- src/pacman/.libs/lt-pacman -Syu + ///// vim: set ts=2 sw=2 syntax=asciidoc et: ///// diff --git a/PKGBUILD-split.proto b/PKGBUILD-split.proto index 08f98d62..68a8cc4d 100644 --- a/PKGBUILD-split.proto +++ b/PKGBUILD-split.proto @@ -21,6 +21,7 @@ replaces=() backup=() options=() install= +changelog= source=($pkgbase-$pkgver.tar.gz) noextract=() md5sums=() #generate with 'makepkg -g' @@ -33,7 +34,10 @@ build() { package_pkg1() { # options and directives that can be overridden + pkgver= + pkgrel= pkgdesc="" + arch=() license=() groups=() depends=() @@ -44,6 +48,7 @@ package_pkg1() { backup=() options=() install= + changelog= cd "$srcdir/$pkgbase-$pkgver" make DESTDIR="$pkgdir/" install-pkg1 diff --git a/PKGBUILD.proto b/PKGBUILD.proto index eddcf759..93da0fc5 100644 --- a/PKGBUILD.proto +++ b/PKGBUILD.proto @@ -21,6 +21,7 @@ replaces=() backup=() options=() install= +changelog= source=($pkgname-$pkgver.tar.gz) noextract=() md5sums=() #generate with 'makepkg -g' @@ -57,7 +57,6 @@ library is initialized. * dbpath: The toplevel database directory (Default: /var/lib/pacman) * logfile: The base path to pacman's log file (Default: /var/log/pacman.log) * usesyslog: Log to syslog instead of `logfile` for file-base logging. -* nopassiveftp: Do not use passive FTP commands for ftp connections. The following options also have `alpm_option_{add,remove}_*` functions, as the values are list structures. diff --git a/contrib/PKGBUILD.vim b/contrib/PKGBUILD.vim index 994eaccb..af0f9817 100644 --- a/contrib/PKGBUILD.vim +++ b/contrib/PKGBUILD.vim @@ -115,6 +115,12 @@ syn match pbValidInstall /\([[:alnum:]]\|\$\|+\|-\|_\)*\.install/ contained syn match pbIllegalInstall /[^=]/ contained contains=pbValidInstall syn match pbInstallGroup /^install=.*/ contains=pb_k_install,pbValidInstall,pbIllegalInstall,shDeref,shDoubleQuote,shSingleQuote +" changelog +syn keyword pb_k_changelog changelog contained +syn match pbValidChangelog /\([[:alnum:]]\|\$\|+\|-\|_\)*/ contained +syn match pbIllegalChangelog /[^=]/ contained contains=pbValidChangelog +syn match pbChangelogGroup /^changelog=.*/ contains=pb_k_changelog,pbValidChangelog,pbIllegalChangelog,shDeref,shDoubleQuote,shSingleQuote + " source: " XXX remove source from shStatement, fix strange bug syn clear shStatement @@ -212,6 +218,9 @@ hi def link pb_k_provides pbKeywords hi def link pbIllegalInstall Error hi def link pb_k_install pbKeywords +hi def link pbIllegalChangelog Error +hi def link pb_k_changelog pbKeywords + hi def link pb_k_source pbKeywords hi def link pbIllegalSource Error diff --git a/contrib/pacdiff b/contrib/pacdiff index 5138d91c..3f26f381 100755 --- a/contrib/pacdiff +++ b/contrib/pacdiff @@ -18,19 +18,23 @@ # diffprog=${DIFFPROG:-vimdiff} +diffsearchpath=${DIFFSEARCHPATH:-/etc} 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" + echo " -l/--locate makes pacdiff use locate rather than find" + echo " DIFFPROG variable allows to override the default vimdiff" + echo " DIFFSEARCHPATH allows to override the default /etc path" + echo "Example : DIFFPROG=meld DIFFSEARCHPATH=\"/boot /etc /usr\" pacdiff" } 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 + find $diffsearchpath \( -name \*.pacnew -o -name \*.pacorig -o -name \*.pacsave \) -print0 fi } diff --git a/doc/Makefile.am b/doc/Makefile.am index de2c5eec..fcbcab88 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -85,12 +85,12 @@ ASCIIDOC_OPTS = \ -a pacman_version="$(REAL_PACKAGE_VERSION)" \ -a pacman_date="`date +%Y-%m-%d`" \ -a sysconfdir=$(sysconfdir) + A2X_OPTS = \ --no-xmllint \ -d manpage \ -f manpage \ - --xsltproc-opts='-param man.endnotes.list.enabled 0' \ - --xsltproc-opts='-param man.endnotes.are.numbered 0' + --xsltproc-opts='-param man.endnotes.list.enabled 0 -param man.endnotes.are.numbered 0' # These rules are due to the includes and files of the asciidoc text $(ASCIIDOC_MANS): asciidoc.conf footer.txt diff --git a/doc/PKGBUILD.5.txt b/doc/PKGBUILD.5.txt index 83cebcdb..2d6589b2 100644 --- a/doc/PKGBUILD.5.txt +++ b/doc/PKGBUILD.5.txt @@ -79,6 +79,12 @@ similar to `$_basekernver`. be copied into the package by makepkg. It does not need to be included in the source array (e.g. `install=pkgname.install`). +*changelog*:: + Specifies a changelog file that is to be included in the package. + This file should reside in the same directory as the PKGBUILD, and will + be copied into the package by makepkg. It does not need to be included + in the source array (e.g. `changelog=$pkgname.changelog`). + *source (array)*:: An array of source files required to build the package. Source files must either reside in the same directory as the PKGBUILD file, or be a @@ -145,7 +151,7 @@ name. The syntax is: `source=('filename::url')`. base functionality, but may be necessary to make full use of the contents of this package. optdepends are currently for informational purposes only and are not utilized by pacman during dependency resolution. The format - should be similar to the following: + for specifying optdepends is: optdepends=('fakeroot: for makepkg usage as normal user') @@ -227,10 +233,10 @@ name. The syntax is: `source=('filename::url')`. build() Function ---------------- -In addition to the above directives, the build() bash function comprises the -remainder of the PKGBUILD. This is directly sourced and executed by makepkg, so -anything that bash or the system has available is available for use here. Be -sure any exotic commands used are covered by `makedepends`. +In addition to the above directives, the optional build() bash function usually +comprises the remainder of the PKGBUILD. This is directly sourced and executed by +makepkg, so anything that bash or the system has available is available for use +here. Be sure any exotic commands used are covered by `makedepends`. All of the above variables such as `pkgname` and `pkgver` are available for use in the build function. In addition, makepkg defines three variables for your @@ -257,8 +263,8 @@ 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. +usage will be limited to running the packaging stage. An existing build() function +will be run as the user calling makepkg. Package Splitting ----------------- @@ -269,9 +275,9 @@ name of the split package. All options and directives for the split packages default to the global values given within the PKGBUILD. However, some of these can be overridden within each split -package's packaging function. The following variables can be overridden: `pkgdesc`, -`license`, `groups`, `depends`, `optdepends`, `provides`, `conflicts`, `replaces`, -`backup`, `options` and `install`. +package's packaging function. The following variables can be overridden: `pkgver`, +`pkgrel`, `pkgdesc`, `arch`, `license`, `groups`, `depends`, `optdepends`, +`provides`, `conflicts`, `replaces`, `backup`, `options`, `install` and `changelog`. An optional global directive is available when building a split package: diff --git a/doc/makepkg.8.txt b/doc/makepkg.8.txt index 198aa954..7e89fa27 100644 --- a/doc/makepkg.8.txt +++ b/doc/makepkg.8.txt @@ -149,6 +149,10 @@ Options remote builder, or a tarball upload. Because integrity checks are verified, all source files of the package need to be present or downloadable. +*\--pkg <`list`>*:: + Only build listed packages from a split package. The use of quotes is + necessary when specifying multiple packages. e.g. `--pkg "pkg1 pkg3"` + *\--noconfirm*:: (Passed to pacman) Prevent pacman from waiting for user input before proceeding with operations. @@ -166,6 +170,15 @@ separate utility 'versionpkg'. See linkman:PKGBUILD[5] for details on how to set up a development PKGBUILD. +Environment Variables +--------------------- +*PACMAN*:: + The command that will be used to check for missing dependencies and to + install and remove packages. Pacman's -U, -T, -S and -Rns operations + must be supported by this command. If the variable is not set or + empty, makepkg will fall back to `pacman'. + + Configuration ------------- See linkman:makepkg.conf[5] for more details on configuring makepkg using the diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt index b288a592..7f92ec71 100644 --- a/doc/pacman.8.txt +++ b/doc/pacman.8.txt @@ -82,7 +82,8 @@ to determine which packages need upgrading. This behavior operates as follows: "bash>=3.2"`. *-U, \--upgrade*:: - Upgrade or add package(s) to the system. Either a URL or file path can be + Upgrade or add package(s) to the system and install the required + dependencies from sync repos. Either a URL or file path can be specified. This is a ``remove-then-add'' process. See <<HCF,Handling Config Files>> for an explanation on how pacman takes care of config files. @@ -166,6 +167,8 @@ Options If an install scriptlet exists, do not execute it. Do not use this unless you know what you are doing. +*\--arch* <'arch'>:: + Specify an alternate architecture. Query Options[[QO]] ------------------- @@ -330,7 +333,9 @@ linkman:pacman.conf[5]. necessary. Pass this option twice to enable package downgrade; in this case pacman will select sync packages whose version does not match with the local version. This can be useful when the user switches from a testing - repo to a stable one. + repo to a stable one. Additional targets can also be specified manually, so + that '-Su foo' will do a system upgrade and install/upgrade the foo package in + the same operation. *-w, \--downloadonly*:: Retrieve all packages from the server, but do not install/upgrade diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt index 3e361102..89c22a12 100644 --- a/doc/pacman.conf.5.txt +++ b/doc/pacman.conf.5.txt @@ -100,6 +100,14 @@ Options Include another config file. This file can include repositories or general configuration options. +*Architecture =* auto | i686 | x86_64 | ...:: + If set, pacman will only allow installation of packages of the given + architecture (e.g. 'i686', 'x86_64', etc). The special value 'auto' will + use the system architecture, provided by in ``uname -m''. If unset, no + architecture checks are made. *NOTE*: packages with the special + architecture 'any' can always be installed, as they are meant to be + architecture independent. + *XferCommand =* /path/to/command %u:: If set, an external program will be used to download all remote files. All instances of `%u` will be replaced with the download URL. If present, @@ -111,9 +119,6 @@ Options http/ftp support, or need the more advanced proxy support that comes with utilities like wget. -*NoPassiveFtp*:: - Disables passive ftp connections when downloading packages. (aka Active Mode) - *NoUpgrade =* file ...:: All files listed with a `NoUpgrade` directive will never be touched during a package install/upgrade, and the new files will be installed with a @@ -179,10 +184,12 @@ Include = /etc/pacman.d/mirrorlist During parsing, pacman will define the `$repo` variable to the name of the current section. This is often utilized in files specified using the 'Include' -directive so all repositories can use the same mirrorfile. +directive so all repositories can use the same mirrorfile. pacman also defines +the `$arch` variable to the value of `Architecture`, so the same mirrorfile can +even be used for different architectures. -------- -Server = ftp://ftp.archlinux.org/$repo/os/arch +Server = ftp://ftp.archlinux.org/$repo/os/$arch -------- The order of repositories in the configuration files matters; repositories diff --git a/etc/makepkg.conf.in b/etc/makepkg.conf.in index 1368ff1f..b92a6975 100644 --- a/etc/makepkg.conf.in +++ b/etc/makepkg.conf.in @@ -26,7 +26,7 @@ DLAGENTS=('ftp::/usr/bin/wget -c --passive-ftp -t 3 --waitretry=3 -O %o %u' CARCH="@CARCH@" CHOST="@CHOST@" -#-- Exclusive: will only run on @CARCHFLAGS@ +#-- Exclusive: will only run on @CARCH@ # -march (or -mcpu) builds exclusively for an architecture # -mtune optimizes for an architecture, but builds for whole processor family CFLAGS="@CARCHFLAGS@-mtune=generic -O2 -pipe" @@ -91,6 +91,8 @@ PURGE_TARGETS=(usr/{,share}/info/dir .packlist *.pod) #PKGDEST=/home/packages #-- Source cache: specify a fixed directory where source files will be cached #SRCDEST=/home/sources +#-- Source packages: specify a fixed directory where all src packages will be placed +#SRCPKGDEST=/home/srcpackages #-- Packager: name/email of the person or organization building packages #PACKAGER="John Doe <john@doe.com>" diff --git a/etc/pacman.conf.in b/etc/pacman.conf.in index 30bfc321..32071196 100644 --- a/etc/pacman.conf.in +++ b/etc/pacman.conf.in @@ -17,8 +17,9 @@ HoldPkg = pacman glibc # If upgrades are available for these packages they will be asked for first SyncFirst = pacman #XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u -#XferCommand = /usr/bin/curl %u > %o +#XferCommand = /usr/bin/curl -C - %u > %o #CleanMethod = KeepInstalled +Architecture = auto # Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup #IgnorePkg = @@ -28,7 +29,6 @@ SyncFirst = pacman #NoExtract = # Misc options (all disabled by default) -#NoPassiveFtp #UseSyslog #ShowSize #UseDelta @@ -42,6 +42,7 @@ SyncFirst = pacman # - repositories listed first will take precedence when packages # have identical names, regardless of version number # - URLs will have $repo replaced by the name of the current repo +# - URLs will have $arch replaced by the name of the architecture # # Repository entries are of the format: # [repo-name] @@ -57,7 +58,7 @@ SyncFirst = pacman # servers immediately after the header and they will be used before the # default mirrors. #[core] -#Server = ftp://ftp.example.com/foobar/$repo/os/i686/ +#Server = ftp://ftp.example.com/foobar/$repo/os/$arch/ # The file referenced here should contain a list of 'Server = ' lines. #Include = @sysconfdir@/pacman.d/mirrorlist diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index 1d143c6f..ebcd6a55 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -50,21 +50,30 @@ #include "remove.h" #include "handle.h" -int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name) +/** Add a file target to the transaction. + * @param target the name of the file target to add + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int SYMEXPORT alpm_add_target(char *target) { pmpkg_t *pkg = NULL; const char *pkgname, *pkgver; alpm_list_t *i; + pmtrans_t *trans; ALPM_LOG_FUNC; + /* Sanity checks */ + ASSERT(target != NULL && strlen(target) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + trans = handle->trans; + ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - ASSERT(name != NULL && strlen(name) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1)); - _alpm_log(PM_LOG_DEBUG, "loading target '%s'\n", name); + _alpm_log(PM_LOG_DEBUG, "loading target '%s'\n", target); - if(alpm_pkg_load(name, 1, &pkg) != 0) { + if(alpm_pkg_load(target, 1, &pkg) != 0) { goto error; } pkgname = alpm_pkg_get_name(pkg); @@ -72,17 +81,19 @@ int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name) /* check if an older version of said package is already in transaction * packages. if so, replace it in the list */ - for(i = trans->packages; i; i = i->next) { + for(i = trans->add; i; i = i->next) { pmpkg_t *transpkg = i->data; if(strcmp(transpkg->name, pkgname) == 0) { if(alpm_pkg_vercmp(transpkg->version, pkgver) < 0) { - _alpm_log(PM_LOG_WARNING, _("replacing older version %s-%s by %s in target list\n"), - transpkg->name, transpkg->version, pkgver); + _alpm_log(PM_LOG_WARNING, + _("replacing older version %s-%s by %s in target list\n"), + transpkg->name, transpkg->version, pkgver); _alpm_pkg_free(i->data); i->data = pkg; } else { - _alpm_log(PM_LOG_WARNING, _("skipping %s-%s because newer version %s is in target list\n"), - pkgname, pkgver, transpkg->version); + _alpm_log(PM_LOG_WARNING, + _("skipping %s-%s because newer version %s is in target list\n"), + pkgname, pkgver, transpkg->version); _alpm_pkg_free(pkg); } return(0); @@ -90,7 +101,7 @@ int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name) } /* add the package to the transaction */ - trans->packages = alpm_list_add(trans->packages, pkg); + trans->add = alpm_list_add(trans->add, pkg); return(0); @@ -99,176 +110,6 @@ error: return(-1); } -int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data) -{ - alpm_list_t *lp = NULL; - - ALPM_LOG_FUNC; - - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - - /* Check dependencies - */ - if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { - EVENT(trans, PM_TRANS_EVT_CHECKDEPS_START, NULL, NULL); - - /* look for unsatisfied dependencies */ - _alpm_log(PM_LOG_DEBUG, "looking for unsatisfied dependencies\n"); - lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, NULL, trans->packages); - if(lp != NULL) { - if(data) { - *data = lp; - } else { - alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free); - alpm_list_free(lp); - } - RET_ERR(PM_ERR_UNSATISFIED_DEPS, -1); - } - - /* no unsatisfied deps, so look for conflicts */ - _alpm_log(PM_LOG_DEBUG, "looking for conflicts\n"); - alpm_list_t *inner = _alpm_innerconflicts(trans->packages); - alpm_list_t *outer = _alpm_outerconflicts(db, trans->packages); - lp = alpm_list_join(inner, outer); - - /* TODO : factorize the conflict resolving code from sync.c to use it here (FS#3492) */ - - if(lp != NULL) { - if(data) { - *data = lp; - } else { - alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_conflict_free); - alpm_list_free(lp); - } - if(inner) { - _alpm_log(PM_LOG_ERROR, _("conflicting packages were found in target list\n")); - _alpm_log(PM_LOG_ERROR, _("you cannot install two conflicting packages at the same time\n")); - } - if(outer) { - _alpm_log(PM_LOG_ERROR, _("replacing packages with -U is not supported yet\n")); - _alpm_log(PM_LOG_ERROR, _("you can replace packages manually using -Rd and -U\n")); - } - RET_ERR(PM_ERR_CONFLICTING_DEPS, -1); - } - - /* re-order w.r.t. dependencies */ - _alpm_log(PM_LOG_DEBUG, "sorting by dependencies\n"); - lp = _alpm_sortbydeps(trans->packages, 0); - /* free the old alltargs */ - alpm_list_free(trans->packages); - trans->packages = lp; - - EVENT(trans, PM_TRANS_EVT_CHECKDEPS_DONE, NULL, NULL); - } - - /* Check for file conflicts */ - if(!(trans->flags & PM_TRANS_FLAG_FORCE)) { - EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_START, NULL, NULL); - - _alpm_log(PM_LOG_DEBUG, "looking for file conflicts\n"); - lp = _alpm_db_find_fileconflicts(db, trans, trans->packages, NULL); - if(lp != NULL) { - if(data) { - *data = lp; - } else { - alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_fileconflict_free); - alpm_list_free(lp); - } - RET_ERR(PM_ERR_FILE_CONFLICTS, -1); - } - - EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_DONE, NULL, NULL); - } - - return(0); -} - -static int upgrade_remove(pmpkg_t *oldpkg, pmpkg_t *newpkg, pmtrans_t *trans, pmdb_t *db) { - /* this is kinda odd. If the old package exists, at this point we make a - * NEW transaction, unrelated to handle->trans, and instantiate a "remove" - * with the type PM_TRANS_TYPE_REMOVEUPGRADE. TODO: kill this weird - * behavior. */ - pmtrans_t *tr = _alpm_trans_new(); - - ALPM_LOG_FUNC; - - _alpm_log(PM_LOG_DEBUG, "removing old package first (%s-%s)\n", - oldpkg->name, oldpkg->version); - - if(!tr) { - RET_ERR(PM_ERR_TRANS_ABORT, -1); - } - - if(_alpm_trans_init(tr, PM_TRANS_TYPE_REMOVEUPGRADE, trans->flags, - NULL, NULL, NULL) == -1) { - _alpm_trans_free(tr); - tr = NULL; - RET_ERR(PM_ERR_TRANS_ABORT, -1); - } - - if(_alpm_remove_loadtarget(tr, db, newpkg->name) == -1) { - _alpm_trans_free(tr); - tr = NULL; - RET_ERR(PM_ERR_TRANS_ABORT, -1); - } - - /* copy the remove skiplist over */ - tr->skip_remove = alpm_list_strdup(trans->skip_remove); - const alpm_list_t *b; - - /* Add files in the NEW backup array to the NoUpgrade array - * so this removal operation doesn't kill them */ - alpm_list_t *old_noupgrade = alpm_list_strdup(handle->noupgrade); - /* old package backup list */ - alpm_list_t *filelist = alpm_pkg_get_files(newpkg); - for(b = alpm_pkg_get_backup(newpkg); b; b = b->next) { - char *backup = _alpm_backup_file(b->data); - /* safety check (fix the upgrade026 pactest) */ - if(!alpm_list_find_str(filelist, backup)) { - FREE(backup); - continue; - } - _alpm_log(PM_LOG_DEBUG, "adding %s to the NoUpgrade array temporarily\n", - backup); - handle->noupgrade = alpm_list_add(handle->noupgrade, - backup); - } - - /* TODO: we could also add files in the OLD backup array, but this would - * change the backup handling behavior, and break several pactests, and we - * can't do this just before 3.1 release. - * The unlink_file function in remove.c would also need to be reviewed. */ -#if 0 - /* new package backup list */ - for(b = alpm_pkg_get_backup(oldpkg); b; b = b->next) { - char *backup = _alpm_backup_file(b->data); - /* make sure we don't add duplicate entries */ - if(!alpm_list_find_ptr(handle->noupgrade, backup)) { - _alpm_log(PM_LOG_DEBUG, "adding %s to the NoUpgrade array temporarily\n", - backup); - handle->noupgrade = alpm_list_add(handle->noupgrade, - backup); - } - } -#endif - - int ret = _alpm_remove_commit(tr, db); - - _alpm_trans_free(tr); - tr = NULL; - - /* restore our "NoUpgrade" list to previous state */ - FREELIST(handle->noupgrade); - handle->noupgrade = old_noupgrade; - - if(ret == -1) { - RET_ERR(PM_ERR_TRANS_ABORT, -1); - } - - return(0); -} - static int extract_single_file(struct archive *archive, struct archive_entry *entry, pmpkg_t *newpkg, pmpkg_t *oldpkg, pmtrans_t *trans, pmdb_t *db) @@ -291,13 +132,13 @@ static int extract_single_file(struct archive *archive, if(strcmp(entryname, ".INSTALL") == 0) { /* the install script goes inside the db */ - snprintf(filename, PATH_MAX, "%s%s-%s/install", db->path, - newpkg->name, newpkg->version); + snprintf(filename, PATH_MAX, "%s%s-%s/install", + _alpm_db_path(db), newpkg->name, newpkg->version); archive_entry_set_perm(entry, 0644); } else if(strcmp(entryname, ".CHANGELOG") == 0) { /* the changelog goes inside the db */ - snprintf(filename, PATH_MAX, "%s%s-%s/changelog", db->path, - newpkg->name, newpkg->version); + snprintf(filename, PATH_MAX, "%s%s-%s/changelog", + _alpm_db_path(db), newpkg->name, newpkg->version); archive_entry_set_perm(entry, 0644); } else if(*entryname == '.') { /* for now, ignore all files starting with '.' that haven't @@ -358,7 +199,7 @@ static int extract_single_file(struct archive *archive, /* case 12: existing dir, ignore it */ if(lsbuf.st_mode != entrymode) { /* if filesystem perms are different than pkg perms, warn user */ - int mask = 07777; + mode_t mask = 07777; _alpm_log(PM_LOG_WARNING, _("directory permissions differ on %s\n" "filesystem: %o package: %o\n"), entryname, lsbuf.st_mode & mask, entrymode & mask); @@ -642,8 +483,9 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count, ALPM_LOG_FUNC; - snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", db->path, - alpm_pkg_get_name(newpkg), alpm_pkg_get_version(newpkg)); + snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", + _alpm_db_path(db), alpm_pkg_get_name(newpkg), + alpm_pkg_get_version(newpkg)); /* see if this is an upgrade. if so, remove the old package first */ pmpkg_t *local = _alpm_db_get_pkgfromcache(db, newpkg->name); @@ -691,8 +533,9 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count, if(oldpkg) { /* set up fake remove transaction */ - int ret = upgrade_remove(oldpkg, newpkg, trans, db); - if(ret != 0) { + if(_alpm_upgraderemove_package(oldpkg, newpkg, trans) == -1) { + pm_errno = PM_ERR_TRANS_ABORT; + ret = -1; goto cleanup; } } @@ -858,7 +701,7 @@ cleanup: return(ret); } -int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db) +int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db) { int pkg_count, pkg_current; alpm_list_t *targ; @@ -868,15 +711,15 @@ int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db) ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - if(trans->packages == NULL) { + if(trans->add == NULL) { return(0); } - pkg_count = alpm_list_count(trans->packages); + pkg_count = alpm_list_count(trans->add); pkg_current = 1; /* loop through our package list adding/upgrading one at a time */ - for(targ = trans->packages; targ; targ = targ->next) { + for(targ = trans->add; targ; targ = targ->next) { if(handle->trans->state == STATE_INTERRUPTED) { return(0); } diff --git a/lib/libalpm/add.h b/lib/libalpm/add.h index 6983de9e..b0467507 100644 --- a/lib/libalpm/add.h +++ b/lib/libalpm/add.h @@ -24,9 +24,7 @@ #include "alpm_list.h" #include "trans.h" -int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name); -int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data); -int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db); +int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db); #endif /* _ALPM_ADD_H */ diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index ce8c6919..05ad82eb 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -67,10 +67,10 @@ const char *alpm_version(void); /* Levels */ typedef enum _pmloglevel_t { - PM_LOG_ERROR = 0x01, - PM_LOG_WARNING = 0x02, - PM_LOG_DEBUG = 0x04, - PM_LOG_FUNCTION = 0x08 + PM_LOG_ERROR = 1, + PM_LOG_WARNING = (1 << 1), + PM_LOG_DEBUG = (1 << 2), + PM_LOG_FUNCTION = (1 << 3) } pmloglevel_t; typedef void (*alpm_cb_log)(pmloglevel_t, char *, va_list); @@ -86,14 +86,12 @@ typedef void (*alpm_cb_totaldl)(off_t total); /** A callback for downloading files * @param url the URL of the file to be downloaded * @param localpath the directory to which the file should be downloaded - * @param mtimeold the modification time of the file previously downloaded - * @param mtimenew the modification time of the newly downloaded file. - * This should be set by the callback. - * @return 0 on success, 1 if the modification times are identical, -1 on + * @param force whether to force an update, even if the file is the same + * @return 0 on success, 1 if the file exists and is identical, -1 on * error. */ typedef int (*alpm_cb_fetch)(const char *url, const char *localpath, - time_t mtimeold, time_t *mtimenew); + int force); /* * Options @@ -128,8 +126,8 @@ int alpm_option_set_logfile(const char *logfile); const char *alpm_option_get_lockfile(); /* no set_lockfile, path is determined from dbpath */ -unsigned short alpm_option_get_usesyslog(); -void alpm_option_set_usesyslog(unsigned short usesyslog); +int alpm_option_get_usesyslog(); +void alpm_option_set_usesyslog(int usesyslog); alpm_list_t *alpm_option_get_noupgrades(); void alpm_option_add_noupgrade(const char *pkg); @@ -151,9 +149,11 @@ void alpm_option_add_ignoregrp(const char *grp); void alpm_option_set_ignoregrps(alpm_list_t *ignoregrps); int alpm_option_remove_ignoregrp(const char *grp); -unsigned short alpm_option_get_nopassiveftp(); -void alpm_option_set_nopassiveftp(unsigned short nopasv); -void alpm_option_set_usedelta(unsigned short usedelta); +const char *alpm_option_get_arch(); +void alpm_option_set_arch(const char *arch); + +int alpm_option_get_usedelta(); +void alpm_option_set_usedelta(int usedelta); pmdb_t *alpm_option_get_localdb(); alpm_list_t *alpm_option_get_syncdbs(); @@ -194,7 +194,7 @@ typedef enum _pmpkgreason_t { PM_PKG_REASON_DEPEND = 1 /* installed as a dependency for another package */ } pmpkgreason_t; -int alpm_pkg_load(const char *filename, unsigned short full, pmpkg_t **pkg); +int alpm_pkg_load(const char *filename, int full, pmpkg_t **pkg); int alpm_pkg_free(pmpkg_t *pkg); int alpm_pkg_checkmd5sum(pmpkg_t *pkg); char *alpm_fetch_pkgurl(const char *url); @@ -224,15 +224,14 @@ 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); -alpm_list_t *alpm_pkg_get_removes(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); /*int alpm_pkg_changelog_feof(const pmpkg_t *pkg, void *fp);*/ int alpm_pkg_changelog_close(const pmpkg_t *pkg, void *fp); -unsigned short alpm_pkg_has_scriptlet(pmpkg_t *pkg); -unsigned short alpm_pkg_has_force(pmpkg_t *pkg); +int alpm_pkg_has_scriptlet(pmpkg_t *pkg); +int alpm_pkg_has_force(pmpkg_t *pkg); off_t alpm_pkg_download_size(pmpkg_t *newpkg); @@ -262,34 +261,27 @@ pmpkg_t *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync); * Transactions */ -/* Types */ -typedef enum _pmtranstype_t { - PM_TRANS_TYPE_UPGRADE = 1, - PM_TRANS_TYPE_REMOVE, - PM_TRANS_TYPE_REMOVEUPGRADE, - PM_TRANS_TYPE_SYNC -} pmtranstype_t; /* Flags */ typedef enum _pmtransflag_t { - PM_TRANS_FLAG_NODEPS = 0x01, - PM_TRANS_FLAG_FORCE = 0x02, - PM_TRANS_FLAG_NOSAVE = 0x04, - /* 0x08 flag can go here */ - PM_TRANS_FLAG_CASCADE = 0x10, - PM_TRANS_FLAG_RECURSE = 0x20, - PM_TRANS_FLAG_DBONLY = 0x40, - /* 0x80 flag can go here */ - PM_TRANS_FLAG_ALLDEPS = 0x100, - PM_TRANS_FLAG_DOWNLOADONLY = 0x200, - PM_TRANS_FLAG_NOSCRIPTLET = 0x400, - PM_TRANS_FLAG_NOCONFLICTS = 0x800, - /* 0x1000 flag can go here */ - PM_TRANS_FLAG_NEEDED = 0x2000, - PM_TRANS_FLAG_ALLEXPLICIT = 0x4000, - PM_TRANS_FLAG_UNNEEDED = 0x8000, - PM_TRANS_FLAG_RECURSEALL = 0x10000, - PM_TRANS_FLAG_NOLOCK = 0x20000 + PM_TRANS_FLAG_NODEPS = 1, + PM_TRANS_FLAG_FORCE = (1 << 1), + PM_TRANS_FLAG_NOSAVE = (1 << 2), + /* (1 << 3) flag can go here */ + PM_TRANS_FLAG_CASCADE = (1 << 4), + PM_TRANS_FLAG_RECURSE = (1 << 5), + PM_TRANS_FLAG_DBONLY = (1 << 6), + /* (1 << 7) flag can go here */ + PM_TRANS_FLAG_ALLDEPS = (1 << 8), + PM_TRANS_FLAG_DOWNLOADONLY = (1 << 9), + PM_TRANS_FLAG_NOSCRIPTLET = (1 << 10), + PM_TRANS_FLAG_NOCONFLICTS = (1 << 11), + /* (1 << 12) flag can go here */ + PM_TRANS_FLAG_NEEDED = (1 << 13), + PM_TRANS_FLAG_ALLEXPLICIT = (1 << 14), + PM_TRANS_FLAG_UNNEEDED = (1 << 15), + PM_TRANS_FLAG_RECURSEALL = (1 << 16), + PM_TRANS_FLAG_NOLOCK = (1 << 17) } pmtransflag_t; /** @@ -376,12 +368,12 @@ typedef enum _pmtransevt_t { /* Transaction Conversations (ie, questions) */ typedef enum _pmtransconv_t { - PM_TRANS_CONV_INSTALL_IGNOREPKG = 0x01, - PM_TRANS_CONV_REPLACE_PKG = 0x02, - PM_TRANS_CONV_CONFLICT_PKG = 0x04, - PM_TRANS_CONV_CORRUPTED_PKG = 0x08, - PM_TRANS_CONV_LOCAL_NEWER = 0x10, - PM_TRANS_CONV_REMOVE_PKGS = 0x20, + PM_TRANS_CONV_INSTALL_IGNOREPKG = 1, + PM_TRANS_CONV_REPLACE_PKG = (1 << 1), + PM_TRANS_CONV_CONFLICT_PKG = (1 << 2), + PM_TRANS_CONV_CORRUPTED_PKG = (1 << 3), + PM_TRANS_CONV_LOCAL_NEWER = (1 << 4), + PM_TRANS_CONV_REMOVE_PKGS = (1 << 5), } pmtransconv_t; /* Transaction Progress */ @@ -402,19 +394,23 @@ typedef void (*alpm_trans_cb_conv)(pmtransconv_t, void *, void *, /* Transaction Progress callback */ typedef void (*alpm_trans_cb_progress)(pmtransprog_t, const char *, int, int, int); -pmtranstype_t alpm_trans_get_type(); -unsigned int alpm_trans_get_flags(); -alpm_list_t * alpm_trans_get_pkgs(); -int alpm_trans_init(pmtranstype_t type, pmtransflag_t flags, +int alpm_trans_get_flags(); +alpm_list_t * alpm_trans_get_add(); +alpm_list_t * alpm_trans_get_remove(); +int alpm_trans_init(pmtransflag_t flags, alpm_trans_cb_event cb_event, alpm_trans_cb_conv conv, alpm_trans_cb_progress cb_progress); -int alpm_trans_sysupgrade(int enable_downgrade); -int alpm_trans_addtarget(char *target); int alpm_trans_prepare(alpm_list_t **data); int alpm_trans_commit(alpm_list_t **data); int alpm_trans_interrupt(void); int alpm_trans_release(void); +int alpm_sync_sysupgrade(int enable_downgrade); +int alpm_sync_target(char *target); +int alpm_sync_dbtarget(char *db, char *target); +int alpm_add_target(char *target); +int alpm_remove_target(char *target); + /* * Dependencies and conflicts */ @@ -441,6 +437,7 @@ 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); +const char *alpm_conflict_get_reason(pmconflict_t *conflict); pmdepmod_t alpm_dep_get_mod(const pmdepend_t *dep); const char *alpm_dep_get_name(const pmdepend_t *dep); @@ -509,6 +506,7 @@ enum _pmerrno_t { PM_ERR_PKG_OPEN, PM_ERR_PKG_CANT_REMOVE, PM_ERR_PKG_INVALID_NAME, + PM_ERR_PKG_INVALID_ARCH, PM_ERR_PKG_REPO_NOT_FOUND, /* Deltas */ PM_ERR_DLT_INVALID, diff --git a/lib/libalpm/alpm_list.c b/lib/libalpm/alpm_list.c index 127f72ac..a395540e 100644 --- a/lib/libalpm/alpm_list.c +++ b/lib/libalpm/alpm_list.c @@ -616,7 +616,7 @@ static int ptr_cmp(const void *p, const void *q) /** * @brief Find an item in a list. * - * Search for the item whos data matches that of the `needle`. + * Search for the item whose data matches that of the `needle`. * * @param needle the data to search for (== comparison) * @param haystack the list @@ -644,11 +644,65 @@ char SYMEXPORT *alpm_list_find_str(const alpm_list_t *haystack, } /** - * @brief Find the items in list `lhs` that are not present in list `rhs`. + * @brief Find the differences between list `left` and list `right` + * + * The two lists must be sorted. Items only in list `left` are added to the + * `onlyleft` list. Items only in list `right` are added to the `onlyright` + * list. * - * Entries are not duplicated. Operation is O(m*n). The first list is stepped - * through one node at a time, and for each node in the first list, each node - * in the second list is compared to it. + * @param left the first list + * @param right the second list + * @param fn the comparison function + * @param onlyleft pointer to the first result list + * @param onlyright pointer to the second result list + * + */ +void SYMEXPORT alpm_list_diff_sorted(alpm_list_t *left, + alpm_list_t *right, alpm_list_fn_cmp fn, + alpm_list_t **onlyleft, alpm_list_t **onlyright) +{ + alpm_list_t *l = left; + alpm_list_t *r = right; + + if(!onlyleft && !onlyright) { + return; + } + + while (l != NULL && r != NULL) { + int cmp = fn(l->data, r->data); + if(cmp < 0) { + if(onlyleft) { + *onlyleft = alpm_list_add(*onlyleft, l->data); + } + l = l->next; + } + else if(cmp > 0) { + if(onlyright) { + *onlyright = alpm_list_add(*onlyright, r->data); + } + r = r->next; + } else { + l = l->next; + r = r->next; + } + } + while (l != NULL) { + if(onlyleft) { + *onlyleft = alpm_list_add(*onlyleft, l->data); + } + l = l->next; + } + while (r != NULL) { + if(onlyright) { + *onlyright = alpm_list_add(*onlyright, r->data); + } + r = r->next; + } +} + + +/** + * @brief Find the items in list `lhs` that are not present in list `rhs`. * * @param lhs the first list * @param rhs the second list @@ -659,21 +713,18 @@ char SYMEXPORT *alpm_list_find_str(const alpm_list_t *haystack, alpm_list_t SYMEXPORT *alpm_list_diff(const alpm_list_t *lhs, const alpm_list_t *rhs, alpm_list_fn_cmp fn) { - const alpm_list_t *i, *j; + alpm_list_t *left, *right; alpm_list_t *ret = NULL; - for(i = lhs; i; i = i->next) { - int found = 0; - for(j = rhs; j; j = j->next) { - if(fn(i->data, j->data) == 0) { - found = 1; - break; - } - } - if(!found) { - ret = alpm_list_add(ret, i->data); - } - } + left = alpm_list_copy(lhs); + left = alpm_list_msort(left, alpm_list_count(left), fn); + right = alpm_list_copy(rhs); + right = alpm_list_msort(right, alpm_list_count(right), fn); + + alpm_list_diff_sorted(left, right, fn, &ret, NULL); + + alpm_list_free(left); + alpm_list_free(right); return(ret); } diff --git a/lib/libalpm/alpm_list.h b/lib/libalpm/alpm_list.h index f079ecfd..48e91173 100644 --- a/lib/libalpm/alpm_list.h +++ b/lib/libalpm/alpm_list.h @@ -78,6 +78,8 @@ void *alpm_list_find(const alpm_list_t *haystack, const void *needle, alpm_list_ void *alpm_list_find_ptr(const alpm_list_t *haystack, const void *needle); char *alpm_list_find_str(const alpm_list_t *haystack, const char *needle); alpm_list_t *alpm_list_diff(const alpm_list_t *lhs, const alpm_list_t *rhs, alpm_list_fn_cmp fn); +void alpm_list_diff_sorted(alpm_list_t *left, alpm_list_t *right, + alpm_list_fn_cmp fn, alpm_list_t **onlyleft, alpm_list_t **onlyright); #ifdef __cplusplus } diff --git a/lib/libalpm/backup.c b/lib/libalpm/backup.c index e628131f..a0c6b7fc 100644 --- a/lib/libalpm/backup.c +++ b/lib/libalpm/backup.c @@ -33,7 +33,7 @@ #include "util.h" /* split a backup string "file\thash" into two strings : file and hash */ -int _alpm_backup_split(const char *string, char **file, char **hash) +static int backup_split(const char *string, char **file, char **hash) { char *str = strdup(string); char *ptr; @@ -65,14 +65,14 @@ int _alpm_backup_split(const char *string, char **file, char **hash) char *_alpm_backup_file(const char *string) { char *file = NULL; - _alpm_backup_split(string, &file, NULL); + backup_split(string, &file, NULL); return(file); } char *_alpm_backup_hash(const char *string) { char *hash = NULL; - _alpm_backup_split(string, NULL, &hash); + backup_split(string, NULL, &hash); return(hash); } @@ -95,7 +95,7 @@ char *_alpm_needbackup(const char *file, const alpm_list_t *backup) char *hash = NULL; /* no hash found */ - if(!_alpm_backup_split((char *)lp->data, &filename, &hash)) { + if(!backup_split((char *)lp->data, &filename, &hash)) { FREE(filename); continue; } diff --git a/lib/libalpm/be_files.c b/lib/libalpm/be_files.c index bfe10867..f624d7cf 100644 --- a/lib/libalpm/be_files.c +++ b/lib/libalpm/be_files.c @@ -47,76 +47,10 @@ #include "dload.h" -/* - * Return the last update time as number of seconds from the epoch. - * Returns 0 if the value is unknown or can't be read. - */ -static time_t getlastupdate(const pmdb_t *db) -{ - FILE *fp; - char *file; - time_t ret = 0; - - ALPM_LOG_FUNC; - - if(db == NULL) { - return(ret); - } - - /* db->path + '.lastupdate' + NULL */ - MALLOC(file, strlen(db->path) + 12, RET_ERR(PM_ERR_MEMORY, ret)); - sprintf(file, "%s.lastupdate", db->path); - - /* get the last update time, if it's there */ - if((fp = fopen(file, "r")) == NULL) { - free(file); - return(ret); - } else { - char line[64]; - if(fgets(line, sizeof(line), fp)) { - ret = atol(line); - } - } - fclose(fp); - free(file); - return(ret); -} - -/* - * writes the dbpath/.lastupdate file with the value in time - */ -static int setlastupdate(const pmdb_t *db, time_t time) -{ - FILE *fp; - char *file; - int ret = 0; - - ALPM_LOG_FUNC; - - if(db == NULL || time == 0) { - return(-1); - } - - /* db->path + '.lastupdate' + NULL */ - MALLOC(file, strlen(db->path) + 12, RET_ERR(PM_ERR_MEMORY, ret)); - sprintf(file, "%s.lastupdate", db->path); - - if((fp = fopen(file, "w")) == NULL) { - free(file); - return(-1); - } - if(fprintf(fp, "%ju", (uintmax_t)time) <= 0) { - ret = -1; - } - fclose(fp); - free(file); - return(ret); -} - static int checkdbdir(pmdb_t *db) { struct stat buf; - char *path = db->path; + const char *path = _alpm_db_path(db); if(stat(path, &buf) != 0) { _alpm_log(PM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n", @@ -148,7 +82,7 @@ static int checkdbdir(pmdb_t *db) * pmdb_t *db; * int result; * db = alpm_list_getdata(alpm_option_get_syncdbs()); - * if(alpm_trans_init(PM_TRANS_TYPE_SYNC, 0, NULL, NULL, NULL) == 0) { + * if(alpm_trans_init(0, NULL, NULL, NULL) == 0) { * result = alpm_db_update(0, db); * alpm_trans_release(); * @@ -174,7 +108,6 @@ static int checkdbdir(pmdb_t *db) int SYMEXPORT alpm_db_update(int force, pmdb_t *db) { char *dbfile, *dbfilepath; - time_t newmtime = 0, lastupdate = 0; const char *dbpath; size_t len; @@ -191,33 +124,22 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db) */ ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); ASSERT(handle->trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); - ASSERT(handle->trans->type == PM_TRANS_TYPE_SYNC, RET_ERR(PM_ERR_TRANS_TYPE, -1)); if(!alpm_list_find_ptr(handle->dbs_sync, db)) { RET_ERR(PM_ERR_DB_NOT_FOUND, -1); } - if(!force) { - /* get the lastupdate time */ - lastupdate = getlastupdate(db); - if(lastupdate == 0) { - _alpm_log(PM_LOG_DEBUG, "failed to get lastupdate time for %s\n", - db->treename); - } - } - len = strlen(db->treename) + strlen(DBEXT) + 1; MALLOC(dbfile, len, RET_ERR(PM_ERR_MEMORY, -1)); sprintf(dbfile, "%s" DBEXT, db->treename); dbpath = alpm_option_get_dbpath(); - ret = _alpm_download_single_file(dbfile, db->servers, dbpath, - lastupdate, &newmtime); + ret = _alpm_download_single_file(dbfile, db->servers, dbpath, force); free(dbfile); if(ret == 1) { - /* mtimes match, do nothing */ + /* files match, do nothing */ pm_errno = 0; return(1); } else if(ret == -1) { @@ -225,12 +147,16 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db) _alpm_log(PM_LOG_DEBUG, "failed to sync db: %s\n", alpm_strerrorlast()); return(-1); } else { + const char *syncdbpath = _alpm_db_path(db); /* remove the old dir */ - if(_alpm_rmrf(db->path) != 0) { + if(_alpm_rmrf(syncdbpath) != 0) { _alpm_log(PM_LOG_ERROR, _("could not remove database %s\n"), db->treename); RET_ERR(PM_ERR_DB_REMOVE, -1); + } else { + _alpm_log(PM_LOG_DEBUG, "database dir %s removed\n", _alpm_db_path(db)); } + /* Cache needs to be rebuilt */ _alpm_db_free_pkgcache(db); @@ -241,20 +167,12 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db) /* uncompress the sync database */ checkdbdir(db); - ret = _alpm_unpack(dbfilepath, db->path, NULL); + ret = _alpm_unpack(dbfilepath, syncdbpath, NULL, 0); if(ret) { free(dbfilepath); RET_ERR(PM_ERR_SYSTEM, -1); } - unlink(dbfilepath); free(dbfilepath); - - /* if we have a new mtime, set the DB last update value */ - if(newmtime) { - _alpm_log(PM_LOG_DEBUG, "sync: new mtime for %s: %ju\n", - db->treename, (uintmax_t)newmtime); - setlastupdate(db, newmtime); - } } return(0); @@ -306,13 +224,15 @@ int _alpm_db_populate(pmdb_t *db) struct dirent *ent = NULL; struct stat sbuf; char path[PATH_MAX]; + const char *dbpath; DIR *dbdir; ALPM_LOG_FUNC; ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - dbdir = opendir(db->path); + dbpath = _alpm_db_path(db); + dbdir = opendir(dbpath); if(dbdir == NULL) { return(0); } @@ -324,7 +244,7 @@ int _alpm_db_populate(pmdb_t *db) continue; } /* stat the entry, make sure it's a directory */ - snprintf(path, PATH_MAX, "%s%s", db->path, name); + snprintf(path, PATH_MAX, "%s%s", dbpath, name); if(stat(path, &sbuf) != 0 || !S_ISDIR(sbuf.st_mode)) { continue; } @@ -342,6 +262,13 @@ int _alpm_db_populate(pmdb_t *db) continue; } + /* duplicated database entries are not allowed */ + if(_alpm_pkg_find(db->pkgcache, pkg->name)) { + _alpm_log(PM_LOG_ERROR, _("duplicated database entry '%s'\n"), pkg->name); + _alpm_pkg_free(pkg); + continue; + } + /* explicitly read with only 'BASE' data, accessors will handle the rest */ if(_alpm_db_read(db, pkg, INFRQ_BASE) == -1) { _alpm_log(PM_LOG_ERROR, _("corrupted database entry '%s'\n"), name); @@ -367,10 +294,12 @@ static char *get_pkgpath(pmdb_t *db, pmpkg_t *info) { size_t len; char *pkgpath; + const char *dbpath; - len = strlen(db->path) + strlen(info->name) + strlen(info->version) + 3; + dbpath = _alpm_db_path(db); + len = strlen(dbpath) + strlen(info->name) + strlen(info->version) + 3; MALLOC(pkgpath, len, RET_ERR(PM_ERR_MEMORY, NULL)); - sprintf(pkgpath, "%s%s-%s/", db->path, info->name, info->version); + sprintf(pkgpath, "%s%s-%s/", dbpath, info->name, info->version); return(pkgpath); } @@ -379,6 +308,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) FILE *fp = NULL; char path[PATH_MAX]; char line[513]; + int sline = sizeof(line)-1; char *pkgpath = NULL; ALPM_LOG_FUNC; @@ -410,7 +340,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) info->name, inforeq); /* clear out 'line', to be certain - and to make valgrind happy */ - memset(line, 0, 513); + memset(line, 0, sline+1); pkgpath = get_pkgpath(db, info); @@ -434,7 +364,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) } _alpm_strtrim(line); if(strcmp(line, "%NAME%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } if(strcmp(_alpm_strtrim(line), info->name) != 0) { @@ -442,7 +372,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) "mismatch on package %s\n"), db->treename, info->name); } } else if(strcmp(line, "%VERSION%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } if(strcmp(_alpm_strtrim(line), info->version) != 0) { @@ -450,44 +380,44 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) "mismatch on package %s\n"), db->treename, info->name); } } else if(strcmp(line, "%FILENAME%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } STRDUP(info->filename, _alpm_strtrim(line), goto error); } else if(strcmp(line, "%DESC%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } STRDUP(info->desc, _alpm_strtrim(line), goto error); } else if(strcmp(line, "%GROUPS%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { char *linedup; STRDUP(linedup, _alpm_strtrim(line), goto error); info->groups = alpm_list_add(info->groups, linedup); } } else if(strcmp(line, "%URL%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } STRDUP(info->url, _alpm_strtrim(line), goto error); } else if(strcmp(line, "%LICENSE%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { char *linedup; STRDUP(linedup, _alpm_strtrim(line), goto error); info->licenses = alpm_list_add(info->licenses, linedup); } } else if(strcmp(line, "%ARCH%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } STRDUP(info->arch, _alpm_strtrim(line), goto error); } else if(strcmp(line, "%BUILDDATE%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } _alpm_strtrim(line); - char first = tolower(line[0]); + char first = tolower((unsigned char)line[0]); if(first > 'a' && first < 'z') { struct tm tmp_tm = {0}; /* initialize to null in case of failure */ setlocale(LC_TIME, "C"); @@ -498,12 +428,12 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) info->builddate = atol(line); } } else if(strcmp(line, "%INSTALLDATE%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } _alpm_strtrim(line); - char first = tolower(line[0]); + char first = tolower((unsigned char)line[0]); if(first > 'a' && first < 'z') { struct tm tmp_tm = {0}; /* initialize to null in case of failure */ setlocale(LC_TIME, "C"); @@ -514,12 +444,12 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) info->installdate = atol(line); } } else if(strcmp(line, "%PACKAGER%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } STRDUP(info->packager, _alpm_strtrim(line), goto error); } else if(strcmp(line, "%REASON%") == 0) { - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } info->reason = (pmpkgreason_t)atol(_alpm_strtrim(line)); @@ -529,7 +459,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) * is currently only used in sync databases, and SIZE is * only used in local databases. */ - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } info->size = atol(_alpm_strtrim(line)); @@ -540,19 +470,19 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) } else if(strcmp(line, "%ISIZE%") == 0) { /* ISIZE (installed size) tag only appears in sync repositories, * not the local one. */ - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } info->isize = atol(_alpm_strtrim(line)); } else if(strcmp(line, "%MD5SUM%") == 0) { /* MD5SUM tag only appears in sync repositories, * not the local one. */ - if(fgets(line, 512, fp) == NULL) { + if(fgets(line, sline, fp) == NULL) { goto error; } STRDUP(info->md5sum, _alpm_strtrim(line), goto error); } else if(strcmp(line, "%REPLACES%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { char *linedup; STRDUP(linedup, _alpm_strtrim(line), goto error); info->replaces = alpm_list_add(info->replaces, linedup); @@ -575,13 +505,13 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) while(fgets(line, 256, fp)) { _alpm_strtrim(line); if(strcmp(line, "%FILES%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { char *linedup; STRDUP(linedup, _alpm_strtrim(line), goto error); info->files = alpm_list_add(info->files, linedup); } } else if(strcmp(line, "%BACKUP%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { char *linedup; STRDUP(linedup, _alpm_strtrim(line), goto error); info->backup = alpm_list_add(info->backup, linedup); @@ -603,24 +533,24 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) fgets(line, 255, fp); _alpm_strtrim(line); if(strcmp(line, "%DEPENDS%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { pmdepend_t *dep = _alpm_splitdep(_alpm_strtrim(line)); info->depends = alpm_list_add(info->depends, dep); } } else if(strcmp(line, "%OPTDEPENDS%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { char *linedup; STRDUP(linedup, _alpm_strtrim(line), goto error); info->optdepends = alpm_list_add(info->optdepends, linedup); } } else if(strcmp(line, "%CONFLICTS%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { char *linedup; STRDUP(linedup, _alpm_strtrim(line), goto error); info->conflicts = alpm_list_add(info->conflicts, linedup); } } else if(strcmp(line, "%PROVIDES%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { char *linedup; STRDUP(linedup, _alpm_strtrim(line), goto error); info->provides = alpm_list_add(info->provides, linedup); @@ -639,7 +569,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) fgets(line, 255, fp); _alpm_strtrim(line); if(strcmp(line, "%DELTAS%") == 0) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + while(fgets(line, sline, fp) && strlen(_alpm_strtrim(line))) { pmdelta_t *delta = _alpm_delta_parse(line); if(delta) { info->deltas = alpm_list_add(info->deltas, delta); diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c index 9c7c1617..c1a43438 100644 --- a/lib/libalpm/be_package.c +++ b/lib/libalpm/be_package.c @@ -82,7 +82,7 @@ static int parse_descfile(struct archive *a, pmpkg_t *newpkg) } else if(!strcmp(key, "license")) { newpkg->licenses = alpm_list_add(newpkg->licenses, strdup(ptr)); } else if(!strcmp(key, "builddate")) { - char first = tolower(ptr[0]); + char first = tolower((unsigned char)ptr[0]); if(first > 'a' && first < 'z') { struct tm tmp_tm = {0}; /* initialize to null in case of failure */ setlocale(LC_TIME, "C"); @@ -132,7 +132,7 @@ static int parse_descfile(struct archive *a, pmpkg_t *newpkg) * through the full archive * @return An information filled pmpkg_t struct */ -static pmpkg_t *pkg_load(const char *pkgfile, unsigned short full) +static pmpkg_t *pkg_load(const char *pkgfile, int full) { int ret = ARCHIVE_OK; int config = 0; @@ -269,8 +269,7 @@ error: * @param pkg address of the package pointer * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int SYMEXPORT alpm_pkg_load(const char *filename, unsigned short full, - pmpkg_t **pkg) +int SYMEXPORT alpm_pkg_load(const char *filename, int full, pmpkg_t **pkg) { ALPM_LOG_FUNC; diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c index 07ef73cf..e934c01e 100644 --- a/lib/libalpm/conflict.c +++ b/lib/libalpm/conflict.c @@ -41,7 +41,7 @@ #include "cache.h" #include "deps.h" -pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2) +pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2, const char *reason) { pmconflict_t *conflict; @@ -51,6 +51,7 @@ pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2) STRDUP(conflict->package1, package1, RET_ERR(PM_ERR_MEMORY, NULL)); STRDUP(conflict->package2, package2, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(conflict->reason, reason, RET_ERR(PM_ERR_MEMORY, NULL)); return(conflict); } @@ -59,6 +60,7 @@ void _alpm_conflict_free(pmconflict_t *conflict) { FREE(conflict->package2); FREE(conflict->package1); + FREE(conflict->reason); FREE(conflict); } @@ -69,6 +71,7 @@ pmconflict_t *_alpm_conflict_dup(const pmconflict_t *conflict) STRDUP(newconflict->package1, conflict->package1, RET_ERR(PM_ERR_MEMORY, NULL)); STRDUP(newconflict->package2, conflict->package2, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(newconflict->reason, conflict->reason, RET_ERR(PM_ERR_MEMORY, NULL)); return(newconflict); } @@ -122,9 +125,9 @@ static int does_conflict(pmpkg_t *pkg1, const char *conflict, pmpkg_t *pkg2) * @param pkg2 package causing conflict */ static void add_conflict(alpm_list_t **baddeps, const char *pkg1, - const char *pkg2) + const char *pkg2, const char *reason) { - pmconflict_t *conflict = _alpm_conflict_new(pkg1, pkg2); + pmconflict_t *conflict = _alpm_conflict_new(pkg1, pkg2, reason); if(conflict && !_alpm_conflict_isin(conflict, *baddeps)) { *baddeps = alpm_list_add(*baddeps, conflict); } else { @@ -168,9 +171,9 @@ static void check_conflict(alpm_list_t *list1, alpm_list_t *list2, if(does_conflict(pkg1, conflict, pkg2)) { if(order >= 0) { - add_conflict(baddeps, pkg1name, pkg2name); + add_conflict(baddeps, pkg1name, pkg2name, conflict); } else { - add_conflict(baddeps, pkg2name, pkg1name); + add_conflict(baddeps, pkg2name, pkg1name, conflict); } } } @@ -513,7 +516,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, /* skip removal of file, but not add. this will prevent a second * package from removing the file when it was already installed * by its new owner (whether the file is in backup array or not */ - trans->skip_remove = alpm_list_add(trans->skip_remove, strdup(path)); + trans->skip_remove = alpm_list_add(trans->skip_remove, strdup(filestr)); _alpm_log(PM_LOG_DEBUG, "file changed packages, adding to remove skiplist: %s\n", filestr); resolved_conflict = 1; } @@ -578,6 +581,17 @@ const char SYMEXPORT *alpm_conflict_get_package2(pmconflict_t *conflict) return conflict->package2; } +const char SYMEXPORT *alpm_conflict_get_reason(pmconflict_t *conflict) +{ + ALPM_LOG_FUNC; + + /* Sanity checks */ + ASSERT(handle != NULL, return(NULL)); + ASSERT(conflict != NULL, return(NULL)); + + return conflict->reason; +} + const char SYMEXPORT *alpm_fileconflict_get_target(pmfileconflict_t *conflict) { ALPM_LOG_FUNC; diff --git a/lib/libalpm/conflict.h b/lib/libalpm/conflict.h index 149c728e..73a6e959 100644 --- a/lib/libalpm/conflict.h +++ b/lib/libalpm/conflict.h @@ -27,6 +27,7 @@ struct __pmconflict_t { char *package1; char *package2; + char *reason; }; struct __pmfileconflict_t { @@ -36,7 +37,7 @@ struct __pmfileconflict_t { char *ctarget; }; -pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2); +pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2, const char *reason); pmconflict_t *_alpm_conflict_dup(const pmconflict_t *conflict); void _alpm_conflict_free(pmconflict_t *conflict); int _alpm_conflict_isin(pmconflict_t *needle, alpm_list_t *haystack); diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c index 62c2e0a3..dca5452a 100644 --- a/lib/libalpm/db.c +++ b/lib/libalpm/db.c @@ -323,18 +323,15 @@ alpm_list_t SYMEXPORT *alpm_db_search(pmdb_t *db, const alpm_list_t* needles) /** @} */ -pmdb_t *_alpm_db_new(const char *dbpath, const char *treename) +static pmdb_t *_alpm_db_new(const char *treename, int is_local) { pmdb_t *db; - const size_t pathsize = strlen(dbpath) + strlen(treename) + 2; ALPM_LOG_FUNC; CALLOC(db, 1, sizeof(pmdb_t), RET_ERR(PM_ERR_MEMORY, NULL)); - CALLOC(db->path, 1, pathsize, RET_ERR(PM_ERR_MEMORY, NULL)); - - sprintf(db->path, "%s%s/", dbpath, treename); STRDUP(db->treename, treename, RET_ERR(PM_ERR_MEMORY, NULL)); + db->is_local = is_local; return(db); } @@ -347,13 +344,44 @@ void _alpm_db_free(pmdb_t *db) _alpm_db_free_pkgcache(db); /* cleanup server list */ FREELIST(db->servers); - FREE(db->path); + FREE(db->_path); FREE(db->treename); FREE(db); return; } +const char *_alpm_db_path(pmdb_t *db) +{ + if(!db) { + return(NULL); + } + if(!db->_path) { + const char *dbpath; + size_t pathsize; + + dbpath = alpm_option_get_dbpath(); + if(!dbpath) { + _alpm_log(PM_LOG_ERROR, _("database path is undefined\n")); + RET_ERR(PM_ERR_DB_OPEN, NULL); + } + + if(db->is_local) { + pathsize = strlen(dbpath) + strlen(db->treename) + 2; + CALLOC(db->_path, 1, pathsize, RET_ERR(PM_ERR_MEMORY, NULL)); + sprintf(db->_path, "%s%s/", dbpath, db->treename); + } else { + pathsize = strlen(dbpath) + 5 + strlen(db->treename) + 2; + CALLOC(db->_path, 1, pathsize, RET_ERR(PM_ERR_MEMORY, NULL)); + /* all sync DBs now reside in the sync/ subdir of the dbpath */ + sprintf(db->_path, "%ssync/%s/", dbpath, db->treename); + } + _alpm_log(PM_LOG_DEBUG, "database path for tree %s set to %s\n", + db->treename, db->_path); + } + return(db->_path); +} + int _alpm_db_cmp(const void *d1, const void *d2) { pmdb_t *db1 = (pmdb_t *)d1; @@ -440,7 +468,6 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) pmdb_t *_alpm_db_register_local(void) { pmdb_t *db; - const char *dbpath; ALPM_LOG_FUNC; @@ -451,13 +478,7 @@ pmdb_t *_alpm_db_register_local(void) _alpm_log(PM_LOG_DEBUG, "registering local database\n"); - dbpath = alpm_option_get_dbpath(); - if(!dbpath) { - _alpm_log(PM_LOG_ERROR, _("database path is undefined\n")); - RET_ERR(PM_ERR_DB_OPEN, NULL); - } - - db = _alpm_db_new(dbpath, "local"); + db = _alpm_db_new("local", 1); if(db == NULL) { RET_ERR(PM_ERR_DB_CREATE, NULL); } @@ -469,8 +490,6 @@ pmdb_t *_alpm_db_register_local(void) pmdb_t *_alpm_db_register_sync(const char *treename) { pmdb_t *db; - const char *dbpath; - char path[PATH_MAX]; alpm_list_t *i; ALPM_LOG_FUNC; @@ -485,15 +504,7 @@ pmdb_t *_alpm_db_register_sync(const char *treename) _alpm_log(PM_LOG_DEBUG, "registering sync database '%s'\n", treename); - 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/", dbpath); - - db = _alpm_db_new(path, treename); + db = _alpm_db_new(treename, 0); if(db == NULL) { RET_ERR(PM_ERR_DB_CREATE, NULL); } diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h index 950ace22..a540d02d 100644 --- a/lib/libalpm/db.h +++ b/lib/libalpm/db.h @@ -28,30 +28,32 @@ /* Database entries */ typedef enum _pmdbinfrq_t { - INFRQ_BASE = 0x01, - INFRQ_DESC = 0x02, - INFRQ_DEPENDS = 0x04, - INFRQ_FILES = 0x08, - INFRQ_SCRIPTLET = 0x10, - INFRQ_DELTAS = 0x20, + INFRQ_BASE = 1, + INFRQ_DESC = (1 << 1), + INFRQ_DEPENDS = (1 << 2), + INFRQ_FILES = (1 << 3), + INFRQ_SCRIPTLET = (1 << 4), + INFRQ_DELTAS = (1 << 5), /* ALL should be sum of all above */ INFRQ_ALL = 0x3F } pmdbinfrq_t; /* Database */ struct __pmdb_t { - char *path; char *treename; - unsigned short pkgcache_loaded; + /* do not access directly, use _alpm_db_path(db) for lazy access */ + char *_path; + int pkgcache_loaded; + int grpcache_loaded; + int is_local; alpm_list_t *pkgcache; - unsigned short grpcache_loaded; alpm_list_t *grpcache; alpm_list_t *servers; }; /* db.c, database general calls */ -pmdb_t *_alpm_db_new(const char *dbpath, const char *treename); void _alpm_db_free(pmdb_t *db); +const char *_alpm_db_path(pmdb_t *db); int _alpm_db_cmp(const void *d1, const void *d2); alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles); pmdb_t *_alpm_db_register_local(void); diff --git a/lib/libalpm/delta.c b/lib/libalpm/delta.c index 599a1b76..523968ec 100644 --- a/lib/libalpm/delta.c +++ b/lib/libalpm/delta.c @@ -71,34 +71,16 @@ off_t SYMEXPORT alpm_delta_get_size(pmdelta_t *delta) /** @} */ -static alpm_list_t *delta_graph_init(alpm_list_t *deltas) +static alpm_list_t *graph_init(alpm_list_t *deltas) { alpm_list_t *i, *j; alpm_list_t *vertices = NULL; /* create the vertices */ for(i = deltas; i; i = i->next) { - char *fpath, *md5sum; pmgraph_t *v = _alpm_graph_new(); pmdelta_t *vdelta = i->data; vdelta->download_size = vdelta->delta_size; v->weight = LONG_MAX; - - /* determine whether the delta file already exists */ - fpath = _alpm_filecache_find(vdelta->delta); - md5sum = alpm_compute_md5sum(fpath); - if(fpath && md5sum && strcmp(md5sum, vdelta->delta_md5) == 0) { - vdelta->download_size = 0; - } - FREE(fpath); - FREE(md5sum); - - /* determine whether a base 'from' file exists */ - fpath = _alpm_filecache_find(vdelta->from); - if(fpath) { - v->weight = vdelta->download_size; - } - FREE(fpath); - v->data = vdelta; vertices = alpm_list_add(vertices, v); } @@ -128,8 +110,36 @@ static alpm_list_t *delta_graph_init(alpm_list_t *deltas) return(vertices); } -static off_t delta_vert(alpm_list_t *vertices, - const char *to, alpm_list_t **path) { +static void graph_init_size(alpm_list_t *vertices) +{ + alpm_list_t *i; + + for(i = vertices; i; i = i->next) { + char *fpath, *md5sum; + pmgraph_t *v = i->data; + pmdelta_t *vdelta = v->data; + + /* determine whether the delta file already exists */ + fpath = _alpm_filecache_find(vdelta->delta); + md5sum = alpm_compute_md5sum(fpath); + if(fpath && md5sum && strcmp(md5sum, vdelta->delta_md5) == 0) { + vdelta->download_size = 0; + } + FREE(fpath); + FREE(md5sum); + + /* determine whether a base 'from' file exists */ + fpath = _alpm_filecache_find(vdelta->from); + if(fpath) { + v->weight = vdelta->download_size; + } + FREE(fpath); + } +} + + +static void dijkstra(alpm_list_t *vertices) +{ alpm_list_t *i; pmgraph_t *v; while(1) { @@ -165,9 +175,14 @@ static off_t delta_vert(alpm_list_t *vertices, } } +} - v = NULL; +static off_t shortest_path(alpm_list_t *vertices, const char *to, alpm_list_t **path) +{ + alpm_list_t *i; + pmgraph_t *v = NULL; off_t bestsize = 0; + alpm_list_t *rpath = NULL; for(i = vertices; i; i = i->next) { pmgraph_t *v_i = i->data; @@ -181,7 +196,6 @@ static off_t delta_vert(alpm_list_t *vertices, } } - alpm_list_t *rpath = NULL; while(v != NULL) { pmdelta_t *vdelta = v->data; rpath = alpm_list_add(rpath, vdelta); @@ -219,9 +233,10 @@ off_t _alpm_shortest_delta_path(alpm_list_t *deltas, _alpm_log(PM_LOG_DEBUG, "started delta shortest-path search for '%s'\n", to); - vertices = delta_graph_init(deltas); - - bestsize = delta_vert(vertices, to, &bestpath); + vertices = graph_init(deltas); + graph_init_size(vertices); + dijkstra(vertices); + bestsize = shortest_path(vertices, to, &bestpath); _alpm_log(PM_LOG_DEBUG, "delta shortest-path search complete : '%jd'\n", (intmax_t)bestsize); diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index 02a4c7b6..46699ac6 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -605,7 +605,7 @@ int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *pkg, ALPM_LOG_FUNC; - if(local == NULL || dbs_sync == NULL) { + if(local == NULL) { return(-1); } diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c index 10be5e9d..6bf9b4db 100644 --- a/lib/libalpm/dload.c +++ b/lib/libalpm/dload.c @@ -25,6 +25,9 @@ #include <errno.h> #include <string.h> #include <unistd.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/stat.h> #include <signal.h> #include <limits.h> /* the following two are needed on BSD for libfetch */ @@ -59,7 +62,7 @@ static char *get_filename(const char *url) { static char *get_destfile(const char *path, const char *filename) { char *destfile; /* len = localpath len + filename len + null */ - int len = strlen(path) + strlen(filename) + 1; + size_t len = strlen(path) + strlen(filename) + 1; CALLOC(destfile, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, NULL)); snprintf(destfile, len, "%s%s", path, filename); @@ -69,37 +72,13 @@ static char *get_destfile(const char *path, const char *filename) { static char *get_tempfile(const char *path, const char *filename) { char *tempfile; /* len = localpath len + filename len + '.part' len + null */ - int len = strlen(path) + strlen(filename) + 6; + size_t len = strlen(path) + strlen(filename) + 6; CALLOC(tempfile, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, NULL)); snprintf(tempfile, len, "%s%s.part", path, filename); return(tempfile); } -/* Build a 'struct url' from an url. */ -static struct url *url_for_string(const char *url) -{ - struct url *ret = NULL; - ret = fetchParseURL(url); - if(!ret) { - _alpm_log(PM_LOG_ERROR, _("url '%s' is invalid\n"), url); - RET_ERR(PM_ERR_SERVER_BAD_URL, NULL); - } - - /* if no URL scheme specified, assume HTTP */ - if(strlen(ret->scheme) == 0) { - _alpm_log(PM_LOG_WARNING, _("url scheme not specified, assuming HTTP\n")); - strcpy(ret->scheme, SCHEME_HTTP); - } - /* add a user & password for anonymous FTP */ - if(strcmp(ret->scheme,SCHEME_FTP) == 0 && strlen(ret->user) == 0) { - strcpy(ret->user, "anonymous"); - strcpy(ret->pwd, "libalpm@guest"); - } - - return(ret); -} - static const char *gethost(struct url *fileurl) { const char *host = _("disk"); @@ -109,75 +88,126 @@ static const char *gethost(struct url *fileurl) return(host); } +int dload_interrupted; +static RETSIGTYPE inthandler(int signum) +{ + dload_interrupted = 1; +} + +#define check_stop() if(dload_interrupted) { ret = -1; goto cleanup; } +enum sighandlers { OLD = 0, NEW = 1 }; + static int download_internal(const char *url, const char *localpath, - time_t mtimeold, time_t *mtimenew) { - fetchIO *dlf = NULL; + int force) { FILE *localf = NULL; - struct url_stat ust; struct stat st; - int chk_resume = 0, ret = 0; - size_t dl_thisfile = 0; + int ret = 0; + off_t dl_thisfile = 0; ssize_t nread = 0; char *tempfile, *destfile, *filename; - struct sigaction new_action, old_action; - struct url *fileurl = url_for_string(url); - char buffer[PM_DLBUF_LEN]; + struct sigaction sig_pipe[2], sig_int[2]; - if(!fileurl) { - return(-1); - } + off_t local_size = 0; + time_t local_time = 0; + + struct url *fileurl; + struct url_stat ust; + fetchIO *dlf = NULL; + + char buffer[PM_DLBUF_LEN]; filename = get_filename(url); if(!filename) { - return(-1); + _alpm_log(PM_LOG_ERROR, _("url '%s' is invalid\n"), url); + RET_ERR(PM_ERR_SERVER_BAD_URL, -1); } - destfile = get_destfile(localpath, filename); - tempfile = get_tempfile(localpath, filename); - if(mtimeold) { - fileurl->last_modified = mtimeold; + fileurl = fetchParseURL(url); + if(!fileurl) { + _alpm_log(PM_LOG_ERROR, _("url '%s' is invalid\n"), url); + RET_ERR(PM_ERR_LIBFETCH, -1); } - /* pass the raw filename for passing to the callback function */ - _alpm_log(PM_LOG_DEBUG, "using '%s' for download progress\n", filename); + destfile = get_destfile(localpath, filename); + tempfile = get_tempfile(localpath, filename); if(stat(tempfile, &st) == 0 && st.st_size > 0) { - _alpm_log(PM_LOG_DEBUG, "existing file found, using it\n"); - fileurl->offset = (off_t)st.st_size; + _alpm_log(PM_LOG_DEBUG, "tempfile found, attempting continuation\n"); + local_time = fileurl->last_modified = st.st_mtime; + local_size = fileurl->offset = (off_t)st.st_size; dl_thisfile = st.st_size; localf = fopen(tempfile, "ab"); - chk_resume = 1; + } else if(!force && stat(destfile, &st) == 0 && st.st_size > 0) { + _alpm_log(PM_LOG_DEBUG, "destfile found, using mtime only\n"); + local_time = fileurl->last_modified = st.st_mtime; + local_size = /* no fu->off here */ (off_t)st.st_size; } else { - fileurl->offset = (off_t)0; - dl_thisfile = 0; + _alpm_log(PM_LOG_DEBUG, "no file found matching criteria, starting from scratch\n"); } + /* pass the raw filename for passing to the callback function */ + _alpm_log(PM_LOG_DEBUG, "using '%s' for download progress\n", filename); + /* print proxy info for debug purposes */ _alpm_log(PM_LOG_DEBUG, "HTTP_PROXY: %s\n", getenv("HTTP_PROXY")); _alpm_log(PM_LOG_DEBUG, "http_proxy: %s\n", getenv("http_proxy")); _alpm_log(PM_LOG_DEBUG, "FTP_PROXY: %s\n", getenv("FTP_PROXY")); _alpm_log(PM_LOG_DEBUG, "ftp_proxy: %s\n", getenv("ftp_proxy")); - /* libfetch does not reset the error code */ - fetchLastErrCode = 0; - /* 10s timeout */ fetchTimeout = 10; /* 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 = fetchXGet(fileurl, &ust, (handle->nopassiveftp ? "i" : "pi")); - - if(fetchLastErrCode == FETCH_UNCHANGED) { - _alpm_log(PM_LOG_DEBUG, "mtimes are identical, skipping %s\n", filename); + sig_pipe[NEW].sa_handler = SIG_IGN; + sigemptyset(&sig_pipe[NEW].sa_mask); + sig_pipe[NEW].sa_flags = 0; + sigaction(SIGPIPE, NULL, &sig_pipe[OLD]); + sigaction(SIGPIPE, &sig_pipe[NEW], NULL); + + dload_interrupted = 0; + sig_int[NEW].sa_handler = &inthandler; + sigemptyset(&sig_int[NEW].sa_mask); + sig_int[NEW].sa_flags = 0; + sigaction(SIGINT, NULL, &sig_int[OLD]); + sigaction(SIGINT, &sig_int[NEW], NULL); + + /* NOTE: libfetch does not reset the error code, be sure to do it before + * calls into the library */ + + /* find out the remote size *and* mtime in one go. there is a lot of + * trouble in trying to do both size and "if-modified-since" logic in a + * non-stat request, so avoid it. */ + fetchLastErrCode = 0; + if(fetchStat(fileurl, &ust, "") == -1) { + pm_errno = PM_ERR_LIBFETCH; + _alpm_log(PM_LOG_ERROR, _("failed retrieving file '%s' from %s : %s\n"), + filename, gethost(fileurl), fetchLastErrString); + ret = -1; + goto cleanup; + } + check_stop(); + + _alpm_log(PM_LOG_DEBUG, "ust.mtime: %ld local_time: %ld compare: %ld\n", + ust.mtime, local_time, local_time - ust.mtime); + _alpm_log(PM_LOG_DEBUG, "ust.size: %"PRId64" local_size: %"PRId64" compare: %"PRId64"\n", + ust.size, local_size, local_size - ust.size); + if(!force && ust.mtime && ust.mtime == local_time + && ust.size && ust.size == local_size) { + /* the remote time and size values agreed with what we have, so move on + * because there is nothing more to do. */ + _alpm_log(PM_LOG_DEBUG, "files are identical, skipping %s\n", filename); ret = 1; goto cleanup; } + if(!ust.mtime || ust.mtime != local_time) { + _alpm_log(PM_LOG_DEBUG, "mtimes were different or unavailable, downloading %s from beginning\n", filename); + fileurl->offset = 0; + } + + fetchLastErrCode = 0; + dlf = fetchGet(fileurl, ""); + check_stop(); if(fetchLastErrCode != 0 || dlf == NULL) { pm_errno = PM_ERR_LIBFETCH; @@ -189,17 +219,14 @@ static int download_internal(const char *url, const char *localpath, _alpm_log(PM_LOG_DEBUG, "connected to %s successfully\n", fileurl->host); } - if(ust.mtime && mtimenew) { - *mtimenew = ust.mtime; + if(localf && fileurl->offset == 0) { + _alpm_log(PM_LOG_WARNING, _("resuming download of %s not possible; starting over\n"), filename); + fclose(localf); + localf = NULL; + } else if(fileurl->offset) { + _alpm_log(PM_LOG_DEBUG, "resuming download at position %"PRId64"\n", fileurl->offset); } - if(chk_resume && fileurl->offset == 0) { - _alpm_log(PM_LOG_WARNING, _("cannot resume download, starting over\n")); - if(localf != NULL) { - fclose(localf); - localf = NULL; - } - } if(localf == NULL) { _alpm_rmrf(tempfile); @@ -207,7 +234,9 @@ static int download_internal(const char *url, const char *localpath, dl_thisfile = 0; localf = fopen(tempfile, "wb"); if(localf == NULL) { /* still null? */ - _alpm_log(PM_LOG_ERROR, _("cannot write to file '%s'\n"), tempfile); + pm_errno = PM_ERR_RETRIEVE; + _alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"), + tempfile, strerror(errno)); ret = -1; goto cleanup; } @@ -219,15 +248,15 @@ static int download_internal(const char *url, const char *localpath, } while((nread = fetchIO_read(dlf, buffer, PM_DLBUF_LEN)) > 0) { + check_stop(); size_t nwritten = 0; - while(nwritten < nread) { - nwritten += fwrite(buffer, 1, (nread - nwritten), localf); - if(ferror(localf)) { - _alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"), - destfile, strerror(errno)); - ret = -1; - goto cleanup; - } + nwritten = fwrite(buffer, 1, nread, localf); + if((nwritten != nread) || ferror(localf)) { + pm_errno = PM_ERR_RETRIEVE; + _alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"), + tempfile, strerror(errno)); + ret = -1; + goto cleanup; } dl_thisfile += nread; @@ -262,36 +291,60 @@ static int download_internal(const char *url, const char *localpath, fetchIO_close(dlf); dlf = NULL; + /* set the times on the file to the same as that of the remote file */ + if(ust.mtime) { + struct timeval tv[2]; + memset(&tv, 0, sizeof(tv)); + tv[0].tv_sec = ust.atime; + tv[1].tv_sec = ust.mtime; + utimes(tempfile, tv); + } rename(tempfile, destfile); ret = 0; cleanup: - /* restore any existing SIGPIPE signal handler */ - sigaction(SIGPIPE, &old_action, NULL); - FREE(tempfile); FREE(destfile); if(localf != NULL) { + /* if we still had a local file open, we got interrupted. set the mtimes on + * the file accordingly. */ + fflush(localf); + if(ust.mtime) { + struct timeval tv[2]; + memset(&tv, 0, sizeof(tv)); + tv[0].tv_sec = ust.atime; + tv[1].tv_sec = ust.mtime; + futimes(fileno(localf), tv); + } fclose(localf); } if(dlf != NULL) { fetchIO_close(dlf); } fetchFreeURL(fileurl); + + /* restore the old signal handlers */ + sigaction(SIGINT, &sig_int[OLD], NULL); + sigaction(SIGPIPE, &sig_pipe[OLD], NULL); + /* if we were interrupted, trip the old handler */ + if(dload_interrupted) { + raise(SIGINT); + } + return(ret); } #endif static int download(const char *url, const char *localpath, - time_t mtimeold, time_t *mtimenew) { + int force) { if(handle->fetchcb == NULL) { #if defined(INTERNAL_DOWNLOAD) - return(download_internal(url, localpath, mtimeold, mtimenew)); + return(download_internal(url, localpath, force)); #else RET_ERR(PM_ERR_EXTERNAL_DOWNLOAD, -1); #endif } else { - int ret = handle->fetchcb(url, localpath, mtimeold, mtimenew); + int ret = handle->fetchcb(url, localpath, force); if(ret == -1) { RET_ERR(PM_ERR_EXTERNAL_DOWNLOAD, -1); } @@ -301,19 +354,15 @@ static int download(const char *url, const char *localpath, /* * Download a single file - * - if mtimeold is non-NULL, then only download the file if it's different - * than mtimeold. - * - if *mtimenew is non-NULL, it will be filled with the mtime of the remote - * file. * - servers must be a list of urls WITHOUT trailing slashes. * * RETURN: 0 for successful download - * 1 if the mtimes are identical + * 1 if the files are identical * -1 on error */ int _alpm_download_single_file(const char *filename, alpm_list_t *servers, const char *localpath, - time_t mtimeold, time_t *mtimenew) + int force) { alpm_list_t *i; int ret = -1; @@ -323,14 +372,14 @@ int _alpm_download_single_file(const char *filename, for(i = servers; i; i = i->next) { const char *server = i->data; char *fileurl = NULL; - int len; + size_t len; /* print server + filename into a buffer */ len = strlen(server) + strlen(filename) + 2; CALLOC(fileurl, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, -1)); snprintf(fileurl, len, "%s/%s", server, filename); - ret = download(fileurl, localpath, mtimeold, mtimenew); + ret = download(fileurl, localpath, force); FREE(fileurl); if(ret != -1) { break; @@ -349,7 +398,7 @@ int _alpm_download_files(alpm_list_t *files, for(lp = files; lp; lp = lp->next) { char *filename = lp->data; if(_alpm_download_single_file(filename, servers, - localpath, 0, NULL) == -1) { + localpath, 0) == -1) { ret++; } } @@ -376,7 +425,7 @@ char SYMEXPORT *alpm_fetch_pkgurl(const char *url) cachedir = _alpm_filecache_setup(); /* download the file */ - ret = download(url, cachedir, 0, NULL); + ret = download(url, cachedir, 0); if(ret == -1) { _alpm_log(PM_LOG_WARNING, _("failed to download %s\n"), url); return(NULL); diff --git a/lib/libalpm/dload.h b/lib/libalpm/dload.h index 64b57d27..ee800244 100644 --- a/lib/libalpm/dload.h +++ b/lib/libalpm/dload.h @@ -25,11 +25,11 @@ #include <time.h> -#define PM_DLBUF_LEN (1024 * 10) +#define PM_DLBUF_LEN (1024 * 16) int _alpm_download_single_file(const char *filename, alpm_list_t *servers, const char *localpath, - time_t mtimeold, time_t *mtimenew); + int force); int _alpm_download_files(alpm_list_t *files, alpm_list_t *servers, const char *localpath); diff --git a/lib/libalpm/error.c b/lib/libalpm/error.c index 81aaa8b1..ae19786e 100644 --- a/lib/libalpm/error.c +++ b/lib/libalpm/error.c @@ -117,8 +117,10 @@ const char SYMEXPORT *alpm_strerror(int err) return _("cannot remove all files for package"); case PM_ERR_PKG_INVALID_NAME: return _("package filename is not valid"); + case PM_ERR_PKG_INVALID_ARCH: + return _("package architecture is not valid"); case PM_ERR_PKG_REPO_NOT_FOUND: - return _("no such repository"); + return _("could not find repository for target"); /* Deltas */ case PM_ERR_DLT_INVALID: return _("invalid or corrupted delta"); diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c index d1a35ad9..5cbf363a 100644 --- a/lib/libalpm/handle.c +++ b/lib/libalpm/handle.c @@ -79,6 +79,7 @@ void _alpm_handle_free(pmhandle_t *handle) FREELIST(handle->cachedirs); FREE(handle->logfile); FREE(handle->lockfile); + FREE(handle->arch); FREELIST(handle->dbs_sync); FREELIST(handle->noupgrade); FREELIST(handle->noextract); @@ -168,7 +169,7 @@ const char SYMEXPORT *alpm_option_get_lockfile() return handle->lockfile; } -unsigned short SYMEXPORT alpm_option_get_usesyslog() +int SYMEXPORT alpm_option_get_usesyslog() { if (handle == NULL) { pm_errno = PM_ERR_HANDLE_NULL; @@ -213,13 +214,22 @@ alpm_list_t SYMEXPORT *alpm_option_get_ignoregrps() return handle->ignoregrp; } -unsigned short SYMEXPORT alpm_option_get_nopassiveftp() +const char SYMEXPORT *alpm_option_get_arch() +{ + if (handle == NULL) { + pm_errno = PM_ERR_HANDLE_NULL; + return NULL; + } + return handle->arch; +} + +int SYMEXPORT alpm_option_get_usedelta() { if (handle == NULL) { pm_errno = PM_ERR_HANDLE_NULL; return -1; } - return handle->nopassiveftp; + return handle->usedelta; } pmdb_t SYMEXPORT *alpm_option_get_localdb() @@ -436,7 +446,7 @@ int SYMEXPORT alpm_option_set_logfile(const char *logfile) return(0); } -void SYMEXPORT alpm_option_set_usesyslog(unsigned short usesyslog) +void SYMEXPORT alpm_option_set_usesyslog(int usesyslog) { handle->usesyslog = usesyslog; } @@ -529,12 +539,13 @@ int SYMEXPORT alpm_option_remove_ignoregrp(const char *grp) return(0); } -void SYMEXPORT alpm_option_set_nopassiveftp(unsigned short nopasv) +void SYMEXPORT alpm_option_set_arch(const char *arch) { - handle->nopassiveftp = nopasv; + if(handle->arch) FREE(handle->arch); + if(arch) handle->arch = strdup(arch); } -void SYMEXPORT alpm_option_set_usedelta(unsigned short usedelta) +void SYMEXPORT alpm_option_set_usedelta(int usedelta) { handle->usedelta = usedelta; } diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h index c7c262cf..a87d0fb2 100644 --- a/lib/libalpm/handle.h +++ b/lib/libalpm/handle.h @@ -57,9 +57,9 @@ typedef struct _pmhandle_t { alpm_list_t *ignoregrp; /* List of groups to ignore */ /* options */ - unsigned short usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */ - unsigned short nopassiveftp; /* Don't use PASV ftp connections */ - unsigned short usedelta; /* Download deltas if possible */ + int usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */ + char *arch; /* Architecture of packages we should allow */ + int usedelta; /* Download deltas if possible */ } pmhandle_t; /* global handle variable */ diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index 002b1c89..4ff04dab 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -295,7 +295,7 @@ alpm_list_t SYMEXPORT *alpm_pkg_get_groups(pmpkg_t *pkg) return pkg->groups; } -unsigned short SYMEXPORT alpm_pkg_has_force(pmpkg_t *pkg) +int SYMEXPORT alpm_pkg_has_force(pmpkg_t *pkg) { ALPM_LOG_FUNC; @@ -423,13 +423,6 @@ alpm_list_t SYMEXPORT *alpm_pkg_get_backup(pmpkg_t *pkg) return pkg->backup; } -alpm_list_t SYMEXPORT *alpm_pkg_get_removes(pmpkg_t *pkg) -{ - ASSERT(pkg != NULL, return(NULL)); - - return(pkg->removes); -} - pmdb_t SYMEXPORT *alpm_pkg_get_db(pmpkg_t *pkg) { /* Sanity checks */ @@ -548,7 +541,7 @@ int SYMEXPORT alpm_pkg_changelog_close(const pmpkg_t *pkg, void *fp) return(ret); } -unsigned short SYMEXPORT alpm_pkg_has_scriptlet(pmpkg_t *pkg) +int SYMEXPORT alpm_pkg_has_scriptlet(pmpkg_t *pkg) { ALPM_LOG_FUNC; @@ -580,7 +573,7 @@ alpm_list_t SYMEXPORT *alpm_pkg_compute_requiredby(pmpkg_t *pkg) } pmpkg_t *cachepkg = i->data; if(_alpm_dep_edge(cachepkg, pkg)) { - const char *cachepkgname = alpm_pkg_get_name(cachepkg); + const char *cachepkgname = cachepkg->name; reqs = alpm_list_add(reqs, strdup(cachepkgname)); } } @@ -858,7 +851,11 @@ void _alpm_pkg_free(pmpkg_t *pkg) FREE(pkg); } -/* Free transaction specific fields */ +/* This function should be used when removing a target from upgrade/sync target list + * Case 1: If pkg is a loaded package file (PKG_FROM_FILE), it will be freed. + * Case 2: If pkg is a pkgcache entry (PKG_FROM_CACHE), it won't be freed, + * only the transaction specific fields of pkg will be freed. + */ void _alpm_pkg_free_trans(pmpkg_t *pkg) { ALPM_LOG_FUNC; @@ -867,6 +864,11 @@ void _alpm_pkg_free_trans(pmpkg_t *pkg) return; } + if(pkg->origin == PKG_FROM_FILE) { + _alpm_pkg_free(pkg); + return; + } + alpm_list_free(pkg->removes); pkg->removes = NULL; } @@ -894,7 +896,7 @@ int _alpm_pkg_cmp(const void *p1, const void *p2) { pmpkg_t *pkg1 = (pmpkg_t *)p1; pmpkg_t *pkg2 = (pmpkg_t *)p2; - return(strcmp(alpm_pkg_get_name(pkg1), alpm_pkg_get_name(pkg2))); + return(strcmp(pkg1->name, pkg2->name)); } /* Test for existence of a package in a alpm_list_t* @@ -913,7 +915,7 @@ pmpkg_t *_alpm_pkg_find(alpm_list_t *haystack, const char *needle) for(lp = haystack; lp; lp = lp->next) { pmpkg_t *info = lp->data; - if(info && strcmp(alpm_pkg_get_name(info), needle) == 0) { + if(info && strcmp(info->name, needle) == 0) { return(info); } } diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h index aea3f394..b003b410 100644 --- a/lib/libalpm/package.h +++ b/lib/libalpm/package.h @@ -49,8 +49,8 @@ struct __pmpkg_t { off_t size; off_t isize; off_t download_size; - unsigned short scriptlet; - unsigned short force; + int scriptlet; + int force; pmpkgreason_t reason; alpm_list_t *licenses; alpm_list_t *replaces; diff --git a/lib/libalpm/po/LINGUAS b/lib/libalpm/po/LINGUAS index 5f661697..60193275 100644 --- a/lib/libalpm/po/LINGUAS +++ b/lib/libalpm/po/LINGUAS @@ -1,4 +1,5 @@ # Set of available languages. +ca cs de el diff --git a/lib/libalpm/po/ca.po b/lib/libalpm/po/ca.po new file mode 100644 index 00000000..05ee007a --- /dev/null +++ b/lib/libalpm/po/ca.po @@ -0,0 +1,569 @@ +# Translation of libpalm.po to Catalan +# Copyright (C) YEAR Pacman Development Team <pacman-dev@archlinux.org> +# This file is distributed under the same license as the PACKAGE package. +# +# Manuel Tortosa <manutortosa@gmail.com>, 2009. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: pacman-dev@archlinux.org\n" +"POT-Creation-Date: 2009-10-04 16:48+0200\n" +"PO-Revision-Date: 2009-11-15 23:05+0100\n" +"Last-Translator: Manuel Tortosa <manutortosa@gmail.com>\n" +"Language-Team: Catalan <kde-i18n-ca@kde.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.0\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#, c-format +msgid "replacing older version %s-%s by %s in target list\n" +msgstr "" +"s'està reemplaçant l'antiga versió %s-%s per %s en la llista " +"d'objectius\n" + +#, c-format +msgid "skipping %s-%s because newer version %s is in target list\n" +msgstr "" +"s'ometrà %s-%s perquè la versió més nova %s és en la llista " +"d'objectius\n" + +#, c-format +msgid "conflicting packages were found in target list\n" +msgstr "s'han trobat paquets conflictius en la llista d'objectius\n" + +#, c-format +msgid "you cannot install two conflicting packages at the same time\n" +msgstr "no podeu instal·lar dos paquets amb conflictes alhora\n" + +#, c-format +msgid "replacing packages with -U is not supported yet\n" +msgstr "no està implementat reemplaçar paquets amb -U\n" + +#, c-format +msgid "you can replace packages manually using -Rd and -U\n" +msgstr "podeu reemplaçar paquets manualment usant -Rd i -U\n" + +#, c-format +msgid "" +"directory permissions differ on %s\n" +"filesystem: %o package: %o\n" +msgstr "" +"els permisos del directori difereixen en %s\n" +"sistema de fitxers: %o paquet: %o\n" + +#, c-format +msgid "extract: not overwriting dir with file %s\n" +msgstr "extracció: no se sobreescriurà el directori amb el fitxer %s\n" + +#, c-format +msgid "extract: symlink %s does not point to dir\n" +msgstr "extracció: l'enllaç simbòlic %s no apunta al directori\n" + +#, c-format +msgid "could not extract %s (%s)\n" +msgstr "no es pot extreure %s (%s)\n" + +#, c-format +msgid "could not rename %s to %s (%s)\n" +msgstr "no es pot reanomenar %s a %s (%s)\n" + +#, c-format +msgid "%s saved as %s\n" +msgstr "%s desat com %s\n" + +#, c-format +msgid "could not install %s as %s (%s)\n" +msgstr "no es pot instal·lar %s com %s (%s)\n" + +#, c-format +msgid "%s installed as %s\n" +msgstr "%s instal·lat com %s\n" + +#, c-format +msgid "extracting %s as %s.pacnew\n" +msgstr "s'està extraient %s com %s.pacnew\n" + +#, c-format +msgid "could not get current working directory\n" +msgstr "no es pot obtenir el directori de treball actual\n" + +#, c-format +msgid "problem occurred while upgrading %s\n" +msgstr "ha ocorregut un problema en actualitzar %s\n" + +#, c-format +msgid "problem occurred while installing %s\n" +msgstr "ha ocorregut un problema en instal·lar %s\n" + +#, c-format +msgid "could not update database entry %s-%s\n" +msgstr "" +"no s'ha pogut actualitzar l'entrada de la base de dades %s-%s\n" + +#, c-format +msgid "could not add entry '%s' in cache\n" +msgstr "no s'ha pogut afegir l'entrada '%s' en la memòria cau\n" + +#, c-format +msgid "removing invalid database: %s\n" +msgstr "s'està eliminant la base de dades invàlida: %s\n" + +#, c-format +msgid "could not remove database %s\n" +msgstr "no s'ha pogut eliminar la base de dades %s\n" + +#, c-format +msgid "invalid name for database entry '%s'\n" +msgstr "nom invàlid per l'entrada de la base de dades '%s'\n" + +#, c-format +msgid "corrupted database entry '%s'\n" +msgstr "entrada de la base de dades corrupta '%s'\n" + +#, c-format +msgid "could not open file %s: %s\n" +msgstr "no es pot obrir el fitxer %s: %s\n" + +#, c-format +msgid "%s database is inconsistent: name mismatch on package %s\n" +msgstr "" +"la base de dades %s és inconsistent: nom erroni en el paquet %s\n" + +#, c-format +msgid "%s database is inconsistent: version mismatch on package %s\n" +msgstr "" +"la base de dades %s és inconsistent: versió errònia en el paquet %s\n" + +#, c-format +msgid "could not create directory %s: %s\n" +msgstr "no s'ha pogut crear el directori %s: %s\n" + +#, c-format +msgid "could not parse package description file in %s\n" +msgstr "" +"no s'ha pogut analitzar el fitxers de descripció de paquet en %s\n" + +#, c-format +msgid "missing package name in %s\n" +msgstr "falta nom de paquet en %s\n" + +#, c-format +msgid "missing package version in %s\n" +msgstr "falta versió de paquet en %s\n" + +#, c-format +msgid "error while reading package %s: %s\n" +msgstr "error en llegir paquet %s: %s\n" + +#, c-format +msgid "missing package metadata in %s\n" +msgstr "falten les metadades del paquet en %s\n" + +#, c-format +msgid "attempt to re-register the 'local' DB\n" +msgstr "intent de re-registre de la BD 'local'\n" + +#, c-format +msgid "database path is undefined\n" +msgstr "no s'ha definit la ruta de la base de dades\n" + +#, c-format +msgid "dependency cycle detected:\n" +msgstr "s'ha detectat una dependència cíclica:\n" + +#, c-format +msgid "%s will be removed after its %s dependency\n" +msgstr "%s serà eliminat després de la seva dependència %s\n" + +#, c-format +msgid "%s will be installed before its %s dependency\n" +msgstr "%s serà instal·lar abans de la seva dependència %s\n" + +#, c-format +msgid "ignoring package %s-%s\n" +msgstr "s'està ignorant paquet %s-%s\n" + +#, c-format +msgid "provider package was selected (%s provides %s)\n" +msgstr "s'ha seleccionat un paquet proveïdor (%s proveeix %s)\n" + +#, c-format +msgid "cannot resolve \"%s\", a dependency of \"%s\"\n" +msgstr "no es pot resoldre \"%s\", una dependència de \"%s\"\n" + +#, c-format +msgid "url '%s' is invalid\n" +msgstr "l'url '%s' és invàlid\n" + +#, c-format +msgid "url scheme not specified, assuming HTTP\n" +msgstr "no s'ha especificat l'esquema url, s'està assumint HTTP\n" + +#, c-format +msgid "disk" +msgstr "disc" + +#, c-format +msgid "failed retrieving file '%s' from %s : %s\n" +msgstr "ha fallat en recuperar el fitxer '%s' des de %s : %s\n" + +#, c-format +msgid "cannot resume download, starting over\n" +msgstr "no es pot la reprendre la baixada, s'està iniciant de nou\n" + +#, c-format +msgid "cannot write to file '%s'\n" +msgstr "no s'ha pogut escriure al fitxer '%s'\n" + +#, c-format +msgid "error writing to file '%s': %s\n" +msgstr "error en escriure al fitxer '%s': %s\n" + +#, c-format +msgid "failed retrieving file '%s' from %s\n" +msgstr "ha fallat en recuperar el fitxer '%s' de %s\n" + +#, c-format +msgid "%s appears to be truncated: %jd/%jd bytes\n" +msgstr "%s sembla estar truncat: %jd/%jd bytes\n" + +#, c-format +msgid "failed to download %s\n" +msgstr "ha fallat en baixar %s\n" + +#, c-format +msgid "out of memory!" +msgstr "memòria esgotada!" + +#, c-format +msgid "unexpected system error" +msgstr "error inesperat del sistema" + +#, c-format +msgid "insufficient privileges" +msgstr "privilegis insuficients" + +#, c-format +msgid "could not find or read file" +msgstr "no es pot trobar o llegir fitxer" + +#, c-format +msgid "could not find or read directory" +msgstr "no es pot trobar o llegir directori" + +#, c-format +msgid "wrong or NULL argument passed" +msgstr "s'ha passat un argument erroni o NULL" + +#, c-format +msgid "library not initialized" +msgstr "llibreria no inicialitzada" + +#, c-format +msgid "library already initialized" +msgstr "la llibreria ja s'ha inicialitzat" + +#, c-format +msgid "unable to lock database" +msgstr "no s'ha pogut bloquejar la base de dades" + +#, c-format +msgid "could not open database" +msgstr "no s'ha pogut obrir la base de dades" + +#, c-format +msgid "could not create database" +msgstr "no s'ha pogut crear la base de dades" + +#, c-format +msgid "database not initialized" +msgstr "base de dades no inicialitzada" + +#, c-format +msgid "database already registered" +msgstr "la base de dades ja s'ha registrat" + +#, c-format +msgid "could not find database" +msgstr "no s'ha pogut trobar la base de dades" + +#, c-format +msgid "could not update database" +msgstr "no s'ha pogut actualitzar la base de dades" + +#, c-format +msgid "could not remove database entry" +msgstr "no s'ha pogut suprimir l'entrada de la base de dades" + +#, c-format +msgid "invalid url for server" +msgstr "url del servidor invàlid" + +#, c-format +msgid "no servers configured for repository" +msgstr "no s'ha configurat cap servidor pel repositori" + +#, c-format +msgid "transaction already initialized" +msgstr "ja s'ha inicialitzat la transacció" + +#, c-format +msgid "transaction not initialized" +msgstr "no s'ha inicialitzat la transacció" + +#, c-format +msgid "duplicate target" +msgstr "objectiu duplicat" + +#, c-format +msgid "transaction not prepared" +msgstr "transacció no preparada" + +#, c-format +msgid "transaction aborted" +msgstr "transacció cancel·lada" + +#, c-format +msgid "operation not compatible with the transaction type" +msgstr "l'operació no és compatible amb el tipus de transacció" + +#, c-format +msgid "transaction commit attempt when database is not locked" +msgstr "" +"intent de publicació de la transacció amb la base de dades no " +"bloquejada" + +#, c-format +msgid "could not find or read package" +msgstr "no s'ha pogut trobar o llegir el paquet" + +#, c-format +msgid "operation cancelled due to ignorepkg" +msgstr "operació cancel·lada degut a ignorepkg" + +#, c-format +msgid "invalid or corrupted package" +msgstr "paquet invàlid o corrupte" + +#, c-format +msgid "cannot open package file" +msgstr "no s'ha pogut obrir el fitxer de paquet" + +#, c-format +msgid "cannot remove all files for package" +msgstr "no s'han pogut eliminar tots els fitxers del paquet" + +#, c-format +msgid "package filename is not valid" +msgstr "el nom de fitxer del paquet no és vàlid" + +#, c-format +msgid "no such repository" +msgstr "no existeix aquest repositori" + +#, c-format +msgid "invalid or corrupted delta" +msgstr "delta invàlid o corrupte" + +#, c-format +msgid "delta patch failed" +msgstr "ha fallat el pedaç delta" + +#, c-format +msgid "could not satisfy dependencies" +msgstr "no s'han pogut satisfer les dependències" + +#, c-format +msgid "conflicting dependencies" +msgstr "dependències conflictives" + +#, c-format +msgid "conflicting files" +msgstr "fitxers conflictius" + +#, c-format +msgid "failed to retrieve some files" +msgstr "ha fallat en recuperar alguns fitxers" + +#, c-format +msgid "invalid regular expression" +msgstr "expressió regular invàlida" + +#, c-format +msgid "libarchive error" +msgstr "error de libarchive" + +#, c-format +msgid "download library error" +msgstr "error de la llibreria de baixades" + +#, c-format +msgid "error invoking external downloader" +msgstr "error en invocar el baixador extern" + +#, c-format +msgid "unexpected error" +msgstr "error inesperat" + +#, c-format +msgid "could not find %s in database -- skipping\n" +msgstr "no s'ha pogut trobar %s en la base de dades -- s'està ometent\n" + +#, c-format +msgid "removing %s from target list\n" +msgstr "s'està eliminant %s de la llista d'objectius\n" + +#, c-format +msgid "cannot remove file '%s': %s\n" +msgstr "no s'ha pogut eliminar el fitxer '%s': %s\n" + +#, c-format +msgid "could not remove database entry %s-%s\n" +msgstr "no s'ha pogut eliminar la entrada de la base de dades %s-%s\n" + +#, c-format +msgid "could not remove entry '%s' from cache\n" +msgstr "no s'ha pogut eliminar l'entrada '%s' de la memòria cau\n" + +#, c-format +msgid "%s: ignoring package upgrade (%s => %s)\n" +msgstr "%s: s'ha ignorat l'actualització del paquet (%s => %s)\n" + +#, c-format +msgid "%s: ignoring package downgrade (%s => %s)\n" +msgstr "%s: s'ha ignorat la desactualització del paquet (%s => %s)\n" + +#, c-format +msgid "%s: downgrading from version %s to version %s\n" +msgstr "%s: desactualitzant de la versió %s a la versió %s\n" + +#, c-format +msgid "%s: local (%s) is newer than %s (%s)\n" +msgstr "%s: local (%s) és més nou que %s (%s)\n" + +#, c-format +msgid "ignoring package replacement (%s-%s => %s-%s)\n" +msgstr "s'està ignorant el reemplaçament del paquet (%s-%s => %s-%s)\n" + +#, c-format +msgid "cannot replace %s by %s\n" +msgstr "no s'ha pogut reemplaçar %s per %s\n" + +#, c-format +msgid "repository '%s' not found\n" +msgstr "no s'ha trobat el repositori '%s'\n" + +#, c-format +msgid "%s-%s is up to date -- skipping\n" +msgstr "%s-%s és al dia -- s'ignorarà\n" + +#, c-format +msgid "%s-%s is up to date -- reinstalling\n" +msgstr "%s-%s és al dia -- es reinstal·larà\n" + +#, c-format +msgid "downgrading package %s (%s => %s)\n" +msgstr "desactualitzant paquet %s (%s => %s)\n" + +#, c-format +msgid "unresolvable package conflicts detected\n" +msgstr "" +"s'ha detectat un paquet amb un conflicte impossible de resoldre\n" + +#, c-format +msgid "removing '%s' from target list because it conflicts with '%s'\n" +msgstr "" +"s'està eliminant '%s' de la llista d'objectius perquè té conflictes " +"amb '%s'\n" + +#, c-format +msgid "failed to retrieve some files from %s\n" +msgstr "ha fallat en recuperar alguns fitxers de %s\n" + +#, c-format +msgid "could not create removal transaction\n" +msgstr "no s'ha pogut crear la transacció d'eliminació\n" + +#, c-format +msgid "could not create transaction\n" +msgstr "no s'ha pogut crear la transacció\n" + +#, c-format +msgid "could not initialize the removal transaction\n" +msgstr "no s'ha pogut inicialitzar la transacció d'eliminació\n" + +#, c-format +msgid "could not initialize transaction\n" +msgstr "no s'ha pogut inicialitzar la transacció\n" + +#, c-format +msgid "could not prepare removal transaction\n" +msgstr "no s'ha pogut preparar la transacció d'eliminació\n" + +#, c-format +msgid "could not commit removal transaction\n" +msgstr "no s'ha pogut publicar la transacció d'eliminació\n" + +#, c-format +msgid "could not commit transaction\n" +msgstr "no s'ha pogut publicar la transacció\n" + +#, c-format +msgid "could not remove lock file %s\n" +msgstr "no s'ha pogut eliminar el fitxer de bloqueig %s\n" + +#, c-format +msgid "could not create temp directory\n" +msgstr "no s'ha pogut crear el directori temporal\n" + +#, c-format +msgid "could not copy tempfile to %s (%s)\n" +msgstr "no s'ha pogut copiar el fitxer temporal a %s (%s)\n" + +#, c-format +msgid "could not remove tmpdir %s\n" +msgstr "no s'ha pogut eliminar el directori temporal %s\n" + +#, c-format +msgid "could not open %s: %s\n" +msgstr "no s'ha pogut obrir %s: %s\n" + +#, c-format +msgid "could not change directory to %s (%s)\n" +msgstr "no s'ha pogut canviar el directori a %s (%s)\n" + +#, c-format +msgid "could not fork a new process (%s)\n" +msgstr "no s'ha pogut bifurcar a un nou procés (%s)\n" + +#, c-format +msgid "could not change the root directory (%s)\n" +msgstr "no s'ha pogut canviar el directori arrel (%s)\n" + +#, c-format +msgid "could not change directory to / (%s)\n" +msgstr "no s'ha pogut canviar el directori a / (%s)\n" + +#, c-format +msgid "call to popen failed (%s)\n" +msgstr "ha fallat la crida a popen (%s)\n" + +#, c-format +msgid "call to waitpid failed (%s)\n" +msgstr "ha fallat la crida a waitpid (%s)\n" + +#, c-format +msgid "command failed to execute correctly\n" +msgstr "l'ordre a fallat a executar-se correctament\n" + +#, c-format +msgid "no %s cache exists, creating...\n" +msgstr "no existeix memòria cau %s, s'està creant...\n" + +#, c-format +msgid "couldn't create package cache, using /tmp instead\n" +msgstr "no s'ha pogut crear la memòria cau del paquet, s'usarà /tmp\n" + + diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c index 1e8f9156..80eec67f 100644 --- a/lib/libalpm/remove.c +++ b/lib/libalpm/remove.c @@ -47,35 +47,45 @@ #include "handle.h" #include "alpm.h" -int _alpm_remove_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name) +int SYMEXPORT alpm_remove_target(char *target) { pmpkg_t *info; - const char *targ; + pmtrans_t *trans; + pmdb_t *db_local; + alpm_list_t *p; ALPM_LOG_FUNC; - ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); + /* Sanity checks */ + ASSERT(target != NULL && strlen(target) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + trans = handle->trans; + db_local = handle->db_local; ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(name != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); + ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - targ = strchr(name, '/'); - if(targ && strncmp(name, "local", 5) == 0) { - targ++; - } else { - targ = name; - } - if(_alpm_pkg_find(trans->packages, targ)) { + if(_alpm_pkg_find(trans->remove, target)) { RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1); } - if((info = _alpm_db_get_pkgfromcache(db, targ)) == NULL) { - _alpm_log(PM_LOG_DEBUG, "could not find %s in database\n", targ); - RET_ERR(PM_ERR_PKG_NOT_FOUND, -1); + if((info = _alpm_db_get_pkgfromcache(db_local, target)) != NULL) { + _alpm_log(PM_LOG_DEBUG, "adding %s in the target list\n", info->name); + trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(info)); + return(0); } - _alpm_log(PM_LOG_DEBUG, "adding %s in target list\n", info->name); - trans->packages = alpm_list_add(trans->packages, _alpm_pkg_dup(info)); + _alpm_log(PM_LOG_DEBUG, "could not find %s in database\n", target); + pmgrp_t *grp = alpm_db_readgrp(db_local, target); + if(grp == NULL) { + RET_ERR(PM_ERR_PKG_NOT_FOUND, -1); + } + for(p = alpm_grp_get_pkgs(grp); p; p = alpm_list_next(p)) { + pmpkg_t *pkg = alpm_list_getdata(p); + _alpm_log(PM_LOG_DEBUG, "adding %s in the target list\n", pkg->name); + trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(pkg)); + } return(0); } @@ -91,10 +101,10 @@ static void remove_prepare_cascade(pmtrans_t *trans, pmdb_t *db, pmdepmissing_t *miss = (pmdepmissing_t *)i->data; pmpkg_t *info = _alpm_db_get_pkgfromcache(db, miss->target); if(info) { - if(!_alpm_pkg_find(trans->packages, alpm_pkg_get_name(info))) { + if(!_alpm_pkg_find(trans->remove, alpm_pkg_get_name(info))) { _alpm_log(PM_LOG_DEBUG, "pulling %s in target list\n", alpm_pkg_get_name(info)); - trans->packages = alpm_list_add(trans->packages, _alpm_pkg_dup(info)); + trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(info)); } } else { _alpm_log(PM_LOG_ERROR, _("could not find %s in database -- skipping\n"), @@ -103,7 +113,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(_alpm_db_get_pkgcache(db), 1, trans->packages, NULL); + lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->remove, NULL); } } @@ -118,11 +128,11 @@ static void remove_prepare_keep_needed(pmtrans_t *trans, pmdb_t *db, for(i = lp; i; i = i->next) { pmdepmissing_t *miss = (pmdepmissing_t *)i->data; void *vpkg; - pmpkg_t *pkg = _alpm_pkg_find(trans->packages, miss->causingpkg); + pmpkg_t *pkg = _alpm_pkg_find(trans->remove, miss->causingpkg); if(pkg == NULL) { continue; } - trans->packages = alpm_list_remove(trans->packages, pkg, _alpm_pkg_cmp, + trans->remove = alpm_list_remove(trans->remove, pkg, _alpm_pkg_cmp, &vpkg); pkg = vpkg; if(pkg) { @@ -133,7 +143,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(_alpm_db_get_pkgcache(db), 1, trans->packages, NULL); + lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->remove, NULL); } } @@ -146,21 +156,16 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data) ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - /* skip all checks if we are doing this removal as part of an upgrade */ - if(trans->type == PM_TRANS_TYPE_REMOVEUPGRADE) { - return(0); - } - if((trans->flags & PM_TRANS_FLAG_RECURSE) && !(trans->flags & PM_TRANS_FLAG_CASCADE)) { _alpm_log(PM_LOG_DEBUG, "finding removable dependencies\n"); - _alpm_recursedeps(db, trans->packages, trans->flags & PM_TRANS_FLAG_RECURSEALL); + _alpm_recursedeps(db, trans->remove, trans->flags & PM_TRANS_FLAG_RECURSEALL); } if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { EVENT(trans, PM_TRANS_EVT_CHECKDEPS_START, NULL, NULL); _alpm_log(PM_LOG_DEBUG, "looking for unsatisfied dependencies\n"); - lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->packages, NULL); + lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->remove, NULL); if(lp != NULL) { if(trans->flags & PM_TRANS_FLAG_CASCADE) { @@ -183,15 +188,15 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data) /* re-order w.r.t. dependencies */ _alpm_log(PM_LOG_DEBUG, "sorting by dependencies\n"); - lp = _alpm_sortbydeps(trans->packages, 1); + lp = _alpm_sortbydeps(trans->remove, 1); /* free the old alltargs */ - alpm_list_free(trans->packages); - trans->packages = lp; + alpm_list_free(trans->remove); + trans->remove = lp; /* -Rcs == -Rc then -Rs */ if((trans->flags & PM_TRANS_FLAG_CASCADE) && (trans->flags & PM_TRANS_FLAG_RECURSE)) { _alpm_log(PM_LOG_DEBUG, "finding removable dependencies\n"); - _alpm_recursedeps(db, trans->packages, trans->flags & PM_TRANS_FLAG_RECURSEALL); + _alpm_recursedeps(db, trans->remove, trans->flags & PM_TRANS_FLAG_RECURSEALL); } if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { @@ -201,13 +206,13 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data) return(0); } -static int can_remove_file(pmtrans_t *trans, const char *path) +static int can_remove_file(const char *path, alpm_list_t *skip) { char file[PATH_MAX+1]; snprintf(file, PATH_MAX, "%s%s", handle->root, path); - if(alpm_list_find_str(trans->skip_remove, file)) { + if(alpm_list_find_str(skip, file)) { /* return success because we will never actually remove this file */ return(1); } @@ -228,7 +233,7 @@ static int can_remove_file(pmtrans_t *trans, const char *path) /* Helper function for iterating through a package's file and deleting them * Used by _alpm_remove_commit. */ -static void unlink_file(pmpkg_t *info, char *filename, pmtrans_t *trans) +static void unlink_file(pmpkg_t *info, char *filename, alpm_list_t *skip_remove, int nosave) { struct stat buf; char file[PATH_MAX+1]; @@ -237,13 +242,13 @@ static void unlink_file(pmpkg_t *info, char *filename, pmtrans_t *trans) snprintf(file, PATH_MAX, "%s%s", handle->root, filename); - if(trans->type == PM_TRANS_TYPE_REMOVEUPGRADE) { - /* check noupgrade */ - if(alpm_list_find_str(handle->noupgrade, filename)) { - _alpm_log(PM_LOG_DEBUG, "Skipping removal of '%s' due to NoUpgrade\n", - file); - return; - } + /* check the remove skip list before removing the file. + * see the big comment block in db_find_fileconflicts() for an + * explanation. */ + if(alpm_list_find_str(skip_remove, filename)) { + _alpm_log(PM_LOG_DEBUG, "%s is in skip_remove, skipping removal\n", + file); + return; } /* we want to do a lstat here, and not a _alpm_lstat. @@ -263,19 +268,10 @@ static void unlink_file(pmpkg_t *info, char *filename, pmtrans_t *trans) _alpm_log(PM_LOG_DEBUG, "removing directory %s\n", file); } } else { - /* check the remove skip list before removing the file. - * see the big comment block in db_find_fileconflicts() for an - * explanation. */ - if(alpm_list_find_str(trans->skip_remove, file)) { - _alpm_log(PM_LOG_DEBUG, "%s is in trans->skip_remove, skipping removal\n", - file); - return; - } - /* if the file needs backup and has been modified, back it up to .pacsave */ char *pkghash = _alpm_needbackup(filename, alpm_pkg_get_backup(info)); if(pkghash) { - if(trans->flags & PM_TRANS_FLAG_NOSAVE) { + if(nosave) { _alpm_log(PM_LOG_DEBUG, "transaction is set to NOSAVE, not backing up '%s'\n", file); FREE(pkghash); } else { @@ -303,7 +299,69 @@ static void unlink_file(pmpkg_t *info, char *filename, pmtrans_t *trans) } } -int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db) +int _alpm_upgraderemove_package(pmpkg_t *oldpkg, pmpkg_t *newpkg, pmtrans_t *trans) +{ + alpm_list_t *skip_remove, *b; + alpm_list_t *newfiles, *lp; + alpm_list_t *files = alpm_pkg_get_files(oldpkg); + const char *pkgname = alpm_pkg_get_name(oldpkg); + + ALPM_LOG_FUNC; + + _alpm_log(PM_LOG_DEBUG, "removing old package first (%s-%s)\n", + oldpkg->name, oldpkg->version); + + /* copy the remove skiplist over */ + skip_remove = + alpm_list_join(alpm_list_strdup(trans->skip_remove),alpm_list_strdup(handle->noupgrade)); + /* Add files in the NEW backup array to the skip_remove array + * so this removal operation doesn't kill them */ + /* old package backup list */ + alpm_list_t *filelist = alpm_pkg_get_files(newpkg); + for(b = alpm_pkg_get_backup(newpkg); b; b = b->next) { + char *backup = _alpm_backup_file(b->data); + /* safety check (fix the upgrade026 pactest) */ + if(!alpm_list_find_str(filelist, backup)) { + FREE(backup); + continue; + } + _alpm_log(PM_LOG_DEBUG, "adding %s to the skip_remove array\n", backup); + skip_remove = alpm_list_add(skip_remove, backup); + } + + for(lp = files; lp; lp = lp->next) { + if(!can_remove_file(lp->data, skip_remove)) { + _alpm_log(PM_LOG_DEBUG, "not removing package '%s', can't remove all files\n", + pkgname); + RET_ERR(PM_ERR_PKG_CANT_REMOVE, -1); + } + } + + /* iterate through the list backwards, unlinking files */ + newfiles = alpm_list_reverse(files); + for(lp = newfiles; lp; lp = alpm_list_next(lp)) { + unlink_file(oldpkg, lp->data, skip_remove, 0); + } + alpm_list_free(newfiles); + FREELIST(skip_remove); + + /* remove the package from the database */ + _alpm_log(PM_LOG_DEBUG, "updating database\n"); + _alpm_log(PM_LOG_DEBUG, "removing database entry '%s'\n", pkgname); + if(_alpm_db_remove(handle->db_local, oldpkg) == -1) { + _alpm_log(PM_LOG_ERROR, _("could not remove database entry %s-%s\n"), + pkgname, alpm_pkg_get_version(oldpkg)); + } + /* remove the package from the cache */ + if(_alpm_db_remove_pkgfromcache(handle->db_local, oldpkg) == -1) { + _alpm_log(PM_LOG_ERROR, _("could not remove entry '%s' from cache\n"), + pkgname); + } + + return(0); +} + +int _alpm_remove_packages(pmtrans_t *trans, pmdb_t *db) { pmpkg_t *info; alpm_list_t *targ, *lp; @@ -314,14 +372,14 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db) ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - pkg_count = alpm_list_count(trans->packages); + pkg_count = alpm_list_count(trans->remove); - for(targ = trans->packages; targ; targ = targ->next) { + for(targ = trans->remove; targ; targ = targ->next) { int position = 0; char scriptlet[PATH_MAX]; - alpm_list_t *files; info = (pmpkg_t*)targ->data; const char *pkgname = NULL; + int targcount = alpm_list_count(targ); if(handle->trans->state == STATE_INTERRUPTED) { return(0); @@ -329,26 +387,23 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db) /* get the name now so we can use it after package is removed */ pkgname = alpm_pkg_get_name(info); - snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", db->path, - pkgname, alpm_pkg_get_version(info)); - - if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) { - EVENT(trans, PM_TRANS_EVT_REMOVE_START, info, NULL); - _alpm_log(PM_LOG_DEBUG, "removing package %s-%s\n", - pkgname, alpm_pkg_get_version(info)); - - /* run the pre-remove scriptlet if it exists */ - if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { - _alpm_runscriptlet(handle->root, scriptlet, "pre_remove", - alpm_pkg_get_version(info), NULL, trans); - } - } + snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", + _alpm_db_path(db), pkgname, alpm_pkg_get_version(info)); - files = alpm_pkg_get_files(info); + EVENT(trans, PM_TRANS_EVT_REMOVE_START, info, NULL); + _alpm_log(PM_LOG_DEBUG, "removing package %s-%s\n", + pkgname, alpm_pkg_get_version(info)); + + /* run the pre-remove scriptlet if it exists */ + if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { + _alpm_runscriptlet(handle->root, scriptlet, "pre_remove", + alpm_pkg_get_version(info), NULL, trans); + } if(!(trans->flags & PM_TRANS_FLAG_DBONLY)) { + alpm_list_t *files = alpm_pkg_get_files(info); for(lp = files; lp; lp = lp->next) { - if(!can_remove_file(trans, lp->data)) { + if(!can_remove_file(lp->data, NULL)) { _alpm_log(PM_LOG_DEBUG, "not removing package '%s', can't remove all files\n", pkgname); RET_ERR(PM_ERR_PKG_CANT_REMOVE, -1); @@ -356,20 +411,20 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db) } int filenum = alpm_list_count(files); - double percent = 0.0; alpm_list_t *newfiles; _alpm_log(PM_LOG_DEBUG, "removing %d files\n", filenum); /* iterate through the list backwards, unlinking files */ newfiles = alpm_list_reverse(files); for(lp = newfiles; lp; lp = alpm_list_next(lp)) { - unlink_file(info, lp->data, trans); + double percent; + unlink_file(info, lp->data, NULL, trans->flags & PM_TRANS_FLAG_NOSAVE); /* update progress bar after each file */ percent = (double)position / (double)filenum; PROGRESS(trans, PM_TRANS_PROGRESS_REMOVE_START, info->name, (double)(percent * 100), pkg_count, - (pkg_count - alpm_list_count(targ) + 1)); + (pkg_count - targcount + 1)); position++; } alpm_list_free(newfiles); @@ -377,14 +432,12 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db) /* set progress to 100% after we finish unlinking files */ PROGRESS(trans, PM_TRANS_PROGRESS_REMOVE_START, pkgname, 100, - pkg_count, (pkg_count - alpm_list_count(targ) + 1)); + pkg_count, (pkg_count - targcount + 1)); - if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) { - /* run the post-remove script if it exists */ - if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { - _alpm_runscriptlet(handle->root, scriptlet, "post_remove", - alpm_pkg_get_version(info), NULL, trans); - } + /* run the post-remove script if it exists */ + if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { + _alpm_runscriptlet(handle->root, scriptlet, "post_remove", + alpm_pkg_get_version(info), NULL, trans); } /* remove the package from the database */ @@ -400,16 +453,11 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db) pkgname); } - /* call a done event if this isn't an upgrade */ - if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) { - EVENT(trans, PM_TRANS_EVT_REMOVE_DONE, info, NULL); - } + EVENT(trans, PM_TRANS_EVT_REMOVE_DONE, info, NULL); } /* run ldconfig if it exists */ - if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) { - _alpm_ldconfig(handle->root); - } + _alpm_ldconfig(handle->root); return(0); } diff --git a/lib/libalpm/remove.h b/lib/libalpm/remove.h index 716fbf72..fbbaa169 100644 --- a/lib/libalpm/remove.h +++ b/lib/libalpm/remove.h @@ -24,9 +24,10 @@ #include "alpm_list.h" #include "trans.h" -int _alpm_remove_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name); int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data); -int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db); +int _alpm_remove_packages(pmtrans_t *trans, pmdb_t *db); + +int _alpm_upgraderemove_package(pmpkg_t *oldpkg, pmpkg_t *newpkg, pmtrans_t *trans); #endif /* _ALPM_REMOVE_H */ diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index 47639248..2cdcd47b 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -43,11 +43,13 @@ #include "deps.h" #include "conflict.h" #include "trans.h" +#include "add.h" #include "util.h" #include "handle.h" #include "alpm.h" #include "dload.h" #include "delta.h" +#include "remove.h" /** Check for new version of pkg in sync repos * (only the first occurrence is considered in sync) @@ -80,17 +82,30 @@ pmpkg_t SYMEXPORT *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync) return(NULL); } -int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, int enable_downgrade) +/** Search for packages to upgrade and add them to the transaction. + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int SYMEXPORT alpm_sync_sysupgrade(int enable_downgrade) { alpm_list_t *i, *j, *k; + pmtrans_t *trans; + pmdb_t *db_local; + alpm_list_t *dbs_sync; ALPM_LOG_FUNC; + ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + trans = handle->trans; + db_local = handle->db_local; + dbs_sync = handle->dbs_sync; + ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); + _alpm_log(PM_LOG_DEBUG, "checking for package upgrades\n"); for(i = _alpm_db_get_pkgcache(db_local); i; i = i->next) { pmpkg_t *lpkg = i->data; - if(_alpm_pkg_find(trans->packages, lpkg->name)) { + if(_alpm_pkg_find(trans->add, lpkg->name)) { _alpm_log(PM_LOG_DEBUG, "%s is already in the target list -- skipping\n", lpkg->name); continue; } @@ -113,7 +128,7 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s } else { _alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", spkg->name, spkg->version); - trans->packages = alpm_list_add(trans->packages, spkg); + trans->add = alpm_list_add(trans->add, spkg); } } else if(cmp < 0) { if(enable_downgrade) { @@ -124,7 +139,7 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s } else { _alpm_log(PM_LOG_WARNING, _("%s: downgrading from version %s to version %s\n"), lpkg->name, lpkg->version, spkg->version); - trans->packages = alpm_list_add(trans->packages, spkg); + trans->add = alpm_list_add(trans->add, spkg); } } else { _alpm_log(PM_LOG_WARNING, _("%s: local (%s) is newer than %s (%s)\n"), @@ -152,7 +167,7 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s } /* If spkg is already in the target list, we append lpkg to spkg's removes list */ - pmpkg_t *tpkg = _alpm_pkg_find(trans->packages, spkg->name); + pmpkg_t *tpkg = _alpm_pkg_find(trans->add, spkg->name); if(tpkg) { /* sanity check, multiple repos can contain spkg->name */ if(tpkg->origin_data.db != sdb) { @@ -173,7 +188,7 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s spkg->removes = alpm_list_add(NULL, lpkg); _alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", spkg->name, spkg->version); - trans->packages = alpm_list_add(trans->packages, spkg); + trans->add = alpm_list_add(trans->add, spkg); } } } @@ -187,57 +202,18 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s return(0); } -int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, char *name) +int _alpm_sync_pkg(pmpkg_t *spkg) { - char *targline; - char *targ; - alpm_list_t *j; - pmpkg_t *local, *spkg; - pmdepend_t *dep; /* provisions and dependencies are also allowed */ + pmtrans_t *trans; + pmdb_t *db_local; + pmpkg_t *local; ALPM_LOG_FUNC; - ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(name != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); - - STRDUP(targline, name, RET_ERR(PM_ERR_MEMORY, -1)); - targ = strchr(targline, '/'); - if(targ) { - /* we are looking for a package in a specific database */ - alpm_list_t *dbs = NULL; - *targ = '\0'; - targ++; - _alpm_log(PM_LOG_DEBUG, "searching for target '%s' in repo '%s'\n", targ, targline); - for(j = dbs_sync; j; j = j->next) { - pmdb_t *db = j->data; - if(strcmp(db->treename, targline) == 0) { - dbs = alpm_list_add(NULL, db); - break; - } - } - if(dbs == NULL) { - _alpm_log(PM_LOG_ERROR, _("repository '%s' not found\n"), targline); - FREE(targline); - RET_ERR(PM_ERR_PKG_REPO_NOT_FOUND, -1); - } - dep = _alpm_splitdep(targ); - 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, 1); - _alpm_dep_free(dep); - } - FREE(targline); - - if(spkg == NULL) { - /* pm_errno is set by _alpm_resolvedep */ - return(-1); - } + trans = handle->trans; + db_local = handle->db_local; - if(_alpm_pkg_find(trans->packages, alpm_pkg_get_name(spkg))) { + if(_alpm_pkg_find(trans->add, alpm_pkg_get_name(spkg))) { RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1); } @@ -267,11 +243,108 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy spkg->reason = PM_PKG_REASON_EXPLICIT; _alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", alpm_pkg_get_name(spkg), alpm_pkg_get_version(spkg)); - trans->packages = alpm_list_add(trans->packages, spkg); + trans->add = alpm_list_add(trans->add, spkg); + + return(0); +} + +int _alpm_sync_target(alpm_list_t *dbs_sync, char *target) +{ + alpm_list_t *i, *j; + pmpkg_t *spkg; + pmdepend_t *dep; /* provisions and dependencies are also allowed */ + pmgrp_t *grp; + int found = 0; + + ALPM_LOG_FUNC; + + /* Sanity checks */ + ASSERT(target != NULL && strlen(target) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + + dep = _alpm_splitdep(target); + spkg = _alpm_resolvedep(dep, dbs_sync, NULL, 1); + _alpm_dep_free(dep); + + if(spkg != NULL) { + return(_alpm_sync_pkg(spkg)); + } + + _alpm_log(PM_LOG_DEBUG, "%s package not found, searching for group...\n", target); + for(i = dbs_sync; i; i = i->next) { + pmdb_t *db = i->data; + grp = alpm_db_readgrp(db, target); + if(grp) { + found = 1; + for(j = alpm_grp_get_pkgs(grp); j; j = j->next) { + pmpkg_t *pkg = j->data; + if(_alpm_sync_pkg(pkg) == -1) { + if(pm_errno == PM_ERR_TRANS_DUP_TARGET || pm_errno == PM_ERR_PKG_IGNORED) { + /* just skip duplicate or ignored targets */ + continue; + } else { + return(-1); + } + } + } + } + } + + if(!found) { + RET_ERR(PM_ERR_PKG_NOT_FOUND, -1); + } return(0); } +/** Add a sync target to the transaction. + * @param target the name of the sync target to add + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int SYMEXPORT alpm_sync_dbtarget(char *dbname, char *target) +{ + alpm_list_t *i; + alpm_list_t *dbs_sync; + + ALPM_LOG_FUNC; + + /* Sanity checks */ + ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + dbs_sync = handle->dbs_sync; + + /* we are looking for a package in a specific database */ + alpm_list_t *dbs = NULL; + _alpm_log(PM_LOG_DEBUG, "searching for target '%s' in repo '%s'\n", target, dbname); + for(i = dbs_sync; i; i = i->next) { + pmdb_t *db = i->data; + if(strcmp(db->treename, dbname) == 0) { + dbs = alpm_list_add(NULL, db); + break; + } + } + if(dbs == NULL) { + RET_ERR(PM_ERR_PKG_REPO_NOT_FOUND, -1); + } + return(_alpm_sync_target(dbs, target)); +} + +/** Add a sync target to the transaction. + * @param target the name of the sync target to add + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int SYMEXPORT alpm_sync_target(char *target) +{ + alpm_list_t *dbs_sync; + + ALPM_LOG_FUNC; + + /* Sanity checks */ + ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + dbs_sync = handle->dbs_sync; + + return(_alpm_sync_target(dbs_sync,target)); +} + /** Compute the size of the files that will be downloaded to install a * package. * @param newpkg the new package to upgrade to @@ -282,6 +355,11 @@ static int compute_download_size(pmpkg_t *newpkg) char *fpath; off_t size = 0; + if(newpkg->origin == PKG_FROM_FILE) { + newpkg->download_size = 0; + return(0); + } + fname = alpm_pkg_get_filename(newpkg); ASSERT(fname != NULL, RET_ERR(PM_ERR_PKG_INVALID_NAME, -1)); fpath = _alpm_filecache_find(fname); @@ -321,10 +399,9 @@ static int compute_download_size(pmpkg_t *newpkg) int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **data) { alpm_list_t *deps = NULL; - alpm_list_t *preferred = NULL; alpm_list_t *unresolvable = NULL; - alpm_list_t *remove = NULL; /* allow checkdeps usage with trans->packages */ alpm_list_t *i, *j; + alpm_list_t *remove = NULL; int ret = 0; ALPM_LOG_FUNC; @@ -344,32 +421,29 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_START, NULL, NULL); _alpm_log(PM_LOG_DEBUG, "resolving target's dependencies\n"); - /* build remove list and preferred list for resolvedeps */ - for(i = trans->packages; i; i = i->next) { + /* build remove list for resolvedeps */ + for(i = trans->add; i; i = i->next) { pmpkg_t *spkg = i->data; for(j = spkg->removes; j; j = j->next) { remove = alpm_list_add(remove, j->data); } - preferred = alpm_list_add(preferred, spkg); } /* 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) { + for(i = trans->add; i; i = i->next) { pmpkg_t *pkg = i->data; - if(_alpm_resolvedeps(db_local, dbs_sync, pkg, preferred, + if(_alpm_resolvedeps(db_local, dbs_sync, pkg, trans->add, &resolved, remove, data) == -1) { unresolvable = alpm_list_add(unresolvable, pkg); } /* Else, [resolved] now additionally contains [pkg] and all of its dependencies not already on the list */ } - alpm_list_free(preferred); /* 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) { - unresolvable = alpm_list_remove_dupes(unresolvable); int remove_unresolvable = 0; QUESTION(handle->trans, PM_TRANS_CONV_REMOVE_PKGS, unresolvable, NULL, NULL, &remove_unresolvable); @@ -392,21 +466,21 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync } } - /* Unresolvable packages will be removed from the target list, so - we free the transaction specific fields */ - alpm_list_free_inner(unresolvable, (alpm_list_fn_free)_alpm_pkg_free_trans); - /* Set DEPEND reason for pulled packages */ for(i = resolved; i; i = i->next) { pmpkg_t *pkg = i->data; - if(!_alpm_pkg_find(trans->packages, pkg->name)) { + if(!_alpm_pkg_find(trans->add, pkg->name)) { pkg->reason = PM_PKG_REASON_DEPEND; } } + /* Unresolvable packages will be removed from the target list, so + we free the transaction specific fields */ + alpm_list_free_inner(unresolvable, (alpm_list_fn_free)_alpm_pkg_free_trans); + /* re-order w.r.t. dependencies */ - alpm_list_free(trans->packages); - trans->packages = _alpm_sortbydeps(resolved, 0); + alpm_list_free(trans->add); + trans->add = _alpm_sortbydeps(resolved, 0); alpm_list_free(resolved); EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_DONE, NULL, NULL); @@ -420,15 +494,15 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync /* 1. check for conflicts in the target list */ _alpm_log(PM_LOG_DEBUG, "check targets vs targets\n"); - deps = _alpm_innerconflicts(trans->packages); + deps = _alpm_innerconflicts(trans->add); for(i = deps; i; i = i->next) { pmconflict_t *conflict = i->data; pmpkg_t *rsync, *sync, *sync1, *sync2; /* have we already removed one of the conflicting targets? */ - sync1 = _alpm_pkg_find(trans->packages, conflict->package1); - sync2 = _alpm_pkg_find(trans->packages, conflict->package2); + sync1 = _alpm_pkg_find(trans->add, conflict->package1); + sync2 = _alpm_pkg_find(trans->add, conflict->package2); if(!sync1 || !sync2) { continue; } @@ -468,8 +542,8 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync _alpm_log(PM_LOG_WARNING, _("removing '%s' from target list because it conflicts with '%s'\n"), rsync->name, sync->name); + trans->add = alpm_list_remove(trans->add, rsync, _alpm_pkg_cmp, NULL); _alpm_pkg_free_trans(rsync); /* rsync is not transaction target anymore */ - trans->packages = alpm_list_remove(trans->packages, rsync, _alpm_pkg_cmp, NULL); continue; } @@ -479,7 +553,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync /* 2. we check for target vs db conflicts (and resolve)*/ _alpm_log(PM_LOG_DEBUG, "check targets vs db and db vs targets\n"); - deps = _alpm_outerconflicts(db_local, trans->packages); + deps = _alpm_outerconflicts(db_local, trans->add); for(i = deps; i; i = i->next) { pmconflict_t *conflict = i->data; @@ -487,7 +561,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync /* if conflict->package2 (the local package) is not elected for removal, we ask the user */ int found = 0; - for(j = trans->packages; j && !found; j = j->next) { + for(j = trans->add; j && !found; j = j->next) { pmpkg_t *spkg = j->data; if(_alpm_pkg_find(spkg->removes, conflict->package2)) { found = 1; @@ -500,11 +574,11 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync _alpm_log(PM_LOG_DEBUG, "package '%s' conflicts with '%s'\n", conflict->package1, conflict->package2); - pmpkg_t *sync = _alpm_pkg_find(trans->packages, conflict->package1); + pmpkg_t *sync = _alpm_pkg_find(trans->add, conflict->package1); pmpkg_t *local = _alpm_db_get_pkgfromcache(db_local, conflict->package2); int doremove = 0; QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, conflict->package1, - conflict->package2, NULL, &doremove); + conflict->package2, conflict->reason, &doremove); if(doremove) { /* append to the removes list */ _alpm_log(PM_LOG_DEBUG, "electing '%s' for removal\n", conflict->package2); @@ -529,19 +603,17 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync alpm_list_free(deps); } - if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { - /* rebuild remove list */ - alpm_list_free(remove); - remove = NULL; - for(i = trans->packages; i; i = i->next) { - pmpkg_t *spkg = i->data; - for(j = spkg->removes; j; j = j->next) { - remove = alpm_list_add(remove, j->data); - } + /* Build trans->remove list */ + for(i = trans->add; i; i = i->next) { + pmpkg_t *spkg = i->data; + for(j = spkg->removes; j; j = j->next) { + trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(j->data)); } + } + if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { _alpm_log(PM_LOG_DEBUG, "checking dependencies\n"); - deps = alpm_checkdeps(_alpm_db_get_pkgcache(db_local), 1, remove, trans->packages); + deps = alpm_checkdeps(_alpm_db_get_pkgcache(db_local), 1, trans->remove, trans->add); if(deps) { pm_errno = PM_ERR_UNSATISFIED_DEPS; ret = -1; @@ -554,7 +626,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync goto cleanup; } } - for(i = trans->packages; i; i = i->next) { + for(i = trans->add; i; i = i->next) { /* update download size field */ pmpkg_t *spkg = i->data; if(compute_download_size(spkg) != 0) { @@ -564,8 +636,8 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync } cleanup: - alpm_list_free(remove); alpm_list_free(unresolvable); + alpm_list_free(remove); return(ret); } @@ -601,7 +673,7 @@ static int apply_deltas(pmtrans_t *trans) int ret = 0; const char *cachedir = _alpm_filecache_setup(); - for(i = trans->packages; i; i = i->next) { + for(i = trans->add; i; i = i->next) { pmpkg_t *spkg = i->data; alpm_list_t *delta_path = spkg->delta_path; alpm_list_t *dlts = NULL; @@ -614,7 +686,7 @@ static int apply_deltas(pmtrans_t *trans) pmdelta_t *d = dlts->data; char *delta, *from, *to; char command[PATH_MAX]; - int len = 0; + size_t len = 0; delta = _alpm_filecache_find(d->delta); /* the initial package might be in a different cachedir */ @@ -711,7 +783,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) { alpm_list_t *i, *j, *files = NULL; alpm_list_t *deltas = NULL; - pmtrans_t *tr_remove = NULL, *tr_upgrade = NULL; int replaces = 0; int errors = 0; const char *cachedir = NULL; @@ -730,7 +801,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) if(handle->totaldlcb) { off_t total_size = (off_t)0; /* sum up the download size for each package and store total */ - for(i = trans->packages; i; i = i->next) { + for(i = trans->add; i; i = i->next) { pmpkg_t *spkg = i->data; total_size += spkg->download_size; } @@ -741,11 +812,10 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) for(i = handle->dbs_sync; i; i = i->next) { pmdb_t *current = i->data; - for(j = trans->packages; j; j = j->next) { + for(j = trans->add; j; j = j->next) { pmpkg_t *spkg = j->data; - pmdb_t *dbs = spkg->origin_data.db; - if(current == dbs) { + if(spkg->origin == PKG_FROM_CACHE && current == spkg->origin_data.db) { const char *fname = NULL; fname = alpm_pkg_get_filename(spkg); @@ -835,15 +905,36 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) EVENT(trans, PM_TRANS_EVT_INTEGRITY_START, NULL, NULL); errors = 0; - for(i = trans->packages; i; i = i->next) { + for(i = trans->add; i; i = i->next) { pmpkg_t *spkg = i->data; + if(spkg->origin == PKG_FROM_FILE) { + continue; /* pkg_load() has been already called, this package is valid */ + } + const char *filename = alpm_pkg_get_filename(spkg); const char *md5sum = alpm_pkg_get_md5sum(spkg); if(test_md5sum(trans, filename, md5sum) != 0) { errors++; *data = alpm_list_add(*data, strdup(filename)); + continue; + } + /* load the package file and replace pkgcache entry with it in the target list */ + /* TODO: alpm_pkg_get_db() will not work on this target anymore */ + _alpm_log(PM_LOG_DEBUG, "replacing pkgcache entry with package file for target %s\n", spkg->name); + char *filepath = _alpm_filecache_find(filename); + pmpkg_t *pkgfile; + if(alpm_pkg_load(filepath, 1, &pkgfile) != 0) { + _alpm_pkg_free(pkgfile); + errors++; + *data = alpm_list_add(*data, strdup(filename)); + FREE(filepath); + continue; } + FREE(filepath); + pkgfile->reason = spkg->reason; /* copy over install reason */ + i->data = pkgfile; + _alpm_pkg_free_trans(spkg); /* spkg has been removed from the target list */ } if(errors) { pm_errno = PM_ERR_PKG_INVALID; @@ -856,71 +947,15 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) trans->state = STATE_COMMITING; - /* Create remove and upgrade transactions */ - tr_remove = _alpm_trans_new(); - if(tr_remove == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not create removal transaction\n")); - goto error; - } - tr_upgrade = _alpm_trans_new(); - if(tr_upgrade == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not create transaction\n")); - goto error; - } - - if(_alpm_trans_init(tr_remove, PM_TRANS_TYPE_REMOVE, PM_TRANS_FLAG_NODEPS, NULL, NULL, NULL) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not initialize the removal transaction\n")); - goto error; - } - if(_alpm_trans_init(tr_upgrade, PM_TRANS_TYPE_UPGRADE, trans->flags, trans->cb_event, trans->cb_conv, trans->cb_progress) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not initialize transaction\n")); - goto error; - } - - /* adding targets */ - for(i = trans->packages; i; i = i->next) { - pmpkg_t *spkg = i->data; - alpm_list_t *j; - /* remove transaction */ - for(j = spkg->removes; j; j = j->next) { - pmpkg_t *pkg = j->data; - if(!_alpm_pkg_find(tr_remove->packages, pkg->name)) { - if(_alpm_trans_addtarget(tr_remove, pkg->name) == -1) { - goto error; - } - replaces++; - } - } - /* upgrade transaction */ - const char *fname; - char *fpath; - - fname = alpm_pkg_get_filename(spkg); - if(fname == NULL) { - goto error; - } - /* Loop through the cache dirs until we find a matching file */ - fpath = _alpm_filecache_find(fname); - - if(_alpm_trans_addtarget(tr_upgrade, fpath) == -1) { - FREE(fpath); - goto error; - } - FREE(fpath); - - /* using alpm_list_last() is ok because addtarget() adds the new target at the - * end of the tr->packages list */ - pmpkg_t *ipkg = alpm_list_last(tr_upgrade->packages)->data; - ipkg->reason = spkg->reason; - } + replaces = alpm_list_count(trans->remove); /* fileconflict check */ if(!(trans->flags & PM_TRANS_FLAG_FORCE)) { EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_START, NULL, NULL); _alpm_log(PM_LOG_DEBUG, "looking for file conflicts\n"); - alpm_list_t *conflict = _alpm_db_find_fileconflicts(db_local, tr_upgrade, - tr_upgrade->packages, tr_remove->packages); + alpm_list_t *conflict = _alpm_db_find_fileconflicts(db_local, trans, + trans->add, trans->remove); if(conflict) { pm_errno = PM_ERR_FILE_CONFLICTS; if(data) { @@ -938,14 +973,8 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) /* remove conflicting and to-be-replaced packages */ if(replaces) { _alpm_log(PM_LOG_DEBUG, "removing conflicting and to-be-replaced packages\n"); - if(_alpm_trans_prepare(tr_remove, data) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not prepare removal transaction\n")); - goto error; - } /* we want the frontend to be aware of commit details */ - tr_remove->cb_event = trans->cb_event; - tr_remove->cb_progress = trans->cb_progress; - if(_alpm_trans_commit(tr_remove, NULL) == -1) { + if(_alpm_remove_packages(trans, handle->db_local) == -1) { _alpm_log(PM_LOG_ERROR, _("could not commit removal transaction\n")); goto error; } @@ -953,8 +982,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) /* install targets */ _alpm_log(PM_LOG_DEBUG, "installing packages\n"); - /* add_prepare is not needed */ - if(_alpm_trans_commit(tr_upgrade, NULL) == -1) { + if(_alpm_upgrade_packages(trans, handle->db_local) == -1) { _alpm_log(PM_LOG_ERROR, _("could not commit transaction\n")); goto error; } @@ -963,8 +991,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) error: FREELIST(files); alpm_list_free(deltas); - _alpm_trans_free(tr_remove); - _alpm_trans_free(tr_upgrade); return(ret); } diff --git a/lib/libalpm/sync.h b/lib/libalpm/sync.h index c2905a45..b432b69e 100644 --- a/lib/libalpm/sync.h +++ b/lib/libalpm/sync.h @@ -24,9 +24,6 @@ #include "alpm.h" -int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, int enable_downgrade); - -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); int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data); diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c index 6e847e64..4879d236 100644 --- a/lib/libalpm/trans.c +++ b/lib/libalpm/trans.c @@ -52,17 +52,18 @@ */ /** Initialize the transaction. - * @param type type of the transaction * @param flags flags of the transaction (like nodeps, etc) * @param event event callback function pointer * @param conv question callback function pointer * @param progress progress callback function pointer * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int SYMEXPORT alpm_trans_init(pmtranstype_t type, pmtransflag_t flags, +int SYMEXPORT alpm_trans_init(pmtransflag_t flags, alpm_trans_cb_event event, alpm_trans_cb_conv conv, alpm_trans_cb_progress progress) { + pmtrans_t *trans; + ALPM_LOG_FUNC; /* Sanity checks */ @@ -78,38 +79,53 @@ int SYMEXPORT alpm_trans_init(pmtranstype_t type, pmtransflag_t flags, } } - handle->trans = _alpm_trans_new(); - if(handle->trans == NULL) { + trans = _alpm_trans_new(); + if(trans == NULL) { RET_ERR(PM_ERR_MEMORY, -1); } - return(_alpm_trans_init(handle->trans, type, flags, event, conv, progress)); -} - -/** Search for packages to upgrade and add them to the transaction. - * @return 0 on success, -1 on error (pm_errno is set accordingly) - */ -int SYMEXPORT alpm_trans_sysupgrade(int enable_downgrade) -{ - pmtrans_t *trans; + trans->flags = flags; + trans->cb_event = event; + trans->cb_conv = conv; + trans->cb_progress = progress; + trans->state = STATE_INITIALIZED; - ALPM_LOG_FUNC; + handle->trans = trans; - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + return(0); +} - trans = handle->trans; - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - 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)); +static alpm_list_t *check_arch(alpm_list_t *pkgs) +{ + alpm_list_t *i; + alpm_list_t *invalid = NULL; - return(_alpm_sync_sysupgrade(trans, handle->db_local, handle->dbs_sync, enable_downgrade)); + const char *arch = alpm_option_get_arch(); + if(!arch) { + return(NULL); + } + for(i = pkgs; i; i = i->next) { + pmpkg_t *pkg = i->data; + const char *pkgarch = alpm_pkg_get_arch(pkg); + if(strcmp(pkgarch,arch) && strcmp(pkgarch,"any")) { + char *string; + const char *pkgname = alpm_pkg_get_name(pkg); + const char *pkgver = alpm_pkg_get_version(pkg); + size_t len = strlen(pkgname) + strlen(pkgver) + strlen(pkgarch) + 3; + MALLOC(string, len, RET_ERR(PM_ERR_MEMORY, invalid)); + sprintf(string, "%s-%s-%s", pkgname, pkgver, pkgarch); + invalid = alpm_list_add(invalid, string); + } + } + return(invalid); } -/** Add a target to the transaction. - * @param target the name of the target to add +/** Prepare a transaction. + * @param data the address of an alpm_list where detailed description + * of an error can be dumped (ie. list of conflicting files) * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int SYMEXPORT alpm_trans_addtarget(char *target) +int SYMEXPORT alpm_trans_prepare(alpm_list_t **data) { pmtrans_t *trans; @@ -117,32 +133,41 @@ int SYMEXPORT alpm_trans_addtarget(char *target) /* Sanity checks */ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(target != NULL && strlen(target) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + ASSERT(data != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); trans = handle->trans; + ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); - return(_alpm_trans_addtarget(trans, target)); -} + /* If there's nothing to do, return without complaining */ + if(trans->add == NULL && trans->remove == NULL) { + return(0); + } -/** Prepare a transaction. - * @param data the address of an alpm_list where detailed description - * of an error can be dumped (ie. list of conflicting files) - * @return 0 on success, -1 on error (pm_errno is set accordingly) - */ -int SYMEXPORT alpm_trans_prepare(alpm_list_t **data) -{ - ALPM_LOG_FUNC; + alpm_list_t *invalid = check_arch(trans->add); + if(invalid) { + if(data) { + *data = invalid; + } + RET_ERR(PM_ERR_PKG_INVALID_ARCH, -1); + } - /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(data != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + if(trans->add == NULL) { + if(_alpm_remove_prepare(trans, handle->db_local, data) == -1) { + /* pm_errno is set by _alpm_remove_prepare() */ + return(-1); + } + } else { + if(_alpm_sync_prepare(trans, handle->db_local, handle->dbs_sync, data) == -1) { + /* pm_errno is set by _alpm_sync_prepare() */ + return(-1); + } + } - ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(handle->trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); + trans->state = STATE_PREPARED; - return(_alpm_trans_prepare(handle->trans, data)); + return(0); } /** Commit a transaction. @@ -152,17 +177,42 @@ int SYMEXPORT alpm_trans_prepare(alpm_list_t **data) */ int SYMEXPORT alpm_trans_commit(alpm_list_t **data) { + pmtrans_t *trans; + ALPM_LOG_FUNC; /* Sanity checks */ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(handle->trans->state == STATE_PREPARED, RET_ERR(PM_ERR_TRANS_NOT_PREPARED, -1)); + trans = handle->trans; + + ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + ASSERT(trans->state == STATE_PREPARED, RET_ERR(PM_ERR_TRANS_NOT_PREPARED, -1)); + + ASSERT(!(trans->flags & PM_TRANS_FLAG_NOLOCK), RET_ERR(PM_ERR_TRANS_NOT_LOCKED, -1)); + + /* If there's nothing to do, return without complaining */ + if(trans->add == NULL && trans->remove == NULL) { + return(0); + } + + trans->state = STATE_COMMITING; - ASSERT(!(handle->trans->flags & PM_TRANS_FLAG_NOLOCK), RET_ERR(PM_ERR_TRANS_NOT_LOCKED, -1)); + if(trans->add == NULL) { + if(_alpm_remove_packages(trans, handle->db_local) == -1) { + /* pm_errno is set by _alpm_remove_commit() */ + return(-1); + } + } else { + if(_alpm_sync_commit(trans, handle->db_local, data) == -1) { + /* pm_errno is set by _alpm_sync_commit() */ + return(-1); + } + } - return(_alpm_trans_commit(handle->trans, data)); + trans->state = STATE_COMMITED; + + return(0); } /** Interrupt a transaction. @@ -203,7 +253,7 @@ int SYMEXPORT alpm_trans_release() ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); ASSERT(trans->state != STATE_IDLE, RET_ERR(PM_ERR_TRANS_NULL, -1)); - unsigned int nolock_flag = trans->flags & PM_TRANS_FLAG_NOLOCK; + int nolock_flag = trans->flags & PM_TRANS_FLAG_NOLOCK; _alpm_trans_free(trans); handle->trans = NULL; @@ -211,7 +261,10 @@ int SYMEXPORT alpm_trans_release() /* unlock db */ if(!nolock_flag) { if(handle->lckfd != -1) { - while(close(handle->lckfd) == -1 && errno == EINTR); + int fd; + do { + fd = close(handle->lckfd); + } while(fd == -1 && errno == EINTR); handle->lckfd = -1; } if(_alpm_lckrm()) { @@ -247,12 +300,10 @@ void _alpm_trans_free(pmtrans_t *trans) return; } - if(trans->type == PM_TRANS_TYPE_SYNC) { - alpm_list_free_inner(trans->packages, (alpm_list_fn_free)_alpm_pkg_free_trans); - } else { - alpm_list_free_inner(trans->packages, (alpm_list_fn_free)_alpm_pkg_free); - } - alpm_list_free(trans->packages); + alpm_list_free_inner(trans->add, (alpm_list_fn_free)_alpm_pkg_free_trans); + alpm_list_free(trans->add); + alpm_list_free_inner(trans->remove, (alpm_list_fn_free)_alpm_pkg_free); + alpm_list_free(trans->remove); FREELIST(trans->skip_add); FREELIST(trans->skip_remove); @@ -260,150 +311,6 @@ void _alpm_trans_free(pmtrans_t *trans) FREE(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) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - - trans->type = type; - trans->flags = flags; - trans->cb_event = event; - trans->cb_conv = conv; - trans->cb_progress = progress; - trans->state = STATE_INITIALIZED; - - return(0); -} - -/** Add a target to the transaction. - * @param trans the current transaction - * @param target the name of the target to add - * @return 0 on success, -1 on error (pm_errno is set accordingly) - */ -int _alpm_trans_addtarget(pmtrans_t *trans, char *target) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(target != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); - - switch(trans->type) { - case PM_TRANS_TYPE_UPGRADE: - if(_alpm_add_loadtarget(trans, handle->db_local, target) == -1) { - /* pm_errno is set by _alpm_add_loadtarget() */ - return(-1); - } - break; - case PM_TRANS_TYPE_REMOVE: - case PM_TRANS_TYPE_REMOVEUPGRADE: - if(_alpm_remove_loadtarget(trans, handle->db_local, target) == -1) { - /* pm_errno is set by _alpm_remove_loadtarget() */ - return(-1); - } - break; - case PM_TRANS_TYPE_SYNC: - if(_alpm_sync_addtarget(trans, handle->db_local, handle->dbs_sync, target) == -1) { - /* pm_errno is set by _alpm_sync_loadtarget() */ - return(-1); - } - break; - } - - return(0); -} - -int _alpm_trans_prepare(pmtrans_t *trans, alpm_list_t **data) -{ - if(data) { - *data = NULL; - } - - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - - /* If there's nothing to do, return without complaining */ - if(trans->packages == NULL) { - return(0); - } - - switch(trans->type) { - case PM_TRANS_TYPE_UPGRADE: - if(_alpm_add_prepare(trans, handle->db_local, data) == -1) { - /* pm_errno is set by _alpm_add_prepare() */ - return(-1); - } - break; - case PM_TRANS_TYPE_REMOVE: - case PM_TRANS_TYPE_REMOVEUPGRADE: - if(_alpm_remove_prepare(trans, handle->db_local, data) == -1) { - /* pm_errno is set by _alpm_remove_prepare() */ - return(-1); - } - break; - case PM_TRANS_TYPE_SYNC: - if(_alpm_sync_prepare(trans, handle->db_local, handle->dbs_sync, data) == -1) { - /* pm_errno is set by _alpm_sync_prepare() */ - return(-1); - } - break; - } - - trans->state = STATE_PREPARED; - - return(0); -} - -int _alpm_trans_commit(pmtrans_t *trans, alpm_list_t **data) -{ - ALPM_LOG_FUNC; - - if(data!=NULL) - *data = NULL; - - /* Sanity checks */ - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - - /* If there's nothing to do, return without complaining */ - if(trans->packages == NULL) { - return(0); - } - - trans->state = STATE_COMMITING; - - switch(trans->type) { - case PM_TRANS_TYPE_UPGRADE: - if(_alpm_add_commit(trans, handle->db_local) == -1) { - /* pm_errno is set by _alpm_add_commit() */ - return(-1); - } - break; - case PM_TRANS_TYPE_REMOVE: - case PM_TRANS_TYPE_REMOVEUPGRADE: - if(_alpm_remove_commit(trans, handle->db_local) == -1) { - /* pm_errno is set by _alpm_remove_commit() */ - return(-1); - } - break; - case PM_TRANS_TYPE_SYNC: - if(_alpm_sync_commit(trans, handle->db_local, data) == -1) { - /* pm_errno is set by _alpm_sync_commit() */ - return(-1); - } - break; - } - - trans->state = STATE_COMMITED; - - return(0); -} - /* A cheap grep for text files, returns 1 if a substring * was found in the text file fn, 0 if it wasn't */ @@ -416,7 +323,8 @@ static int grep(const char *fn, const char *needle) } while(!feof(fp)) { char line[1024]; - fgets(line, 1024, fp); + int sline = sizeof(line)-1; + fgets(line, sline, fp); if(feof(fp)) { continue; } @@ -464,7 +372,7 @@ int _alpm_runscriptlet(const char *root, const char *installfn, /* either extract or copy the scriptlet */ snprintf(scriptfn, PATH_MAX, "%s/.INSTALL", tmpdir); if(!strcmp(script, "pre_upgrade") || !strcmp(script, "pre_install")) { - if(_alpm_unpack(installfn, tmpdir, ".INSTALL")) { + if(_alpm_unpack_single(installfn, tmpdir, ".INSTALL")) { retval = 1; } } else { @@ -503,30 +411,30 @@ cleanup: return(retval); } -pmtranstype_t SYMEXPORT alpm_trans_get_type() +int SYMEXPORT alpm_trans_get_flags() { /* Sanity checks */ ASSERT(handle != NULL, return(-1)); ASSERT(handle->trans != NULL, return(-1)); - return handle->trans->type; + return handle->trans->flags; } -unsigned int SYMEXPORT alpm_trans_get_flags() +alpm_list_t SYMEXPORT * alpm_trans_get_add() { /* Sanity checks */ - ASSERT(handle != NULL, return(-1)); - ASSERT(handle->trans != NULL, return(-1)); + ASSERT(handle != NULL, return(NULL)); + ASSERT(handle->trans != NULL, return(NULL)); - return handle->trans->flags; + return handle->trans->add; } -alpm_list_t SYMEXPORT * alpm_trans_get_pkgs() +alpm_list_t SYMEXPORT * alpm_trans_get_remove() { /* Sanity checks */ ASSERT(handle != NULL, return(NULL)); ASSERT(handle->trans != NULL, return(NULL)); - return handle->trans->packages; + return handle->trans->remove; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/trans.h b/lib/libalpm/trans.h index 0537bc72..ca1e141a 100644 --- a/lib/libalpm/trans.h +++ b/lib/libalpm/trans.h @@ -37,10 +37,10 @@ typedef enum _pmtransstate_t { /* Transaction */ struct __pmtrans_t { - pmtranstype_t type; pmtransflag_t flags; pmtransstate_t state; - alpm_list_t *packages; /* list of (pmpkg_t *) */ + alpm_list_t *add; /* list of (pmpkg_t *) */ + alpm_list_t *remove; /* list of (pmpkg_t *) */ alpm_list_t *skip_add; /* list of (char *) */ alpm_list_t *skip_remove; /* list of (char *) */ alpm_trans_cb_event cb_event; @@ -69,12 +69,9 @@ do { \ pmtrans_t *_alpm_trans_new(void); void _alpm_trans_free(pmtrans_t *trans); -int _alpm_trans_init(pmtrans_t *trans, pmtranstype_t type, pmtransflag_t flags, +int _alpm_trans_init(pmtrans_t *trans, pmtransflag_t flags, alpm_trans_cb_event event, alpm_trans_cb_conv conv, alpm_trans_cb_progress progress); -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); int _alpm_runscriptlet(const char *root, const char *installfn, const char *script, const char *ver, const char *oldver, pmtrans_t *trans); diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 2b006e21..27e861e4 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -175,7 +175,7 @@ char *_alpm_strtrim(char *str) return(str); } - while(isspace((int)*pch)) { + while(isspace((unsigned char)*pch)) { pch++; } if(pch != str) { @@ -188,7 +188,7 @@ char *_alpm_strtrim(char *str) } pch = (str + (strlen(str) - 1)); - while(isspace((int)*pch)) { + while(isspace((unsigned char)*pch)) { pch--; } *++pch = '\0'; @@ -196,57 +196,11 @@ char *_alpm_strtrim(char *str) return(str); } -/* Helper function for _alpm_strreplace */ -static void _strnadd(char **str, const char *append, unsigned int count) -{ - if(*str) { - *str = realloc(*str, strlen(*str) + count + 1); - } else { - *str = calloc(count + 1, sizeof(char)); - } - - strncat(*str, append, count); -} - -/* Replace all occurances of 'needle' with 'replace' in 'str', returning - * a new string (must be free'd) */ -char *_alpm_strreplace(const char *str, const char *needle, const char *replace) -{ - const char *p, *q; - p = q = str; - - char *newstr = NULL; - unsigned int needlesz = strlen(needle), - replacesz = strlen(replace); - - while (1) { - q = strstr(p, needle); - if(!q) { /* not found */ - if(*p) { - /* add the rest of 'p' */ - _strnadd(&newstr, p, strlen(p)); - } - break; - } else { /* found match */ - if(q > p){ - /* add chars between this occurance and last occurance, if any */ - _strnadd(&newstr, p, q - p); - } - _strnadd(&newstr, replace, replacesz); - p = q + needlesz; - } - } - - return newstr; -} - - /* Create a lock file */ int _alpm_lckmk() { int fd; - pid_t pid; - char *dir, *ptr, *spid = NULL; + char *dir, *ptr; const char *file = alpm_option_get_lockfile(); /* create the dir of the lockfile first */ @@ -258,16 +212,15 @@ int _alpm_lckmk() _alpm_makepath(dir); FREE(dir); - while((fd = open(file, O_WRONLY | O_CREAT | O_EXCL, 0000)) == -1 - && errno == EINTR); + do { + fd = open(file, O_WRONLY | O_CREAT | O_EXCL, 0000); + } while (fd == -1 && errno == EINTR); 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); + FILE *f = fdopen(fd, "w"); + fprintf(f, "%ld\n", (long)getpid()); + fflush(f); fsync(fd); - free(spid); + fclose(f); return(fd); } return(-1); @@ -286,14 +239,38 @@ int _alpm_lckrm() /* Compression functions */ /** - * @brief Unpack a specific file or all files in an archive. + * @brief Unpack a specific file in an archive. * * @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 + * @param fn a file within the archive to unpack * @return 0 on success, 1 on failure */ -int _alpm_unpack(const char *archive, const char *prefix, const char *fn) +int _alpm_unpack_single(const char *archive, const char *prefix, const char *fn) +{ + alpm_list_t *list = NULL; + int ret = 0; + if(fn == NULL) { + return(1); + } + list = alpm_list_add(list, (void *)fn); + ret = _alpm_unpack(archive, prefix, list, 1); + alpm_list_free(list); + return(ret); +} + +/** + * @brief Unpack a list of files in an archive. + * + * @param archive the archive to unpack + * @param prefix where to extract the files + * @param list a list of files within the archive to unpack or + * NULL for all + * @param breakfirst break after the first entry found + * + * @return 0 on success, 1 on failure + */ +int _alpm_unpack(const char *archive, const char *prefix, alpm_list_t *list, int breakfirst) { int ret = 0; mode_t oldmask; @@ -339,21 +316,30 @@ int _alpm_unpack(const char *archive, const char *prefix, const char *fn) st = archive_entry_stat(entry); entryname = archive_entry_pathname(entry); - + if(S_ISREG(st->st_mode)) { archive_entry_set_perm(entry, 0644); } else if(S_ISDIR(st->st_mode)) { archive_entry_set_perm(entry, 0755); } - /* If a specific file was requested skip entries that don't match. */ - if (fn && strcmp(fn, entryname)) { - _alpm_log(PM_LOG_DEBUG, "skipping: %s\n", entryname); - if (archive_read_data_skip(_archive) != ARCHIVE_OK) { - ret = 1; - goto cleanup; + /* If specific files were requested, skip entries that don't match. */ + if(list) { + char *prefix = strdup(entryname); + char *p = strstr(prefix,"/"); + if(p) { + *(p+1) = '\0'; + } + char *found = alpm_list_find_str(list, prefix); + free(prefix); + if(!found) { + _alpm_log(PM_LOG_DEBUG, "skipping: %s\n", entryname); + if (archive_read_data_skip(_archive) != ARCHIVE_OK) { + ret = 1; + goto cleanup; + } + continue; } - continue; } /* Extract the archive entry. */ @@ -369,7 +355,7 @@ int _alpm_unpack(const char *archive, const char *prefix, const char *fn) goto cleanup; } - if(fn) { + if(breakfirst) { break; } } @@ -426,8 +412,7 @@ int _alpm_rmrf(const char *path) return(0); } -int _alpm_logaction(unsigned short usesyslog, FILE *f, - const char *fmt, va_list args) +int _alpm_logaction(int usesyslog, FILE *f, const char *fmt, va_list args) { int ret = 0; @@ -527,7 +512,9 @@ int _alpm_run_chroot(const char *root, const char *cmd) /* this code runs for the parent only (wait on the child) */ pid_t retpid; int status; - while((retpid = waitpid(pid, &status, 0)) == -1 && errno == EINTR); + do { + retpid = waitpid(pid, &status, 0); + } while(retpid == -1 && errno == EINTR); if(retpid == -1) { _alpm_log(PM_LOG_ERROR, _("call to waitpid failed (%s)\n"), strerror(errno)); diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h index 4bc8b92f..37893c8b 100644 --- a/lib/libalpm/util.h +++ b/lib/libalpm/util.h @@ -26,6 +26,8 @@ #include "config.h" +#include "alpm_list.h" + #include <stdio.h> #include <string.h> #include <stdarg.h> @@ -60,12 +62,12 @@ int _alpm_makepath(const char *path); int _alpm_makepath_mode(const char *path, mode_t mode); int _alpm_copyfile(const char *src, const char *dest); char *_alpm_strtrim(char *str); -char *_alpm_strreplace(const char *str, const char *needle, const char *replace); int _alpm_lckmk(); int _alpm_lckrm(); -int _alpm_unpack(const char *archive, const char *prefix, const char *fn); +int _alpm_unpack_single(const char *archive, const char *prefix, const char *fn); +int _alpm_unpack(const char *archive, const char *prefix, alpm_list_t *list, int breakfirst); int _alpm_rmrf(const char *path); -int _alpm_logaction(unsigned short usesyslog, FILE *f, const char *fmt, va_list args); +int _alpm_logaction(int usesyslog, FILE *f, const char *fmt, va_list args); int _alpm_run_chroot(const char *root, const char *cmd); int _alpm_ldconfig(const char *root); int _alpm_str_cmp(const void *s1, const void *s2); diff --git a/pactest/tests/depconflict110.py b/pactest/tests/depconflict110.py index fd56fa89..82e17d0b 100644 --- a/pactest/tests/depconflict110.py +++ b/pactest/tests/depconflict110.py @@ -7,7 +7,7 @@ self.addpkg(p); lp = pmpkg("pkg2", "1.0-1") self.addpkg2db("local", lp) -self.args = "-U %s" % p.filename() -self.addrule("PACMAN_RETCODE=1") -self.addrule("!PKG_EXIST=pkg1") -self.addrule("PKG_EXIST=pkg2") +self.args = "-U %s --ask=4" % p.filename() +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg1") +self.addrule("!PKG_EXIST=pkg2") diff --git a/pactest/tests/ignore002.py b/pactest/tests/ignore002.py index b2c5593a..9b09e8f7 100644 --- a/pactest/tests/ignore002.py +++ b/pactest/tests/ignore002.py @@ -28,7 +28,7 @@ self.addpkg2db("sync", package4up) self.option["IgnorePkg"] = ["package2"] self.args = "-Su" -self.addrule("PACMAN_RETCODE=0") +self.addrule("PACMAN_RETCODE=1") self.addrule("PKG_VERSION=package1|1.0-1") self.addrule("PKG_VERSION=package2|1.0-1") self.addrule("PKG_VERSION=package3|1.0-1") diff --git a/pactest/tests/ignore003.py b/pactest/tests/ignore003.py index 02b3c91c..8768a6ef 100644 --- a/pactest/tests/ignore003.py +++ b/pactest/tests/ignore003.py @@ -28,7 +28,7 @@ self.addpkg2db("sync", package4up) self.option["IgnorePkg"] = ["package2"] self.args = "-Su" -self.addrule("PACMAN_RETCODE=0") +self.addrule("PACMAN_RETCODE=1") self.addrule("PKG_VERSION=package1|1.0-1") self.addrule("PKG_VERSION=package2|1.0-1") self.addrule("PKG_VERSION=package3|1.0-1") diff --git a/pactest/tests/ignore004.py b/pactest/tests/ignore004.py index fff12f62..e6af48bd 100644 --- a/pactest/tests/ignore004.py +++ b/pactest/tests/ignore004.py @@ -38,7 +38,7 @@ self.addpkg2db("sync", packageA5up) self.option["IgnorePkg"] = ["packageA3"] self.args = "-S packageA1" -self.addrule("PACMAN_RETCODE=0") +self.addrule("PACMAN_RETCODE=1") self.addrule("PKG_VERSION=packageA1|1.0-1") self.addrule("PKG_VERSION=packageA2|1.0-1") self.addrule("PKG_VERSION=packageA3|1.0-1") diff --git a/pactest/tests/ignore005.py b/pactest/tests/ignore005.py index 1957ea4f..274e44c3 100644 --- a/pactest/tests/ignore005.py +++ b/pactest/tests/ignore005.py @@ -36,7 +36,7 @@ self.addpkg2db("sync", packageA5up) self.option["IgnorePkg"] = ["packageA3"] -self.args = "-S packageA1 packageA2" +self.args = "-S packageA1 packageA2 --ask=32" self.addrule("PACMAN_RETCODE=0") self.addrule("PKG_VERSION=packageA1|1.0-1") diff --git a/pactest/tests/provision020.py b/pactest/tests/provision020.py index c9c0ac36..7cb0a01b 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=0") +self.addrule("PACMAN_RETCODE=1") self.addrule("!PKG_EXIST=pkg1") self.addrule("PKG_EXIST=pkg2") diff --git a/pactest/tests/provision022.py b/pactest/tests/provision022.py index 190a8b66..4883d428 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=0") +self.addrule("PACMAN_RETCODE=1") self.addrule("!PKG_EXIST=pkg1") self.addrule("PKG_EXIST=pkg2") diff --git a/pactest/tests/sync042.py b/pactest/tests/sync042.py index 0aa7e37b..7c3498d3 100644 --- a/pactest/tests/sync042.py +++ b/pactest/tests/sync042.py @@ -9,6 +9,6 @@ self.addpkg2db("local", lp); self.args = "-S %s" % sp.name -self.addrule("PACMAN_RETCODE=0") -self.addrule("PKG_EXIST=pkg1") -self.addrule("!PKG_EXIST=pkg2") +self.addrule("PACMAN_RETCODE=1") +self.addrule("!PKG_EXIST=pkg1") +self.addrule("PKG_EXIST=pkg2") diff --git a/pactest/tests/sync043.py b/pactest/tests/sync043.py index 1302bf04..8461e9f9 100644 --- a/pactest/tests/sync043.py +++ b/pactest/tests/sync043.py @@ -7,10 +7,10 @@ self.addpkg2db("sync", sp); lp1 = pmpkg("pkg2") self.addpkg2db("local", lp1); -lp1 = pmpkg("pkg3") -self.addpkg2db("local", lp1); +lp2 = pmpkg("pkg3") +self.addpkg2db("local", lp2); -self.args = "-S %s" % sp.name +self.args = "-S %s --ask=4" % sp.name self.addrule("PACMAN_RETCODE=0") self.addrule("PKG_EXIST=pkg1") diff --git a/pactest/tests/sync044.py b/pactest/tests/sync044.py index c4ff1549..0c8fd2e9 100644 --- a/pactest/tests/sync044.py +++ b/pactest/tests/sync044.py @@ -11,7 +11,7 @@ sp3 = pmpkg("pkg3") sp3.conflicts = ["pkg1"] self.addpkg2db("sync", sp3); -self.args = "-S pkg2" +self.args = "-S pkg2 --ask=4" self.addrule("PACMAN_RETCODE=0") self.addrule("!PKG_EXIST=pkg1") diff --git a/pactest/tests/sync045.py b/pactest/tests/sync045.py new file mode 100644 index 00000000..574c0a52 --- /dev/null +++ b/pactest/tests/sync045.py @@ -0,0 +1,18 @@ +self.description = "Install a sync package conflicting with two local ones (-d)" + +sp = pmpkg("pkg1") +sp.conflicts = ["pkg2", "pkg3"] +self.addpkg2db("sync", sp); + +lp1 = pmpkg("pkg2") +self.addpkg2db("local", lp1); + +lp2 = pmpkg("pkg3") +self.addpkg2db("local", lp2); + +self.args = "-Sd %s --ask=4" % sp.name + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg1") +self.addrule("!PKG_EXIST=pkg2") +self.addrule("!PKG_EXIST=pkg3") diff --git a/pactest/tests/sync1004.py b/pactest/tests/sync1004.py index f87bbe9b..a9cee49c 100644 --- a/pactest/tests/sync1004.py +++ b/pactest/tests/sync1004.py @@ -11,7 +11,7 @@ self.addpkg2db("sync", sp2) lp = pmpkg("depend") self.addpkg2db("local", lp) -self.args = "-S pkg1 pkg2" +self.args = "-S pkg1 pkg2 --ask=4" self.addrule("PACMAN_RETCODE=1") self.addrule("PKG_EXIST=depend") diff --git a/pactest/tests/sync1008.py b/pactest/tests/sync1008.py index 90c61dfb..a6064597 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=0") +self.addrule("PACMAN_RETCODE=1") self.addrule("!PKG_EXIST=pkg") self.addrule("!PKG_EXIST=cpkg") diff --git a/pactest/tests/sync150.py b/pactest/tests/sync150.py new file mode 100644 index 00000000..b62bd984 --- /dev/null +++ b/pactest/tests/sync150.py @@ -0,0 +1,25 @@ +self.description = "-Su foo" + +sp1 = pmpkg("pkg1", "1.0-2") +sp1.depends = ["pkg2"] + +sp2 = pmpkg("pkg2") +sp2.depends = ["pkg3"] + +sp3 = pmpkg("pkg3") + +sp4 = pmpkg("pkg4") + +for p in sp1, sp2, sp3, sp4: + self.addpkg2db("sync", p) + +lp1 = pmpkg("pkg1") +self.addpkg2db("local", lp1) + +self.args = "-Su %s" % sp4.name + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=pkg1|1.0-2") +for p in sp2, sp3: + self.addrule("PKG_REASON=%s|1" % p.name) +self.addrule("PKG_REASON=%s|0" % sp4.name) diff --git a/pactest/tests/sync200.py.in b/pactest/tests/sync200.py.in index 3c11f83f..c83e9ac7 100644 --- a/pactest/tests/sync200.py.in +++ b/pactest/tests/sync200.py.in @@ -1,6 +1,6 @@ self.description = "Synchronize the local database" -if not "download" in "@LIBS@": +if not "fetch" in "@LIBS@": self.option['XferCommand'] = ['/usr/bin/curl %u > %o'] sp1 = pmpkg("spkg1", "1.0-1") diff --git a/pactest/tests/sync300.py b/pactest/tests/sync300.py index 36d6758a..31b520a8 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=0") +self.addrule("PACMAN_RETCODE=1") self.addrule("!PKG_EXIST=pkg1") self.addrule("!PKG_EXIST=pkg2") diff --git a/pactest/tests/sync890.py b/pactest/tests/sync890.py index 75947e9a..e8380b79 100644 --- a/pactest/tests/sync890.py +++ b/pactest/tests/sync890.py @@ -12,7 +12,7 @@ lp2.conflicts = ["pkg3"] for p in lp1, lp2: self.addpkg2db("local", p) -self.args = "-S %s" % sp.name +self.args = "-S %s --ask=4" % sp.name self.addrule("PACMAN_RETCODE=0") self.addrule("PKG_EXIST=pkg1") diff --git a/pactest/tests/sync892.py b/pactest/tests/sync892.py index 04cc79c5..dfd889ea 100644 --- a/pactest/tests/sync892.py +++ b/pactest/tests/sync892.py @@ -16,7 +16,7 @@ lp2.conflicts = ["pkg3"] for p in lp1, lp2: self.addpkg2db("local", p) -self.args = "-S %s" % " ".join([p.name for p in sp1, sp2]) +self.args = "-S %s --ask=4" % " ".join([p.name for p in sp1, sp2]) self.addrule("PACMAN_RETCODE=0") self.addrule("!PKG_EXIST=pkg1") diff --git a/pactest/tests/sync893.py b/pactest/tests/sync893.py index 1c8494a3..e96bb7b6 100644 --- a/pactest/tests/sync893.py +++ b/pactest/tests/sync893.py @@ -13,7 +13,7 @@ self.addpkg2db("local", lp1) lp2 = pmpkg("pkg2") self.addpkg2db("local", lp2) -self.args = "-S %s" % " ".join([p.name for p in sp1, sp2]) +self.args = "-S %s --ask=4" % " ".join([p.name for p in sp1, sp2]) self.addrule("PACMAN_RETCODE=1") self.addrule("PKG_EXIST=pkg1") diff --git a/pactest/tests/sync895.py b/pactest/tests/sync895.py index 1b348c19..fd987864 100644 --- a/pactest/tests/sync895.py +++ b/pactest/tests/sync895.py @@ -12,7 +12,7 @@ lp2 = pmpkg("pkg2") lp2.depends = ["foo"] self.addpkg2db("local", lp2) -self.args = "-S %s" % sp.name +self.args = "-S %s --ask=4" % sp.name self.addrule("PACMAN_RETCODE=1") self.addrule("PKG_EXIST=pkg1") diff --git a/pactest/tests/sync896.py b/pactest/tests/sync896.py index a89b5c70..492bd7b4 100644 --- a/pactest/tests/sync896.py +++ b/pactest/tests/sync896.py @@ -13,7 +13,7 @@ lp2 = pmpkg("pkg2") lp2.depends = ["foo"] self.addpkg2db("local", lp2) -self.args = "-S %s" % sp.name +self.args = "-S %s --ask=4" % sp.name self.addrule("PACMAN_RETCODE=0") self.addrule("!PKG_EXIST=pkg1") diff --git a/pactest/tests/sync897.py b/pactest/tests/sync897.py index f7bd3d71..8a1c5a7c 100644 --- a/pactest/tests/sync897.py +++ b/pactest/tests/sync897.py @@ -16,7 +16,7 @@ self.addpkg2db("local", lp2) lp3 = pmpkg("pkg3") self.addpkg2db("local", lp3) -self.args = "-Su" +self.args = "-Su --ask=4" self.addrule("PACMAN_RETCODE=1") self.addrule("PKG_EXIST=pkg1") diff --git a/pactest/tests/sync899.py b/pactest/tests/sync899.py index a561ae63..fd308050 100644 --- a/pactest/tests/sync899.py +++ b/pactest/tests/sync899.py @@ -11,7 +11,7 @@ self.addpkg2db("local", lp1) lp2 = pmpkg("pkg2") self.addpkg2db("local", lp2) -self.args = "-Su" +self.args = "-Su --ask=4" self.addrule("PACMAN_RETCODE=0") self.addrule("PKG_EXIST=pkg1") diff --git a/pactest/tests/sync900.py b/pactest/tests/sync900.py index 16dfee12..744fad03 100644 --- a/pactest/tests/sync900.py +++ b/pactest/tests/sync900.py @@ -16,7 +16,7 @@ lp2 = pmpkg("pkg2") lp2.depends = ["foo"] self.addpkg2db("local", lp2) -self.args = "-S %s" % sp.name +self.args = "-S %s --ask=4" % sp.name self.addrule("PACMAN_RETCODE=0") self.addrule("!PKG_EXIST=foo") diff --git a/pactest/tests/sync901.py b/pactest/tests/sync901.py index bb420b79..f5834533 100644 --- a/pactest/tests/sync901.py +++ b/pactest/tests/sync901.py @@ -16,7 +16,7 @@ lp2 = pmpkg("pkg2") lp2.depends = ["foo"] self.addpkg2db("local", lp2) -self.args = "-S %s" % sp.name +self.args = "-S %s --ask=4" % sp.name self.addrule("PACMAN_RETCODE=0") self.addrule("PKG_EXIST=foo") diff --git a/pactest/tests/sync992.py b/pactest/tests/sync992.py index a7ad1110..63faaaba 100644 --- a/pactest/tests/sync992.py +++ b/pactest/tests/sync992.py @@ -15,7 +15,7 @@ for p in sp1, sp2, sp3: lp1 = pmpkg("pkg2", "0.1-1") self.addpkg2db("local", lp1) -self.args = "-S %s" % " ".join([p.name for p in sp1, sp2]) +self.args = "-S %s --ask=4" % " ".join([p.name for p in sp1, sp2]) self.addrule("PACMAN_RETCODE=0") self.addrule("PKG_EXIST=pkg1") diff --git a/pactest/tests/sync999.py b/pactest/tests/sync999.py index 69089fa1..89447cad 100644 --- a/pactest/tests/sync999.py +++ b/pactest/tests/sync999.py @@ -14,7 +14,7 @@ self.addpkg2db("local", lp1) lp2 = pmpkg("pkg2") self.addpkg2db("local", lp2) -self.args = "-Su" +self.args = "-Su --ask=4" self.addrule("PACMAN_RETCODE=0") self.addrule("PKG_EXIST=pkg1") diff --git a/pactest/tests/upgrade051.py b/pactest/tests/upgrade051.py index 4346c24d..1d173218 100644 --- a/pactest/tests/upgrade051.py +++ b/pactest/tests/upgrade051.py @@ -8,10 +8,8 @@ p.conflicts = ["pkg1"] p.provides = ["pkg1"] self.addpkg(p) -self.args = "-U %s" % p.filename() +self.args = "-U %s --ask=4" % p.filename() self.addrule("PACMAN_RETCODE=0") self.addrule("!PKG_EXIST=pkg1") self.addrule("PKG_EXIST=pkg2") - -self.expectfailure = True diff --git a/pactest/tests/upgrade080.py b/pactest/tests/upgrade080.py new file mode 100644 index 00000000..9ddbd708 --- /dev/null +++ b/pactest/tests/upgrade080.py @@ -0,0 +1,16 @@ +self.description = "Install a package (correct architecture)" + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +p.arch = 'testarch' +self.addpkg(p) + +self.option["Architecture"] = ['testarch'] + +self.args = "-U %s" % p.filename() + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=dummy") +for f in p.files: + self.addrule("FILE_EXIST=%s" % f) diff --git a/pactest/tests/upgrade081.py b/pactest/tests/upgrade081.py new file mode 100644 index 00000000..99e22311 --- /dev/null +++ b/pactest/tests/upgrade081.py @@ -0,0 +1,16 @@ +self.description = "Install a package (wrong architecture)" + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +p.arch = 'testarch' +self.addpkg(p) + +self.option["Architecture"] = ['nottestarch'] + +self.args = "-U %s" % p.filename() + +self.addrule("PACMAN_RETCODE=1") +self.addrule("!PKG_EXIST=dummy") +for f in p.files: + self.addrule("!FILE_EXIST=%s" % f) diff --git a/pactest/tests/upgrade082.py b/pactest/tests/upgrade082.py new file mode 100644 index 00000000..0bdbdf71 --- /dev/null +++ b/pactest/tests/upgrade082.py @@ -0,0 +1,19 @@ +self.description = "Install a package (correct architecture, auto)" + +import os +machine = os.uname()[4] + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +p.arch = machine +self.addpkg(p) + +self.option["Architecture"] = ['auto'] + +self.args = "-U %s" % p.filename() + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=dummy") +for f in p.files: + self.addrule("FILE_EXIST=%s" % f) diff --git a/pactest/tests/upgrade083.py b/pactest/tests/upgrade083.py new file mode 100644 index 00000000..097ae02c --- /dev/null +++ b/pactest/tests/upgrade083.py @@ -0,0 +1,19 @@ +self.description = "Install a package (wrong architecture, auto)" + +import os +machine = os.uname()[4] + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +p.arch = machine + 'wrong' +self.addpkg(p) + +self.option["Architecture"] = ['auto'] + +self.args = "-U %s" % p.filename() + +self.addrule("PACMAN_RETCODE=1") +self.addrule("!PKG_EXIST=dummy") +for f in p.files: + self.addrule("!FILE_EXIST=%s" % f) diff --git a/pactest/tests/upgrade084.py b/pactest/tests/upgrade084.py new file mode 100644 index 00000000..8268e3ff --- /dev/null +++ b/pactest/tests/upgrade084.py @@ -0,0 +1,16 @@ +self.description = "Install a package ('any' architecture)" + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +p.arch = 'any' +self.addpkg(p) + +self.option["Architecture"] = ['auto'] + +self.args = "-U %s" % p.filename() + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=dummy") +for f in p.files: + self.addrule("FILE_EXIST=%s" % f) diff --git a/pactest/tests/upgrade090.py b/pactest/tests/upgrade090.py new file mode 100644 index 00000000..26e531c9 --- /dev/null +++ b/pactest/tests/upgrade090.py @@ -0,0 +1,28 @@ +self.description = "-U syncdeps test" + +p1 = pmpkg("pkg1", "1.0-2") +p1.files = ["bin/pkg1"] + +p2 = pmpkg("pkg2", "1.0-2") +p2.depends = ["dep"] + +p3 = pmpkg("pkg3", "1.0-2") +p3.depends = ["unres"] + +for p in p1, p2, p3: + self.addpkg(p) + +sp = pmpkg("dep") +sp.files = ["bin/dep"] +self.addpkg2db("sync", sp) + +self.args = "-U %s --ask=32" % " ".join([p.filename() for p in p1, p2, p3]) + +self.addrule("PACMAN_RETCODE=0") +for p in p1, p2, sp: + self.addrule("PKG_EXIST=%s" % p.name) + for f in p.files: + self.addrule("FILE_EXIST=%s" % f) +self.addrule("PKG_VERSION=pkg1|1.0-2") +self.addrule("PKG_VERSION=pkg2|1.0-2") +self.addrule("!PKG_EXIST=pkg3") @@ -1,4 +1,5 @@ # Set of available languages. +ca cs de el diff --git a/po/ca.po b/po/ca.po new file mode 100644 index 00000000..b8bc37c2 --- /dev/null +++ b/po/ca.po @@ -0,0 +1,1755 @@ +# Translation of pacman.po to Catalan +# Copyright (C) 2009 Pacman Development Team <pacman-dev@archlinux.org> +# This file is distributed under the same license as the Pacman package. +# +# Manuel Tortosa <manutortosa@gmail.com>, 2009. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: pacman-dev@archlinux.org\n" +"POT-Creation-Date: 2009-10-04 16:48+0200\n" +"PO-Revision-Date: 2009-11-16 00:01+0100\n" +"Last-Translator: Manuel Tortosa <manutortosa@gmail.com>\n" +"Language-Team: Catalan <kde-i18n-ca@kde.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.0\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#, c-format +msgid "checking dependencies...\n" +msgstr "s'estan comprovant les dependències...\n" + +#, c-format +msgid "checking for file conflicts...\n" +msgstr "s'estan comprovant els conflictes amb fitxers...\n" + +#, c-format +msgid "resolving dependencies...\n" +msgstr "s'estan resolent les dependències...\n" + +#, c-format +msgid "looking for inter-conflicts...\n" +msgstr "s'estan cercant conflictes interns...\n" + +#, c-format +msgid "installing %s...\n" +msgstr "s'està instal·lant %s...\n" + +#, c-format +msgid "removing %s...\n" +msgstr "s'està eliminant %s...\n" + +#, c-format +msgid "upgrading %s...\n" +msgstr "s'està actualitzant %s...\n" + +#, c-format +msgid "checking package integrity...\n" +msgstr "s'està comprovant la integritat dels paquets...\n" + +#, c-format +msgid "checking delta integrity...\n" +msgstr "s'està comprovant la integritat delta...\n" + +#, c-format +msgid "applying deltas...\n" +msgstr "s'estan aplicant deltas...\n" + +#, c-format +msgid "generating %s with %s... " +msgstr "s'està generant %s amb %s... " + +#, c-format +msgid "success!\n" +msgstr "exit!\n" + +#, c-format +msgid "failed.\n" +msgstr "fallat.\n" + +#, c-format +msgid ":: Retrieving packages from %s...\n" +msgstr ":: Recuperant paquets des de %s...\n" + +#, c-format +msgid ":: %s is in IgnorePkg/IgnoreGroup. Install anyway?" +msgstr ":: %s és en IgnorePkg/IgnoreGroup. L'instal·lo igualment?" + +#, c-format +msgid ":: Replace %s with %s/%s?" +msgstr ":: Reemplaço %s amb %s/%s?" + +#, c-format +msgid ":: %s conflicts with %s. Remove %s?" +msgstr ":: %s té conflictes amb %s. Elimino %s?" + +#, c-format +msgid "" +":: the following package(s) cannot be upgraded due to unresolvable " +"dependencies:\n" +msgstr "" +":: els següents paquets no es poden actualitzar degut a dependències que no " +"es poden resoldre:\n" + +#, c-format +msgid "" +"\n" +"Do you want to skip the above package(s) for this upgrade?" +msgstr "" +"\n" +"Voleu ometre els paquets de dalt per a aquesta actualització?" + +#, c-format +msgid ":: %s-%s: local version is newer. Upgrade anyway?" +msgstr ":: %s-%s: la versió local és més nova. Actualitzo igualment?" + +#, c-format +msgid ":: File %s is corrupted. Do you want to delete it?" +msgstr ":: El fitxer %s és corrupte. Voleu esborrar-lo?" + +#, c-format +msgid "installing" +msgstr "s'està instal.lant" + +#, c-format +msgid "upgrading" +msgstr "s'està actualitzant" + +#, c-format +msgid "removing" +msgstr "s'està eliminant" + +#, c-format +msgid "checking for file conflicts" +msgstr "s'estan comprovant els conflictes amb fitxers" + +#, c-format +msgid "downloading %s...\n" +msgstr "s'està baixant %s...\n" + +#, c-format +msgid "malloc failure: could not allocate %zd bytes\n" +msgstr "fallada d'assignació de memòria: no es poden assignar %zd bytes\n" + +#, c-format +msgid "Explicitly installed" +msgstr "Instal·lat explícitament" + +#, c-format +msgid "Installed as a dependency for another package" +msgstr "Instal·lat com a dependència d'una altre paquet" + +#, c-format +msgid "Unknown" +msgstr "Desconegut" + +#, c-format +msgid "Name :" +msgstr "Nom :" + +#, c-format +msgid "Version :" +msgstr "Versió :" + +#, c-format +msgid "URL :" +msgstr "URL :" + +#, c-format +msgid "Licenses :" +msgstr "Llicències :" + +#, c-format +msgid "Groups :" +msgstr "Grups :" + +#, c-format +msgid "Provides :" +msgstr "Proporciona :" + +#, c-format +msgid "Depends On :" +msgstr "Depen de :" + +#, c-format +msgid "Optional Deps :" +msgstr "Dep opcionals :" + +#, c-format +msgid "Required By :" +msgstr "Requerit per :" + +#, c-format +msgid "Conflicts With :" +msgstr "Conflictes amb :" + +#, c-format +msgid "Replaces :" +msgstr "Substitueix :" + +#, c-format +msgid "Download Size : %6.2f K\n" +msgstr "Mida de la baixada: %6.2f K\n" + +#, c-format +msgid "Compressed Size: %6.2f K\n" +msgstr "Mida comprimida: %6.2f K\n" + +#, c-format +msgid "Installed Size : %6.2f K\n" +msgstr "Mida instal. : %6.2f K\n" + +#, c-format +msgid "Packager :" +msgstr "Empaquetador :" + +#, c-format +msgid "Architecture :" +msgstr "Arquitectura :" + +#, c-format +msgid "Build Date :" +msgstr "Data de constr.:" + +#, c-format +msgid "Install Date :" +msgstr "Data instal. :" + +#, c-format +msgid "Install Reason :" +msgstr "Raó instal. :" + +#, c-format +msgid "Install Script :" +msgstr "Script instal. :" + +#, c-format +msgid "Yes" +msgstr "Sí" + +#, c-format +msgid "No" +msgstr "No" + +#, c-format +msgid "MD5 Sum :" +msgstr "Suma MS5 :" + +#, c-format +msgid "Description :" +msgstr "Descripció :" + +#, c-format +msgid "Repository :" +msgstr "Repositori :" + +#, c-format +msgid "Backup Files:\n" +msgstr "Còpia de seguretat dels fitxers:\n" + +#, c-format +msgid "could not calculate checksums for %s\n" +msgstr "No es poden calcular les sumes de comprovació per %s\n" + +#, c-format +msgid "MODIFIED\t%s\n" +msgstr "MODIFICAT\t%s\n" + +#, c-format +msgid "Not Modified\t%s\n" +msgstr "No modificat\t%s\n" + +#, c-format +msgid "MISSING\t\t%s\n" +msgstr "FALTA\t\t%s\n" + +#, c-format +msgid "(none)\n" +msgstr "(cap)\n" + +#, c-format +msgid "no changelog available for '%s'.\n" +msgstr "no hi ha registre de canvis disponible per '%s'.\n" + +#, c-format +msgid "options" +msgstr "opcions" + +#, c-format +msgid "file(s)" +msgstr "fitxer(s)" + +#, c-format +msgid "package(s)" +msgstr "paquet(s)" + +#, c-format +msgid "usage" +msgstr "sintaxi" + +#, c-format +msgid "operation" +msgstr "operació" + +#, c-format +msgid "operations:\n" +msgstr "operacions:\n" + +#, c-format +msgid "" +"\n" +"use '%s {-h --help}' with an operation for available options\n" +msgstr "" +"\n" +"useu '%s {-h --help}' amb una operació per les opcions disponibles\n" + +#, c-format +msgid "" +" -c, --cascade remove packages and all packages that depend on them\n" +msgstr "" +" -c, --cascade elimina paquets i tots els paques que depenen d'ells\n" + +#, c-format +msgid " -d, --nodeps skip dependency checks\n" +msgstr " -d, --nodeps salta la comprovació de dependències\n" + +#, c-format +msgid " -k, --dbonly only remove database entry, do not remove files\n" +msgstr "" +" -k, --dbonly elimina només les entrades de la base de dades, no " +"elimina els fitxers\n" + +#, c-format +msgid " -n, --nosave remove configuration files as well\n" +msgstr " -n, --nosave elimina també els fitxers de configuració\n" + +#, c-format +msgid "" +" -s, --recursive remove dependencies also (that won't break packages)\n" +" (-ss includes explicitly installed dependencies too)\n" +msgstr "" +" -s, --recursive elimina també les dependències (que no trenquen " +"paquets)\n" +" (-ss inclou també les dependències instal·las " +"explícitament)\n" + +#, c-format +msgid "" +" -u, --unneeded remove unneeded packages (that won't break packages)\n" +msgstr "" +" -u, --unneeded elimina els paquets innecessaris (que no trenquen " +"paquets)\n" + +#, c-format +msgid " --asdeps install packages as non-explicitly installed\n" +msgstr "" +" --asdeps instal·la paquets com a no instal·lats explícitament\n" + +#, c-format +msgid " --asexplicit install packages as explicitly installed\n" +msgstr "" +" --asexplicit instal·la paquets com a explícitament instal·lats\n" + +#, c-format +msgid " -f, --force force install, overwrite conflicting files\n" +msgstr "" +" -f, --force força la instal·lació. sobreescrivint els fitxers amb " +"conflictes\n" + +#, c-format +msgid " -c, --changelog view the changelog of a package\n" +msgstr " -c, --changelog mostra el registre de canvis d'un paquet\n" + +#, c-format +msgid " -d, --deps list packages installed as dependencies [filter]\n" +msgstr "" +" -d, --deps llista els paquets instal·lats com a dependències " +"[filtre]\n" + +#, c-format +msgid " -e, --explicit list packages explicitly installed [filter]\n" +msgstr "" +" -e, --explicit llista els paquets instal·lats explícitament " +"[filtre]\n" + +#, c-format +msgid " -g, --groups view all members of a package group\n" +msgstr " -g, --groups mostra tots els membre d'un grup de paquets\n" + +#, c-format +msgid " -i, --info view package information (-ii for backup files)\n" +msgstr "" +" -i, --info mostra informació dels paquets (-ii per fitxers de " +"còpia de seguretat)\n" + +#, c-format +msgid "" +" -k, --check check that the files owned by the package(s) are " +"present\n" +msgstr "" +" -k, --check comprova que els fitxers que pertanyen als paquets són " +"presents\n" + +#, c-format +msgid " -l, --list list the contents of the queried package\n" +msgstr " -l, --list llista el contingut del paquet consultat\n" + +#, c-format +msgid "" +" -m, --foreign list installed packages not found in sync db(s) " +"[filter]\n" +msgstr "" +" -m, --foreign llista els paquets instal·lats que no es troben en les " +"bd sinc. [filtre]\n" + +#, c-format +msgid " -o, --owns <file> query the package that owns <file>\n" +msgstr " -o, --own <fitxer> consulta el paquet al que pertany <fitxer>\n" + +#, c-format +msgid " -p, --file <package> query a package file instead of the database\n" +msgstr "" +" -p, --file <paquet> consulta un fitxer de paquet enlloc de la base de " +"dades\n" + +#, c-format +msgid "" +" -s, --search <regex> search locally-installed packages for matching " +"strings\n" +msgstr "" +" -s, --search <exreg> cerca cadenes coincidents en paquets instal·lats " +"localment\n" + +#, c-format +msgid "" +" -t, --unrequired list packages not required by any package [filter]\n" +msgstr "" +" -t, --unrequired llista els paquets no requerits per cap paquet " +"[filtre]\n" + +#, c-format +msgid " -u, --upgrades list outdated packages [filter]\n" +msgstr " -u, --upgrades llista els paquets obsolets [filtre]\n" + +#, c-format +msgid " -q, --quiet show less information for query and search\n" +msgstr " -q, --quiet mostra menys informació per consultes i cerques\n" + +#, c-format +msgid "" +" -c, --clean remove old packages from cache directory (-cc for " +"all)\n" +msgstr "" +" -c, --clean elimina paquets antics del directori de memòria cau " +"(-cc per tots)\n" + +#, c-format +msgid " -i, --info view package information\n" +msgstr " -i, --info mostra informació del paquet\n" + +#, c-format +msgid " -l, --list <repo> view a list of packages in a repo\n" +msgstr " -l, --list <repo> mostra una llista dels paquets en un repositori\n" + +#, c-format +msgid "" +" -p, --print-uris print out URIs for given packages and their " +"dependencies\n" +msgstr "" +" -p, --print-uris imprimeix URI pels paquets donats i les seves " +"dependències\n" + +#, c-format +msgid " -s, --search <regex> search remote repositories for matching strings\n" +msgstr " -s, --search <exreg> cerca cadenes coincidents en repositoris remots\n" + +#, c-format +msgid "" +" -u, --sysupgrade upgrade installed packages (-uu allows downgrade)\n" +msgstr "" +" -u, --sysupgrade actualitza els paquets instal·lats (-uu permet la " +"desactualització)\n" + +#, c-format +msgid "" +" -w, --downloadonly download packages but do not install/upgrade " +"anything\n" +msgstr " -w, --downloadonly baixa paquets però no instal·la/actualitza res\n" + +#, c-format +msgid " -y, --refresh download fresh package databases from the server\n" +msgstr " -y, --refresh baixa bases de dades fresques des del servidor\n" + +#, c-format +msgid " --needed don't reinstall up to date packages\n" +msgstr " --needed no reinstal·la paquets al dia\n" + +#, c-format +msgid "" +" --ignore <pkg> ignore a package upgrade (can be used more than " +"once)\n" +msgstr "" +" --ignore <paq> ignora l'actualització d'un paquet (es pot usar més " +"d'un alhora)\n" + +#, c-format +msgid "" +" --ignoregroup <grp>\n" +" ignore a group upgrade (can be used more than once)\n" +msgstr "" +" --ignoregroup <grup>\n" +" ignora l'actualització d'un grup (es pot usar més " +"d'un alhora)\n" + +#, c-format +msgid " --config <path> set an alternate configuration file\n" +msgstr " --config <ruta> estableix un fitxer de configuració alternatiu\n" + +#, c-format +msgid " --logfile <path> set an alternate log file\n" +msgstr " --logfile <ruta> estableix un fitxer de registre alternatiu\n" + +#, c-format +msgid " --noconfirm do not ask for any confirmation\n" +msgstr " --noconfirm no demana cap confirmació\n" + +#, c-format +msgid "" +" --noprogressbar do not show a progress bar when downloading files\n" +msgstr "" +" --noprogressbar no mostra una barra de progrés en baixar fitxers\n" + +#, c-format +msgid "" +" --noscriptlet do not execute the install scriptlet if one exists\n" +msgstr "" +" --noscriptlet no executa l'scriptlet d'instal·lació si existeix\n" + +#, c-format +msgid " -v, --verbose be verbose\n" +msgstr " -v, --verbose detallat\n" + +#, c-format +msgid " --debug display debug messages\n" +msgstr " --debug mostra missatges de depuració\n" + +#, c-format +msgid " -r, --root <path> set an alternate installation root\n" +msgstr " -r, --root <ruta> estableix una arrel d'instal·lació alternativa\n" + +#, c-format +msgid " -b, --dbpath <path> set an alternate database location\n" +msgstr "" +" -b, --dbpath <ruta> estableix una ubicació alternativa de la base de " +"dades\n" + +#, c-format +msgid " --cachedir <dir> set an alternate package cache location\n" +msgstr "" +" --cachedir <dir> estableix una ubicació de la memòria cau de paquets " +"alternativa\n" + +#, c-format +msgid "" +" This program may be freely redistributed under\n" +" the terms of the GNU General Public License.\n" +msgstr "" +" Aquest programa es pot distribuir lliurement sota\n" +" els termes de la llicència pública general de GNU.\n" + +#, c-format +msgid "problem setting rootdir '%s' (%s)\n" +msgstr "problema en establir el directori arrel '%s' (%s)\n" + +#, c-format +msgid "problem setting dbpath '%s' (%s)\n" +msgstr "problema en establir la ruta de la base de dades '%s' (%s)\n" + +#, c-format +msgid "problem setting logfile '%s' (%s)\n" +msgstr "problema en establir el fitxer de registre '%s' (%s)\n" + +#, c-format +msgid "'%s' is not a valid debug level\n" +msgstr "'%s' no és un nivell de depuració vàlid\n" + +#, c-format +msgid "problem adding cachedir '%s' (%s)\n" +msgstr "problema en afegir directori de memòria cau '%s' (%s)\n" + +#, c-format +msgid "only one operation may be used at a time\n" +msgstr "només es pot usar una operació alhora\n" + +#, c-format +msgid "could not chdir to download directory %s\n" +msgstr "no es pot canviar al directori de baixades %s\n" + +#, c-format +msgid "running XferCommand: fork failed!\n" +msgstr "execució XferCommand: ha fallat la bifurcació!\n" + +#, c-format +msgid "config file %s could not be read.\n" +msgstr "no es pot llegir el fitxer de configuració %s.\n" + +#, c-format +msgid "config file %s, line %d: bad section name.\n" +msgstr "fitxer de configuració %s, línia %d: nom de secció incorrecte.\n" + +#, c-format +msgid "could not register '%s' database (%s)\n" +msgstr "no es pot registrar '%s' base de dades (%s)\n" + +#, c-format +msgid "config file %s, line %d: syntax error in config file- missing key.\n" +msgstr "" +"fitxer de configuració %s, línia %d: error de sintaxi en el fitxer de " +"configuració- falta una clau.\n" + +#, c-format +msgid "config file %s, line %d: All directives must belong to a section.\n" +msgstr "" +"fitxer de configuració %s, línia %d: totes les directives han de pertànyer a " +"una secció.\n" + +#, c-format +msgid "config file %s, line %d: directive '%s' not recognized.\n" +msgstr "fitxer de configuració %s, línia %d: directiva '%s' no reconeguda.\n" + +#, c-format +msgid "invalid value for 'CleanMethod' : '%s'\n" +msgstr "valor invàlid per 'CleanMethod' : '%s'\n" + +#, c-format +msgid "could not add server URL to database '%s': %s (%s)\n" +msgstr "no es pot afegir l'URL del servidor a la base de dades '%s': %s (%s)\n" + +#, c-format +msgid "failed to initialize alpm library (%s)\n" +msgstr "ha fallat en iniciar la llibreria alpm (%s)\n" + +#, c-format +msgid "you cannot perform this operation unless you are root.\n" +msgstr "no podeu realitzar aquesta operació si no sou root.\n" + +#, c-format +msgid "could not register 'local' database (%s)\n" +msgstr "no es pot registrar la base de dades 'local' (%s)\n" + +#, c-format +msgid "no operation specified (use -h for help)\n" +msgstr "no s'ha especificat cap operació (useu -h per ajuda)\n" + +#, c-format +msgid "no file was specified for --owns\n" +msgstr "no s'ha especificat cap fitxer per --owns\n" + +#, c-format +msgid "failed to read file '%s': %s\n" +msgstr "ha fallat en llegir el fitxer '%s': %s\n" + +#, c-format +msgid "cannot determine ownership of a directory\n" +msgstr "no es pot determinar el propietari d'un directori\n" + +#, c-format +msgid "cannot determine real path for '%s': %s\n" +msgstr "no es pot determinar la ruta real per '%s': %s\n" + +#, c-format +msgid "%s is owned by %s %s\n" +msgstr "%s pertany a %s %s\n" + +#, c-format +msgid "No package owns %s\n" +msgstr "Cap paquet conté %s\n" + +#, c-format +msgid "group \"%s\" was not found\n" +msgstr "no s'ha trobat el grup \"%s\"\n" + +#, c-format +msgid "root path too long\n" +msgstr "ruta arrel massa llarga\n" + +#, c-format +msgid "file path too long\n" +msgstr "ruta de fitxer massa llarga\n" + +#, c-format +msgid "%s: %d total files, %d missing file(s)\n" +msgstr "%s: %d fitxers en total, falten %d fitxers\n" + +#, c-format +msgid "no usable package repositories configured.\n" +msgstr "no s'ha configurat cap repositori de paquets usable.\n" + +#, c-format +msgid "no targets specified (use -h for help)\n" +msgstr "no s'ha especificat cap objectiu (useu -h per ajuda)\n" + +#, c-format +msgid "package \"%s\" not found\n" +msgstr "no s'ha trobat el paquet \"%s\"\n" + +#, c-format +msgid "%s not found, searching for group...\n" +msgstr "no s'ha trobat %s, s'està cercant per grup..\n" + +#, c-format +msgid "'%s': not found in local db\n" +msgstr "'%s': no s'ha trobat en la bd local\n" + +#, c-format +msgid ":: group %s:\n" +msgstr ":: grup %s:\n" + +#, c-format +msgid " Remove whole content?" +msgstr " Elimino tot el contingut?" + +#, c-format +msgid ":: Remove %s from group %s?" +msgstr ":: Elimino %s del grup %s?" + +#, c-format +msgid "failed to prepare transaction (%s)\n" +msgstr "ha fallat en preparar la transacció (%s)\n" + +#, c-format +msgid ":: %s: requires %s\n" +msgstr ":: %s: requereix %s\n" + +#, c-format +msgid "%s is designated as a HoldPkg.\n" +msgstr "%s és designat com a HoldPkg.\n" + +#, c-format +msgid "HoldPkg was found in target list. Do you want to continue?" +msgstr "S'ha trobat un HoldPkg en la llista d'objectius. Voleu continuar?" + +#, c-format +msgid "Do you want to remove these packages?" +msgstr "Voleu eliminar aquests paquets?" + +#, c-format +msgid "failed to commit transaction (%s)\n" +msgstr "ha fallat en publicar la transacció (%s)\n" + +#, c-format +msgid "could not access database directory\n" +msgstr "no es pot accedit al directori de la base de dades\n" + +#, c-format +msgid "Do you want to remove %s?" +msgstr "Voleu eliminar %s?" + +#, c-format +msgid "could not remove repository directory\n" +msgstr "no es pot eliminar el directori del repositori\n" + +#, c-format +msgid "Database directory: %s\n" +msgstr "Directori de la bd: %s\n" + +#, c-format +msgid "Do you want to remove unused repositories?" +msgstr "Voleu eliminar els repositoris no usats?" + +#, c-format +msgid "Database directory cleaned up\n" +msgstr "S'ha netejat el directori de la bd\n" + +#, c-format +msgid "Cache directory: %s\n" +msgstr "Directori de memòria cau: %s\n" + +#, c-format +msgid "Do you want to remove uninstalled packages from cache?" +msgstr "Voleu eliminar els paquets no instal·lats de la memòria cau?" + +#, c-format +msgid "Do you want to remove outdated packages from cache?" +msgstr "Voleu eliminar els paquets obsolets de la memòria cau?" + +#, c-format +msgid "removing old packages from cache...\n" +msgstr "s'estan eliminat els paquets obsolets de la memòria cau...\n" + +#, c-format +msgid "could not access cache directory\n" +msgstr "no es pot accedir al directori de memòria cau\n" + +#, c-format +msgid "File %s does not seem to be a valid package, remove it?" +msgstr "El fitxer %s no sembla ser un paquet vàlid, l'elimino?" + +#, c-format +msgid "Do you want to remove ALL files from cache?" +msgstr "Voleu eliminar TOTS els fitxers de la memòria cau?" + +#, c-format +msgid "removing all files from cache...\n" +msgstr "s'està eliminant tots els fitxers de la memòria cau...\n" + +#, c-format +msgid "could not remove cache directory\n" +msgstr "no es pot eliminar el directori de memòria cau\n" + +#, c-format +msgid "could not create new cache directory\n" +msgstr "no es pot crear un not directori de memòria cau\n" + +#, c-format +msgid "failed to update %s (%s)\n" +msgstr "ha fallat en actualitzar %s (%s)\n" + +#, c-format +msgid " %s is up to date\n" +msgstr " %s és al dia\n" + +#, c-format +msgid "failed to synchronize any databases\n" +msgstr "ha fallat en sincronitzar algunes bases de dades\n" + +#, c-format +msgid "repository '%s' does not exist\n" +msgstr "el repositori '%s' no existeix\n" + +#, c-format +msgid "package '%s' was not found in repository '%s'\n" +msgstr "no s'ha trobat el paquet '%s' en el repositori '%s'\n" + +#, c-format +msgid "package '%s' was not found\n" +msgstr "no s'ha trobat el paquet '%s'\n" + +#, c-format +msgid "repository \"%s\" was not found.\n" +msgstr "no s'ha trobat el repositori \"%s\".\n" + +#, c-format +msgid ":: Starting full system upgrade...\n" +msgstr ":: S'està iniciant una actualització completa del sistema...\n" + +#, c-format +msgid "skipping target: %s\n" +msgstr "s'ometrà l'objectiu: %s\n" + +#, c-format +msgid "%s package not found, searching for group...\n" +msgstr "no s'ha trobat el paquet %s, s'està cercant per grup...\n" + +#, c-format +msgid ":: group %s (including ignored packages):\n" +msgstr ":: grup %s (incloent paquets ignorats):\n" + +#, c-format +msgid ":: Install whole content?" +msgstr ":: Instal·lo tot el contingut?" + +#, c-format +msgid ":: Install %s from group %s?" +msgstr ":: Instal·lo %s del grup %s?" + +#, c-format +msgid "'%s': not found in sync db\n" +msgstr "'%s': no s'ha trobat en la bd sinc.\n" + +#, c-format +msgid ":: %s: conflicts with %s\n" +msgstr ":: %s: té conflictes amb %s\n" + +#, c-format +msgid " local database is up to date\n" +msgstr " la base de dades local és al dia\n" + +#, c-format +msgid "no URL for package: %s\n" +msgstr "no hi ha URL pel paquet: %s\n" + +#, c-format +msgid "Proceed with download?" +msgstr "Inicio la baixada?" + +#, c-format +msgid "Proceed with installation?" +msgstr "Inicio la instal·lació?" + +#, c-format +msgid "%s exists in both '%s' and '%s'\n" +msgstr "%s existeix en ambdós '%s' i '%s'\n" + +#, c-format +msgid "%s: %s exists in filesystem\n" +msgstr "%s: %s existeix en el sistema de fitxers\n" + +#, c-format +msgid "%s is invalid or corrupted\n" +msgstr "%s és invalid o corrupte\n" + +#, c-format +msgid "Errors occurred, no packages were upgraded.\n" +msgstr "Han ocorregut errors, no s'ha actualitzat cap paquet.\n" + +#, c-format +msgid ":: Synchronizing package databases...\n" +msgstr ":: S'estan sincronitzant les bases de dades de paquets...\n" + +#, c-format +msgid ":: The following packages should be upgraded first :\n" +msgstr ":: Primer s'han d'actualitzar els següents paquets:\n" + +#, c-format +msgid "" +":: Do you want to cancel the current operation\n" +":: and upgrade these packages now?" +msgstr "" +":: Voleu cancel·lar l'operació actual i\n" +":: actualitzar primer aquests paquets?" + +#, c-format +msgid "loading package data...\n" +msgstr "s'estan carregant les dades dels paquets...\n" + +#, c-format +msgid "" +"\n" +"errors occurred, no packages were upgraded.\n" +msgstr "" +"\n" +"han ocorregut errors, no s'ha actualitzat cap paquet.\n" + +#, c-format +msgid "failed to init transaction (%s)\n" +msgstr "ha fallat en iniciar la transacció (%s)\n" + +#, c-format +msgid "" +" if you're sure a package manager is not already\n" +" running, you can remove %s\n" +msgstr "" +" si esteu segur que no hi ha cap gestor de paquets\n" +" en execució, podeu eliminar %s\n" + +#, c-format +msgid "failed to release transaction (%s)\n" +msgstr "ha fallat en alliberar la transacció (%s)\n" + +#, c-format +msgid "None" +msgstr "Cap" + +#, c-format +msgid "Targets (%d):" +msgstr "Objectius (%d):" + +#, c-format +msgid "Total Download Size: %.2f MB\n" +msgstr "Mida total baixada: %.2f MB\n" + +#, c-format +msgid "Total Installed Size: %.2f MB\n" +msgstr "Mida total instal·lada: %.2f MB\n" + +#, c-format +msgid "Remove (%d):" +msgstr "Elimino (%d):" + +#, c-format +msgid "Total Removed Size: %.2f MB\n" +msgstr "Mida total eliminada: %.2f MB\n" + +#, c-format +msgid "New optional dependencies for %s\n" +msgstr "Noves dependències opcionals per %s\n" + +#, c-format +msgid "Optional dependencies for %s\n" +msgstr "Dependències opcionals per %s\n" + +#, c-format +msgid "[Y/n]" +msgstr "[S/n]" + +#, c-format +msgid "[y/N]" +msgstr "[s/N]" + +#, c-format +msgid "Y" +msgstr "S" + +#, c-format +msgid "YES" +msgstr "SÍ" + +#, c-format +msgid "N" +msgstr "N" + +#, c-format +msgid "NO" +msgstr "NO" + +#, c-format +msgid "error: %s" +msgstr "error: %s" + +#, c-format +msgid "warning: %s" +msgstr "avís: %s" + +#, c-format +msgid "function: %s" +msgstr "funció: %s" + +#, c-format +msgid "error: " +msgstr "error: " + +#, c-format +msgid "warning: " +msgstr "avís: " + +#, c-format +msgid "function: " +msgstr "funció: " + +msgid "WARNING:" +msgstr "AVÍS:" + +msgid "ERROR:" +msgstr "ERROR:" + +msgid "Cleaning up..." +msgstr "S'està netejant..." + +msgid "There is no agent set up to handle %s URLs. Check %s." +msgstr "No hi ha cap agent establert per gestionar URL %s. Comproveu %s." + +msgid "Aborting..." +msgstr "S'està cancel·lant..." + +msgid "The download program %s is not installed." +msgstr "El programa de baixades %s no està instal·lat." + +msgid "Pacman returned a fatal error (%i): %s" +msgstr "Pacman ha retornat un error fatal (%i): %s" + +msgid "Installing missing dependencies..." +msgstr "S'estan instal·lant les dependències que falten..." + +msgid "Pacman failed to install missing dependencies." +msgstr "Pacman ha fallat en instal·lar les dependències que falten." + +msgid "Failed to install all missing dependencies." +msgstr "Ha fallat en instal·lar les dependències que falten." + +msgid "Missing Dependencies:" +msgstr "Dependències que falten:" + +msgid "Failed to remove installed dependencies." +msgstr "Ha fallat en eliminar les dependències instal·lades." + +msgid "Retrieving Sources..." +msgstr "S'estan recuperant les fonts..." + +msgid "You do not have write permission to store downloads in %s." +msgstr "No teniu permisos d'escriptura per emmagatzemar les baixades en %s." + +msgid "Found %s in build dir" +msgstr "S'ha trobat %s en el directori de construcció" + +msgid "Using cached copy of %s" +msgstr "S'està usant la còpia de la memòria cau de %s" + +msgid "%s was not found in the build directory and is not a URL." +msgstr "%s no s'ha trobat en el directori de construcció i no és un URL." + +msgid "Downloading %s..." +msgstr "S'està baixant %s..." + +msgid "Failure while downloading %s" +msgstr "Fallada mentre es baixava %s" + +msgid "Generating checksums for source files..." +msgstr "S'estan generant les sumes de comprovació dels fitxer de codi font..." + +msgid "Cannot find openssl." +msgstr "No es pot trobar openssl." + +msgid "Invalid integrity algorithm '%s' specified." +msgstr "Algoritme d'integritat especificat '%s' invàlid." + +msgid "Unable to find source file %s to generate checksum." +msgstr "" +"No s'ha pogut trobar el fitxer de codi font %s per generar la suma de " +"comprovació." + +msgid "Validating source files with %s..." +msgstr "S'està validant el fitxer de codi font amb %s..." + +msgid "NOT FOUND" +msgstr "NO S'HA TROBAT" + +msgid "Passed" +msgstr "Ha passat" + +msgid "FAILED" +msgstr "HA FALLAT" + +msgid "One or more files did not pass the validity check!" +msgstr "Un o més fitxer no han passat la comprovació de la validació!" + +msgid "Integrity checks (%s) differ in size from the source array." +msgstr "" +"Les comprovacions de la integritat (%s) difereixen en mida de la cadena de les " +"fonts." + +msgid "Integrity checks are missing." +msgstr "Falten les comprovacions de la integritat." + +msgid "Extracting Sources..." +msgstr "S'està extraient el codi font..." + +msgid "Unable to find source file %s for extraction." +msgstr "No s'ha pogut trobar el fitxer de codi font %s per l'extracció." + +msgid "Extracting %s with %s" +msgstr "S'està extraient %s amb %s" + +msgid "Failed to extract %s" +msgstr "Ha fallat en extreure %s" + +msgid "Starting build()..." +msgstr "S'està iniciant la construcció()..." + +msgid "Build Failed." +msgstr "Ha fallat la construcció." + +msgid "Starting %s()..." +msgstr "Iniciant %s()..." + +msgid "Packaging Failed." +msgstr "Ha fallat l'empaquetatge." + +msgid "Tidying install..." +msgstr "S'està netejant la instal·lació..." + +msgid "Removing doc files..." +msgstr "S'estan eliminant els fitxers doc..." + +msgid "Purging other files..." +msgstr "S'estan purgant altres fitxers..." + +msgid "Compressing man and info pages..." +msgstr "S'està comprimint el manual i les pàgines d'informació..." + +msgid "Stripping debugging symbols from binaries and libraries..." +msgstr "" +"S'estan retirant els símbols de depuració dels binaris i les llibreries..." + +msgid "Removing libtool .la files..." +msgstr "S'estan eliminant els fitxers .la de libtool..." + +msgid "Removing empty directories..." +msgstr "S'estan eliminant els directoris buits..." + +msgid "Generating .PKGINFO file..." +msgstr "S'està generant el fitxer .PKGINFO..." + +msgid "Please add a license line to your %s!" +msgstr "Si us plau, afegiu una línia de llicència al vostre %s!" + +msgid "Example for GPL'ed software: license=('GPL')." +msgstr "Exemple per programari amb llicència GPL: license=('GPL')." + +msgid "Missing pkg/ directory." +msgstr "Falta el directori pkg/." + +msgid "Creating package..." +msgstr "S'està creant el paquet..." + +msgid "Adding install script..." +msgstr "S'està afegint l'script d'instal·lació..." + +msgid "Adding package changelog..." +msgstr "S'està afegint el registre de canvis del paquet..." + +msgid "Compressing package..." +msgstr "S'està comprimint el paquet..." + +msgid "'%s' is not a valid archive extension." +msgstr "'%s' no és una extensió de fitxer vàlida." + +msgid "Failed to create package file." +msgstr "Ha fallat en crear el fitxer de paquet." + +msgid "Creating source package..." +msgstr "S'està creant el paquet de codi font..." + +msgid "Adding %s..." +msgstr "S'està afegint %s..." + +msgid "Install script %s not found." +msgstr "No s'ha trobat l'script d'instal·lació %s." + +msgid "Compressing source package..." +msgstr "S'està comprimint el paquet de codi font..." + +msgid "Failed to create source package file." +msgstr "Ha fallat en crear el fitxer de paquet de codi font." + +msgid "Failed to install built package(s)." +msgstr "Ha fallat en instal·lar els paquets construïts." + +msgid "%s is not allowed to be empty." +msgstr "%s no pot estar buit." + +msgid "%s is not allowed to start with a hyphen." +msgstr "%s no pot començar amb un guionet." + +msgid "%s is not allowed to contain hyphens." +msgstr "%s no pot contenir guionets." + +msgid "%s is not available for the '%s' architecture." +msgstr "%s no és disponible per l'arquitectura '%s'." + +msgid "Note that many packages may need a line added to their %s" +msgstr "Noteu que molts paquets poden necessitar una línia afegida als seus %s" + +msgid "such as arch=('%s')." +msgstr "com ara arch=('%s')." + +msgid "Provides array cannot contain comparison (< or >) operators." +msgstr "La cadena proporcionada no pot contenir operadors de comparació (< o >)." + +msgid "Install scriptlet (%s) does not exist." +msgstr "L'scriptlet d'instal·lació (%s) no existeix." + +msgid "options array contains unknown option '%s'" +msgstr "la cadena d'opcions conté una opció desconeguda '%s'." + +msgid "missing package function for split package '%s'" +msgstr "falta la funció del paquet pel paquet dividit '%s'" + +msgid "Determining latest darcs revision..." +msgstr "S'està determinant la darrera revisió darcs..." + +msgid "Determining latest cvs revision..." +msgstr "S'està determinant la darrera revisió cvs..." + +msgid "Determining latest git revision..." +msgstr "S'està determinant la darrera revisió git..." + +msgid "Determining latest svn revision..." +msgstr "S'està determinant la darrera revisió svn..." + +msgid "Determining latest bzr revision..." +msgstr "S'està determinant la darrera revisió bzr..." + +msgid "Determining latest hg revision..." +msgstr "S'està determinant la darrera revisió hg..." + +msgid "Version found: %s" +msgstr "S'ha trobat la versió: %s" + +msgid "requires an argument" +msgstr "requereix un argument" + +msgid "unrecognized option" +msgstr "opció no reconeguda" + +msgid "invalid option" +msgstr "opció invàlida" + +msgid "Usage: %s [options]" +msgstr "Sintaxi: %s (opcions)" + +msgid "Options:" +msgstr "Opcions:" + +msgid " -A, --ignorearch Ignore incomplete arch field in %s" +msgstr " -A, --ignorearch Ignora camp arch incomplet en %s" + +msgid " -c, --clean Clean up work files after build" +msgstr " -c, --clean Neteja els fitxers de treball després de construir" + +msgid " -C, --cleancache Clean up source files from the cache" +msgstr " -C, --cleancache Neteja els fitxers font de la memòria cau" + +msgid " --config <config> Use an alternate config file (instead of '%s')" +msgstr "" +" --config <config> Usa un fitxer de configuració alternatiu (enlloc de '%s')" + +msgid " -d, --nodeps Skip all dependency checks" +msgstr " -d, --nodeps Salta totes les comprovacions de dependències" + +msgid " -e, --noextract Do not extract source files (use existing src/ dir)" +msgstr "" +" -e, --noextract No extreure fitxers font (usar els existents en el " +"directori src/)" + +msgid " -f, --force Overwrite existing package" +msgstr " -f, --force Sobreescriu els paquets existents" + +msgid " -g, --geninteg Generate integrity checks for source files" +msgstr "" +" -g, --geninteg Genera comprovacions de la integritat pels fitxers font" + +msgid " --skipinteg Do not fail when integrity checks are missing" +msgstr "" +" --skipinteg No fallar quan les comprovacions de la integritat falten" + +msgid " -h, --help This help" +msgstr " -h, --help Aquesta ajuda" + +msgid " -i, --install Install package after successful build" +msgstr "" +" -i, --install Instal·la el paquet després d'una construcció satisfactòria" + +msgid " -L, --log Log package build process" +msgstr " -L, --log Crea registre del procés de construcció del paquet" + +msgid " -m, --nocolor Disable colorized output messages" +msgstr " -m, --nocolor Deshabilita els missatges de sortida acolorits" + +msgid " -o, --nobuild Download and extract files only" +msgstr " -o, --nobuild Només baixa i extreu els fitxers" + +msgid " -p <buildscript> Use an alternate build script (instead of '%s')" +msgstr "" +" -p <buildscript> Usa un script d'instal·lació alternatiu (enlloc de '%s')" + +msgid " -r, --rmdeps Remove installed dependencies after a successful build" +msgstr "" +" -r, --rmdeps Elimina les dependències instal·lades després d'una " +"construcció satisfactòria" + +msgid " -R, --repackage Repackage contents of the package without rebuilding" +msgstr "" +" -R, --repackage Reempaqueta el contingut del paquet sense tornar a construir" + +msgid " -s, --syncdeps Install missing dependencies with pacman" +msgstr " -s, --syncdeps Instal·la les dependències que falten amb pacman" + +msgid "" +" --allsource Generate a source-only tarball including downloaded " +"sources" +msgstr "" +" --allsource Genera tarball només amb codi font incloent el codi font " +"baixat" + +msgid " --asroot Allow makepkg to run as root user" +msgstr " --asroot Permet a makepkg executar-se com a usuari root" + +msgid "" +" --holdver Prevent automatic version bumping for development " +"PKGBUILDs" +msgstr "" +" --holdver Evita els salts de versió automàtics per PKGBUILD de " +"desenvolupament " + +msgid "" +" --source Generate a source-only tarball without downloaded sources" +msgstr "" +" --source Genera tarball només amb codi font sense el codi font baixat" + +msgid "These options can be passed to pacman:" +msgstr "Es poden passar aquestes opcions a pacman:" + +msgid "" +" --noconfirm Do not ask for confirmation when resolving " +"dependencies" +msgstr " --noconfirm No demana confirmació en resoldre dependències" + +msgid " --noprogressbar Do not show a progress bar when downloading files" +msgstr " --noprogressbar No mostra un barra de progrés en baixar fitxers" + +msgid "If -p is not specified, makepkg will look for '%s'" +msgstr "Si no s'ha especificat -p, makepkg cercarà '%s'" + +msgid "" +"Copyright (c) 2006-2009 Pacman Development Team <pacman-dev@archlinux.org>." +"\\nCopyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>.\\n\\nThis is " +"free software; see the source for copying conditions.\\nThere is NO " +"WARRANTY, to the extent permitted by law.\\n" +msgstr "" +"Copyright (c) 2006-2009 L'equip de desenvolupament del Pacman <" +"pacman-dev@archlinux.org>." +"\\nCopyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>.\\n\\nAquest és un " +"programari lliure; mireu el codi font per les condicions de còpia.\\nNO hi ha " +"GARANTIA ampliada a la permesa per la llei.\\n" + +msgid "%s not found." +msgstr "no s'ha trobat %s" + +msgid "\\0--holdver and --forcever cannot both be specified" +msgstr "\\0--holdver i --forcever no es poden especificar alhora" + +msgid "Cleaning up ALL files from %s." +msgstr "S'estan netejant TOTS els fitxers de %s." + +msgid " Are you sure you wish to do this? " +msgstr " Esteu segur que desitgeu fer això?" + +msgid "Problem removing files; you may not have correct permissions in %s" +msgstr "Problema en eliminar fitxers: no teniu els permisos correctes en %s" + +msgid "Source cache cleaned." +msgstr "S'ha netejat la memòria cau del codi font." + +msgid "No files have been removed." +msgstr "No s'ha eliminat cap fitxer." + +msgid "Source destination must be defined in %s." +msgstr "S'ha de definir el desti de la font en %s." + +msgid "In addition, please run makepkg -C outside of your cache directory." +msgstr "" +"Addicionalment, si us plau executeu makepkg -C fora del vostre directori de " +"memòria cau." + +msgid "Running makepkg as root is a BAD idea and can cause" +msgstr "L'execució de makepkg com a root NO és una bona idea i pot causar" + +msgid "permanent, catastrophic damage to your system. If you" +msgstr "danys catastròfics permanents en el vostre sistema. Si" + +msgid "wish to run as root, please use the --asroot option." +msgstr "desitgeu executar com a root, useu l'opció --asroot." + +msgid "The --asroot option is meant for the root user only." +msgstr "L'opció --asroot està pensada només per a l'usuari root." + +msgid "Please rerun makepkg without the --asroot flag." +msgstr "Si us plau, executeu makepkg sense l'indicador --asroot." + +msgid "Fakeroot must be installed if using the 'fakeroot' option" +msgstr "S'ha d'instal·lar fakeroot si esteu usant l'opció 'fakeroot'" + +msgid "in the BUILDENV array in %s." +msgstr "en la cadena BUILDENV en %s." + +msgid "Running makepkg as an unprivileged user will result in non-root" +msgstr "L'execució de makepkg com a usuari sense privilegis resulta en que els" + +msgid "ownership of the packaged files. Try using the fakeroot environment by" +msgstr "fitxer no pertanyen a root. Intenteu usar l'entorn fakeroot per" + +msgid "placing 'fakeroot' in the BUILDENV array in %s." +msgstr "emplaçar 'fakeroot' en la cadena BUILDENV en %s." + +msgid "Do not use the '-F' option. This option is only for use by makepkg." +msgstr "No useu l'opció '-F'. Aquesta opció només s'ha d'usar amb makepkg." + +msgid "Cannot find the sudo binary! Is sudo installed?" +msgstr "No es pot trobar el binari sudo! Està instal·lat sudo?" + +msgid "Missing dependencies cannot be installed or removed as a normal user" +msgstr "" +"Les dependències que falten no es poden instal·lar o esborrar com a usuari " +"normal" + +msgid "without sudo; install and configure sudo to auto-resolve dependencies." +msgstr "" +"sense sudo; instal·leu i configureu sudo per resoldre automàticament les " +"dependències." + +msgid "%s does not exist." +msgstr "%s no existeix." + +msgid "%s contains CRLF characters and cannot be sourced." +msgstr "%s conté caràcters CRLF i no es pot afegir a les fonts." + +msgid "A package has already been built, installing existing package..." +msgstr "Un paquet ja s'ha construït, s'està instal·lant el paquet existent..." + +msgid "A package has already been built. (use -f to overwrite)" +msgstr "Un paquet ja s'ha construït. (useu -f per sobreescriure'l)" + +msgid "The package group has already been built, installing existing packages..." +msgstr "" +"El grup de paquets ja s'ha construït, s'estan instal·lant els paquets " +"existents..." + +msgid "The package group has already been built. (use -f to overwrite)" +msgstr "El grup de paquets ja s'ha construït. (useu -f per sobreescriure'ls)" + +msgid "Part of the package group has already been built. (use -f to overwrite)" +msgstr "" +"Part del grup de paquets ja s'ha construït. (useu -f per sobreescriure'ls)" + +msgid "Leaving fakeroot environment." +msgstr "S'està sortint de l'entorn fakeroot." + +msgid "Making package: %s" +msgstr "S'està fent el paquet: %s" + +msgid "Source package created: %s" +msgstr "Paquet de codi font creat: %s" + +msgid "Skipping dependency checks." +msgstr "S'està ometent la comprovació de les dependències." + +msgid "Checking Runtime Dependencies..." +msgstr "S'estan comprovant les dependències en temps d'execució..." + +msgid "Checking Buildtime Dependencies..." +msgstr "S'estan comprovant les dependències en temps de construcció..." + +msgid "Could not resolve all dependencies." +msgstr "No es poden resoldre totes les dependències." + +msgid "pacman was not found in PATH; skipping dependency checks." +msgstr "" +"No s'ha trobat pacman en PATH; s'està ometent la comprovació de les " +"dependències." + +msgid "Skipping source retrieval -- using existing src/ tree" +msgstr "Ometent recuperació de fonts -- usant les existents en l'arbre src/" + +msgid "Skipping source integrity checks -- using existing src/ tree" +msgstr "Ometent comprovació integritat -- usant les existents en l'arbre src/" + +msgid "Skipping source extraction -- using existing src/ tree" +msgstr "Ometent extracció de les fonts -- usant les existents en l'arbre src/" + +msgid "The source directory is empty, there is nothing to build!" +msgstr "El directori de codi font és buit, no hi ha res a construir!" + +msgid "The package directory is empty, there is nothing to repackage!" +msgstr "El directori del paquet és buit, no hi ha res a reempaquetar!" + +msgid "Sources are ready." +msgstr "Les fonts estan preparades." + +msgid "Removing existing pkg/ directory..." +msgstr "S'està eliminant el directori pkg/ existent..." + +msgid "Entering fakeroot environment..." +msgstr "S'està entrant en l'entorn fakeroot..." + +msgid "Finished making: %s" +msgstr "S'ha acabat de fer: %s" + +msgid "Usage: %s [pacman_db_root]" +msgstr "Sintaxi: %s [arrel_bd_pacman]" + +msgid "" +"pacman-optimize is a little hack that should improve the performance\\nof " +"pacman when reading/writing to its filesystem-based database.\\n\\n" +msgstr "" +"pacman-optimize és un petit arranjament que hauria de millorar el " +"rendiment\\nde pacman en llegir/escriure a la seva base de dades basada en un " +"sistema de fitxers.\\n\\n" + +msgid "" +"Because pacman uses many small files to keep track of packages,\\nthere is a " +"tendency for these files to become fragmented over time.\\nThis script " +"attempts to relocate these small files into one\\ncontinuous location on " +"your hard drive. The result is that the hard\\ndrive should be able to read " +"them faster, since the hard drive head\\ndoes not have to move around the " +"disk as much.\\n" +msgstr "" +"Com que pacman usa molts fitxers petits per mantenir el seguiment dels paquets." +"\\nHi ha tendència a que aquests fitxers es fragmentin.\\nAquest script " +"intenta reassignar aquests petits fitxers en una\\nubicació contínua en el " +"vostre disc dur. Des resultes d'això el disc\\ndur hauria de poder llegir-los " +"més fàcilment, ja que la capçalera del disc\\nno s'ha de moure massa per tot " +"el disc.\\n" + +msgid "diff tool was not found, please install diffutils." +msgstr "no s'ha trobat l'eina diff, si us plau instal·leu diffutils." + +msgid "%s does not exist or is not a directory." +msgstr "%s no existeix o no és un directori." + +msgid "You must have correct permissions to optimize the database." +msgstr "Heu de tenir els permisos correctes per optimitzar la base de dades." + +msgid "Pacman lock file was found. Cannot run while pacman is running." +msgstr "" +"S'ha trobat el fitxer de bloqueig del Pacman. No es pot executar mentre pacman " +"és en execució." + +msgid "ERROR: Can not create temp directory for database building." +msgstr "" +"ERROR: no es pot crear el directori temporal per construir la base de dades." + +msgid "MD5sum'ing the old database..." +msgstr "S'està MD5sumant la antiga base de dades..." + +msgid "Tar'ing up %s..." +msgstr "Creant Tar de %s..." + +msgid "Tar'ing up %s failed." +msgstr "Ha fallat la creació del Tar de %s." + +msgid "Making and MD5sum'ing the new database..." +msgstr "Fent i MD5sumant la nova base de dades..." + +msgid "Untar'ing %s failed." +msgstr "Ha fallat en fer Untar de %s" + +msgid "Syncing database to disk..." +msgstr "S'està sincronitzant la base de dades al disc..." + +msgid "Checking integrity..." +msgstr "S'està comprovant la integritat..." + +msgid "Integrity check FAILED, reverting to old database." +msgstr "" +"Ha FALLAT la comprovació de la integritat, s'està revertint a la antiga base " +"de dades." + +msgid "Rotating database into place..." +msgstr "S'està rotant la base de dades en l'emplaçament..." + +msgid "Finished. Your pacman database has been optimized." +msgstr "Ha finalitzat. S'ha optimitzat la base de dades del pacman." + +msgid "Usage: repo-add [-q] <path-to-db> <package|delta> ...\\n" +msgstr "Sintaxi: repo-add [-q] <ruta-a-la-bd> <paquet|delta> ...\\n" + +msgid "Usage: repo-remove [-q] <path-to-db> <packagename|delta> ...\\n\\n" +msgstr "Sintaxi: repo-remove [-q] <ruta-a-la-bd> <nomdepaquet|delta> ...\\n\\n" + +msgid "" +"repo-add will update a package database by reading a package file." +"\\nMultiple packages to add can be specified on the command line.\\n\\n" +msgstr "" +"repo-add actualitza una base de dades de paquets llegint un fitxer de paquet." +"\\nEs poden especificar múltiples paquets a afegir en la línia d'ordres.\\n\\n" + +msgid "" +"repo-remove will update a package database by removing the package name" +"\\nspecified on the command line from the given repo database. Multiple" +"\\npackages to remove can be specified on the command line.\\n\\n" +msgstr "" +"repo-remove actualitza una base de dades de paquets eliminant el nom del " +"paquet\\nespecificat en la línia d'ordres de la base de dades del repositori " +"donada.\\nEs poden especificar múltiples paquets a eliminar en la línia " +"d'ordres.\\n\\n" + +msgid "" +"Use the -q/--quiet flag to minimize output to basic messages, warnings," +"\\nand errors\\n\\n" +msgstr "" +"Useu el marcador -q/--quiet per minimitzar la sortida a missatges " +"bàsics,\\navisos i erros\\n\\n" + +msgid "Example: repo-add /path/to/repo.db.tar.gz pacman-3.0.0.pkg.tar.gz" +msgstr "Exemple: repo-add /ruta/a/repo.bd.tar.gz pacman-3.0.0.pkg.tar.gz" + +msgid "Example: repo-remove /path/to/repo.db.tar.gz kernel26" +msgstr "Exemple: repo-remove /ruta/a/repo.bd.tar.gz kernel26" + +msgid "" +"Copyright (C) 2006-2008 Aaron Griffin <aaron@archlinux.org>.\\nCopyright (c) " +"2007-2008 Dan McGee <dan@archlinux.org>.\\n\\nThis is free software; see the " +"source for copying conditions.\\nThere is NO WARRANTY, to the extent " +"permitted by law.\\n" +msgstr "" +"Copyright (C) 2006-2008 Aaron Griffin <aaron@archlinux.org>.\\nCopyright (c) " +"2007-2008 Dan McGee <dan@archlinux.org>.\\n\\nAquest és un programari lliure; " +"mireu el codi font per les condicions de còpia.\\nNO hi ha cap GARANTIA " +"ampliada a " +"la permesa per la llei.\\n" + +msgid "Creating 'deltas' db entry..." +msgstr "S'està creant la entrada 'deltas' de la bd..." + +msgid "An entry for '%s' already existed" +msgstr "Ja existeix una entrada per '%s'" + +msgid "Removing existing entry '%s'..." +msgstr "S'està eliminant l'entrada existent '%s'..." + +msgid "Invalid package file '%s'." +msgstr "Fitxer de paquet invàlid '%s'..." + +msgid "Creating 'desc' db entry..." +msgstr "S'està creant l'entrada 'desc' en la bd..." + +msgid "Computing md5 checksums..." +msgstr "S'estan computant les sumes de comprovació md5" + +msgid "Creating 'depends' db entry..." +msgstr "S'està creant l'entrada 'depends' en la bd..." + +msgid "Failed to acquire lockfile: %s." +msgstr "Ha fallat en adquirir el fitxer de bloqueig: %s." + +msgid "Held by process %s" +msgstr "Retingut pel procés %s" + +msgid "Repository file '%s' is not a proper pacman database." +msgstr "El fitxer de repositori '%s' no és una base de dades de pacman adequada." + +msgid "Extracting database to a temporary location..." +msgstr "S'està extraient la base de dades a una ubicació temporal...." + +msgid "Repository file '%s' was not found." +msgstr "No s'ha trobat el fitxer de repositori '%s'." + +msgid "Repository file '%s' could not be created." +msgstr "No s'ha pogut crear el fitxer de repositori '%s'." + +msgid "File '%s' not found." +msgstr "No s'ha trobat el fitxer '%s'." + +msgid "Adding delta '%s'" +msgstr "S'està afegint delta '%s'" + +msgid "Cannot find the xdelta3 binary! Is xdelta3 installed?" +msgstr "No es pot trobar el binari xdelta3! Està instal·lat xdelta3?" + +msgid "'%s' is not a package file, skipping" +msgstr "'%s' no és un fitxer de paquet. S'està ometent" + +msgid "Adding package '%s'" +msgstr "S'està afegint el paquet '%s'" + +msgid "Searching for delta '%s'..." +msgstr "S'està cercant delta '%s'..." + +msgid "Delta matching '%s' not found." +msgstr "No s'ha trobat delta coincident per '%s'." + +msgid "Searching for package '%s'..." +msgstr "S'està cercant el paquet '%s'..." + +msgid "Package matching '%s' not found." +msgstr "No s'ha trobat coincidència pel paquet '%s'." + +msgid "Invalid command name '%s' specified." +msgstr "S'ha especificat un nom d'ordre '%s' invàlid." + +msgid "Cannot create temp directory for database building." +msgstr "" +"No s'ha pogut crear el directori temporal per construir la base de dades." + +msgid "the -f and --force options are no longer recognized" +msgstr "les opcions -f i --force ja no es reconeixen" + +msgid "use options=(force) in the PKGBUILD instead" +msgstr "substituïu-les per opcions=(force) en el PKGBUILD" + +msgid "Creating updated database file '%s'" +msgstr "S'està creant el fitxer de base de dades actualitzada '%s'" + +msgid "'%s' does not have a valid archive extension." +msgstr "'%s' no té una extensió d'arxiu vàlida." + +msgid "No packages remain, creating empty database." +msgstr "No queda cap paquet, s'està creant una base de dades buida." + +msgid "No packages modified, nothing to do." +msgstr "No s'ha modificat cap paquet, res a fer." + + diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 5d656534..330acb98 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -16,7 +16,7 @@ EXTRA_DIST = \ makepkg.sh.in \ pacman-optimize.sh.in \ pkgdelta.sh.in \ - rankmirrors.py.in \ + rankmirrors.sh.in \ repo-add.sh.in # Files that should be removed, but which Automake does not know. @@ -62,7 +62,7 @@ $(OURSCRIPTS): Makefile makepkg: $(srcdir)/makepkg.sh.in pacman-optimize: $(srcdir)/pacman-optimize.sh.in pkgdelta: $(srcdir)/pkgdelta.sh.in -rankmirrors: $(srcdir)/rankmirrors.py.in +rankmirrors: $(srcdir)/rankmirrors.sh.in repo-add: $(srcdir)/repo-add.sh.in repo-remove: $(srcdir)/repo-add.sh.in rm -f repo-remove diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in index f58e2742..5bd294c1 100644 --- a/scripts/makepkg.sh.in +++ b/scripts/makepkg.sh.in @@ -27,8 +27,8 @@ # makepkg uses quite a few external programs during its execution. You # need to have at least the following installed for makepkg to function: -# awk, bsdtar (libarchive), bzip2, coreutils, fakeroot, find (findutils), -# getopt (util-linux), gettext, grep, gzip, openssl, sed +# bsdtar (libarchive), bzip2, coreutils, fakeroot, find (findutils), +# getopt (util-linux), gettext, grep, gzip, openssl, sed, tput (ncurses) # gettext initialization export TEXTDOMAIN='pacman' @@ -46,8 +46,9 @@ pkgdir="$startdir/pkg" 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') +splitpkg_overrides=('pkgver' 'pkgrel' 'pkgdesc' 'arch' 'license' 'groups' \ + 'depends' 'optdepends' 'provides' 'conflicts' 'replaces' \ + 'backup' 'options' 'install' 'changelog') readonly -a packaging_options other_options splitpkg_overrides # Options @@ -69,9 +70,10 @@ LOGGING=0 SOURCEONLY=0 IGNOREARCH=0 HOLDVER=0 +BUILDFUNC=0 PKGFUNC=0 SPLITPKG=0 -COLORMSG=0 +PKGLIST="" # Forces the pkgver of the current PKGBUILD. Used by the fakeroot call # when dealing with svn/cvs/etc PKGBUILDs. @@ -83,47 +85,27 @@ PACMAN_OPTS= plain() { local mesg=$1; shift - if [ $COLORMSG -eq 1 ]; then - printf "\033[1;1m ${mesg}\033[1;0m\n" "$@" >&2 - else - printf " ${mesg}\n" "$@" >&2 - fi + printf "${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } msg() { local mesg=$1; shift - if [ $COLORMSG -eq 1 ]; then - printf "\033[1;32m==>\033[1;0m\033[1;1m ${mesg}\033[1;0m\n" "$@" >&2 - else - printf "==> ${mesg}\n" "$@" >&2 - fi + printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } msg2() { local mesg=$1; shift - if [ $COLORMSG -eq 1 ]; then - printf "\033[1;34m ->\033[1;0m\033[1;1m ${mesg}\033[1;0m\n" "$@" >&2 - else - printf " -> ${mesg}\n" "$@" >&2 - fi + printf "${BLUE} ->${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } warning() { local mesg=$1; shift - if [ $COLORMSG -eq 1 ]; then - printf "\033[1;33m==> $(gettext "WARNING:")\033[1;0m\033[1;1m ${mesg}\033[1;0m\n" "$@" >&2 - else - printf "==> $(gettext "WARNING:") ${mesg}\n" "$@" >&2 - fi + printf "${YELLOW}==> $(gettext "WARNING:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } error() { local mesg=$1; shift - if [ $COLORMSG -eq 1 ]; then - printf "\033[1;31m==> $(gettext "ERROR:")\033[1;0m\033[1;1m ${mesg}\033[1;0m\n" "$@" >&2 - else - printf "==> $(gettext "ERROR:") ${mesg}\n" "$@" >&2 - fi + printf "${RED}==> $(gettext "ERROR:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } @@ -132,10 +114,11 @@ error() { # the fakeroot call, the error message will be printed by the main call. ## trap_exit() { - if [ "$INFAKEROOT" -eq 0 ]; then + if (( ! INFAKEROOT )); then echo error "$@" fi + [[ -n $srclinks ]] && rm -rf "$srclinks" exit 1 } @@ -146,25 +129,36 @@ trap_exit() { clean_up() { local EXIT_CODE=$? - if [ "$INFAKEROOT" -eq 1 ]; then + if (( INFAKEROOT )); then # Don't clean up when leaving fakeroot, we're not done yet. return fi - if [ $EXIT_CODE -eq 0 -a "$CLEANUP" -eq 1 ]; then + if (( ! EXIT_CODE && CLEANUP )); then # If it's a clean exit and -c/--clean has been passed... msg "$(gettext "Cleaning up...")" rm -rf "$pkgdir" "$srcdir" - if [ -n "$pkgbase" ]; then + if [[ -n $pkgbase ]]; then # Can't do this unless the BUILDSCRIPT has been sourced. - rm -f "${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-build.log"* - if [ "$PKGFUNC" -eq 1 ]; then + if (( BUILDFUNC )); then + rm -f "${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-build.log"* + fi + if (( PKGFUNC )); then rm -f "${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-package.log"* - elif [ "$SPLITPKG" -eq 1 ]; then + elif (( SPLITPKG )); then for pkg in ${pkgname[@]}; do - rm -f "${pkg}-${pkgver}-${pkgrel}-${CARCH}-package.log"* + rm -f "${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-package_${pkg}.log"* done fi + + # clean up dangling symlinks to packages + for pkg in ${pkgname[@]}; do + for file in ${pkg}-*-*-${CARCH}${PKGEXT}; do + if [[ -h $file && ! -e $file ]]; then + rm -f $file + fi + done + done fi fi @@ -175,6 +169,7 @@ clean_up() { ## # Signal Traps ## +set -E trap 'clean_up' 0 trap 'trap_exit "$(gettext "TERM signal caught. Exiting...")"' TERM HUP QUIT trap 'trap_exit "$(gettext "Aborted by user! Exiting...")"' INT @@ -187,15 +182,15 @@ trap 'trap_exit "$(gettext "An unknown error has occurred. Exiting...")"' ERR # extract the filename from a source entry get_filename() { # if a filename is specified, use it - local filename=$(echo $1 | sed 's|::.*||') + local filename="${1%%::*}" # if it is just an URL, we only keep the last component - echo "$filename" | sed 's|^.*://.*/||g' + echo "${filename##*/}" } # extract the URL from a source entry get_url() { # strip an eventual filename - echo $1 | sed 's|.*::||' + echo "${1#*::}" } ## @@ -209,14 +204,14 @@ get_url() { ## check_option() { local ret=$(in_opt_array "$1" ${options[@]}) - if [ "$ret" != '?' ]; then + if [[ $ret != '?' ]]; then echo $ret return fi # fall back to makepkg.conf options ret=$(in_opt_array "$1" ${OPTIONS[@]}) - if [ "$ret" != '?' ]; then + if [[ $ret != '?' ]]; then echo $ret return fi @@ -245,15 +240,15 @@ check_buildenv() { # ? - not found ## in_opt_array() { - local needle=$(echo $1 | tr '[:upper:]' '[:lower:]'); shift + local needle="${1,,}"; shift local opt for opt in "$@"; do - opt=$(echo $opt | tr '[:upper:]' '[:lower:]') - if [ "$opt" = "$needle" ]; then + opt="${opt,,}" + if [[ $opt = $needle ]]; then echo 'y' # Enabled return - elif [ "$opt" = "!$needle" ]; then + elif [[ $opt = "!$needle" ]]; then echo 'n' # Disabled return fi @@ -270,10 +265,10 @@ in_opt_array() { ## in_array() { local needle=$1; shift - [ -z "$1" ] && return 1 # Not Found + [[ -z $1 ]] && return 1 # Not Found local item for item in "$@"; do - [ "$item" = "$needle" ] && return 0 # Found + [[ $item = $needle ]] && return 0 # Found done return 1 # Not Found } @@ -281,28 +276,28 @@ in_array() { get_downloadclient() { # $1 = URL with valid protocol prefix local url=$1 - local proto=$(echo "$url" | sed 's|://.*||') + local proto="${url%%://*}" # loop through DOWNLOAD_AGENTS variable looking for protocol local i for i in "${DLAGENTS[@]}"; do - local handler=$(echo $i | sed 's|::.*||') - if [ "$proto" = "$handler" ]; then - agent=$(echo $i | sed 's|^.*::||') + local handler="${i%%::*}" + if [[ $proto = $handler ]]; then + agent="${i##*::}" break fi done # if we didn't find an agent, return an error - if [ -z "$agent" ]; then + if [[ -z $agent ]]; then 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 # ensure specified program is installed - local program="$(echo $agent | awk '{print $1 }')" - if [ ! -x "$program" ]; then + local program="${agent%% *}" + if [[ ! -x $program ]]; then local baseprog=$(basename $program) error "$(gettext "The download program %s is not installed.")" "$baseprog" plain "$(gettext "Aborting...")" @@ -320,7 +315,7 @@ download_file() { # destination file local file=$3 # temporary download file, default to last component of the URL - local dlfile=$(echo "$url" | sed 's|^.*://.*/||g') + local dlfile="${url##*/}" # replace %o by the temporary dlfile if it exists if echo "$dlcmd" | grep -q "%o" ; then @@ -334,52 +329,61 @@ download_file() { dlcmd="$dlcmd \"$url\"" fi - eval $dlcmd || return $? + local ret=0 + eval "$dlcmd || ret=\$?" + if (( ret )); then + [[ ! -s $dlfile ]] && rm -f -- "$dlfile" + return $ret + fi # rename the temporary download file to the final destination - if [ "$dlfile" != "$file" ]; then + if [[ $dlfile != $file ]]; then mv -f "$SRCDEST/$dlfile" "$SRCDEST/$file" fi } +run_pacman() { + local ret=0 + if (( ! ASROOT )) && [[ $1 != "-T" ]] && sudo -l $PACMAN &>/dev/null; then + sudo $PACMAN $PACMAN_OPTS "$@" || ret=$? + else + $PACMAN $PACMAN_OPTS "$@" || ret=$? + fi + return $ret +} + check_deps() { - [ $# -gt 0 ] || return + (( $# > 0 )) || return - pmout=$(pacman $PACMAN_OPTS -T "$@") + local ret=0 + pmout=$(run_pacman -T "$@") ret=$? - if [ $ret -eq 127 ]; then #unresolved deps + if (( ret == 127 )); then #unresolved deps echo "$pmout" - elif [ $ret -ne 0 ]; then - error "$(gettext "Pacman returned a fatal error (%i): %s")" "$ret" "$pmout" + elif (( ret )); then + error "$(gettext "'%s' returned a fatal error (%i): %s")" "$PACMAN" "$ret" "$pmout" exit 1 fi } -handledeps() { +handle_deps() { local R_DEPS_SATISFIED=0 local R_DEPS_MISSING=1 - [ $# -eq 0 ] && return $R_DEPS_SATISFIED + (( $# == 0 )) && return $R_DEPS_SATISFIED local deplist="$*" - if [ "$DEP_BIN" -eq 0 ]; then + if (( ! DEP_BIN )); then return $R_DEPS_MISSING fi - if [ "$DEP_BIN" -eq 1 ]; then + if (( DEP_BIN )); then # install missing deps from binary packages (using pacman -S) msg "$(gettext "Installing missing dependencies...")" - local ret=0 - if [ "$ASROOT" -eq 0 ]; then - sudo pacman $PACMAN_OPTS -S --asdeps $deplist || ret=$? - else - pacman $PACMAN_OPTS -S --asdeps $deplist || ret=$? - fi - - if [ $ret -ne 0 ]; then - error "$(gettext "Pacman failed to install missing dependencies.")" + if ! run_pacman -S --asdeps $deplist; then + error "$(gettext "'%s' failed to install missing dependencies.")" "$PACMAN" exit 1 # TODO: error code fi fi @@ -400,16 +404,16 @@ resolve_deps() { local R_DEPS_MISSING=1 local deplist="$(check_deps $*)" - if [ -z "$deplist" ]; then + if [[ -z $deplist ]]; then return $R_DEPS_SATISFIED fi - if handledeps $deplist; then + if handle_deps $deplist; then pkgdeps="$pkgdeps $deplist" # check deps again to make sure they were resolved deplist="$(check_deps $*)" - [ -z "$deplist" ] && return $R_DEPS_SATISFIED - elif [ "$DEP_BIN" -eq 1 ]; then + [[ -z $deplist ]] && return $R_DEPS_SATISFIED + elif (( DEP_BIN )); then error "$(gettext "Failed to install all missing dependencies.")" fi @@ -425,26 +429,20 @@ resolve_deps() { # fix flyspray bug #5923 remove_deps() { # $pkgdeps is a GLOBAL variable, set by resolve_deps() - [ "$RMDEPS" -eq 0 ] && return - [ -z "$pkgdeps" ] && return + (( ! RMDEPS )) && return + [[ -z $pkgdeps ]] && return local dep depstrip deplist deplist="" for dep in $pkgdeps; do - depstrip=$(echo $dep | sed -e 's|=.*$||' -e 's|>.*$||' -e 's|<.*$||') + depstrip="${dep%%[<=>]*}" deplist="$deplist $depstrip" done msg "Removing installed dependencies..." - local ret=0 - if [ "$ASROOT" -eq 0 ]; then - sudo pacman $PACMAN_OPTS -Rns $deplist || ret=$? - else - pacman $PACMAN_OPTS -Rns $deplist || ret=$? - fi - # Fixes FS#10039 - exit cleanly as package has built successfully - if [ $ret -ne 0 ]; then + # exit cleanly on failure to remove deps as package has been built successfully + if ! run_pacman -Rns $deplist; then warning "$(gettext "Failed to remove installed dependencies.")" return 0 fi @@ -453,7 +451,7 @@ remove_deps() { download_sources() { msg "$(gettext "Retrieving Sources...")" - if [ ! -w "$SRCDEST" ] ; then + if [[ ! -w $SRCDEST ]] ; then error "$(gettext "You do not have write permission to store downloads in %s.")" "$SRCDEST" plain "$(gettext "Aborting...")" exit 1 @@ -465,12 +463,12 @@ download_sources() { for netfile in "${source[@]}"; do local file=$(get_filename "$netfile") local url=$(get_url "$netfile") - if [ -f "$startdir/$file" ]; then + if [[ -f $startdir/$file ]]; then msg2 "$(gettext "Found %s in build dir")" "$file" rm -f "$srcdir/$file" ln -s "$startdir/$file" "$srcdir/" continue - elif [ -f "$SRCDEST/$file" ]; then + elif [[ -f $SRCDEST/$file ]]; then msg2 "$(gettext "Using cached copy of %s")" "$file" rm -f "$srcdir/$file" ln -s "$SRCDEST/$file" "$srcdir/" @@ -478,7 +476,7 @@ download_sources() { fi # if we get here, check to make sure it was a URL, else fail - if [ "$file" = "$url" ]; then + if [[ $file = $url ]]; then error "$(gettext "%s was not found in the build directory and is not a URL.")" "$file" exit 1 # $E_MISSING_FILE fi @@ -490,7 +488,7 @@ download_sources() { # fix flyspray bug #3289 local ret=0 download_file "$dlclient" "$url" "$file" || ret=$? - if [ $ret -gt 0 ]; then + if (( ret )); then error "$(gettext "Failure while downloading %s")" "$file" plain "$(gettext "Aborting...")" exit 1 @@ -513,7 +511,7 @@ generate_checksums() { local integ for integ in ${INTEGRITY_CHECK[@]}; do - integ="$(echo $integ | tr '[:upper:]' '[:lower:]')" + integ="${integ,,}" case "$integ" in md5|sha1|sha256|sha384|sha512) : ;; *) @@ -525,19 +523,18 @@ generate_checksums() { local numsrc=${#source[@]} echo -n "${integ}sums=(" - local i=0; + local i local indent='' - while [ $i -lt $((${#integ}+6)) ]; do + for (( i = 0; i < ${#integ} + 6; i++ )); do indent="$indent " - i=$(($i+1)) done local netfile for netfile in "${source[@]}"; do local file="$(get_filename "$netfile")" - if [ ! -f "$file" ] ; then - if [ ! -f "$SRCDEST/$file" ] ; then + if [[ ! -f $file ]] ; then + if [[ ! -f $SRCDEST/$file ]] ; then error "$(gettext "Unable to find source file %s to generate checksum.")" "$file" plain "$(gettext "Aborting...")" exit 1 @@ -546,11 +543,12 @@ generate_checksums() { fi fi - local sum="$(openssl dgst -${integ} "$file" | awk '{print $NF}')" - [ $ct -gt 0 ] && echo -n "$indent" + local sum="$(openssl dgst -${integ} "$file")" + sum=${sum##* } + (( ct )) && echo -n "$indent" echo -n "'$sum'" ct=$(($ct+1)) - [ $ct -lt $numsrc ] && echo + (( $ct < $numsrc )) && echo done echo ")" @@ -558,7 +556,7 @@ generate_checksums() { } check_checksums() { - [ ${#source[@]} -eq 0 ] && return 0 + (( ! ${#source[@]} )) && return 0 if [ ! $(type -p openssl) ]; then error "$(gettext "Cannot find openssl.")" @@ -569,7 +567,7 @@ check_checksums() { 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 + if (( ${#integrity_sums[@]} == ${#source[@]} )); then msg "$(gettext "Validating source files with %s...")" "${integ}sums" correlation=1 local errors=0 @@ -580,8 +578,8 @@ check_checksums() { file="$(get_filename "$file")" echo -n " $file ... " >&2 - if [ ! -f "$file" ] ; then - if [ ! -f "$SRCDEST/$file" ] ; then + if [[ ! -f $file ]] ; then + if [[ ! -f $SRCDEST/$file ]] ; then echo "$(gettext "NOT FOUND")" >&2 errors=1 found=0 @@ -590,10 +588,11 @@ check_checksums() { fi fi - if [ $found -gt 0 ] ; then - local expectedsum="$(echo ${integrity_sums[$idx]} | tr '[A-F]' '[a-f]')" - local realsum="$(openssl dgst -${integ} "$file" | awk '{print $NF}')" - if [ "$expectedsum" = "$realsum" ]; then + if (( $found )) ; then + local expectedsum="${integrity_sums[$idx],,}" + local realsum="$(openssl dgst -${integ} "$file")" + realsum="${realsum##* }" + if [[ $expectedsum = $realsum ]]; then echo "$(gettext "Passed")" >&2 else echo "$(gettext "FAILED")" >&2 @@ -604,18 +603,18 @@ check_checksums() { idx=$((idx + 1)) done - if [ $errors -gt 0 ]; then + if (( errors )); then error "$(gettext "One or more files did not pass the validity check!")" exit 1 # TODO: error code fi - elif [ ${#integrity_sums[@]} -gt 0 ]; then + elif (( ${#integrity_sums[@]} )); 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 - if [ $SKIPINTEG -eq 1 ]; then + if (( ! correlation )); then + if (( SKIPINTEG )); then warning "$(gettext "Integrity checks are missing.")" else error "$(gettext "Integrity checks are missing.")" @@ -635,8 +634,8 @@ extract_sources() { continue fi - if [ ! -f "$file" ] ; then - if [ ! -f "$SRCDEST/$file" ] ; then + if [[ ! -f $file ]] ; then + if [[ ! -f $SRCDEST/$file ]] ; then error "$(gettext "Unable to find source file %s for extraction.")" "$file" plain "$(gettext "Aborting...")" exit 1 @@ -675,94 +674,45 @@ extract_sources() { local ret=0 msg2 "$(gettext "Extracting %s with %s")" "$file" "$cmd" - if [ "$cmd" = "bsdtar" ]; then + if [[ $cmd = bsdtar ]]; then $cmd -xf "$file" || ret=? else rm -f "${file%.*}" $cmd -dcf "$file" > "${file%.*}" || ret=? fi - if [ $ret -ne 0 ]; then + if (( ret )); then error "$(gettext "Failed to extract %s")" "$file" plain "$(gettext "Aborting...")" exit 1 fi done - if [ $EUID -eq 0 ]; then + if (( EUID == 0 )); then # change perms of all source files to root user & root group chown -R 0:0 "$srcdir" fi } -run_build() { - # use distcc if it is requested (check buildenv and PKGBUILD opts) - if [ "$(check_buildenv distcc)" = "y" -a "$(check_option distcc)" != "n" ]; then - [ -d /usr/lib/distcc/bin ] && export PATH="/usr/lib/distcc/bin:$PATH" - export DISTCC_HOSTS - elif [ "$(check_option distcc)" = "n" ]; then - # if it is not wanted, clear the makeflags too - MAKEFLAGS="" - fi - - # use ccache if it is requested (check buildenv and PKGBUILD opts) - if [ "$(check_buildenv ccache)" = "y" -a "$(check_option ccache)" != "n" ]; then - [ -d /usr/lib/ccache/bin ] && export PATH="/usr/lib/ccache/bin:$PATH" - fi - - # clear user-specified makeflags if requested - if [ "$(check_option makeflags)" = "n" ]; then - MAKEFLAGS="" - fi - - msg "$(gettext "Starting build()...")" - cd "$srcdir" - - # ensure all necessary build variables are exported - 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" -eq 1 ]; then - BUILDLOG="${startdir}/${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-build.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 - - build 2>&1 | tee "$BUILDLOG"; ret=${PIPESTATUS[0]} - else - build 2>&1 || ret=$? +error_function() { + if [[ -p $logpipe ]]; then + rm "$logpipe" fi - # reset our shell options - eval "$shellopts" - - if [ $ret -gt 0 ]; then - error "$(gettext "Build Failed.")" + # first exit all subshells, then print the error + if (( ! BASH_SUBSHELL )); then plain "$(gettext "Aborting...")" remove_deps - exit 2 # $E_BUILD_FAILED fi + exit 2 # $E_BUILD_FAILED } -run_package() { - if [ -z "$1" ]; then - pkgfunc="package" - nameofpkg="$pkgname" - else - pkgfunc="package_$1" - nameofpkg="$1" +run_function() { + if [[ -z $1 ]]; then + return 1 fi + pkgfunc="$1" # clear user-specified makeflags if requested - if [ "$(check_option makeflags)" = "n" ]; then + if [[ $(check_option makeflags) = "n" ]]; then MAKEFLAGS="" fi @@ -771,14 +721,16 @@ run_package() { # ensure all necessary build variables are exported export CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST + # save our shell options so pkgfunc() can't override what we need + local shellopts=$(shopt -p) local ret=0 - if [ "$LOGGING" -eq 1 ]; then - BUILDLOG="${startdir}/${nameofpkg}-${pkgver}-${pkgrel}-${CARCH}-package.log" - if [ -f "$BUILDLOG" ]; then + if (( LOGGING )); then + BUILDLOG="${startdir}/${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-$pkgfunc.log" + if [[ -f $BUILDLOG ]]; then local i=1 while true; do - if [ -f "$BUILDLOG.$i" ]; then + if [[ -f $BUILDLOG.$i ]]; then i=$(($i +1)) else break @@ -793,36 +745,65 @@ run_package() { exec 3>&1 tee "$BUILDLOG" < "$logpipe" & exec 1>"$logpipe" 2>"$logpipe" - $pkgfunc 2>&1 || ret=$? + restoretrap=$(trap -p ERR) + trap 'error_function' ERR + $pkgfunc 2>&1 + eval $restoretrap sync exec 1>&3 2>&3 3>&- rm "$logpipe" else - $pkgfunc 2>&1 || ret=$? + restoretrap=$(trap -p ERR) + trap 'error_function' ERR + $pkgfunc 2>&1 + eval $restoretrap fi + # reset our shell options + eval "$shellopts" +} - if [ $ret -gt 0 ]; then - error "$(gettext "Packaging Failed.")" - plain "$(gettext "Aborting...")" - remove_deps - exit 2 # $E_BUILD_FAILED +run_build() { + # use distcc if it is requested (check buildenv and PKGBUILD opts) + if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then + [[ -d /usr/lib/distcc/bin ]] && export PATH="/usr/lib/distcc/bin:$PATH" + export DISTCC_HOSTS + elif [[ $(check_option distcc) = "n" ]]; then + # if it is not wanted, clear the makeflags too + MAKEFLAGS="" + fi + + # use ccache if it is requested (check buildenv and PKGBUILD opts) + if [[ $(check_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; then + [[ -d /usr/lib/ccache/bin ]] && export PATH="/usr/lib/ccache/bin:$PATH" + fi + + run_function "build" +} + +run_package() { + if [[ -z $1 ]]; then + pkgfunc="package" + else + pkgfunc="package_$1" fi + + run_function "$pkgfunc" } tidy_install() { cd "$pkgdir" msg "$(gettext "Tidying install...")" - if [ "$(check_option docs)" = "n" -a -n "${DOC_DIRS[*]}" ]; then + if [[ $(check_option docs) = "n" && -n ${DOC_DIRS[*]} ]]; then msg2 "$(gettext "Removing doc files...")" rm -rf ${DOC_DIRS[@]} fi - if [ "$(check_option purge)" = "y" -a -n "${PURGE_TARGETS[*]}" ]; then + if [[ $(check_option purge) = "y" && -n ${PURGE_TARGETS[*]} ]]; then msg2 "$(gettext "Purging other files...")" local pt for pt in "${PURGE_TARGETS[@]}"; do - if [ "${pt}" = "${pt//\/}" ]; then + if [[ ${pt} = ${pt//\/} ]]; then find . -type f -name "${pt}" -exec rm -f -- '{}' \; else rm -f ${pt} @@ -830,16 +811,16 @@ tidy_install() { done fi - if [ "$(check_option zipman)" = "y" -a -n "${MAN_DIRS[*]}" ]; then + if [[ $(check_option zipman) = "y" && -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 + if [[ -f ${manpage} ]]; then ext="${manpage##*.}" file="${manpage##*/}" - if [ "$ext" != "gz" -a "$ext" != "bz2" ]; then + if [[ $ext != gz && $ext != bz2 ]]; then # update symlinks to this manpage find ${MAN_DIRS[@]} -lname "$file" 2>/dev/null | while read link ; do @@ -865,7 +846,7 @@ tidy_install() { done fi - if [ "$(check_option strip)" = "y" -a -n "${STRIP_DIRS[*]}" ]; then + if [[ $(check_option strip) = y && -n ${STRIP_DIRS[*]} ]]; then msg2 "$(gettext "Stripping debugging symbols from binaries and libraries...")" local binary find ${STRIP_DIRS[@]} -type f 2>/dev/null | while read binary ; do @@ -882,12 +863,12 @@ tidy_install() { done fi - if [ "$(check_option libtool)" = "n" ]; then + if [[ $(check_option libtool) = "n" ]]; then msg2 "$(gettext "Removing libtool .la files...")" find . ! -type d -name "*.la" -exec rm -f -- '{}' \; fi - if [ "$(check_option emptydirs)" = "n" ]; then + if [[ $(check_option emptydirs) = "n" ]]; then msg2 "$(gettext "Removing empty directories...")" find . -depth -type d -empty -delete fi @@ -895,31 +876,30 @@ tidy_install() { write_pkginfo() { local builddate=$(date -u "+%s") - if [ -n "$PACKAGER" ]; then + if [[ -n $PACKAGER ]]; then local packager="$PACKAGER" else local packager="Unknown Packager" fi - local size=$(du -sk | awk '{print $1 * 1024}') + local size="$(du -sk)" + size="$(( ${size%%[^0-9]*} * 1024 ))" msg2 "$(gettext "Generating .PKGINFO file...")" echo "# Generated by makepkg $myver" >.PKGINFO - if [ "$INFAKEROOT" -eq 1 ]; then + if (( INFAKEROOT )); then echo "# using $(fakeroot -v)" >>.PKGINFO fi echo "# $(LC_ALL=C date -u)" >>.PKGINFO echo "pkgname = $1" >>.PKGINFO - [ "$SPLITPKG" -eq 1 ] && echo "pkgbase = $pkgbase" >>.PKGINFO + (( SPLITPKG )) && echo pkgbase = $pkgbase >>.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 [ -n "$CARCH" ]; then - echo "arch = $CARCH" >>.PKGINFO - fi - if [ "$(check_option force)" = "y" ]; then + echo "arch = $PKGARCH" >>.PKGINFO + if [[ $(check_option force) = "y" ]]; then echo "force = true" >> .PKGINFO fi @@ -950,8 +930,8 @@ write_pkginfo() { done for it in "${packaging_options[@]}"; do local ret="$(check_option $it)" - if [ "$ret" != "?" ]; then - if [ "$ret" = "y" ]; then + if [[ $ret != "?" ]]; then + if [[ $ret = y ]]; then echo "makepkgopt = $it" >>.PKGINFO else echo "makepkgopt = !$it" >>.PKGINFO @@ -961,43 +941,68 @@ write_pkginfo() { # TODO maybe remove this at some point # warn if license array is not present or empty - if [ -z "$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 } +check_package() { + cd "$pkgdir" + + # check existence of backup files + local file + for file in "${backup[@]}"; do + if [[ ! -f $file ]]; then + warning "$(gettext "Invalid backup entry : %s")" "$file" + fi + done + + # check for references to the build directory + if grep -R "${srcdir}" "${pkgdir}" &>/dev/null; then + warning "$(gettext "Package contains reference to %s")" "\$srcdir" + fi +} + create_package() { - if [ ! -d "$pkgdir" ]; then + if [[ ! -d $pkgdir ]]; then error "$(gettext "Missing pkg/ directory.")" plain "$(gettext "Aborting...")" exit 1 # $E_MISSING_PKGDIR fi + check_package + cd "$pkgdir" msg "$(gettext "Creating package...")" - if [ -z "$1" ]; then + if [[ -z $1 ]]; then nameofpkg="$pkgname" else nameofpkg="$1" fi + if [[ $arch = "any" ]]; then + PKGARCH="any" + else + PKGARCH=$CARCH + fi + write_pkginfo $nameofpkg local comp_files=".PKGINFO" # check for an install script - if [ -n "$install" ]; then + if [[ -n $install ]]; then msg2 "$(gettext "Adding install script...")" cp "$startdir/$install" .INSTALL comp_files="$comp_files .INSTALL" fi # do we have a changelog? - if [ -f "$startdir/ChangeLog" ]; then + if [[ -n $changelog ]]; then msg2 "$(gettext "Adding package changelog...")" - cp "$startdir/ChangeLog" .CHANGELOG + cp "$startdir/$changelog" .CHANGELOG comp_files="$comp_files .CHANGELOG" fi @@ -1011,29 +1016,39 @@ create_package() { *) warning "$(gettext "'%s' is not a valid archive extension.")" \ "$PKGEXT" ; EXT=$PKGEXT ;; esac - local pkg_file="$PKGDEST/${nameofpkg}-${pkgver}-${pkgrel}-${CARCH}${EXT}" + local tar_file="$PKGDEST/${nameofpkg}-${pkgver}-${pkgrel}-${PKGARCH}${EXT}" + local pkg_file="$PKGDEST/${nameofpkg}-${pkgver}-${pkgrel}-${PKGARCH}${PKGEXT}" local ret=0 # when fileglobbing, we want * in an empty directory to expand to # the null string rather than itself shopt -s nullglob - bsdtar -cf - $comp_files * > "$pkg_file" || ret=$? + bsdtar -cf - $comp_files * > "$tar_file" || ret=$? shopt -u nullglob - if [ $ret -eq 0 ]; then + if (( ! ret )); then case "$PKGEXT" in - *tar.gz) gzip -f -n "$pkg_file" ;; - *tar.bz2) bzip2 -f "$pkg_file" ;; - *tar.xz) xz -z -f "$pkg_file" ;; + *tar.gz) gzip -f -n "$tar_file" ;; + *tar.bz2) bzip2 -f "$tar_file" ;; + *tar.xz) xz -z -f "$tar_file" ;; esac ret=$? fi - if [ $ret -ne 0 ]; then + if (( ret )); then error "$(gettext "Failed to create package file.")" exit 1 # TODO: error code fi + + if (( ! ret )) && [[ "$PKGDEST" != "${startdir}" ]]; then + ln -sf "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}" + ret=$? + fi + + if (( ret )); then + warning "$(gettext "Failed to create symlink to package file.")" + fi } create_srcpackage() { @@ -1054,27 +1069,31 @@ create_srcpackage() { msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT" ln -s "${BUILDFILE}" "${srclinks}/${pkgbase}/${BUILDSCRIPT}" - if [ -n "$install" ]; then - if [ -f $install ]; then + if [[ -n $install ]]; then + if [[ -f $install ]]; then msg2 "$(gettext "Adding install script...")" ln -s "${startdir}/$install" "${srclinks}/${pkgbase}/" else - error "$(gettext "Install script %s not found.")" "$install" + error "$(gettext "Install scriptlet (%s) does not exist.")" "$install" fi fi - if [ -f ChangeLog ]; then - msg2 "$(gettext "Adding %s...")" "ChangeLog" - ln -s "${startdir}/ChangeLog" "${srclinks}/${pkgbase}" + if [[ -n $changelog ]]; then + if [[ -f $changelog ]]; then + msg2 "$(gettext "Adding package changelog...")" + ln -s "${startdir}/$changelog" "${srclinks}/${pkgbase}/" + else + error "$(gettext "Changelog file (%s) does not exist.")" "$changelog" + fi fi local netfile for netfile in "${source[@]}"; do local file=$(get_filename "$netfile") - if [ -f "$netfile" ]; then + if [[ -f $netfile ]]; then msg2 "$(gettext "Adding %s...")" "$netfile" ln -s "${startdir}/$netfile" "${srclinks}/${pkgbase}" - elif [ "$SOURCEONLY" -eq 2 -a -f "$SRCDEST/$file" ]; then + elif (( SOURCEONLY == 2 )) && [[ -f $SRCDEST/$file ]]; then msg2 "$(gettext "Adding %s...")" "$file" ln -s "$SRCDEST/$file" "${srclinks}/${pkgbase}/" fi @@ -1089,7 +1108,7 @@ create_srcpackage() { "$SRCEXT" ;; esac - local pkg_file="$PKGDEST/${pkgbase}-${pkgver}-${pkgrel}${SRCEXT}" + local pkg_file="$SRCPKGDEST/${pkgbase}-${pkgver}-${pkgrel}${SRCEXT}" # tar it up msg2 "$(gettext "Compressing source package...")" @@ -1103,27 +1122,24 @@ create_srcpackage() { } install_package() { - [ "$INSTALL" -eq 0 ] && return + (( ! INSTALL )) && return - if [ "$SPLITPKG" -eq 0 ]; then - msg "$(gettext "Installing package ${pkgname} with pacman -U...")" + if (( ! SPLITPKG )); then + msg "$(gettext "Installing package %s with %s -U...")" "$pkgname" "$PACMAN" else - msg "$(gettext "Installing ${pkgbase} package group with pacman -U...")" + msg "$(gettext "Installing %s package group with %s -U...")" "$pkgbase" "$PACMAN" fi local pkglist for pkg in ${pkgname[@]}; do - pkglist="${pkglist} $PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" + if [[ -f $PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT} ]]; then + pkglist="${pkglist} $PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" + else + pkglist="${pkglist} $PKGDEST/${pkg}-${pkgver}-${pkgrel}-any${PKGEXT}" + fi done - local ret=0 - if [ "$ASROOT" -eq 0 ]; then - sudo pacman $PACMAN_OPTS -U ${pkglist} || ret=$? - else - pacman $PACMAN_OPTS -U ${pkglist} || ret=$? - fi - - if [ $ret -ne 0 ]; then + if ! run_pacman -U $pkglist; then warning "$(gettext "Failed to install built package(s).")" return 0 fi @@ -1131,76 +1147,105 @@ install_package() { check_sanity() { # check for no-no's in the build script - if [ -z "$pkgname" ]; then + if [[ -z $pkgname ]]; then error "$(gettext "%s is not allowed to be empty.")" "pkgname" return 1 fi - if [ -z "$pkgver" ]; then + if [[ -z $pkgver ]]; then error "$(gettext "%s is not allowed to be empty.")" "pkgver" return 1 fi - if [ -z "$pkgrel" ]; then + if [[ -z $pkgrel ]]; then error "$(gettext "%s is not allowed to be empty.")" "pkgrel" return 1 fi - if [ "${pkgname:0:1}" == "-" ]; then - error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname" + + local name + for name in "${pkgname[@]}"; do + if [[ ${name:0:1} = "-" ]]; then + error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname" + return 1 + fi + done + + if [[ ${pkgbase:0:1} = "-" ]]; then + error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgbase" return 1 fi - if [ "$pkgver" != "${pkgver//-/}" ]; then + if [[ $pkgver != ${pkgver//-/} ]]; then error "$(gettext "%s is not allowed to contain hyphens.")" "pkgver" return 1 fi - if [ "$pkgrel" != "${pkgrel//-/}" ]; then + if [[ $pkgrel != ${pkgrel//-/} ]]; then error "$(gettext "%s is not allowed to contain hyphens.")" "pkgrel" return 1 fi - if [ "$arch" = 'any' ]; then - CARCH='any' - fi - if ! in_array $CARCH ${arch[@]}; then - if [ "$IGNOREARCH" -eq 0 ]; then - error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH" - plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT" - plain "$(gettext "such as arch=('%s').")" "$CARCH" - return 1 + if [[ $arch != 'any' ]]; then + if ! in_array $CARCH ${arch[@]}; then + if (( ! IGNOREARCH )); then + error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH" + plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT" + plain "$(gettext "such as arch=('%s').")" "$CARCH" + return 1 + fi fi fi local provide for provide in ${provides[@]}; do - if [ $provide != ${provide//</} -o $provide != ${provide//>/} ]; then + if [[ $provide != ${provide//</} || $provide != ${provide//>/} ]]; then error "$(gettext "Provides array cannot contain comparison (< or >) operators.")" return 1 fi done - if [ "$install" -a ! -f "$install" ]; then + local file + for file in "${backup[@]}"; do + if [[ ${file:0:1} = "/" ]]; then + error "$(gettext "Invalid backup entry : %s")" "$file" + return 1 + fi + done + + local optdepend + for optdepend in "${optdepends[@]}"; do + pkg=${optdepend%%:*} + if [[ ! $pkg =~ ^[[:alnum:]\>\<\=\.\+\_\-]*$ ]]; then + error "$(gettext "Invalid syntax for optdepend : '%s'")" "$optdepend" + fi + done + + if [[ $install && ! -f $install ]]; then error "$(gettext "Install scriptlet (%s) does not exist.")" "$install" return 1 fi + if [[ -n $changelog && ! -f $changelog ]]; then + error "$(gettext "Changelog file (%s) does not exist.")" "$changelog" + return 1 + fi + local valid_options=1 local opt known kopt for opt in ${options[@]}; do known=0 # check if option matches a known option or its inverse for kopt in ${packaging_options[@]} ${other_options[@]}; do - if [ "${opt}" = "${kopt}" -o "${opt}" = "!${kopt}" ]; then + if [[ ${opt} = ${kopt} || ${opt} = "!${kopt}" ]]; then known=1 fi done - if [ $known -eq 0 ]; then + if (( ! known )); then error "$(gettext "options array contains unknown option '%s'")" "$opt" valid_options=0 fi done - if [ $valid_options -eq 0 ]; then + if (( ! valid_options )); then return 1 fi - if [ "${#pkgname[@]}" -gt "1" ]; then + if (( ${#pkgname[@]} > 1 )); then for pkg in ${pkgname[@]}; do if [ "$(type -t package_${pkg})" != "function" ]; then error "$(gettext "missing package function for split package '%s'")" "$pkg" @@ -1209,50 +1254,59 @@ check_sanity() { done fi + if [[ -n "${PKGLIST[@]}" ]]; then + for pkg in ${PKGLIST[@]}; do + if ! in_array $pkg ${pkgname[@]}; then + error "$(gettext "requested package %s is not provided in %s")" "$pkg" "$BUILDSCRIPT" + return 1 + fi + done + fi + return 0 } devel_check() { newpkgver="" - # Do not update pkgver if --holdver is set, when building a source package, - # when reading PKGBUILD from pipe (-f), or if we cannot write to the file (-w) - if [ "$HOLDVER" -eq 1 -o "$SOURCEONLY" -ne 0 -o ! -f "$BUILDFILE" \ - -o ! -w "$BUILDFILE" ]; then + # Do not update pkgver if --holdver is set, when building a source package, repackaging, + # reading PKGBUILD from pipe (-f), or if we cannot write to the file (-w) + if (( HOLDVER || SOURCEONLY || REPKG )) \ + || [[ ! -f $BUILDFILE || ! -w $BUILDFILE ]]; then return fi - if [ -z "$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 # number to avoid having to determine the version number twice. # Also do a brief check to make sure we have the VCS tool available. oldpkgver=$pkgver - if [ -n "${_darcstrunk}" -a -n "${_darcsmod}" ] ; then + if [[ -n ${_darcstrunk} && -n ${_darcsmod} ]] ; then [ $(type -p darcs) ] || return 0 msg "$(gettext "Determining latest darcs revision...")" newpkgver=$(date +%Y%m%d) - elif [ -n "${_cvsroot}" -a -n "${_cvsmod}" ] ; then + elif [[ -n ${_cvsroot} && -n ${_cvsmod} ]] ; then [ $(type -p cvs) ] || return 0 msg "$(gettext "Determining latest cvs revision...")" newpkgver=$(date +%Y%m%d) - elif [ -n "${_gitroot}" -a -n "${_gitname}" ] ; then + elif [[ -n ${_gitroot} && -n ${_gitname} ]] ; then [ $(type -p git) ] || return 0 msg "$(gettext "Determining latest git revision...")" newpkgver=$(date +%Y%m%d) - elif [ -n "${_svntrunk}" -a -n "${_svnmod}" ] ; then + elif [[ -n ${_svntrunk} && -n ${_svnmod} ]] ; then [ $(type -p svn) ] || return 0 msg "$(gettext "Determining latest svn revision...")" newpkgver=$(LC_ALL=C svn info $_svntrunk | sed -n 's/^Last Changed Rev: \([0-9]*\)$/\1/p') - elif [ -n "${_bzrtrunk}" -a -n "${_bzrmod}" ] ; then + elif [[ -n ${_bzrtrunk} && -n ${_bzrmod} ]] ; then [ $(type -p bzr) ] || return 0 msg "$(gettext "Determining latest bzr revision...")" newpkgver=$(bzr revno ${_bzrtrunk}) - elif [ -n "${_hgroot}" -a -n "${_hgrepo}" ] ; then + elif [[ -n ${_hgroot} && -n ${_hgrepo} ]] ; then [ $(type -p hg) ] || return 0 msg "$(gettext "Determining latest hg revision...")" - if [ -d ./src/$_hgrepo ] ; then + if [[ -d ./src/$_hgrepo ]] ; then cd ./src/$_hgrepo hg pull hg update @@ -1265,7 +1319,7 @@ devel_check() { cd ../../ fi - if [ -n "$newpkgver" ]; then + if [[ -n $newpkgver ]]; then msg2 "$(gettext "Version found: %s")" "$newpkgver" fi @@ -1285,9 +1339,9 @@ devel_update() { # ... # _foo=pkgver # - if [ -n "$newpkgver" ]; then - if [ "$newpkgver" != "$pkgver" ]; then - if [ -f "$BUILDFILE" -a -w "$BUILDFILE" ]; then + if [[ -n $newpkgver ]]; then + if [[ $newpkgver != $pkgver ]]; then + if [[ -f $BUILDFILE && -w $BUILDFILE ]]; then @SEDINPLACE@ "s/^pkgver=[^ ]*/pkgver=$newpkgver/" "$BUILDFILE" @SEDINPLACE@ "s/^pkgrel=[^ ]*/pkgrel=1/" "$BUILDFILE" source "$BUILDFILE" @@ -1306,7 +1360,7 @@ backup_package_variables() { restore_package_variables() { for var in ${splitpkg_overrides[@]}; do indirect="${var}_backup" - if [ -n "${!indirect}" ]; then + if [[ -n ${!indirect} ]]; then eval "${var}=(\"\${$indirect[@]}\")" else unset ${var} @@ -1321,21 +1375,21 @@ parse_options() { local ret=0; local unused_options="" - while [ -n "$1" ]; do - if [ ${1:0:2} = '--' ]; then - if [ -n "${1:2}" ]; then + while [[ -n $1 ]]; do + if [[ ${1:0:2} = '--' ]]; then + if [[ -n ${1:2} ]]; then local match="" for i in ${long_options//,/ }; do - if [ ${1:2} = ${i//:} ]; then + if [[ ${1:2} = ${i//:} ]]; then match=$i break fi done - if [ -n "$match" ]; then - if [ ${1:2} = $match ]; then + if [[ -n $match ]]; then + if [[ ${1:2} = $match ]]; then printf ' %s' "$1" else - if [ -n "$2" ]; then + if [[ -n $2 ]]; then printf ' %s' "$1" shift printf " '%s'" "$1" @@ -1352,15 +1406,15 @@ parse_options() { shift break fi - elif [ ${1:0:1} = '-' ]; then + elif [[ ${1:0:1} = '-' ]]; then for ((i=1; i<${#1}; i++)); do - if [[ "$short_options" =~ "${1:i:1}" ]]; then - if [[ "$short_options" =~ "${1:i:1}:" ]]; then - if [ -n "${1:$i+1}" ]; then + if [[ $short_options =~ ${1:i:1} ]]; then + if [[ $short_options =~ "${1:i:1}:" ]]; then + if [[ -n ${1:$i+1} ]]; then printf ' -%s' "${1:i:1}" printf " '%s'" "${1:$i+1}" else - if [ -n "$2" ]; then + if [[ -n $2 ]]; then printf ' -%s' "${1:i:1}" shift printf " '%s'" "${1}" @@ -1385,13 +1439,13 @@ parse_options() { done printf " --" - if [ -n "$unused_options" ]; then + if [[ -n $unused_options ]]; then for i in ${unused_options[@]}; do printf ' %s' "$i" done fi - if [ -n "$1" ]; then - while [ -n "$1" ]; do + if [[ -n $1 ]]; then + while [[ -n $1 ]]; do printf " '%s'" "${1}" shift done @@ -1410,31 +1464,31 @@ 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")" echo "$(gettext " -g, --geninteg Generate integrity checks for source files")" - echo "$(gettext " --skipinteg Do not fail when integrity checks are missing")" echo "$(gettext " -h, --help This help")" echo "$(gettext " -i, --install Install package after successful build")" echo "$(gettext " -L, --log Log package build process")" echo "$(gettext " -m, --nocolor Disable colorized output messages")" echo "$(gettext " -o, --nobuild Download and extract files only")" - printf "$(gettext " -p <buildscript> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT" + printf "$(gettext " -p <file> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT" echo "$(gettext " -r, --rmdeps Remove installed dependencies after a successful build")" - # fix flyspray feature request #2978 echo "$(gettext " -R, --repackage Repackage contents of the package without rebuilding")" echo "$(gettext " -s, --syncdeps Install missing dependencies with pacman")" - echo "$(gettext " --allsource Generate a source-only tarball including downloaded sources")" - echo "$(gettext " --asroot Allow makepkg to run as root user")" - echo "$(gettext " --holdver Prevent automatic version bumping for development PKGBUILDs")" - echo "$(gettext " --source Generate a source-only tarball without downloaded sources")" + echo "$(gettext " --allsource Generate a source-only tarball including downloaded sources")" + echo "$(gettext " --asroot Allow makepkg to run as root user")" + printf "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf" + echo "$(gettext " --holdver Prevent automatic version bumping for development PKGBUILDs")" + echo "$(gettext " --pkg <list> Only build listed packages from a split package")" + echo "$(gettext " --skipinteg Do not fail when integrity checks are missing")" + echo "$(gettext " --source Generate a source-only tarball without downloaded sources")" echo echo "$(gettext "These options can be passed to pacman:")" echo - echo "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")" - echo "$(gettext " --noprogressbar Do not show a progress bar when downloading files")" + echo "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")" + echo "$(gettext " --noprogressbar Do not show a progress bar when downloading files")" echo printf "$(gettext "If -p is not specified, makepkg will look for '%s'")\n" "$BUILDSCRIPT" echo @@ -1464,7 +1518,7 @@ ARGLIST=("$@") OPT_SHORT="AcCdefFghiLmop:rRsV" OPT_LONG="allsource,asroot,ignorearch,clean,cleancache,nodeps" OPT_LONG="$OPT_LONG,noextract,force,forcever:,geninteg,help,holdver" -OPT_LONG="$OPT_LONG,install,log,nocolor,nobuild,rmdeps,repackage,skipinteg" +OPT_LONG="$OPT_LONG,install,log,nocolor,nobuild,pkg:,rmdeps,repackage,skipinteg" OPT_LONG="$OPT_LONG,source,syncdeps,version,config:" # Pacman Options OPT_LONG="$OPT_LONG,noconfirm,noprogressbar" @@ -1502,6 +1556,7 @@ while true; do -m|--nocolor) USE_COLOR='n' ;; -o|--nobuild) NOBUILD=1 ;; -p) shift; BUILDFILE=$1 ;; + --pkg) shift; PKGLIST=$1 ;; -r|--rmdeps) RMDEPS=1 ;; -R|--repackage) REPKG=1 ;; --skipinteg) SKIPINTEG=1 ;; @@ -1520,12 +1575,13 @@ done #preserve environment variables _PKGDEST=${PKGDEST} _SRCDEST=${SRCDEST} +_SRCPKGDEST=${SRCPKGDEST} # 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 +if [[ -r $MAKEPKG_CONF ]]; then source "$MAKEPKG_CONF" else error "$(gettext "%s not found.")" "$MAKEPKG_CONF" @@ -1534,39 +1590,51 @@ else fi # Source user-specific makepkg.conf overrides -if [ -r ~/.makepkg.conf ]; then +if [[ -r ~/.makepkg.conf ]]; then source ~/.makepkg.conf fi +# set pacman command if not already defined +PACMAN=${PACMAN:-pacman} + # check if messages are to be printed using color -if [ -t 2 -a ! "$USE_COLOR" = "n" -a "$(check_buildenv color)" = "y" ]; then - COLORMSG=1 +unset ALL_OFF BOLD BLUE GREEN RED YELLOW +if [[ -t 2 && ! $USE_COLOR = "n" && $(check_buildenv color) = "y" ]]; then + ALL_OFF="$(tput sgr0)" + BOLD="$(tput bold)" + BLUE="${BOLD}$(tput setaf 4)" + GREEN="${BOLD}$(tput setaf 2)" + RED="${BOLD}$(tput setaf 1)" + YELLOW="${BOLD}$(tput setaf 3)" fi +readonly ALL_OFF BOLD BLUE GREEN RED YELLOW # 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 +SRCPKGDEST=${_SRCPKGDEST:-$SRCPKGDEST} +SRCPKGDEST=${SRCPKGDEST:-$PKGDEST} #default to $PKGDEST if undefined -if [ "$HOLDVER" -eq 1 -a -n "$FORCE_VER" ]; then +if (( HOLDVER )) && [[ -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" -eq 1 ]; then +if (( CLEANCACHE )); then #fix flyspray feature request #5223 - if [ -n "$SRCDEST" -a "$SRCDEST" != "$startdir" ]; then + if [[ -n $SRCDEST && $SRCDEST != $startdir ]]; then msg "$(gettext "Cleaning up ALL files from %s.")" "$SRCDEST" echo -n "$(gettext " Are you sure you wish to do this? ")" echo -n "$(gettext "[y/N]")" read answer - answer=$(echo $answer | tr '[:lower:]' '[:upper:]') - if [ "$answer" = "$(gettext "YES")" -o "$answer" = "$(gettext "Y")" ]; then + answer="${answer^^}" + if [[ $answer = $(gettext YES) || $answer = $(gettext Y) ]]; then rm "$SRCDEST"/* - if [ $? -ne 0 ]; then + if (( $? )); then error "$(gettext "Problem removing files; you may not have correct permissions in %s")" "$SRCDEST" exit 1 else @@ -1587,40 +1655,39 @@ if [ "$CLEANCACHE" -eq 1 ]; then fi fi -if [ "$INFAKEROOT" -eq 0 ]; then - if [ $EUID -eq 0 -a "$ASROOT" -eq 0 ]; then +if (( ! INFAKEROOT )); then + if (( EUID == 0 && ! ASROOT )); 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" -eq 1 ]; then + elif (( EUID > 0 && ASROOT )); 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.")" exit 1 # $E_USER_ABORT - elif [ "$(check_buildenv fakeroot)" = "y" -a $EUID -gt 0 ]; then + elif [[ $(check_buildenv fakeroot) = "y" ]] && (( EUID > 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.")" "$MAKEPKG_CONF" exit 1 fi - elif [ $EUID -gt 0 ]; then + elif (( EUID > 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 %s.")" "$MAKEPKG_CONF" sleep 1 fi else - if [ -z "$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" -eq 0 \ - -a \( "$DEP_BIN" -eq 1 -o "$RMDEPS" -eq 1 -o "$INSTALL" -eq 1 \) ]; then +if (( ! ASROOT && ( DEP_BIN || RMDEPS || INSTALL ) )); 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")" @@ -1630,12 +1697,12 @@ if [ "$ASROOT" -eq 0 \ fi unset pkgname pkgbase pkgver pkgrel pkgdesc url license groups provides -unset md5sums replaces depends conflicts backup source install build +unset md5sums replaces depends conflicts backup source install changelog build unset makedepends optdepends options noextract BUILDFILE=${BUILDFILE:-$BUILDSCRIPT} -if [ ! -f "$BUILDFILE" ]; then - if [ -t 0 ]; then +if [[ ! -f $BUILDFILE ]]; then + if [[ -t 0 ]]; then error "$(gettext "%s does not exist.")" "$BUILDFILE" exit 1 else @@ -1645,18 +1712,18 @@ if [ ! -f "$BUILDFILE" ]; then fi else crlftest=$(file "$BUILDFILE" | grep -F 'CRLF' || true) - if [ -n "$crlftest" ]; then + if [[ -n $crlftest ]]; then error "$(gettext "%s contains CRLF characters and cannot be sourced.")" "$BUILDFILE" exit 1 fi - if [ "${BUILDFILE:0:1}" != "/" ]; then + if [[ ${BUILDFILE:0:1} != "/" ]]; then BUILDFILE="$startdir/$BUILDFILE" fi source "$BUILDFILE" fi -if [ "$GENINTEG" -eq 1 ]; then +if (( GENINTEG )); then mkdir -p "$srcdir" cd "$srcdir" download_sources @@ -1664,10 +1731,6 @@ if [ "$GENINTEG" -eq 1 ]; then exit 0 # $E_OK fi -if [ "$(type -t package)" = "function" ]; then - PKGFUNC=1 -fi - # check the PKGBUILD for some basic requirements check_sanity || exit 1 @@ -1678,16 +1741,34 @@ check_sanity || exit 1 devel_check devel_update -if [ "${#pkgname[@]}" -gt "1" ]; then +if (( ${#pkgname[@]} > 1 )); then + SPLITPKG=1 +fi + +# test for available PKGBUILD functions +# The exclamation mark is required here to avoid triggering the ERR trap when +# a tested function does not exist. +if [[ $(! type -t build) = "function" ]]; then + BUILDFUNC=1 +fi +if [ "$(type -t package)" = "function" ]; then + PKGFUNC=1 +elif [ $SPLITPKG -eq 0 -a "$(type -t package_${pkgname})" = "function" ]; then SPLITPKG=1 fi pkgbase=${pkgbase:-${pkgname[0]}} -if [ "$SPLITPKG" -eq 0 ]; then - if [ -f "$PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" \ - -a "$FORCE" -eq 0 -a "$SOURCEONLY" -eq 0 -a "$NOBUILD" -eq 0 ]; then - if [ "$INSTALL" -eq 1 ]; then +if [[ -n "${PKGLIST[@]}" ]]; then + unset pkgname + pkgname="${PKGLIST[@]}" +fi + +if (( ! SPLITPKG )); then + if [[ -f $PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT} \ + || -f $PKGDEST/${pkgname}-${pkgver}-${pkgrel}-any${PKGEXT} ]] \ + && ! (( FORCE || SOURCEONLY || NOBUILD )); then + if (( INSTALL )); then warning "$(gettext "A package has already been built, installing existing package...")" install_package exit $? @@ -1700,15 +1781,16 @@ else allpkgbuilt=1 somepkgbuilt=0 for pkg in ${pkgname[@]}; do - if [ -f "$PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" ]; then + if [[ -f $PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT} \ + || -f $PKGDEST/${pkg}-${pkgver}-${pkgrel}-any${PKGEXT} ]]; then somepkgbuilt=1 else allpkgbuilt=0 fi done - if [ "$FORCE" -eq 0 -a "$SOURCEONLY" -eq 0 -a "$NOBUILD" -eq 0 ]; then - if [ "$allpkgbuilt" -eq 1 ]; then - if [ "$INSTALL" -eq 1 ]; then + if ! (( FORCE || SOURCEONLY || NOBUILD )); then + if (( allpkgbuilt )); then + if (( INSTALL )); then warning "$(gettext "The package group has already been built, installing existing packages...")" install_package exit $? @@ -1717,7 +1799,7 @@ else exit 1 fi fi - if [ "$somepkgbuilt" -eq 1 ]; then + if (( somepkgbuilt )); then error "$(gettext "Part of the package group has already been built. (use -f to overwrite)")" exit 1 fi @@ -1726,10 +1808,10 @@ else fi # Run the bare minimum in fakeroot -if [ "$INFAKEROOT" -eq 1 ]; then - if [ "$SPLITPKG" -eq 0 ]; then - if [ "$PKGFUNC" -eq 0 ]; then - if [ "$REPKG" -eq 0 ]; then +if (( INFAKEROOT )); then + if (( ! SPLITPKG )); then + if (( ! PKGFUNC )); then + if (( BUILDFUNC && ! REPKG )); then run_build tidy_install fi @@ -1755,13 +1837,13 @@ if [ "$INFAKEROOT" -eq 1 ]; then exit 0 # $E_OK fi -msg "$(gettext "Making package: %s")" "$pkgbase $pkgver-$pkgrel $CARCH ($(date))" +msg "$(gettext "Making package: %s")" "$pkgbase $pkgver-$pkgrel ($(date))" # if we are creating a source-only package, go no further -if [ "$SOURCEONLY" -ne 0 ]; then - if [ -f "$PKGDEST/${pkgbase}-${pkgver}-${pkgrel}${SRCEXT}" \ - -a "$FORCE" -eq 0 ]; then - error "$(gettext "A package has already been built. (use -f to overwrite)")" +if (( SOURCEONLY )); then + if [[ -f $SRCPKGDEST/${pkgbase}-${pkgver}-${pkgrel}${SRCEXT} ]] \ + && (( ! FORCE )); then + error "$(gettext "A source package has already been built. (use -f to overwrite)")" exit 1 fi create_srcpackage @@ -1770,12 +1852,12 @@ if [ "$SOURCEONLY" -ne 0 ]; then fi # fix flyspray bug #5973 -if [ "$NODEPS" -eq 1 -o "$NOBUILD" -eq 1 -o "$REPKG" -eq 1 ]; then +if (( NODEPS || NOBUILD || REPKG )); then # no warning message needed for nobuild, repkg - if [ "$NODEPS" -eq 1 ]; then + if (( NODEPS )); then warning "$(gettext "Skipping dependency checks.")" fi -elif [ $(type -p pacman) ]; then +elif [ $(type -p "${PACMAN%% *}") ]; then unset pkgdeps # Set by resolve_deps() and used by remove_deps() deperr=0 @@ -1785,12 +1867,12 @@ elif [ $(type -p pacman) ]; then msg "$(gettext "Checking Buildtime Dependencies...")" resolve_deps ${makedepends[@]} || deperr=1 - if [ $deperr -eq 1 ]; then + if (( deperr )); then error "$(gettext "Could not resolve all dependencies.")" exit 1 fi else - warning "$(gettext "pacman was not found in PATH; skipping dependency checks.")" + warning "$(gettext "%s was not found in PATH; skipping dependency checks.")" "${PACMAN%% *}" fi # ensure we have a sane umask set @@ -1800,19 +1882,19 @@ umask 0022 mkdir -p "$srcdir" cd "$srcdir" -if [ "$NOEXTRACT" -eq 1 ]; then +if (( NOEXTRACT )); 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" -eq 1 -a -z "$(ls "$srcdir" 2>/dev/null)" ]; then + if (( NOEXTRACT )) && [[ -z $(ls "$srcdir" 2>/dev/null) ]]; then error "$(gettext "The source directory is empty, there is nothing to build!")" plain "$(gettext "Aborting...")" exit 1 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 +elif (( REPKG )); then + if (( ! PKGFUNC && ! SPLITPKG )) \ + && [[ ! -d $pkgdir || -z $(ls "$pkgdir" 2>/dev/null) ]]; then error "$(gettext "The package directory is empty, there is nothing to repackage!")" plain "$(gettext "Aborting...")" exit 1 @@ -1823,13 +1905,12 @@ else extract_sources fi -if [ "$NOBUILD" -eq 1 ]; then +if (( NOBUILD )); 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" -eq 0 -o "$PKGFUNC" -eq 1 -o "$SPLITPKG" -eq 1 \) ]; then + if [[ -d $pkgdir ]] && (( ! REPKG || PKGFUNC || SPLITPKG )); then msg "$(gettext "Removing existing pkg/ directory...")" rm -rf "$pkgdir" fi @@ -1837,16 +1918,16 @@ else 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 [ "$REPKG" -eq 0 ]; then + if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then + if (( ! REPKG )); then devel_update - run_build + (( BUILDFUNC )) && run_build fi - if [ "$SPLITPKG" -eq 0 ]; then - if [ "$PKGFUNC" -eq 1 ]; then + if (( ! SPLITPKG )); then + if (( PKGFUNC )); then run_package tidy_install - elif [ "$REPKG" -eq 0 ]; then + elif (( ! REPKG )); then tidy_install fi create_package @@ -1863,15 +1944,15 @@ else done fi else - if [ "$REPKG" -eq 0 -a \( "$PKGFUNC" -eq 1 -o "$SPLITPKG" -eq 1 \) ]; then + if (( ! REPKG && ( PKGFUNC || SPLITPKG ) )); then devel_update - run_build + (( BUILDFUNC )) && run_build cd "$startdir" fi msg "$(gettext "Entering fakeroot environment...")" - if [ -n "$newpkgver" ]; then + if [[ -n $newpkgver ]]; then fakeroot -- $0 --forcever $newpkgver -F "${ARGLIST[@]}" || exit $? else fakeroot -- $0 -F "${ARGLIST[@]}" || exit $? @@ -1879,7 +1960,7 @@ else fi fi -msg "$(gettext "Finished making: %s")" "$pkgbase $pkgver-$pkgrel $CARCH ($(date))" +msg "$(gettext "Finished making: %s")" "$pkgbase $pkgver-$pkgrel ($(date))" install_package diff --git a/scripts/pacman-optimize.sh.in b/scripts/pacman-optimize.sh.in index e43e946d..d9f1ca2e 100644 --- a/scripts/pacman-optimize.sh.in +++ b/scripts/pacman-optimize.sh.in @@ -74,23 +74,23 @@ die_r() { # PROGRAM START # determine whether we have gettext; make it a no-op if we do not -if [ ! $(type -t gettext) ]; then +if ! type gettext &>/dev/null; then gettext() { echo "$@" } fi -if [ "$1" = "-h" -o "$1" = "--help" ]; then +if [[ $1 = "-h" || $1 = "--help" ]]; then usage exit 0 fi -if [ "$1" = "-V" -o "$1" = "--version" ]; then +if [[ $1 = "-V" || $1 = "--version" ]]; then version exit 0 fi -if [ "$1" != "" ]; then +if [[ -n $1 ]]; then dbroot="$1" fi @@ -99,11 +99,11 @@ if ! type diff >/dev/null 2>&1; then die "$(gettext "diff tool was not found, please install diffutils.")" fi -if [ ! -d "$dbroot" ]; then +if [[ ! -d $dbroot ]]; then die "$(gettext "%s does not exist or is not a directory.")" "$dbroot" fi -if [ ! -w "$dbroot" ]; then +if [[ ! -w $dbroot ]]; then die "$(gettext "You must have correct permissions to optimize the database.")" fi @@ -113,7 +113,7 @@ dbroot="${dbroot%/}" lockfile="${dbroot}/db.lck" # make sure pacman isn't running -if [ -f "$lockfile" ]; then +if [[ -f $lockfile ]]; then die "$(gettext "Pacman lock file was found. Cannot run while pacman is running.")" fi # do not let pacman run while we do this @@ -130,7 +130,7 @@ find "$dbroot" -type f | sort | xargs md5sum > "$workdir/pacsums.old" msg "$(gettext "Tar'ing up %s...")" "$dbroot" cd "$dbroot" bsdtar -czf "$workdir/pacman-db.tar.gz" ./ -if [ $? -ne 0 ]; then +if (( $? )); then rm -rf "$workdir" die_r "$(gettext "Tar'ing up %s failed.")" "$dbroot" fi @@ -139,7 +139,7 @@ fi msg "$(gettext "Making and MD5sum'ing the new database...")" mkdir "$dbroot.new" bsdtar -xpf "$workdir/pacman-db.tar.gz" -C "$dbroot.new" -if [ $? -ne 0 ]; then +if (( $? )); then rm -rf "$workdir" die_r "$(gettext "Untar'ing %s failed.")" "$dbroot" fi @@ -152,7 +152,7 @@ find "$dbroot.new" -type f | sort | \ # step 4: compare the sums msg "$(gettext "Checking integrity...")" diff "$workdir/pacsums.old" "$workdir/pacsums.new" >/dev/null 2>&1 -if [ $? -ne 0 ]; then +if (( $? )); then # failed # leave our pacman-optimize tmpdir for checking to see what doesn't match up rm -rf "$dbroot.new" @@ -167,7 +167,7 @@ mv "$dbroot" "$dbroot.old" || fail=1 mv "$dbroot.new" "$dbroot" || fail=1 chmod --reference="$dbroot.old" "$dbroot" || fail=1 chown --reference="$dbroot.old" "$dbroot" || fail=1 -if [ $fail -ne 0 ]; then +if (( fail )); then # failure with our directory shuffle die_r "$(gettext "New database substitution failed. Check for $dbroot,\n$dbroot.old, and $dbroot.new directories.")" fi diff --git a/scripts/pkgdelta.sh.in b/scripts/pkgdelta.sh.in index 588dc49d..1550fa10 100644 --- a/scripts/pkgdelta.sh.in +++ b/scripts/pkgdelta.sh.in @@ -35,7 +35,7 @@ QUIET=0 umask 0022 msg() { - [ $QUIET -ne 0 ] && return + (( QUIET )) && return local mesg=$1; shift printf "==> ${mesg}\n" "$@" >&1 } @@ -79,7 +79,7 @@ read_pkginfo() for line in $(bsdtar -xOf "$1" .PKGINFO 2>/dev/null | grep -v "^#" | sed 's|\(\w*\)\s*=\s*\(.*\)|\1="\2"|'); do eval "$line" - if [ -n "$pkgname" -a -n "$pkgver" -a -n "$arch" ]; then + if [[ -n $pkgname && -n $pkgver && -n $arch ]]; then IFS=$OLDIFS return 0 fi @@ -108,17 +108,17 @@ create_xdelta() newver="$pkgver" newarch="$arch" - if [ "$oldname" != "$newname" ]; then + if [[ $oldname != $newname ]]; then error "$(gettext "The package names don't match : '%s' and '%s'")" "$oldname" "$newname" return 1 fi - if [ "$oldarch" != "$newarch" ]; then + if [[ $oldarch != $newarch ]]; then error "$(gettext "The package architectures don't match : '%s' and '%s'")" "$oldarch" "$newarch" return 1 fi - if [ "$oldver" == "$newver" ]; then + if [[ $oldver == $newver ]]; then error "$(gettext "Both packages have the same version : '%s'")" "$newver" return 1 fi @@ -128,12 +128,12 @@ create_xdelta() local ret=0 xdelta3 -q -f -s "$oldfile" "$newfile" "$deltafile" || ret=$? - if [ $ret -ne 0 ]; then + if (( ret )); then error "$(gettext "Delta could not be created.")" return 1 else msg "$(gettext "Generated delta : '%s'")" "$deltafile" - [ $QUIET -eq 1 ] && echo "$deltafile" + (( QUIET )) && echo "$deltafile" fi return 0 } @@ -142,22 +142,22 @@ case "$1" in -q|--quiet) QUIET=1; shift ;; esac -if [ $# -ne 2 ]; then +if (( $# != 2 )); then usage exit 0 fi -if [ ! -f "$1" ]; then +if [[ ! -f $1 ]]; then error "$(gettext "File '%s' does not exist")" "$1" exit 0 fi -if [ ! -f "$2" ]; then +if [[ ! -f $2 ]]; then error "$(gettext "File '%s' does not exist")" "$2" exit 0 fi -if [ ! "$(type -p xdelta3)" ]; then +if ! type xdelta3 &>/dev/null; then error "$(gettext "Cannot find the xdelta3 binary! Is xdelta3 installed?")" exit 1 fi diff --git a/scripts/rankmirrors.py.in b/scripts/rankmirrors.py.in deleted file mode 100644 index 4b253b67..00000000 --- a/scripts/rankmirrors.py.in +++ /dev/null @@ -1,189 +0,0 @@ -#! /usr/bin/python -# -# rankmirrors - read a list of mirrors from a file and rank them by speed -# @configure_input@ -# -# Copyright (c) 2006-2009 Pacman Development Team <pacman-dev@archlinux.org> -# Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -import os, sys, datetime, time, socket, urllib2 -from optparse import OptionParser -from string import Template - -def createOptParser(): - usage = "usage: %prog [options] MIRRORFILE | URL" - version = "%prog (pacman) @PACKAGE_VERSION@\n" \ - "Copyright (c) 2006-2009 Pacman Development Team <pacman-dev@archlinux.org>.\n" \ - "Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>.\n\n" \ - "This is free software; see the source for copying conditions.\n" \ - "There is NO WARRANTY, to the extent permitted by law." - description = "Ranks pacman mirrors by their connection and opening " \ - "speed. Pacman mirror files are located in /etc/pacman.d/. It " \ - "can also rank one mirror if the URL is provided." - parser = OptionParser(usage = usage, version = version, - description = description) - parser.add_option("-n", type = "int", dest = "num", default = 0, - help = "number of servers to output, 0 for all") - parser.add_option("-t", "--times", action = "store_true", - dest = "times", default = False, - help = "only output mirrors and their response times") - parser.add_option("-u", "--url", action = "store_true", dest = "url", - default = False, help = "test a specific url") - parser.add_option("-v", "--verbose", action = "store_true", - dest = "verbose", default = False, - help = "be verbose in ouptut") - # The following two options should be automatic - #parser.add_option("-h", "--help", action = "help") - #parser.add_option("-V", "--version", action = "version") - return parser - -def timeCmd(cmd): - before = time.time() - try: - cmd() - except KeyboardInterrupt, ki: - raise ki - except socket.timeout, ioe: - return 'timeout' - except Exception, e: - return 'unreachable' - return time.time() - before - -def talkToServer(serverUrl): - opener = urllib2.build_opener() - # retrieve first 50,000 bytes only - tmp = opener.open(serverUrl).read(50000) - -def getFuncToTime(serverUrl): - return lambda : talkToServer(serverUrl) - -def cmpPairBySecond(p1, p2): - if p1[1] == p2[1]: - return 0 - if p1[1] < p2[1]: - return -1 - return 1 - -def printResults(servers, time, verbose, num): - items = servers.items() - items.sort(cmpPairBySecond) - itemsLen = len(items) - numToShow = num - if numToShow > itemsLen or numToShow == 0: - numToShow = itemsLen - if itemsLen > 0: - if time: - print - print ' Servers sorted by time (seconds):' - for i in items[0:numToShow]: - if i[1] == 'timeout' or i[1] == 'unreachable': - print i[0], ':', i[1] - else: - print i[0], ':', "%.2f" % i[1] - else: - for i in items[0:numToShow]: - print 'Server =', i[0] - -if __name__ == "__main__": - parser = createOptParser() - (options, args) = parser.parse_args() - - if len(args) != 1: - parser.print_help(sys.stderr) - sys.exit(0) - - # allows connections to time out if they take too long - socket.setdefaulttimeout(10) - - if options.url: - if options.verbose: - print 'Testing', args[0] + '...' - try: - serverToTime = timeCmd(getFuncToTime(args[0])) - except KeyboardInterrupt, ki: - sys.exit(1) - if serverToTime == 'timeout' or serverToTime == 'unreachable': - print args[0], ':', serverToTime - else: - print args[0], ':', "%.2f" % serverToTime - sys.exit(0) - - if not os.path.isfile(args[0]) and args[0] != "-": - print >>sys.stderr, 'rankmirrors: file', args[0], 'does not exist.' - sys.exit(1) - - if args[0] == "-": - fl = sys.stdin - else: - fl = open(args[0], 'r') - - serverToTime = {} - if options.times: - print 'Querying servers, this may take some time...' - else: - print "# Server list generated by rankmirrors on", - print datetime.date.today() - for ln in fl.readlines(): - splitted = ln.split('=') - if splitted[0].strip() != 'Server': - if not options.times: - print ln, - continue - - serverUrl = splitted[1].strip() - if serverUrl[-1] == '\n': - serverUrl = serverUrl[0:-1] - if options.verbose and options.times: - print serverUrl, '...', - elif options.verbose: - print '#', serverUrl, '...', - elif options.times: - print ' * ', - sys.stdout.flush() - - # if the $repo var is used in the url, replace it by core - tempUrl = Template(serverUrl).safe_substitute(repo='core') - - # add @DBEXT@ to server name. the repo name is parsed - # from the mirror url; it is the third (or fourth) dir - # from the end, where the url is http://foo/bar/REPO/os/arch - try: - splitted2 = tempUrl.split('/') - if tempUrl[-1] != '/': - repoName = splitted2[-3] - dbFileName = '/' + repoName + '@DBEXT@' - else: - repoName = splitted2[-4] - dbFileName = repoName + '@DBEXT@' - except: - dbFileName = '' - - try: - serverToTime[serverUrl] = timeCmd(getFuncToTime(tempUrl + dbFileName)) - if options.verbose: - try: - print "%.2f" % serverToTime[serverUrl] - except: - print serverToTime[serverUrl] - except: - print - printResults(serverToTime, options.times, options.verbose, - options.num) - sys.exit(0) - - printResults(serverToTime, options.times, options.verbose, options.num) - -# vim: set ts=4 sw=4 et: diff --git a/scripts/rankmirrors.sh.in b/scripts/rankmirrors.sh.in new file mode 100644 index 00000000..d5cbaddd --- /dev/null +++ b/scripts/rankmirrors.sh.in @@ -0,0 +1,202 @@ +#!/bin/bash +# +# rankmirrors - read a list of mirrors from a file and rank them by speed +# @configure_input@ +# +# Copyright (c) 2009 Matthew Bruenig <matthewbruenig@gmail.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# traps interrupt key to spit out pre-interrupt info +trap finaloutput INT + +usage() { + echo "Usage: rankmirrors [options] MIRRORFILE | URL" + echo + echo "Ranks pacman mirrors by their connection and opening speed. Pacman mirror" + echo "files are located in /etc/pacman.d/. It can also rank one mirror if the URL is" + echo "provided." + echo + echo "Options:" + echo " --version show program's version number and exit" + echo " -h, --help show this help message and exit" + echo " -n NUM number of servers to output, 0 for all" + echo " -t, --times only output mirrors and their response times" + echo " -u, --url test a specific url" + echo " -v, --verbose be verbose in ouptut" + exit 0 +} + +version() { + echo "rankmirrors (pacman) @PACKAGE_VERSION@" + echo "Copyright (c) 2009 Matthew Bruenig <matthewbruenig@gmail.com>." + echo + echo "This is free software; see the source for copying conditions." + echo "There is NO WARRANTY, to the extent permitted by law." + exit 0 +} + +err() { + echo "$1" + exit 1 +} + +# gettime fetchurl (e.g gettime http://foo.com/core/os/i686/core.db.tar.gz) +# returns the fetching time, or timeout, or unreachable +gettime() { + IFS=' ' output=( $(curl -s -m 10 -w "%{time_total} %{http_code}" "$1" -o/dev/null) ) + (( $? == 28 )) && echo timeout && return + (( ${output[1]} >= 400 || ! ${output[1]} )) && echo unreachable && return + echo "${output[0]}" +} + +# getfetchurl serverurl (e.g. getturl http://foo.com/core/os/i686) +# if $repo is in the line, then assumes core +# if $arch is in the line, then assumes $(uname -m) +# returns a fetchurl (e.g. http://foo.com/core/os/i686/core.db.tar.gz) +ARCH="$(uname -m)" +getfetchurl() { + local strippedurl="${1%/}" + + local replacedurl="${strippedurl//'$repo'/core}" + replacedurl="${replacedurl//'$arch'/$ARCH}" + + local tmp="${replacedurl%/*}" + tmp="${tmp%/*}" + + local reponame="${tmp##*/}" + if [[ -z $reponame || $reponame = $replacedurl ]]; then + echo "fail" + else + local fetchurl="${replacedurl}/$reponame@DBEXT@" + echo "$fetchurl" + fi +} + +# This exists to remove the need for a separate interrupt function +finaloutput() { + IFS=$'\n' sortedarray=( $(LC_COLLATE=C printf "%s\n" "${timesarray[@]}" | sort) ) + + # Final output for mirrorfile + numiterator="0" + if [[ $TIMESONLY ]]; then + echo + echo " Servers sorted by time (seconds):" + for line in "${sortedarray[@]}"; do + echo "${line#* } : ${line% *}" + ((numiterator++)) + (( NUM && numiterator >= NUM )) && break + done + else + for line in "${sortedarray[@]}"; do + echo "Server = ${line#* }" + ((numiterator++)) + (( NUM && numiterator >= NUM )) && break + done + fi + exit 0 +} + + +# Argument parsing +[[ $1 ]] || usage +while [[ $1 ]]; do + if [[ ${1:0:2} = -- ]]; then + case "${1:2}" in + help) usage ;; + version) version ;; + times) TIMESONLY=1 ; shift ;; + verbose) VERBOSE=1 ; shift ;; + url) CHECKURL=1; [[ $2 ]] || err "Must specify url."; URL="$2"; shift 2;; + *) err "\`$1' is an invalid argument." + esac + elif [[ ${1:0:1} = - ]]; then + + if [[ ! ${1:1:1} ]]; then + [[ -t 0 ]] && err "Stdin is empty." + IFS=$'\n' linearray=( $(</dev/stdin) ) + STDIN=1 + shift + else + snum=1 + for ((i=1 ; i<${#1}; i++)); do + case ${1:$i:1} in + h) usage ;; + t) TIMESONLY=1 ;; + v) VERBOSE=1 ;; + u) CHECKURL=1; [[ $2 ]] || err "Must specify url."; URL="$2"; snum=2;; + n) [[ $2 ]] || err "Must specify number." ; NUM="$2" ; snum=2;; + *) err "\`-$1' is an invald argument." ;; + esac + done + shift $snum + fi + elif [[ -f $1 ]]; then + FILE="1" + IFS=$'\n' linearray=( $(<$1) ) + [[ $linearray ]] || err "File is empty." + shift + else + err "\`$1' does not exist." + fi +done + +# Some sanity checks +[[ $NUM ]] || NUM=0 +[[ $FILE && $CHECKURL ]] && err "Cannot specify a url and mirrorfile." +[[ $FILE || $CHECKURL || $STDIN ]] || err "Must specify url, mirrorfile, or stdin." + +# Single url handling +if [[ $CHECKURL ]]; then + url="$(getfetchurl "$URL")" + [[ $url = fail ]] && err "url \`$URL' is malformed." + [[ $VERBOSE ]] && echo "Testing $url..." + time=$(gettime "$url") + echo "$URL : $time" + exit 0 +fi + +# Get url results from mirrorfile, fill up the array, and so on +if [[ $TIMESONLY ]]; then + echo "Querying servers, this may take some time..." +elif [[ $FILE ]]; then + echo "# Server list generated by rankmirrors on $(date +%Y-%m-%d)" +fi + +timesarray=() +for line in "${linearray[@]}"; do + if [[ $line =~ ^# ]]; then + [[ $TIMESONLY ]] || echo $line + elif [[ $line =~ ^Server ]]; then + + # Getting values and times and such + server="${line#*= }" + url="$(getfetchurl "$server")" + [[ $url = fail ]] && err "url \`$URL' is malformed." + time=$(gettime "$url") + timesarray+=("$time $server") + + # Output + if [[ $VERBOSE && $TIMESONLY ]]; then + echo "$server ... $time" + elif [[ $VERBOSE ]]; then + echo "# $server ... $time" + elif [[ $TIMESONLY ]]; then + echo -n " *" + fi + fi +done +finaloutput + +# vim: set ts=2 sw=2 noet: diff --git a/scripts/repo-add.sh.in b/scripts/repo-add.sh.in index c8380c4e..0e46c371 100644 --- a/scripts/repo-add.sh.in +++ b/scripts/repo-add.sh.in @@ -42,7 +42,7 @@ msg() { } msg2() { - [ $QUIET -ne 0 ] && return + (( QUIET )) && return local mesg=$1; shift printf " -> ${mesg}\n" "$@" >&1 } @@ -90,7 +90,7 @@ There is NO WARRANTY, to the extent permitted by law.\n")" # arg2 - List # arg3 - File to write to write_list_entry() { - if [ -n "$2" ]; then + if [[ -n $2 ]]; then echo "%$1%" >>$3 echo -e $2 >>$3 fi @@ -102,7 +102,7 @@ find_pkgentry() local pkgentry for pkgentry in $tmpdir/$pkgname*; do name=${pkgentry##*/} - if [ "${name%-*-*}" = "$pkgname" ]; then + if [[ ${name%-*-*} = $pkgname ]]; then echo $pkgentry return 0 fi @@ -126,17 +126,18 @@ db_write_delta() pkgname="$(get_delta_pkgname $deltafile)" pkgentry=$(find_pkgentry $pkgname) - if [ -z "$pkgentry" ]; then + if [[ -z $pkgentry ]]; then return 1 fi deltas="$pkgentry/deltas" # create deltas file if it does not already exist - if [ ! -f "$deltas" ]; then + if [[ ! -f $deltas ]]; then msg2 "$(gettext "Creating 'deltas' db entry...")" echo -e "%DELTAS%" >>$deltas fi # get md5sum and compressed size of package - md5sum="$(openssl dgst -md5 "$deltafile" | awk '{print $NF}')" + md5sum="$(openssl dgst -md5 "$deltafile")" + md5sum="${md5sum##* }" csize=$(@SIZECMD@ "$deltafile") oldfile=$(xdelta3 printhdr $deltafile | grep "XDELTA filename (source)" | sed 's/.*: *//') @@ -161,11 +162,11 @@ db_remove_delta() pkgname="$(get_delta_pkgname $deltafile)" pkgentry=$(find_pkgentry $pkgname) - if [ -z "$pkgentry" ]; then + if [[ -z $pkgentry ]]; then return 1 fi deltas="$pkgentry/deltas" - if [ ! -f "$deltas" ]; then + if [[ ! -f $deltas ]]; then return 1 fi if grep -q "$filename" $deltas; then @@ -213,18 +214,19 @@ db_write_entry() IFS=$OLDIFS # get md5sum and compressed size of package - md5sum="$(openssl dgst -md5 "$pkgfile" | awk '{print $NF}')" + md5sum="$(openssl dgst -md5 "$pkgfile")" + md5sum="${md5sum##* }" csize=$(@SIZECMD@ "$pkgfile") # ensure $pkgname and $pkgver variables were found - if [ -z "$pkgname" -o -z "$pkgver" ]; then + if [[ -z $pkgname || -z $pkgver ]]; then error "$(gettext "Invalid package file '%s'.")" "$pkgfile" return 1 fi cd "$tmpdir" - if [ -d "$pkgname-$pkgver" ]; then + if [[ -d $pkgname-$pkgver ]]; then warning "$(gettext "An entry for '%s' already existed")" "$pkgname-$pkgver" fi @@ -236,30 +238,30 @@ db_write_entry() cd "$pkgname-$pkgver" # restore an eventual deltas file - [ -f "../$pkgname.deltas" ] && mv "../$pkgname.deltas" deltas + [[ -f ../$pkgname.deltas ]] && mv "../$pkgname.deltas" deltas # create desc entry msg2 "$(gettext "Creating 'desc' db entry...")" echo -e "%FILENAME%\n$(basename "$1")\n" >>desc echo -e "%NAME%\n$pkgname\n" >>desc - [ -n "$pkgbase" ] && echo -e "%BASE%\n$pkgbase\n" >>desc + [[ -n $pkgbase ]] && echo -e "%BASE%\n$pkgbase\n" >>desc echo -e "%VERSION%\n$pkgver\n" >>desc - [ -n "$pkgdesc" ] && echo -e "%DESC%\n$pkgdesc\n" >>desc + [[ -n $pkgdesc ]] && echo -e "%DESC%\n$pkgdesc\n" >>desc write_list_entry "GROUPS" "$_groups" "desc" - [ -n "$csize" ] && echo -e "%CSIZE%\n$csize\n" >>desc - [ -n "$size" ] && echo -e "%ISIZE%\n$size\n" >>desc + [[ -n $csize ]] && echo -e "%CSIZE%\n$csize\n" >>desc + [[ -n $size ]] && echo -e "%ISIZE%\n$size\n" >>desc # compute checksums msg2 "$(gettext "Computing md5 checksums...")" echo -e "%MD5SUM%\n$md5sum\n" >>desc - [ -n "$url" ] && echo -e "%URL%\n$url\n" >>desc + [[ -n $url ]] && echo -e "%URL%\n$url\n" >>desc write_list_entry "LICENSE" "$_licenses" "desc" - [ -n "$arch" ] && echo -e "%ARCH%\n$arch\n" >>desc - [ -n "$builddate" ] && echo -e "%BUILDDATE%\n$builddate\n" >>desc - [ -n "$packager" ] && echo -e "%PACKAGER%\n$packager\n" >>desc + [[ -n $arch ]] && echo -e "%ARCH%\n$arch\n" >>desc + [[ -n $builddate ]] && echo -e "%BUILDDATE%\n$builddate\n" >>desc + [[ -n $packager ]] && echo -e "%PACKAGER%\n$packager\n" >>desc write_list_entry "REPLACES" "$_replaces" "desc" - [ -n "$force" ] && echo -e "%FORCE%\n" >>desc + [[ -n $force ]] && echo -e "%FORCE%\n" >>desc # create depends entry msg2 "$(gettext "Creating 'depends' db entry...")" @@ -281,9 +283,9 @@ db_remove_entry() { local pkgname=$1 local notfound=1 local pkgentry=$(find_pkgentry $pkgname) - while [ -n "$pkgentry" ]; do + while [[ -n $pkgentry ]]; do notfound=0 - if [ -f "$pkgentry/deltas" ]; then + if [[ -f $pkgentry/deltas ]]; then mv "$pkgentry/deltas" "$tmpdir/$pkgname.deltas" fi msg2 "$(gettext "Removing existing entry '%s'...")" \ @@ -301,16 +303,16 @@ check_repo_db() CLEAN_LOCK=1 else error "$(gettext "Failed to acquire lockfile: %s.")" "$LOCKFILE" - [ -f "$LOCKFILE" ] && error "$(gettext "Held by process %s")" "$(cat $LOCKFILE)" + [[ -f $LOCKFILE ]] && error "$(gettext "Held by process %s")" "$(cat $LOCKFILE)" exit 1 fi - if [ -f "$REPO_DB_FILE" ]; then + if [[ -f $REPO_DB_FILE ]]; then # there are two situations we can have here- a DB with some entries, # or a DB with no contents at all. if ! bsdtar -tqf "$REPO_DB_FILE" '*/desc' >/dev/null 2>&1; then # check empty case - if [ -n "$(bsdtar -tqf "$REPO_DB_FILE" '*' 2>/dev/null)" ]; then + if [[ -n $(bsdtar -tqf "$REPO_DB_FILE" '*' 2>/dev/null) ]]; then error "$(gettext "Repository file '%s' is not a proper pacman database.")" "$REPO_DB_FILE" exit 1 fi @@ -337,15 +339,15 @@ check_repo_db() add() { - if [ ! -f "$1" ]; then + if [[ ! -f $1 ]]; then error "$(gettext "File '%s' not found.")" "$1" return 1 fi - if [ "${1##*.}" == "delta" ]; then + if [[ ${1##*.} == "delta" ]]; then deltafile=$1 msg "$(gettext "Adding delta '%s'")" "$deltafile" - if [ ! "$(type -p xdelta3)" ]; then + if ! type xdelta3 &>/dev/null; then error "$(gettext "Cannot find the xdelta3 binary! Is xdelta3 installed?")" exit 1 fi @@ -357,7 +359,7 @@ add() fi pkgfile=$1 - if ! bsdtar -tqf "$pkgfile" .PKGINFO 2>&1 >/dev/null; then + if ! bsdtar -tqf "$pkgfile" .PKGINFO >/dev/null 2>&1; then error "$(gettext "'%s' is not a package file, skipping")" "$pkgfile" return 1 fi @@ -369,7 +371,7 @@ add() remove() { - if [ "${1##*.}" == "delta" ]; then + if [[ ${1##*.} == "delta" ]]; then deltafile=$1 msg "$(gettext "Searching for delta '%s'...")" "$deltafile" if db_remove_delta "$deltafile"; then @@ -403,8 +405,8 @@ clean_up() { local exit_code=$? cd "$startdir" - [ -d "$tmpdir" ] && rm -rf "$tmpdir" - [ $CLEAN_LOCK -eq 1 -a -f "$LOCKFILE" ] && rm -f "$LOCKFILE" + [[ -d $tmpdir ]] && rm -rf "$tmpdir" + (( CLEAN_LOCK )) && [[ -f $LOCKFILE ]] && rm -f "$LOCKFILE" exit $exit_code } @@ -412,7 +414,7 @@ clean_up() { # PROGRAM START # determine whether we have gettext; make it a no-op if we do not -if [ ! $(type -t gettext) ]; then +if ! type gettext &>/dev/null; then gettext() { echo "$@" } @@ -423,15 +425,9 @@ case "$1" in -V|--version) version; exit 0;; esac -# check for correct number of args -if [ $# -lt 2 ]; then - usage - exit 1 -fi - # figure out what program we are cmd="$(basename $0)" -if [ "$cmd" != "repo-add" -a "$cmd" != "repo-remove" ]; then +if [[ $cmd != "repo-add" && $cmd != "repo-remove" ]]; then error "$(gettext "Invalid command name '%s' specified.")" "$cmd" exit 1 fi @@ -450,14 +446,8 @@ success=0 for arg in "$@"; do case "$arg" in -q|--quiet) QUIET=1;; - - -f|--force) - warning "$(gettext "the -f and --force options are no longer recognized")" - msg2 "$(gettext "use options=(force) in the PKGBUILD instead")" - ;; - *) - if [ -z "$REPO_DB_FILE" ]; then + if [[ -z $REPO_DB_FILE ]]; then REPO_DB_FILE="$arg" LOCKFILE="$REPO_DB_FILE.lck" check_repo_db @@ -472,7 +462,7 @@ for arg in "$@"; do done # if at least one operation was a success, re-zip database -if [ $success -eq 1 ]; then +if (( success )); then msg "$(gettext "Creating updated database file '%s'")" "$REPO_DB_FILE" case "$REPO_DB_FILE" in @@ -486,7 +476,7 @@ if [ $success -eq 1 ]; then filename=$(basename "$REPO_DB_FILE") cd "$tmpdir" - if [ -n "$(ls)" ]; then + if [[ -n $(ls) ]]; then bsdtar -c${TAR_OPT}f "$filename" * else # we have no packages remaining? zip up some emptyness @@ -495,10 +485,11 @@ if [ $success -eq 1 ]; then fi cd "$startdir" - [ -f "$REPO_DB_FILE" ] && mv -f "$REPO_DB_FILE" "${REPO_DB_FILE}.old" - [ -f "$tmpdir/$filename" ] && mv "$tmpdir/$filename" "$REPO_DB_FILE" + [[ -f $REPO_DB_FILE ]] && mv -f "$REPO_DB_FILE" "${REPO_DB_FILE}.old" + [[ -f $tmpdir/$filename ]] && mv "$tmpdir/$filename" "$REPO_DB_FILE" else msg "$(gettext "No packages modified, nothing to do.")" + exit 1 fi exit 0 diff --git a/src/pacman/callback.c b/src/pacman/callback.c index 1cdb1153..858bfdf4 100644 --- a/src/pacman/callback.c +++ b/src/pacman/callback.c @@ -259,10 +259,20 @@ void cb_trans_conv(pmtransconv_t event, void *data1, void *data2, alpm_pkg_get_name(data2)); break; case PM_TRANS_CONV_CONFLICT_PKG: - *response = yesno(_(":: %s conflicts with %s. Remove %s?"), - (char *)data1, - (char *)data2, - (char *)data2); + /* data parameters: target package, local package, conflict (strings) */ + /* print conflict only if it contains new information */ + if(!strcmp(data1, data3) || !strcmp(data2, data3)) { + *response = noyes(_(":: %s and %s are in conflict. Remove %s?"), + (char *)data1, + (char *)data2, + (char *)data2); + } else { + *response = noyes(_(":: %s and %s are in conflict (%s). Remove %s?"), + (char *)data1, + (char *)data2, + (char *)data3, + (char *)data2); + } break; case PM_TRANS_CONV_REMOVE_PKGS: { @@ -275,7 +285,7 @@ void cb_trans_conv(pmtransconv_t event, void *data1, void *data2, 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 " + *response = noyes(_("\nDo you want to skip the above " "package(s) for this upgrade?")); alpm_list_free(namelist); } @@ -294,6 +304,12 @@ void cb_trans_conv(pmtransconv_t event, void *data1, void *data2, (char *)data1); break; } + if(config->noask) { + if(config->ask & event) { + /* inverse the default answer */ + *response = !*response; + } + } } /* callback to handle display of transaction progress */ diff --git a/src/pacman/conf.h b/src/pacman/conf.h index 2d3de987..c97e5d78 100644 --- a/src/pacman/conf.h +++ b/src/pacman/conf.h @@ -63,6 +63,8 @@ typedef struct __config_t { unsigned short group; pmtransflag_t flags; + unsigned short noask; + unsigned int ask; /* conf file options */ unsigned short chomp; /* I Love Candy! */ @@ -86,6 +88,24 @@ enum { PM_OP_DEPTEST }; +/* Long Operations */ +enum { + OP_NOCONFIRM = 1000, + OP_CONFIG, + OP_IGNORE, + OP_DEBUG, + OP_NOPROGRESSBAR, + OP_NOSCRIPTLET, + OP_ASK, + OP_CACHEDIR, + OP_ASDEPS, + OP_LOGFILE, + OP_IGNOREGROUP, + OP_NEEDED, + OP_ASEXPLICIT, + OP_ARCH +}; + /* clean method */ enum { PM_CLEAN_KEEPINST = 0, /* default */ diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index 4c556a7d..0e80fb22 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -34,6 +34,7 @@ #include <signal.h> #include <unistd.h> #include <sys/types.h> +#include <sys/stat.h> #include <sys/utsname.h> /* uname */ #include <locale.h> /* setlocale */ #include <time.h> /* time_t */ @@ -149,6 +150,7 @@ static void usage(int op, const char * const myname) printf(_(" -r, --root <path> set an alternate installation root\n")); printf(_(" -b, --dbpath <path> set an alternate database location\n")); printf(_(" --cachedir <dir> set an alternate package cache location\n")); + printf(_(" --arch <arch> set an alternate architecture\n")); } } @@ -195,6 +197,19 @@ static void setuseragent(void) setenv("HTTP_USER_AGENT", agent, 0); } +static void setarch(const char *arch) +{ + if (strcmp(arch, "auto") == 0) { + struct utsname un; + uname(&un); + pm_printf(PM_LOG_DEBUG, "config: architecture: %s\n", un.machine); + alpm_option_set_arch(un.machine); + } else { + pm_printf(PM_LOG_DEBUG, "config: architecture: %s\n", arch); + alpm_option_set_arch(arch); + } +} + /** Free the resources. * * @param ret the return value @@ -220,7 +235,9 @@ static void cleanup(int ret) { static ssize_t xwrite(int fd, const void *buf, size_t count) { ssize_t ret; - while((ret = write(fd, buf, count)) == -1 && errno == EINTR); + do { + ret = write(fd, buf, count); + } while(ret == -1 && errno == EINTR); return(ret); } @@ -317,6 +334,8 @@ static void setlibpaths(void) } } +#define check_optarg() if(!optarg) { return(1); } + /** Parse command-line arguments for each operation. * @param argc argc * @param argv argv @@ -364,18 +383,20 @@ static int parseargs(int argc, char *argv[]) {"verbose", no_argument, 0, 'v'}, {"downloadonly", no_argument, 0, 'w'}, {"refresh", no_argument, 0, 'y'}, - {"noconfirm", no_argument, 0, 1000}, - {"config", required_argument, 0, 1001}, - {"ignore", required_argument, 0, 1002}, - {"debug", optional_argument, 0, 1003}, - {"noprogressbar", no_argument, 0, 1004}, - {"noscriptlet", no_argument, 0, 1005}, - {"cachedir", required_argument, 0, 1007}, - {"asdeps", no_argument, 0, 1008}, - {"logfile", required_argument, 0, 1009}, - {"ignoregroup", required_argument, 0, 1010}, - {"needed", no_argument, 0, 1011}, - {"asexplicit", no_argument, 0, 1012}, + {"noconfirm", no_argument, 0, OP_NOCONFIRM}, + {"config", required_argument, 0, OP_CONFIG}, + {"ignore", required_argument, 0, OP_IGNORE}, + {"debug", optional_argument, 0, OP_DEBUG}, + {"noprogressbar", no_argument, 0, OP_NOPROGRESSBAR}, + {"noscriptlet", no_argument, 0, OP_NOSCRIPTLET}, + {"ask", required_argument, 0, OP_ASK}, + {"cachedir", required_argument, 0, OP_CACHEDIR}, + {"asdeps", no_argument, 0, OP_ASDEPS}, + {"logfile", required_argument, 0, OP_LOGFILE}, + {"ignoregroup", required_argument, 0, OP_IGNOREGROUP}, + {"needed", no_argument, 0, OP_NEEDED}, + {"asexplicit", no_argument, 0, OP_ASEXPLICIT}, + {"arch", required_argument, 0, OP_ARCH}, {0, 0, 0, 0} }; @@ -387,21 +408,23 @@ static int parseargs(int argc, char *argv[]) } switch(opt) { case 0: break; - case 1000: config->noconfirm = 1; break; - case 1001: + case OP_NOCONFIRM: config->noconfirm = 1; break; + case OP_CONFIG: + check_optarg(); if(config->configfile) { free(config->configfile); } config->configfile = strndup(optarg, PATH_MAX); break; - case 1002: + case OP_IGNORE: + check_optarg(); list = strsplit(optarg, ','); for(item = list; item; item = alpm_list_next(item)) { alpm_option_add_ignorepkg((char *)alpm_list_getdata(item)); } FREELIST(list); break; - case 1003: + case OP_DEBUG: /* debug levels are made more 'human readable' than using a raw logmask * here, error and warning are set in config_new, though perhaps a * --quiet option will remove these later */ @@ -424,32 +447,44 @@ static int parseargs(int argc, char *argv[]) /* progress bars get wonky with debug on, shut them off */ config->noprogressbar = 1; break; - case 1004: config->noprogressbar = 1; break; - case 1005: config->flags |= PM_TRANS_FLAG_NOSCRIPTLET; break; - case 1007: + case OP_NOPROGRESSBAR: config->noprogressbar = 1; break; + case OP_NOSCRIPTLET: config->flags |= PM_TRANS_FLAG_NOSCRIPTLET; break; + case OP_ASK: + check_optarg(); + config->noask = 1; + config->ask = atoi(optarg); + break; + case OP_CACHEDIR: + check_optarg(); if(alpm_option_add_cachedir(optarg) != 0) { pm_printf(PM_LOG_ERROR, _("problem adding cachedir '%s' (%s)\n"), optarg, alpm_strerrorlast()); return(1); } break; - case 1008: + case OP_ASDEPS: config->flags |= PM_TRANS_FLAG_ALLDEPS; break; - case 1009: + case OP_LOGFILE: + check_optarg(); config->logfile = strndup(optarg, PATH_MAX); break; - case 1010: + case OP_IGNOREGROUP: + check_optarg(); list = strsplit(optarg, ','); for(item = list; item; item = alpm_list_next(item)) { alpm_option_add_ignoregrp((char *)alpm_list_getdata(item)); } FREELIST(list); break; - case 1011: config->flags |= PM_TRANS_FLAG_NEEDED; break; - case 1012: + case OP_NEEDED: config->flags |= PM_TRANS_FLAG_NEEDED; break; + case OP_ASEXPLICIT: config->flags |= PM_TRANS_FLAG_ALLEXPLICIT; break; + case OP_ARCH: + check_optarg(); + setarch(optarg); + break; case 'Q': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_QUERY); break; case 'R': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_REMOVE); break; case 'S': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_SYNC); break; @@ -457,6 +492,7 @@ static int parseargs(int argc, char *argv[]) case 'U': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_UPGRADE); break; case 'V': config->version = 1; break; case 'b': + check_optarg(); config->dbpath = strdup(optarg); break; case 'c': @@ -493,6 +529,7 @@ static int parseargs(int argc, char *argv[]) config->quiet = 1; break; case 'r': + check_optarg(); config->rootdir = strdup(optarg); break; case 's': @@ -592,7 +629,7 @@ static char *get_filename(const char *url) { static char *get_destfile(const char *path, const char *filename) { char *destfile; /* len = localpath len + filename len + null */ - int len = strlen(path) + strlen(filename) + 1; + size_t len = strlen(path) + strlen(filename) + 1; destfile = calloc(len, sizeof(char)); snprintf(destfile, len, "%s%s", path, filename); @@ -602,7 +639,7 @@ static char *get_destfile(const char *path, const char *filename) { static char *get_tempfile(const char *path, const char *filename) { char *tempfile; /* len = localpath len + filename len + '.part' len + null */ - int len = strlen(path) + strlen(filename) + 6; + size_t len = strlen(path) + strlen(filename) + 6; tempfile = calloc(len, sizeof(char)); snprintf(tempfile, len, "%s%s.part", path, filename); @@ -611,13 +648,12 @@ static char *get_tempfile(const char *path, const char *filename) { /** External fetch callback */ int download_with_xfercommand(const char *url, const char *localpath, - time_t mtimeold, time_t *mtimenew) { + int force) { int ret = 0; int retval; int usepart = 0; - char *ptr1, *ptr2; - char origCmd[PATH_MAX]; - char parsedCmd[PATH_MAX] = ""; + struct stat st; + char *parsedcmd,*tempcmd; char cwd[PATH_MAX]; char *destfile, *tempfile, *filename; @@ -632,28 +668,25 @@ int download_with_xfercommand(const char *url, const char *localpath, destfile = get_destfile(localpath, filename); tempfile = get_tempfile(localpath, filename); - strncpy(origCmd, config->xfercommand, sizeof(origCmd)); + if(force && stat(tempfile, &st) == 0) { + unlink(tempfile); + } + if(force && stat(destfile, &st) == 0) { + unlink(destfile); + } + + tempcmd = strdup(config->xfercommand); /* replace all occurrences of %o with fn.part */ - ptr1 = origCmd; - while((ptr2 = strstr(ptr1, "%o"))) { + if(strstr(tempcmd, "%o")) { usepart = 1; - ptr2[0] = '\0'; - strcat(parsedCmd, ptr1); - strcat(parsedCmd, tempfile); - ptr1 = ptr2 + 2; + parsedcmd = strreplace(tempcmd, "%o", tempfile); + free(tempcmd); + tempcmd = parsedcmd; } - strcat(parsedCmd, ptr1); /* replace all occurrences of %u with the download URL */ - strncpy(origCmd, parsedCmd, sizeof(origCmd)); - parsedCmd[0] = '\0'; - ptr1 = origCmd; - while((ptr2 = strstr(ptr1, "%u"))) { - ptr2[0] = '\0'; - strcat(parsedCmd, ptr1); - strcat(parsedCmd, url); - ptr1 = ptr2 + 2; - } - strcat(parsedCmd, ptr1); + parsedcmd = strreplace(tempcmd, "%u", url); + free(tempcmd); + /* cwd to the download directory */ getcwd(cwd, PATH_MAX); if(chdir(localpath)) { @@ -662,8 +695,8 @@ int download_with_xfercommand(const char *url, const char *localpath, goto cleanup; } /* execute the parsed command via /bin/sh -c */ - pm_printf(PM_LOG_DEBUG, "running command: %s\n", parsedCmd); - retval = system(parsedCmd); + pm_printf(PM_LOG_DEBUG, "running command: %s\n", parsedcmd); + retval = system(parsedcmd); if(retval == -1) { pm_printf(PM_LOG_WARNING, _("running XferCommand: fork failed!\n")); @@ -689,10 +722,132 @@ cleanup: } free(destfile); free(tempfile); + free(parsedcmd); return(ret); } +static int _parse_options(char *key, char *value) +{ + if(value == NULL) { + /* options without settings */ + if(strcmp(key, "UseSyslog") == 0) { + alpm_option_set_usesyslog(1); + pm_printf(PM_LOG_DEBUG, "config: usesyslog\n"); + } else if(strcmp(key, "ILoveCandy") == 0) { + config->chomp = 1; + pm_printf(PM_LOG_DEBUG, "config: chomp\n"); + } else if(strcmp(key, "ShowSize") == 0) { + config->showsize = 1; + pm_printf(PM_LOG_DEBUG, "config: showsize\n"); + } else if(strcmp(key, "UseDelta") == 0) { + alpm_option_set_usedelta(1); + pm_printf(PM_LOG_DEBUG, "config: usedelta\n"); + } else if(strcmp(key, "TotalDownload") == 0) { + config->totaldownload = 1; + pm_printf(PM_LOG_DEBUG, "config: totaldownload\n"); + } else { + pm_printf(PM_LOG_ERROR, _("directive '%s' without value not recognized\n"), key); + return(1); + } + } else { + /* options with settings */ + if(strcmp(key, "NoUpgrade") == 0) { + setrepeatingoption(value, "NoUpgrade", alpm_option_add_noupgrade); + } else if(strcmp(key, "NoExtract") == 0) { + setrepeatingoption(value, "NoExtract", alpm_option_add_noextract); + } else if(strcmp(key, "IgnorePkg") == 0) { + setrepeatingoption(value, "IgnorePkg", alpm_option_add_ignorepkg); + } else if(strcmp(key, "IgnoreGroup") == 0) { + setrepeatingoption(value, "IgnoreGroup", alpm_option_add_ignoregrp); + } else if(strcmp(key, "HoldPkg") == 0) { + setrepeatingoption(value, "HoldPkg", option_add_holdpkg); + } else if(strcmp(key, "SyncFirst") == 0) { + setrepeatingoption(value, "SyncFirst", option_add_syncfirst); + } else if(strcmp(key, "Architecture") == 0) { + if(!alpm_option_get_arch()) { + setarch(value); + } + } else if(strcmp(key, "DBPath") == 0) { + /* don't overwrite a path specified on the command line */ + if(!config->dbpath) { + config->dbpath = strdup(value); + pm_printf(PM_LOG_DEBUG, "config: dbpath: %s\n", value); + } + } else if(strcmp(key, "CacheDir") == 0) { + if(alpm_option_add_cachedir(value) != 0) { + pm_printf(PM_LOG_ERROR, _("problem adding cachedir '%s' (%s)\n"), + value, alpm_strerrorlast()); + return(1); + } + pm_printf(PM_LOG_DEBUG, "config: cachedir: %s\n", value); + } else if(strcmp(key, "RootDir") == 0) { + /* don't overwrite a path specified on the command line */ + if(!config->rootdir) { + config->rootdir = strdup(value); + pm_printf(PM_LOG_DEBUG, "config: rootdir: %s\n", value); + } + } else if (strcmp(key, "LogFile") == 0) { + if(!config->logfile) { + config->logfile = strdup(value); + pm_printf(PM_LOG_DEBUG, "config: logfile: %s\n", value); + } + } else if (strcmp(key, "XferCommand") == 0) { + config->xfercommand = strdup(value); + alpm_option_set_fetchcb(download_with_xfercommand); + pm_printf(PM_LOG_DEBUG, "config: xfercommand: %s\n", value); + } else if (strcmp(key, "CleanMethod") == 0) { + if (strcmp(value, "KeepInstalled") == 0) { + config->cleanmethod = PM_CLEAN_KEEPINST; + } else if (strcmp(value, "KeepCurrent") == 0) { + config->cleanmethod = PM_CLEAN_KEEPCUR; + } else { + pm_printf(PM_LOG_ERROR, _("invalid value for 'CleanMethod' : '%s'\n"), value); + return(1); + } + pm_printf(PM_LOG_DEBUG, "config: cleanmethod: %s\n", value); + } else { + pm_printf(PM_LOG_ERROR, _("directive '%s' with a value not recognized\n"), key); + return(1); + } + + } + return(0); +} + +static int _add_mirror(pmdb_t *db, char *value) +{ + const char *dbname = alpm_db_get_name(db); + /* let's attempt a replacement for the current repo */ + char *temp = strreplace(value, "$repo", dbname); + /* let's attempt a replacement for the arch */ + const char *arch = alpm_option_get_arch(); + char *server; + if(arch) { + server = strreplace(temp, "$arch", arch); + free(temp); + } else { + if(strstr(temp, "$arch")) { + free(temp); + pm_printf(PM_LOG_ERROR, _("The mirror '%s' contains the $arch" + " variable, but no Architecture is defined.\n"), value); + return(1); + } + server = temp; + } + + if(alpm_db_setserver(db, server) != 0) { + /* pm_errno is set by alpm_db_setserver */ + pm_printf(PM_LOG_ERROR, _("could not add server URL to database '%s': %s (%s)\n"), + dbname, server, alpm_strerrorlast()); + free(server); + return(1); + } + + free(server); + return(0); +} + /* The real parseconfig. Called with a null section argument by the publicly * visible parseconfig so we can recall from within ourself on an include */ static int _parseconfig(const char *file, const char *givensection, @@ -749,11 +904,8 @@ static int _parseconfig(const char *file, const char *givensection, ret = 1; goto cleanup; } - /* if we are not looking at the options section, register a db and also - * ensure we have set all of our library paths as the library is too stupid - * at the moment to do lazy opening of the databases */ + /* if we are not looking at the options section, register a db */ if(strcmp(section, "options") != 0) { - setlibpaths(); db = alpm_db_register_sync(section); if(db == NULL) { pm_printf(PM_LOG_ERROR, _("could not register '%s' database (%s)\n"), @@ -762,142 +914,70 @@ static int _parseconfig(const char *file, const char *givensection, goto cleanup; } } - } else { - /* directive */ - char *key; - /* strsep modifies the 'line' string: 'key \0 ptr' */ - key = line; - ptr = line; - strsep(&ptr, "="); - strtrim(key); - strtrim(ptr); + continue; + } - if(key == NULL) { - pm_printf(PM_LOG_ERROR, _("config file %s, line %d: syntax error in config file- missing key.\n"), - file, linenum); - ret = 1; - goto cleanup; - } - /* For each directive, compare to the camelcase string. */ - if(section == NULL) { - pm_printf(PM_LOG_ERROR, _("config file %s, line %d: All directives must belong to a section.\n"), + /* directive */ + char *key, *value; + /* strsep modifies the 'line' string: 'key \0 value' */ + key = line; + value = line; + strsep(&value, "="); + strtrim(key); + strtrim(value); + + if(key == NULL) { + pm_printf(PM_LOG_ERROR, _("config file %s, line %d: syntax error in config file- missing key.\n"), + file, linenum); + ret = 1; + goto cleanup; + } + /* For each directive, compare to the camelcase string. */ + if(section == NULL) { + pm_printf(PM_LOG_ERROR, _("config file %s, line %d: All directives must belong to a section.\n"), + file, linenum); + ret = 1; + goto cleanup; + } + if(strcmp(section, "options") == 0) { + if((ret = _parse_options(key, value)) != 0) { + pm_printf(PM_LOG_ERROR, _("config file %s, line %d: problem in options section\n"), file, linenum); ret = 1; goto cleanup; } - if(ptr == NULL && strcmp(section, "options") == 0) { - /* directives without settings, all in [options] */ - if(strcmp(key, "NoPassiveFtp") == 0) { - alpm_option_set_nopassiveftp(1); - pm_printf(PM_LOG_DEBUG, "config: nopassiveftp\n"); - } else if(strcmp(key, "UseSyslog") == 0) { - alpm_option_set_usesyslog(1); - pm_printf(PM_LOG_DEBUG, "config: usesyslog\n"); - } else if(strcmp(key, "ILoveCandy") == 0) { - config->chomp = 1; - pm_printf(PM_LOG_DEBUG, "config: chomp\n"); - } else if(strcmp(key, "ShowSize") == 0) { - config->showsize = 1; - pm_printf(PM_LOG_DEBUG, "config: showsize\n"); - } else if(strcmp(key, "UseDelta") == 0) { - alpm_option_set_usedelta(1); - pm_printf(PM_LOG_DEBUG, "config: usedelta\n"); - } else if(strcmp(key, "TotalDownload") == 0) { - config->totaldownload = 1; - pm_printf(PM_LOG_DEBUG, "config: totaldownload\n"); - } else { - pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' not recognized.\n"), + continue; + } else { + /* we are in a repo section */ + if(strcmp(key, "Include") == 0) { + if(value == NULL) { + pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive %s needs a value\n"), file, linenum, key); ret = 1; goto cleanup; } - } else { - /* directives with settings */ - if(strcmp(key, "Include") == 0) { - pm_printf(PM_LOG_DEBUG, "config: including %s\n", ptr); - _parseconfig(ptr, section, db); - /* Ignore include failures... assume non-critical */ - } else if(strcmp(section, "options") == 0) { - if(strcmp(key, "NoUpgrade") == 0) { - setrepeatingoption(ptr, "NoUpgrade", alpm_option_add_noupgrade); - } else if(strcmp(key, "NoExtract") == 0) { - setrepeatingoption(ptr, "NoExtract", alpm_option_add_noextract); - } else if(strcmp(key, "IgnorePkg") == 0) { - setrepeatingoption(ptr, "IgnorePkg", alpm_option_add_ignorepkg); - } else if(strcmp(key, "IgnoreGroup") == 0) { - setrepeatingoption(ptr, "IgnoreGroup", alpm_option_add_ignoregrp); - } else if(strcmp(key, "HoldPkg") == 0) { - setrepeatingoption(ptr, "HoldPkg", option_add_holdpkg); - } else if(strcmp(key, "SyncFirst") == 0) { - setrepeatingoption(ptr, "SyncFirst", option_add_syncfirst); - } else if(strcmp(key, "DBPath") == 0) { - /* don't overwrite a path specified on the command line */ - if(!config->dbpath) { - config->dbpath = strdup(ptr); - pm_printf(PM_LOG_DEBUG, "config: dbpath: %s\n", ptr); - } - } else if(strcmp(key, "CacheDir") == 0) { - if(alpm_option_add_cachedir(ptr) != 0) { - pm_printf(PM_LOG_ERROR, _("problem adding cachedir '%s' (%s)\n"), - ptr, alpm_strerrorlast()); - ret = 1; - goto cleanup; - } - pm_printf(PM_LOG_DEBUG, "config: cachedir: %s\n", ptr); - } else if(strcmp(key, "RootDir") == 0) { - /* don't overwrite a path specified on the command line */ - if(!config->rootdir) { - config->rootdir = strdup(ptr); - pm_printf(PM_LOG_DEBUG, "config: rootdir: %s\n", ptr); - } - } else if (strcmp(key, "LogFile") == 0) { - if(!config->logfile) { - config->logfile = strdup(ptr); - pm_printf(PM_LOG_DEBUG, "config: logfile: %s\n", ptr); - } - } else if (strcmp(key, "XferCommand") == 0) { - config->xfercommand = strdup(ptr); - alpm_option_set_fetchcb(download_with_xfercommand); - pm_printf(PM_LOG_DEBUG, "config: xfercommand: %s\n", ptr); - } else if (strcmp(key, "CleanMethod") == 0) { - if (strcmp(ptr, "KeepInstalled") == 0) { - config->cleanmethod = PM_CLEAN_KEEPINST; - } else if (strcmp(ptr, "KeepCurrent") == 0) { - config->cleanmethod = PM_CLEAN_KEEPCUR; - } else { - pm_printf(PM_LOG_ERROR, _("invalid value for 'CleanMethod' : '%s'\n"), ptr); - ret = 1; - goto cleanup; - } - pm_printf(PM_LOG_DEBUG, "config: cleanmethod: %s\n", ptr); - } else { - pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' not recognized.\n"), - file, linenum, key); - ret = 1; - goto cleanup; - } - } else if(strcmp(key, "Server") == 0) { - /* let's attempt a replacement for the current repo */ - char *server = strreplace(ptr, "$repo", section); - - if(alpm_db_setserver(db, server) != 0) { - /* pm_errno is set by alpm_db_setserver */ - pm_printf(PM_LOG_ERROR, _("could not add server URL to database '%s': %s (%s)\n"), - alpm_db_get_name(db), server, alpm_strerrorlast()); - free(server); - ret = 1; - goto cleanup; - } - - free(server); - } else { - pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' not recognized.\n"), + pm_printf(PM_LOG_DEBUG, "config: including %s\n", value); + _parseconfig(value, section, db); + /* Ignore include failures... assume non-critical */ + } else if(strcmp(key, "Server") == 0) { + if(value == NULL) { + pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive %s needs a value\n"), file, linenum, key); ret = 1; goto cleanup; } + if(_add_mirror(db, value) != 0) { + ret = 1; + goto cleanup; + } + } else { + pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' in repository section '%s' not recognized.\n"), + file, linenum, key, section); + ret = 1; + goto cleanup; } } + } cleanup: @@ -923,6 +1003,29 @@ static int parseconfig(const char *file) return(_parseconfig(file, NULL, NULL)); } +/** print commandline to logfile + */ +static void cl_to_log(int argc, char* argv[]) +{ + size_t size = 0; + int i; + for(i = 0; i<argc; i++) { + size += strlen(argv[i]) + 1; + } + char *cl_text = malloc(size); + if(!cl_text) + return; + char *p = cl_text; + for(i = 0; i<argc-1; i++) { + strcpy(p, argv[i]); + p += strlen(argv[i]); + *p++ = ' '; + } + strcpy(p, argv[i]); + alpm_logaction("Running '%s'\n", cl_text); + free(cl_text); +} + /** Main function. * @param argc argc * @param argv argv @@ -1018,6 +1121,11 @@ int main(int argc, char *argv[]) alpm_option_set_totaldlcb(cb_dl_total); } + /* noask is meant to be non-interactive */ + if(config->noask) { + config->noconfirm = 1; + } + #if defined(HAVE_GETEUID) && !defined(CYGWIN) /* check if we have sufficient permission for the requested operation */ if(myuid > 0 && needs_root()) { @@ -1049,6 +1157,11 @@ int main(int argc, char *argv[]) cleanup(EXIT_FAILURE); } + /* Log commandline */ + if(needs_root()) { + cl_to_log(argc, argv); + } + /* start the requested operation */ switch(config->op) { case PM_OP_REMOVE: diff --git a/src/pacman/remove.c b/src/pacman/remove.c index 0efbd94e..6d44350b 100644 --- a/src/pacman/remove.c +++ b/src/pacman/remove.c @@ -51,50 +51,23 @@ int pacman_remove(alpm_list_t *targets) } /* Step 0: create a new transaction */ - if(trans_init(PM_TRANS_TYPE_REMOVE, config->flags) == -1) { + if(trans_init(config->flags) == -1) { return(1); } /* Step 1: add targets to the created transaction */ for(i = targets; i; i = alpm_list_next(i)) { - char *targ = alpm_list_getdata(i); - if(alpm_trans_addtarget(targ) == -1) { - if(pm_errno == PM_ERR_PKG_NOT_FOUND) { - printf(_("%s not found, searching for group...\n"), targ); - pmgrp_t *grp = alpm_db_readgrp(db_local, targ); - if(grp == NULL) { - pm_fprintf(stderr, PM_LOG_ERROR, _("'%s': not found in local db\n"), targ); - retval = 1; - goto cleanup; - } else { - alpm_list_t *p, *pkgnames = NULL; - /* convert packages to package names */ - for(p = alpm_grp_get_pkgs(grp); p; p = alpm_list_next(p)) { - pmpkg_t *pkg = alpm_list_getdata(p); - pkgnames = alpm_list_add(pkgnames, (void *)alpm_pkg_get_name(pkg)); - } - printf(_(":: group %s:\n"), targ); - list_display(" ", pkgnames); - int all = yesno(_(" Remove whole content?")); - for(p = pkgnames; p; p = alpm_list_next(p)) { - char *pkgn = alpm_list_getdata(p); - 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()); - retval = 1; - alpm_list_free(pkgnames); - goto cleanup; - } - } - } - alpm_list_free(pkgnames); - } - } else { - pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerrorlast()); - retval = 1; - goto cleanup; - } + char *target = alpm_list_getdata(i); + char *targ = strchr(target, '/'); + if(targ && strncmp(target, "local", 5) == 0) { + targ++; + } else { + targ = target; + } + if(alpm_remove_target(targ) == -1) { + pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerrorlast()); + retval = 1; + goto cleanup; } } @@ -103,6 +76,12 @@ int pacman_remove(alpm_list_t *targets) pm_fprintf(stderr, PM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), alpm_strerrorlast()); switch(pm_errno) { + case PM_ERR_PKG_INVALID_ARCH: + for(i = data; i; i = alpm_list_next(i)) { + char *pkg = alpm_list_getdata(i); + printf(_(":: package %s does not have a valid architecture\n"), pkg); + } + break; case PM_ERR_UNSATISFIED_DEPS: for(i = data; i; i = alpm_list_next(i)) { pmdepmissing_t *miss = alpm_list_getdata(i); @@ -123,7 +102,7 @@ int pacman_remove(alpm_list_t *targets) /* Search for holdpkg in target list */ int holdpkg = 0; - for(i = alpm_trans_get_pkgs(); i; i = alpm_list_next(i)) { + for(i = alpm_trans_get_remove(); 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"), @@ -136,23 +115,19 @@ int pacman_remove(alpm_list_t *targets) goto cleanup; } - /* Warn user in case of dangerous operation */ - if(config->flags & PM_TRANS_FLAG_RECURSE || - config->flags & PM_TRANS_FLAG_CASCADE) { - /* list transaction targets */ - alpm_list_t *pkglist = alpm_trans_get_pkgs(); - - display_targets(pkglist, 0); - printf("\n"); - - /* get confirmation */ - if(yesno(_("Do you want to remove these packages?")) == 0) { - retval = 1; - goto cleanup; - } + /* Step 3: actually perform the removal */ + alpm_list_t *pkglist = alpm_trans_get_remove(); + if(pkglist == NULL) { + goto cleanup; /* we are done */ + } + /* print targets and ask user confirmation */ + display_targets(pkglist, 0); + printf("\n"); + if(yesno(_("Do you want to remove these packages?")) == 0) { + retval = 1; + goto cleanup; } - /* Step 3: actually perform the removal */ if(alpm_trans_commit(NULL) == -1) { pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"), alpm_strerrorlast()); diff --git a/src/pacman/sync.c b/src/pacman/sync.c index 12f67df2..a2ef616d 100644 --- a/src/pacman/sync.c +++ b/src/pacman/sync.c @@ -93,18 +93,21 @@ static int sync_cleandb(const char *dbpath, int keep_used) { if(rmrf(path)) { pm_fprintf(stderr, PM_LOG_ERROR, _("could not remove repository directory\n")); + closedir(dir); return(1); } } - } + closedir(dir); return(0); } static int sync_cleandb_all(void) { - const char *dbpath = alpm_option_get_dbpath(); + const char *dbpath; char newdbpath[PATH_MAX]; + int ret = 0; + dbpath = alpm_option_get_dbpath(); printf(_("Database directory: %s\n"), dbpath); if(!yesno(_("Do you want to remove unused repositories?"))) { return(0); @@ -112,28 +115,26 @@ static int sync_cleandb_all(void) { /* The sync dbs were previously put in dbpath/, but are now in dbpath/sync/, * so we will clean everything in dbpath/ (except dbpath/local/ and dbpath/sync/, * and only the unused sync dbs in dbpath/sync/ */ - sync_cleandb(dbpath, 0); + ret += sync_cleandb(dbpath, 0); sprintf(newdbpath, "%s%s", dbpath, "sync/"); - sync_cleandb(newdbpath, 1); + ret += sync_cleandb(newdbpath, 1); printf(_("Database directory cleaned up\n")); - return(0); + return(ret); } static int sync_cleancache(int level) { - /* TODO for now, just mess with the first cache directory */ - alpm_list_t* cachedirs = alpm_option_get_cachedirs(); - const char *cachedir = alpm_list_getdata(cachedirs); + alpm_list_t *i; + alpm_list_t *sync_dbs = alpm_option_get_syncdbs(); + int ret = 0; + + for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) { + printf(_("Cache directory: %s\n"), (char*)alpm_list_getdata(i)); + } if(level == 1) { - /* incomplete cleanup */ - DIR *dir; - struct dirent *ent; - /* Open up each package and see if it should be deleted, - * depending on the clean method used */ - printf(_("Cache directory: %s\n"), cachedir); switch(config->cleanmethod) { case PM_CLEAN_KEEPINST: if(!yesno(_("Do you want to remove uninstalled packages from cache?"))) { @@ -150,11 +151,23 @@ static int sync_cleancache(int level) return(1); } printf(_("removing old packages from cache...\n")); + } else { + if(!noyes(_("Do you want to remove ALL files from cache?"))) { + return(0); + } + printf(_("removing all files from cache...\n")); + } + + for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) { + const char *cachedir = alpm_list_getdata(i); + DIR *dir = opendir(cachedir); + struct dirent *ent; - dir = opendir(cachedir); if(dir == NULL) { - pm_fprintf(stderr, PM_LOG_ERROR, _("could not access cache directory\n")); - return(1); + pm_fprintf(stderr, PM_LOG_ERROR, + _("could not access cache directory %s\n"), cachedir); + ret++; + continue; } rewinddir(dir); @@ -163,7 +176,6 @@ static int sync_cleancache(int level) char path[PATH_MAX]; int delete = 1; pmpkg_t *localpkg = NULL, *pkg = NULL; - alpm_list_t *sync_dbs = alpm_option_get_syncdbs(); alpm_list_t *j; if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { @@ -172,11 +184,20 @@ static int sync_cleancache(int level) /* build the full filepath */ snprintf(path, PATH_MAX, "%s%s", cachedir, ent->d_name); + /* short circuit for removing all packages from cache */ + if(level > 1) { + unlink(path); + continue; + } + /* attempt to load the package, prompt removal on failures as we may have * files here that aren't valid packages. we also don't need a full * load of the package, just the metadata. */ if(alpm_pkg_load(path, 0, &localpkg) != 0 || localpkg == NULL) { if(yesno(_("File %s does not seem to be a valid package, remove it?"), path)) { + if(localpkg) { + alpm_pkg_free(localpkg); + } unlink(path); } continue; @@ -215,26 +236,10 @@ static int sync_cleancache(int level) unlink(path); } } - } else { - /* full cleanup */ - printf(_("Cache directory: %s\n"), cachedir); - if(!noyes(_("Do you want to remove ALL files from cache?"))) { - return(0); - } - printf(_("removing all files from cache...\n")); - - if(rmrf(cachedir)) { - pm_fprintf(stderr, PM_LOG_ERROR, _("could not remove cache directory\n")); - return(1); - } - - if(makepath(cachedir)) { - pm_fprintf(stderr, PM_LOG_ERROR, _("could not create new cache directory\n")); - return(1); - } + closedir(dir); } - return(0); + return(ret); } static int sync_synctree(int level, alpm_list_t *syncs) @@ -242,7 +247,7 @@ static int sync_synctree(int level, alpm_list_t *syncs) alpm_list_t *i; int success = 0, ret; - if(trans_init(PM_TRANS_TYPE_SYNC, 0) == -1) { + if(trans_init(0) == -1) { return(0); } @@ -548,89 +553,68 @@ static alpm_list_t *syncfirst() { return(res); } +static int process_target(char *target) +{ + /* process targets */ + char *targstring = strdup(target); + char *targname = strchr(targstring, '/'); + char *dbname = NULL; + int ret = 0; + if(targname) { + *targname = '\0'; + targname++; + dbname = targstring; + ret = alpm_sync_dbtarget(dbname,targname); + } else { + targname = targstring; + ret = alpm_sync_target(targname); + } + + if(ret == -1) { + if(pm_errno == PM_ERR_TRANS_DUP_TARGET + || pm_errno == PM_ERR_PKG_IGNORED) { + /* just skip duplicate or ignored targets */ + pm_printf(PM_LOG_WARNING, _("skipping target: %s\n"), target); + } else { + pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", target, + alpm_strerrorlast()); + ret = 1; + } + } + + free(targstring); + return(ret); +} + static int sync_trans(alpm_list_t *targets) { int retval = 0; alpm_list_t *data = NULL; - alpm_list_t *sync_dbs = alpm_option_get_syncdbs(); alpm_list_t *packages = NULL; + alpm_list_t *i; /* Step 1: create a new transaction... */ - if(trans_init(PM_TRANS_TYPE_SYNC, config->flags) == -1) { + if(trans_init(config->flags) == -1) { return(1); } + /* process targets */ + for(i = targets; i; i = alpm_list_next(i)) { + char *targ = alpm_list_getdata(i); + if(process_target(targ) == 1) { + retval = 1; + goto cleanup; + } + } + if(config->op_s_upgrade) { printf(_(":: Starting full system upgrade...\n")); alpm_logaction("starting full system upgrade\n"); - if(alpm_trans_sysupgrade(config->op_s_upgrade >= 2) == -1) { + if(alpm_sync_sysupgrade(config->op_s_upgrade >= 2) == -1) { pm_fprintf(stderr, PM_LOG_ERROR, "%s\n", alpm_strerrorlast()); retval = 1; goto cleanup; } - } else { - alpm_list_t *i; - - /* process targets */ - for(i = targets; i; i = alpm_list_next(i)) { - char *targ = alpm_list_getdata(i); - if(alpm_trans_addtarget(targ) == -1) { - pmgrp_t *grp = NULL; - int found = 0; - alpm_list_t *j; - - if(pm_errno == PM_ERR_TRANS_DUP_TARGET || pm_errno == PM_ERR_PKG_IGNORED) { - /* just skip duplicate or ignored targets */ - pm_printf(PM_LOG_WARNING, _("skipping target: %s\n"), targ); - continue; - } - if(pm_errno != PM_ERR_PKG_NOT_FOUND) { - pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", - targ, alpm_strerrorlast()); - retval = 1; - goto cleanup; - } - /* target not found: check if it's a group */ - printf(_("%s package not found, searching for group...\n"), targ); - for(j = sync_dbs; j; j = alpm_list_next(j)) { - pmdb_t *db = alpm_list_getdata(j); - grp = alpm_db_readgrp(db, targ); - if(grp) { - alpm_list_t *k, *pkgnames = NULL; - - found++; - printf(_(":: group %s (including ignored packages):\n"), targ); - /* remove dupe entries in case a package exists in multiple repos */ - alpm_list_t *grppkgs = alpm_grp_get_pkgs(grp); - alpm_list_t *pkgs = alpm_list_remove_dupes(grppkgs); - for(k = pkgs; k; k = alpm_list_next(k)) { - pkgnames = alpm_list_add(pkgnames, - (char*)alpm_pkg_get_name(k->data)); - } - list_display(" ", pkgnames); - 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(_(":: Install %s from group %s?"), pkgname, targ)) { - targets = alpm_list_add(targets, strdup(pkgname)); - } - } - } - alpm_list_free(pkgnames); - alpm_list_free(pkgs); - } - } - if(!found) { - pm_fprintf(stderr, PM_LOG_ERROR, _("'%s': not found in sync db\n"), targ); - retval = 1; - goto cleanup; - } - } - } } /* Step 2: "compute" the transaction based on targets and flags */ @@ -639,6 +623,12 @@ static int sync_trans(alpm_list_t *targets) alpm_strerrorlast()); switch(pm_errno) { alpm_list_t *i; + case PM_ERR_PKG_INVALID_ARCH: + for(i = data; i; i = alpm_list_next(i)) { + char *pkg = alpm_list_getdata(i); + printf(_(":: package %s does not have a valid architecture\n"), pkg); + } + break; case PM_ERR_UNSATISFIED_DEPS: for(i = data; i; i = alpm_list_next(i)) { pmdepmissing_t *miss = alpm_list_getdata(i); @@ -650,10 +640,17 @@ static int sync_trans(alpm_list_t *targets) } break; case PM_ERR_CONFLICTING_DEPS: - for(i = data; i; i = alpm_list_next(i)) { + for(i = data; i; i = alpm_list_next(i)) { pmconflict_t *conflict = alpm_list_getdata(i); - printf(_(":: %s: conflicts with %s\n"), - alpm_conflict_get_package1(conflict), alpm_conflict_get_package2(conflict)); + const char *package1 = alpm_conflict_get_package1(conflict); + const char *package2 = alpm_conflict_get_package2(conflict); + const char *reason = alpm_conflict_get_reason(conflict); + /* only print reason if it contains new information */ + if(!strcmp(package1, reason) || !strcmp(package2, reason)) { + printf(_(":: %s and %s are in conflict\n"), package1, package2); + } else { + printf(_(":: %s and %s are in conflict (%s)\n"), package1, package2, reason); + } } break; default: @@ -663,7 +660,7 @@ static int sync_trans(alpm_list_t *targets) goto cleanup; } - packages = alpm_trans_get_pkgs(); + packages = alpm_trans_get_add(); if(packages == NULL) { /* nothing to do: just exit without complaining */ printf(_(" local database is up to date\n")); @@ -691,7 +688,8 @@ static int sync_trans(alpm_list_t *targets) goto cleanup; } - display_synctargets(packages); + display_targets(alpm_trans_get_remove(), 0); + display_targets(alpm_trans_get_add(), 1); printf("\n"); int confirm; @@ -768,7 +766,7 @@ int pacman_sync(alpm_list_t *targets) if(config->op_s_clean) { int ret = 0; - if(trans_init(PM_TRANS_TYPE_SYNC, 0) == -1) { + if(trans_init(0) == -1) { return(1); } diff --git a/src/pacman/upgrade.c b/src/pacman/upgrade.c index 1570f95e..57c7b790 100644 --- a/src/pacman/upgrade.c +++ b/src/pacman/upgrade.c @@ -42,7 +42,6 @@ int pacman_upgrade(alpm_list_t *targets) { alpm_list_t *i, *data = NULL; - pmtranstype_t transtype = PM_TRANS_TYPE_UPGRADE; int retval = 0; if(targets == NULL) { @@ -65,7 +64,7 @@ int pacman_upgrade(alpm_list_t *targets) } /* Step 1: create a new transaction */ - if(trans_init(transtype, config->flags) == -1) { + if(trans_init(config->flags) == -1) { return(1); } @@ -73,7 +72,7 @@ int pacman_upgrade(alpm_list_t *targets) printf(_("loading package data...\n")); for(i = targets; i; i = alpm_list_next(i)) { char *targ = alpm_list_getdata(i); - if(alpm_trans_addtarget(targ) == -1) { + if(alpm_add_target(targ) == -1) { pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerrorlast()); trans_release(); @@ -87,6 +86,12 @@ int pacman_upgrade(alpm_list_t *targets) pm_fprintf(stderr, PM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), alpm_strerrorlast()); switch(pm_errno) { + case PM_ERR_PKG_INVALID_ARCH: + for(i = data; i; i = alpm_list_next(i)) { + char *pkg = alpm_list_getdata(i); + printf(_(":: package %s does not have a valid architecture\n"), pkg); + } + break; case PM_ERR_UNSATISFIED_DEPS: for(i = data; i; i = alpm_list_next(i)) { pmdepmissing_t *miss = alpm_list_getdata(i); @@ -104,42 +109,75 @@ int pacman_upgrade(alpm_list_t *targets) case PM_ERR_CONFLICTING_DEPS: for(i = data; i; i = alpm_list_next(i)) { pmconflict_t *conflict = alpm_list_getdata(i); - printf(_(":: %s: conflicts with %s\n"), - alpm_conflict_get_package1(conflict), alpm_conflict_get_package2(conflict)); + const char *package1 = alpm_conflict_get_package1(conflict); + const char *package2 = alpm_conflict_get_package2(conflict); + const char *reason = alpm_conflict_get_reason(conflict); + /* only print reason if it contains new information */ + if(!strcmp(package1, reason) || !strcmp(package2, reason)) { + printf(_(":: %s and %s are in conflict\n"), package1, package2); + } else { + printf(_(":: %s and %s are in conflict (%s)\n"), package1, package2, reason); + } } break; + default: + break; + } + trans_release(); + FREELIST(data); + return(1); + } + + /* Step 3: perform the installation */ + /* print targets and ask user confirmation */ + alpm_list_t *packages = alpm_trans_get_add(); + if(packages == NULL) { /* we are done */ + trans_release(); + return(retval); + } + display_targets(alpm_trans_get_remove(), 0); + display_targets(alpm_trans_get_add(), 1); + printf("\n"); + int confirm = yesno(_("Proceed with installation?")); + if(!confirm) { + trans_release(); + return(retval); + } + + if(alpm_trans_commit(&data) == -1) { + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"), + alpm_strerrorlast()); + switch(pm_errno) { + alpm_list_t *i; case PM_ERR_FILE_CONFLICTS: for(i = data; i; i = alpm_list_next(i)) { pmfileconflict_t *conflict = alpm_list_getdata(i); switch(alpm_fileconflict_get_type(conflict)) { case PM_FILECONFLICT_TARGET: printf(_("%s exists in both '%s' and '%s'\n"), - alpm_fileconflict_get_file(conflict), - alpm_fileconflict_get_target(conflict), - alpm_fileconflict_get_ctarget(conflict)); - break; + alpm_fileconflict_get_file(conflict), + alpm_fileconflict_get_target(conflict), + alpm_fileconflict_get_ctarget(conflict)); + break; case PM_FILECONFLICT_FILESYSTEM: printf(_("%s: %s exists in filesystem\n"), - alpm_fileconflict_get_target(conflict), - alpm_fileconflict_get_file(conflict)); - break; + alpm_fileconflict_get_target(conflict), + alpm_fileconflict_get_file(conflict)); + break; } } - printf(_("\nerrors occurred, no packages were upgraded.\n")); + break; + case PM_ERR_PKG_INVALID: + case PM_ERR_DLT_INVALID: + for(i = data; i; i = alpm_list_next(i)) { + char *filename = alpm_list_getdata(i); + printf(_("%s is invalid or corrupted\n"), filename); + } break; default: break; } - trans_release(); FREELIST(data); - return(1); - } - alpm_list_free(data); - - /* Step 3: perform the installation */ - if(alpm_trans_commit(NULL) == -1) { - pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"), - alpm_strerrorlast()); trans_release(); return(1); } diff --git a/src/pacman/util.c b/src/pacman/util.c index c68e6841..14a0f6cd 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -45,9 +45,9 @@ #include "callback.h" -int trans_init(pmtranstype_t type, pmtransflag_t flags) +int trans_init(pmtransflag_t flags) { - if(alpm_trans_init(type, flags, cb_trans_evt, + if(alpm_trans_init(flags, cb_trans_evt, cb_trans_conv, cb_trans_progress) == -1) { pm_fprintf(stderr, PM_LOG_ERROR, _("failed to init transaction (%s)\n"), alpm_strerrorlast()); @@ -85,70 +85,18 @@ int needs_root(void) /* gets the current screen column width */ int getcols(void) { - if(!isatty(1)) { - /* We will default to 80 columns if we're not a tty - * this seems a fairly standard file width. - */ - return 80; - } else { #ifdef TIOCGSIZE - struct ttysize win; - if(ioctl(1, TIOCGSIZE, &win) == 0) { - return win.ts_cols; - } -#elif defined(TIOCGWINSZ) - struct winsize win; - if(ioctl(1, TIOCGWINSZ, &win) == 0) { - return win.ws_col; - } -#endif - /* If we can't figure anything out, we'll just assume 80 columns */ - /* TODO any problems caused by this assumption? */ - return 80; - } - /* Original envvar way - prone to display issues - const char *cenv = getenv("COLUMNS"); - if(cenv != NULL) { - return atoi(cenv); + struct ttysize win; + if(ioctl(1, TIOCGSIZE, &win) == 0) { + return win.ts_cols; } - return -1; - */ -} - -/* does the same thing as 'mkdir -p' */ -int makepath(const char *path) -{ - /* A bit of pointer hell here. Descriptions: - * orig - a copy of path so we can safely butcher it with strsep - * str - the current position in the path string (after the delimiter) - * ptr - the original position of str after calling strsep - * incr - incrementally generated path for use in access/mkdir call - */ - char *orig, *str, *ptr, *incr; - mode_t oldmask = umask(0000); - int ret = 0; - - orig = strdup(path); - incr = calloc(strlen(orig) + 1, sizeof(char)); - str = orig; - while((ptr = strsep(&str, "/"))) { - if(strlen(ptr)) { - /* we have another path component- append the newest component to - * existing string and create one more level of dir structure */ - strcat(incr, "/"); - strcat(incr, ptr); - if(access(incr, F_OK)) { - if(mkdir(incr, 0755)) { - ret = 1; - break; - } - } - } +#elif defined(TIOCGWINSZ) + struct winsize win; + if(ioctl(1, TIOCGWINSZ, &win) == 0) { + return win.ws_col; } - free(orig); - free(incr); - umask(oldmask); - return(ret); +#endif + return 0; } /* does the same thing as 'rm -rf' */ @@ -257,6 +205,14 @@ void indentprint(const char *str, int indent) return; } + cols = getcols(); + + /* if we're not a tty, print without indenting */ + if(cols == 0) { + printf("%s", str); + return; + } + len = strlen(str) + 1; wcstr = calloc(len, sizeof(wchar_t)); len = mbstowcs(wcstr, str, len); @@ -266,7 +222,6 @@ void indentprint(const char *str, int indent) if(!p) { return; } - cols = getcols(); while(*p) { if(*p == L' ') { @@ -285,7 +240,7 @@ void indentprint(const char *str, int indent) } if(len > (cols - cidx - 1)) { /* wrap to a newline and reindent */ - fprintf(stdout, "\n%-*s", indent, ""); + printf("\n%-*s", indent, ""); cidx = indent; } else { printf(" "); @@ -293,7 +248,7 @@ void indentprint(const char *str, int indent) } continue; } - fprintf(stdout, "%lc", (wint_t)*p); + printf("%lc", (wint_t)*p); cidx += wcwidth(*p); p++; } @@ -307,7 +262,7 @@ char *strtoupper(char *str) char *ptr = str; while(*ptr) { - (*ptr) = toupper(*ptr); + (*ptr) = toupper((unsigned char)*ptr); ptr++; } return str; @@ -324,7 +279,7 @@ char *strtrim(char *str) return(str); } - while(isspace(*pch)) { + while(isspace((unsigned char)*pch)) { pch++; } if(pch != str) { @@ -337,7 +292,7 @@ char *strtrim(char *str) } pch = (str + (strlen(str) - 1)); - while(isspace(*pch)) { + while(isspace((unsigned char)*pch)) { pch--; } *++pch = '\0'; @@ -345,48 +300,65 @@ char *strtrim(char *str) return(str); } -/* Helper function for strreplace */ -static void _strnadd(char **str, const char *append, unsigned int count) -{ - if(*str) { - *str = realloc(*str, strlen(*str) + count + 1); - } else { - *str = calloc(sizeof(char), count + 1); - } - - strncat(*str, append, count); -} - /* Replace all occurances of 'needle' with 'replace' in 'str', returning * a new string (must be free'd) */ char *strreplace(const char *str, const char *needle, const char *replace) { - const char *p, *q; - p = q = str; + const char *p = NULL, *q = NULL; + char *newstr = NULL, *newp = NULL; + alpm_list_t *i = NULL, *list = NULL; + size_t needlesz = strlen(needle), replacesz = strlen(replace); + size_t newsz; - char *newstr = NULL; - unsigned int needlesz = strlen(needle), - replacesz = strlen(replace); + if(!str) { + return(NULL); + } - while (1) { + p = str; + q = strstr(p, needle); + while(q) { + list = alpm_list_add(list, (char *)q); + p = q + needlesz; q = strstr(p, needle); - if(!q) { /* not found */ - if(*p) { - /* add the rest of 'p' */ - _strnadd(&newstr, p, strlen(p)); - } - break; - } else { /* found match */ - if(q > p){ - /* add chars between this occurance and last occurance, if any */ - _strnadd(&newstr, p, q - p); - } - _strnadd(&newstr, replace, replacesz); - p = q + needlesz; + } + + /* no occurences of needle found */ + if(!list) { + return(strdup(str)); + } + /* size of new string = size of old string + "number of occurences of needle" + * x "size difference between replace and needle" */ + newsz = strlen(str) + 1 + + alpm_list_count(list) * (replacesz - needlesz); + newstr = malloc(newsz); + if(!newstr) { + return(NULL); + } + *newstr = '\0'; + + p = str; + newp = newstr; + for(i = list; i; i = alpm_list_next(i)) { + q = alpm_list_getdata(i); + if(q > p){ + /* add chars between this occurence and last occurence, if any */ + strncpy(newp, p, q - p); + newp += q - p; } + strncpy(newp, replace, replacesz); + newp += replacesz; + p = q + needlesz; } + alpm_list_free(list); - return newstr; + if(*p) { + /* add the rest of 'p' */ + strcpy(newp, p); + newp += strlen(p); + } + *newp = '\0'; + + return(newstr); } /** Splits a string into a list of strings using the chosen character as @@ -446,13 +418,13 @@ void string_display(const char *title, const char *string) int len = 0; if(title) { - /* compute the length of title + a space */ - len = string_length(title) + 1; printf("%s ", title); } if(string == NULL || string[0] == '\0') { printf(_("None")); } else { + /* compute the length of title + a space */ + len = string_length(title) + 1; indentprint(string, len); } printf("\n"); @@ -474,18 +446,20 @@ void list_display(const char *title, const alpm_list_t *list) for(i = list, cols = len; i; i = alpm_list_next(i)) { char *str = alpm_list_getdata(i); int s = string_length(str); - /* two additional spaces are added to the length */ - s += 2; int maxcols = getcols(); - if(s + cols > maxcols) { + if(maxcols > 0 && (cols + s + 2) >= maxcols) { int j; cols = len; printf("\n"); for (j = 1; j <= len; j++) { printf(" "); } + } else if (cols != len) { + /* 2 spaces are added if this is not the first element on a line. */ + printf(" "); + cols += 2; } - printf("%s ", str); + printf("%s", str); cols += s; } printf("\n"); @@ -577,37 +551,6 @@ void display_targets(const alpm_list_t *pkgs, int install) FREELIST(targets); } -/* Display a list of transaction targets. - * `pkgs` should be a list of pmpkg_t's, - * retrieved from a transaction object - */ -void display_synctargets(const alpm_list_t *syncpkgs) -{ - const alpm_list_t *i, *j; - alpm_list_t *pkglist = NULL, *rpkglist = NULL; - - for(i = syncpkgs; i; i = alpm_list_next(i)) { - pmpkg_t *pkg = alpm_list_getdata(i); - pkglist = alpm_list_add(pkglist, pkg); - - /* The removes member contains a list of packages to be removed - * due to the package that is being installed. */ - alpm_list_t *to_replace = alpm_pkg_get_removes(pkg); - - for(j = to_replace; j; j = alpm_list_next(j)) { - pmpkg_t *rp = alpm_list_getdata(j); - rpkglist = alpm_list_add(rpkglist, rp); - } - } - - /* start displaying information */ - display_targets(rpkglist, 0); - display_targets(pkglist, 1); - - alpm_list_free(pkglist); - alpm_list_free(rpkglist); -} - /* Helper function for comparing strings using the * alpm "compare func" signature */ int str_cmp(const void *s1, const void *s2) @@ -640,6 +583,7 @@ void display_optdepends(pmpkg_t *pkg) static int question(short preset, char *fmt, va_list args) { char response[32]; + int sresponse = sizeof(response)-1; FILE *stream; if(config->noconfirm) { @@ -662,7 +606,7 @@ static int question(short preset, char *fmt, va_list args) return(preset); } - if(fgets(response, 32, stdin)) { + if(fgets(response, sresponse, stdin)) { strtrim(response); if(strlen(response) == 0) { return(preset); diff --git a/src/pacman/util.h b/src/pacman/util.h index 12824221..7a8c39d1 100644 --- a/src/pacman/util.h +++ b/src/pacman/util.h @@ -37,11 +37,10 @@ /* update speed for the fill_progress based functions */ #define UPDATE_SPEED_SEC 0.2f -int trans_init(pmtranstype_t type, pmtransflag_t flags); +int trans_init(pmtransflag_t flags); int trans_release(void); int needs_root(void); int getcols(void); -int makepath(const char *path); int rmrf(const char *path); char *mbasename(const char *path); char *mdirname(const char *path); @@ -54,7 +53,6 @@ void string_display(const char *title, const char *string); 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(char *fmt, ...); diff --git a/src/util/testdb.c b/src/util/testdb.c index e521e6b3..6d351ebd 100644 --- a/src/util/testdb.c +++ b/src/util/testdb.c @@ -92,6 +92,11 @@ static int db_test(char *dbpath, int local) } } } + if(closedir(dir)) { + fprintf(stderr, "error closing dbpath : %s\n", strerror(errno)); + return(1); + } + return(ret); } @@ -110,6 +115,7 @@ int checkdeps(alpm_list_t *pkglist) free(depstring); ret++; } + FREELIST(data); return(ret); } @@ -125,6 +131,7 @@ int checkconflicts(alpm_list_t *pkglist) alpm_conflict_get_package2(conflict)); ret++; } + FREELIST(data); return(ret); } @@ -163,21 +170,23 @@ int check_syncdbs(char *dbpath, alpm_list_t *dbnames) { snprintf(syncdbpath, PATH_MAX, "%s/sync/%s", dbpath, dbname); ret = db_test(syncdbpath, 0); if(ret) { - return(ret); + ret = 1; + goto cleanup; } db = alpm_db_register_sync(dbname); if(db == NULL) { fprintf(stderr, "error: could not register sync database (%s)\n", alpm_strerrorlast()); - cleanup(EXIT_FAILURE); + ret = 1; + goto cleanup; } 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(); +cleanup: + alpm_list_free(syncpkglist); return(ret); } @@ -227,6 +236,7 @@ int main(int argc, char **argv) ret = check_localdb(dbpath); } else { ret = check_syncdbs(dbpath,dbnames); + alpm_list_free(dbnames); } cleanup(ret); |