summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/.gitignore1
-rw-r--r--doc/Makefile.am4
-rw-r--r--doc/pactree.8.txt62
-rw-r--r--etc/makepkg.conf.in6
-rw-r--r--lib/libalpm/conflict.c37
-rw-r--r--test/pacman/tests/fileconflict009.py20
-rw-r--r--test/pacman/tests/fileconflict010.py20
-rw-r--r--test/pacman/tests/fileconflict012.py17
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/")