summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan McRae <allan@archlinux.org>2013-02-12 22:00:53 +1000
committerAllan McRae <allan@archlinux.org>2013-02-24 13:11:54 +1000
commit34749e177db5d4aafdb9f3de630c7ab193a0f36d (patch)
tree93d21fc0a0c170589acf19617e15cd9d9d8949d1
parent19754b34a36203266c4e02f29178084c77282efd (diff)
downloadpacman-34749e177db5d4aafdb9f3de630c7ab193a0f36d.tar.xz
Perform limited conflict checking with --force
Pacman currently bails when trying to extract a file over a directory when using --force. Instead of ignoring all conflict, perform the check and skip any file-file conflicts. Conflicts between directories and files are still flagged and cause the transation to abort. As a bonus, we now know about files changing packages when using --force, so we can skip removing them fixing upgrade046. Signed-off-by: Allan McRae <allan@archlinux.org>
-rw-r--r--doc/pacman.8.txt2
-rw-r--r--lib/libalpm/conflict.c28
-rw-r--r--lib/libalpm/sync.c2
-rw-r--r--src/pacman/sync.c3
-rw-r--r--test/pacman/tests/upgrade046.py2
5 files changed, 32 insertions, 5 deletions
diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt
index 358d5065..33a94214 100644
--- a/doc/pacman.8.txt
+++ b/doc/pacman.8.txt
@@ -205,6 +205,8 @@ Upgrade Options (apply to '-S' and '-U')[[UO]]
Bypass file conflict checks and overwrite conflicting files. If the
package that is about to be installed contains files that are already
installed, this option will cause all those files to be overwritten.
+ Using '--force' will not allow overwriting a directory with a file or
+ installing packages with conflicting files and directories.
This option should be used with care, ideally not at all.
*\--asdeps*::
diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c
index afed8953..18e29a89 100644
--- a/lib/libalpm/conflict.c
+++ b/lib/libalpm/conflict.c
@@ -443,8 +443,10 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
alpm_list_t *common_files;
alpm_pkg_t *p2 = j->data;
- common_files = _alpm_filelist_intersection(alpm_pkg_get_files(p1),
- alpm_pkg_get_files(p2));
+ alpm_filelist_t *p1_files = alpm_pkg_get_files(p1);
+ alpm_filelist_t *p2_files = alpm_pkg_get_files(p2);
+
+ common_files = _alpm_filelist_intersection(p1_files, p2_files);
if(common_files) {
alpm_list_t *k;
@@ -452,6 +454,20 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
for(k = common_files; k; k = k->next) {
char *filename = k->data;
snprintf(path, PATH_MAX, "%s%s", handle->root, filename);
+
+ /* can skip file-file conflicts when forced *
+ * checking presence in p2_files detects dir-file or file-dir
+ * conflicts as the path from p1 is returned */
+ if((handle->trans->flags & ALPM_TRANS_FLAG_FORCE) &&
+ alpm_filelist_contains(p2_files, filename)) {
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "%s exists in both '%s' and '%s'\n", filename,
+ p1->name, p2->name);
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "file-file conflict being forced\n");
+ continue;
+ }
+
conflicts = add_fileconflict(handle, conflicts, path, p1, p2);
if(handle->pm_errno == ALPM_ERR_MEMORY) {
FREELIST(conflicts);
@@ -606,6 +622,14 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
}
}
+ /* skip file-file conflicts when being forced */
+ if((handle->trans->flags & ALPM_TRANS_FLAG_FORCE) &&
+ !S_ISDIR(lsbuf.st_mode)) {
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "conflict with file on filesystem being forced\n");
+ resolved_conflict = 1;
+ }
+
if(!resolved_conflict) {
conflicts = add_fileconflict(handle, conflicts, path, p1, NULL);
if(handle->pm_errno == ALPM_ERR_MEMORY) {
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index f7b956ca..204456d6 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -1241,7 +1241,7 @@ int _alpm_sync_commit(alpm_handle_t *handle, alpm_list_t **data)
trans->state = STATE_COMMITING;
/* fileconflict check */
- if(!(trans->flags & (ALPM_TRANS_FLAG_FORCE|ALPM_TRANS_FLAG_DBONLY))) {
+ if(!(trans->flags & ALPM_TRANS_FLAG_DBONLY)) {
EVENT(handle, ALPM_EVENT_FILECONFLICTS_START, NULL, NULL);
_alpm_log(handle, ALPM_LOG_DEBUG, "looking for file conflicts\n");
diff --git a/src/pacman/sync.c b/src/pacman/sync.c
index 417773dc..924cdf50 100644
--- a/src/pacman/sync.c
+++ b/src/pacman/sync.c
@@ -881,6 +881,9 @@ int sync_prepare_execute(void)
alpm_strerror(err));
switch(err) {
case ALPM_ERR_FILE_CONFLICTS:
+ if(config->flags & ALPM_TRANS_FLAG_FORCE) {
+ printf(_("unable to %s directory-file conflicts\n"), "--force");
+ }
for(i = data; i; i = alpm_list_next(i)) {
alpm_fileconflict_t *conflict = i->data;
switch(conflict->type) {
diff --git a/test/pacman/tests/upgrade046.py b/test/pacman/tests/upgrade046.py
index a02a7132..d9ac66b9 100644
--- a/test/pacman/tests/upgrade046.py
+++ b/test/pacman/tests/upgrade046.py
@@ -29,5 +29,3 @@ self.addrule("FILE_MODIFIED=bin/dummy")
self.addrule("FILE_MODIFIED=bin/foobar")
self.addrule("FILE_EXIST=usr/share/file")
self.addrule("FILE_MODIFIED=usr/share/file")
-
-self.expectfailure = True