diff options
-rw-r--r-- | lib/libalpm/conflict.c | 35 | ||||
-rw-r--r-- | test/pacman/tests/fileconflict008.py | 21 |
2 files changed, 43 insertions, 13 deletions
diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c index 39f42bfe..94d82dd9 100644 --- a/lib/libalpm/conflict.c +++ b/lib/libalpm/conflict.c @@ -275,10 +275,10 @@ static alpm_list_t *filelist_operation(alpm_list_t *filesA, alpm_list_t *filesB, return ret; } -/* Adds pmfileconflict_t to a conflicts list. Pass the conflicts list, type (either - * PM_FILECONFLICT_TARGET or PM_FILECONFLICT_FILESYSTEM), a file string, and either - * two package names or one package name and NULL. This is a wrapper for former - * functionality that was done inline. +/* Adds pmfileconflict_t to a conflicts list. Pass the conflicts list, type + * (either PM_FILECONFLICT_TARGET or PM_FILECONFLICT_FILESYSTEM), a file + * string, and either two package names or one package name and NULL. This is + * a wrapper for former functionality that was done inline. */ static alpm_list_t *add_fileconflict(pmhandle_t *handle, alpm_list_t *conflicts, pmfileconflicttype_t type, const char *filestr, @@ -440,7 +440,9 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmhandle_t *handle, for(j = tmpfiles; j; j = j->next) { struct stat lsbuf; - const char *filestr = j->data; + const char *filestr = j->data, *relative_path; + /* have we acted on this conflict? */ + int resolved_conflict = 0; snprintf(path, PATH_MAX, "%s%s", handle->root, filestr); @@ -449,7 +451,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmhandle_t *handle, continue; } - if(path[strlen(path)-1] == '/') { + if(path[strlen(path) - 1] == '/') { struct stat sbuf; if(S_ISDIR(lsbuf.st_mode)) { _alpm_log(handle, PM_LOG_DEBUG, "%s is a directory, not a conflict\n", path); @@ -461,17 +463,22 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmhandle_t *handle, "%s is a symlink to a dir, hopefully not a conflict\n", path); continue; } + /* if we made it to here, we want all subsequent path comparisons to + * not include the trailing slash. This allows things like file -> + * directory replacements. */ + path[strlen(path) - 1] = '\0'; } - _alpm_log(handle, PM_LOG_DEBUG, "checking possible conflict: %s\n", path); - int resolved_conflict = 0; /* have we acted on this conflict? */ + _alpm_log(handle, PM_LOG_DEBUG, "checking possible conflict: %s\n", path); + relative_path = path + strlen(handle->root); /* Check remove list (will we remove the conflicting local file?) */ for(k = remove; k && !resolved_conflict; k = k->next) { pmpkg_t *rempkg = k->data; - if(rempkg && alpm_list_find_str(alpm_pkg_get_files(rempkg), filestr)) { + if(alpm_list_find_str(alpm_pkg_get_files(rempkg), relative_path)) { _alpm_log(handle, PM_LOG_DEBUG, - "local file will be removed, not a conflict: %s\n", filestr); + "local file will be removed, not a conflict: %s\n", + relative_path); resolved_conflict = 1; } } @@ -492,7 +499,8 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmhandle_t *handle, handle->trans->skip_remove = alpm_list_add(handle->trans->skip_remove, strdup(filestr)); _alpm_log(handle, PM_LOG_DEBUG, - "file changed packages, adding to remove skiplist: %s\n", filestr); + "file changed packages, adding to remove skiplist: %s\n", + filestr); resolved_conflict = 1; } } @@ -512,12 +520,13 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmhandle_t *handle, if(!resolved_conflict && dbpkg) { char *rpath = calloc(PATH_MAX, sizeof(char)); + const char *relative_rpath; if(!realpath(path, rpath)) { free(rpath); continue; } - char *filestr = rpath + strlen(handle->root); - if(alpm_list_find_str(alpm_pkg_get_files(dbpkg), filestr)) { + relative_rpath = rpath + strlen(handle->root); + if(alpm_list_find_str(alpm_pkg_get_files(dbpkg), relative_rpath)) { resolved_conflict = 1; } free(rpath); diff --git a/test/pacman/tests/fileconflict008.py b/test/pacman/tests/fileconflict008.py new file mode 100644 index 00000000..24ea8852 --- /dev/null +++ b/test/pacman/tests/fileconflict008.py @@ -0,0 +1,21 @@ +self.description = "Fileconflict file -> dir on package replacement (FS#24904)" + +lp = pmpkg("dummy") +lp.files = ["dir/filepath", + "dir/file"] +self.addpkg2db("local", lp) + +p1 = pmpkg("replace") +p1.provides = ["dummy"] +p1.replaces = ["dummy"] +p1.files = ["dir/filepath/", + "dir/filepath/file", + "dir/file", + "dir/file2"] +self.addpkg2db("sync", p1) + +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("!PKG_EXIST=dummy") +self.addrule("PKG_EXIST=replace") |