diff options
-rw-r--r-- | doc/.gitignore | 1 | ||||
-rw-r--r-- | doc/Makefile.am | 4 | ||||
-rw-r--r-- | doc/pactree.8.txt | 62 | ||||
-rw-r--r-- | etc/makepkg.conf.in | 6 | ||||
-rw-r--r-- | lib/libalpm/conflict.c | 37 | ||||
-rw-r--r-- | test/pacman/tests/fileconflict009.py | 20 | ||||
-rw-r--r-- | test/pacman/tests/fileconflict010.py | 20 | ||||
-rw-r--r-- | test/pacman/tests/fileconflict012.py | 17 |
8 files changed, 158 insertions, 9 deletions
diff --git a/doc/.gitignore b/doc/.gitignore index 5625735a..a96ddb30 100644 --- a/doc/.gitignore +++ b/doc/.gitignore @@ -5,6 +5,7 @@ makepkg.conf.5 pacman.8 pacman-key.8 pacman.conf.5 +pactree.8 pkgdelta.8 repo-add.8 repo-remove.8 diff --git a/doc/Makefile.am b/doc/Makefile.am index e6ed29c0..bcb05b74 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -10,6 +10,7 @@ ASCIIDOC_MANS = \ vercmp.8 \ pkgdelta.8 \ pacman-key.8 \ + pactree.8 \ PKGBUILD.5 \ makepkg.conf.5 \ pacman.conf.5 \ @@ -24,6 +25,7 @@ HTML_MANPAGES = \ vercmp.8.html \ pkgdelta.8.html \ pacman-key.8.html \ + pactree.8.html \ PKGBUILD.5.html \ makepkg.conf.5.html \ pacman.conf.5.html \ @@ -48,6 +50,7 @@ EXTRA_DIST = \ vercmp.8.txt \ pkgdelta.8.txt \ pacman-key.8.txt \ + pactree.8.txt \ PKGBUILD.5.txt \ PKGBUILD-example.txt \ makepkg.conf.5.txt \ @@ -148,6 +151,7 @@ repo-add.8 repo-add.8.html: repo-add.8.txt vercmp.8 vercmp.8.html: vercmp.8.txt pkgdelta.8 pkgdelta.8.html: pkgdelta.8.txt pacman-key.8 pacman-key.8.html: pacman-key.8.txt +pactree.8 pactree.8.html: pactree.8.txt PKGBUILD.5 PKGBUILD.5.html: PKGBUILD.5.txt PKGBUILD-example.txt makepkg.conf.5 makepkg.conf.5.html: makepkg.conf.5.txt pacman.conf.5 pacman.conf.5.html: pacman.conf.5.txt diff --git a/doc/pactree.8.txt b/doc/pactree.8.txt new file mode 100644 index 00000000..669a14bb --- /dev/null +++ b/doc/pactree.8.txt @@ -0,0 +1,62 @@ +///// +vim:set ts=4 sw=4 syntax=asciidoc noet spell spelllang=en_us: +///// +pactree(8) +========= + +Name +---- +pactree - package dependency tree viewer + + +Synopsis +-------- +'pactree' [options] package + +Description +----------- +Pactree produces a dependency tree for a package. + +By default a tree like output is generated, but with the -g option a graphviz +description is generated. + +Options +------- +*-b, \--dbpath*:: + Specify an alternative database location. + +*-c, \--color*:: + Colorize output. + +*-d, \--depth <num>*:: + Limits the number of levels of dependency to show. A zero means + show the named package only, one shows the packages that are directly + required. + +*-g, \--graph*:: + Generate graphviz description. If this option is given, the -c and -l + options are ignored. + +*-h, \--help*:: + Output syntax and command line options. + +*-l, \--linear*:: + Prints package names at the start of each line, one per line. + +*-r, \--reverse*:: + Show packages that depend on the named package. + +*-s, \--sync*:: + Read package data from sync databases instead of local database. + +*-u, \--unique*:: + List dependent packages once. Implies --linear. + +*\--config <file>*:: + Specify an alternate pacman configuration file. + +See Also +-------- +linkman:pacman[8], linkman:pacman.conf[5], linkman:makepkg[8] + +include::footer.txt[] diff --git a/etc/makepkg.conf.in b/etc/makepkg.conf.in index 51df4939..dcec6f5c 100644 --- a/etc/makepkg.conf.in +++ b/etc/makepkg.conf.in @@ -8,9 +8,9 @@ # #-- The download utilities that makepkg should use to acquire sources # Format: 'protocol::agent' -DLAGENTS=('ftp::/usr/bin/curl -fC - --ftp-pasv --retry 3 --retry-delay 3 -o %o %u' - 'http::/usr/bin/curl -b "" -fLC - --retry 3 --retry-delay 3 -o %o %u' - 'https::/usr/bin/curl -b "" -fLC - --retry 3 --retry-delay 3 -o %o %u' +DLAGENTS=('ftp::/usr/bin/curl -qfC - --ftp-pasv --retry 3 --retry-delay 3 -o %o %u' + 'http::/usr/bin/curl -qb "" -fLC - --retry 3 --retry-delay 3 -o %o %u' + 'https::/usr/bin/curl -qb "" -fLC - --retry 3 --retry-delay 3 -o %o %u' 'rsync::/usr/bin/rsync --no-motd -z %u %o' 'scp::/usr/bin/scp -C %u %o') diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c index 3b8fce0e..7494fd77 100644 --- a/lib/libalpm/conflict.c +++ b/lib/libalpm/conflict.c @@ -330,15 +330,40 @@ const alpm_file_t *_alpm_filelist_contains(alpm_filelist_t *filelist, return NULL; } -static int dir_belongsto_pkg(const char *root, const char *dirpath, +static int dir_belongsto_pkg(alpm_handle_t *handle, const char *dirpath, alpm_pkg_t *pkg) { + alpm_list_t *i; struct stat sbuf; char path[PATH_MAX]; char abspath[PATH_MAX]; - struct dirent *ent = NULL; DIR *dir; + struct dirent *ent = NULL; + const char *root = handle->root; + + /* check directory is actually in package - used for subdirectory checks */ + if(!_alpm_filelist_contains(alpm_pkg_get_files(pkg), dirpath)) { + return 0; + } + + /* TODO: this is an overly strict check but currently pacman will not + * overwrite a directory with a file (case 10/11 in add.c). Adjusting that + * is not simple as even if the directory is being unowned by a conflicting + * package, pacman does not sort this to ensure all required directory + * "removals" happen before installation of file/symlink */ + + /* check that no other _installed_ package owns the directory */ + for(i = _alpm_db_get_pkgcache(handle->db_local); i; i = i->next) { + if(pkg == i->data) { + continue; + } + + if(_alpm_filelist_contains(alpm_pkg_get_files(i->data), dirpath)) { + return 0; + } + } + /* check all files in directory are owned by the package */ snprintf(abspath, PATH_MAX, "%s%s", root, dirpath); dir = opendir(abspath); if(dir == NULL) { @@ -351,13 +376,13 @@ static int dir_belongsto_pkg(const char *root, const char *dirpath, if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { continue; } - snprintf(path, PATH_MAX, "%s/%s", dirpath, name); + snprintf(path, PATH_MAX, "%s%s", dirpath, name); snprintf(abspath, PATH_MAX, "%s%s", root, path); if(stat(abspath, &sbuf) != 0) { continue; } if(S_ISDIR(sbuf.st_mode)) { - if(dir_belongsto_pkg(root, path, pkg)) { + if(dir_belongsto_pkg(handle, path, pkg)) { continue; } else { closedir(dir); @@ -535,9 +560,9 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, sprintf(dir, "%s/", filestr); if(_alpm_filelist_contains(alpm_pkg_get_files(dbpkg), dir)) { _alpm_log(handle, ALPM_LOG_DEBUG, - "check if all files in %s belongs to %s\n", + "check if all files in %s belong to %s\n", dir, dbpkg->name); - resolved_conflict = dir_belongsto_pkg(handle->root, filestr, dbpkg); + resolved_conflict = dir_belongsto_pkg(handle, dir, dbpkg); } free(dir); } diff --git a/test/pacman/tests/fileconflict009.py b/test/pacman/tests/fileconflict009.py new file mode 100644 index 00000000..904af4a3 --- /dev/null +++ b/test/pacman/tests/fileconflict009.py @@ -0,0 +1,20 @@ +self.description = "dir->symlink change during package upgrade (directory conflict)" + +lp1 = pmpkg("pkg1") +lp1.files = ["dir/"] +self.addpkg2db("local", lp1) + +lp2 = pmpkg("pkg2") +lp2.files = ["dir/"] +self.addpkg2db("local", lp2) + +p = pmpkg("pkg1", "1.0-2") +p.files = ["dir -> /usr/dir"] +self.addpkg2db("sync", p) + +self.args = "-S pkg1" + +self.addrule("PACMAN_RETCODE=1") +self.addrule("PKG_VERSION=pkg1|1.0-1") +self.addrule("PKG_VERSION=pkg2|1.0-1") +self.addrule("DIR_EXIST=dir/") diff --git a/test/pacman/tests/fileconflict010.py b/test/pacman/tests/fileconflict010.py new file mode 100644 index 00000000..0a3ce835 --- /dev/null +++ b/test/pacman/tests/fileconflict010.py @@ -0,0 +1,20 @@ +self.description = "dir->file change during package upgrade (directory conflict)" + +lp1 = pmpkg("pkg1") +lp1.files = ["dir/"] +self.addpkg2db("local", lp1) + +lp2 = pmpkg("pkg2") +lp2.files = ["dir/"] +self.addpkg2db("local", lp2) + +p = pmpkg("pkg1", "1.0-2") +p.files = ["dir"] +self.addpkg2db("sync", p) + +self.args = "-S pkg1" + +self.addrule("PACMAN_RETCODE=1") +self.addrule("PKG_VERSION=pkg1|1.0-1") +self.addrule("PKG_VERSION=pkg2|1.0-1") +self.addrule("DIR_EXIST=dir/") diff --git a/test/pacman/tests/fileconflict012.py b/test/pacman/tests/fileconflict012.py new file mode 100644 index 00000000..421b739a --- /dev/null +++ b/test/pacman/tests/fileconflict012.py @@ -0,0 +1,17 @@ +self.description = "dir->file change during package upgrade (filesystem file conflict)" + +lp1 = pmpkg("pkg1") +lp1.files = ["dir/"] +self.addpkg2db("local", lp1) + +self.filesystem = ["dir/file"] + +p = pmpkg("pkg1", "1.0-2") +p.files = ["dir"] +self.addpkg2db("sync", p) + +self.args = "-S pkg1" + +self.addrule("PACMAN_RETCODE=1") +self.addrule("PKG_VERSION=pkg1|1.0-1") +self.addrule("DIR_EXIST=dir/") |