forked from tools/pkgutils
pkgadd: apply rejection rules against old files when upgrading
This commit is contained in:
parent
e2a57cd1a4
commit
95944344b4
10
pkgadd.cc
10
pkgadd.cc
@ -99,17 +99,19 @@ void pkgadd::run(int argc, char** argv)
|
||||
}
|
||||
}
|
||||
|
||||
set<string> keep_list;
|
||||
set<string> keep_new;
|
||||
|
||||
if (o_upgrade) {
|
||||
keep_list = make_keep_list(package.second.files, config_rules);
|
||||
db_rm_pkg(package.first, keep_list);
|
||||
keep_new = make_keep_list(package.second.files, config_rules);
|
||||
set<string> files_old = packages[package.first].files;
|
||||
set<string> keep_old = make_keep_list(files_old, config_rules);
|
||||
db_rm_pkg(package.first, keep_old, keep_new);
|
||||
}
|
||||
|
||||
db_add_pkg(package.first, package.second);
|
||||
db_commit();
|
||||
try {
|
||||
pkg_install(o_package, keep_list, non_install_files, installed);
|
||||
pkg_install(o_package, keep_new, non_install_files, installed);
|
||||
} catch (runtime_error&) {
|
||||
if (!installed) {
|
||||
db_rm_pkg(package.first);
|
||||
|
38
pkgutil.cc
38
pkgutil.cc
@ -22,6 +22,7 @@
|
||||
|
||||
#include "pkgutil.h"
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
@ -199,7 +200,12 @@ void pkgutil::db_rm_pkg(const string& name)
|
||||
}
|
||||
}
|
||||
|
||||
void pkgutil::db_rm_pkg(const string& name, const set<string>& keep_list)
|
||||
/* Three-argument db_rm_pkg (to address FS#1074)
|
||||
* arg1: name of the package being upgraded
|
||||
* arg2: keep list from the old version of the package
|
||||
* arg3: keep list from the new version of the package */
|
||||
void pkgutil::db_rm_pkg(const string& name, const set<string>& keep_old,
|
||||
const set<string>& keep_new)
|
||||
{
|
||||
set<string> files = packages[name].files;
|
||||
packages.erase(name);
|
||||
@ -210,9 +216,33 @@ void pkgutil::db_rm_pkg(const string& name, const set<string>& keep_list)
|
||||
cerr << endl;
|
||||
#endif
|
||||
|
||||
// Don't delete files found in the keep list
|
||||
for (set<string>::const_iterator i = keep_list.begin(); i != keep_list.end(); ++i)
|
||||
files.erase(*i);
|
||||
// Files common to both old and new packages, matching an "UPGRADE NO"
|
||||
// rule, can be left in place (won't be clobbered later by pkg_install).
|
||||
// Files that only exist in the old package will be stashed in reject_dir.
|
||||
const string reject_dir = trim_filename(root + string("/") + string(PKG_REJECTED));
|
||||
for (set<string>::const_iterator i = keep_old.begin(); i != keep_old.end(); ++i) {
|
||||
// Exempt directories, which might be shared among other ports,
|
||||
// but if db_rm_files empties them out, allow them to be deleted.
|
||||
if ((*i)[i->length()-1] == '/') {
|
||||
continue;
|
||||
} else {
|
||||
files.erase(*i);
|
||||
}
|
||||
|
||||
if ( keep_new.find(*i) == keep_new.end() ) {
|
||||
const string filename = root + *i;
|
||||
const string savname = trim_filename(reject_dir + filename);
|
||||
char* savpath = strdup(const_cast<char*>( savname.c_str() ));
|
||||
const string savdir = dirname(savpath);
|
||||
std::filesystem::create_directories(savdir);
|
||||
if ( file_exists(filename) &&
|
||||
rename(filename.c_str(),savname.c_str()) == -1 ) {
|
||||
const char* msg = strerror(errno);
|
||||
cerr << utilname << ": could not rename " << filename
|
||||
<< ": " << msg << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
cerr << "Removing package phase 2 (files that is in the keep list excluded):" << endl;
|
||||
|
@ -65,7 +65,7 @@ protected:
|
||||
void db_add_pkg(const string& name, const pkginfo_t& info);
|
||||
bool db_find_pkg(const string& name);
|
||||
void db_rm_pkg(const string& name);
|
||||
void db_rm_pkg(const string& name, const set<string>& keep_list);
|
||||
void db_rm_pkg(const string& name, const set<string>& keep_old, const set<string>& keep_new);
|
||||
void db_rm_files(set<string> files, const set<string>& keep_list);
|
||||
set<string> db_find_conflicts(const string& name, const pkginfo_t& info);
|
||||
|
||||
|
30
rejmerge.in
30
rejmerge.in
@ -155,6 +155,32 @@ diff_menu() {
|
||||
: > "$TMPFILE"
|
||||
}
|
||||
|
||||
relic_menu() {
|
||||
while true; do
|
||||
info "$(basename "$1") has been disowned by the package that installed it."
|
||||
file "$1"
|
||||
while true; do
|
||||
info_n "[R]estore [M]ove to other location [D]elete? "
|
||||
read -n1 CMD
|
||||
echo
|
||||
|
||||
case "$CMD" in
|
||||
m|M) info_n "New (absolute) path?"
|
||||
read DEST
|
||||
mv "$1" "$DEST" || { info "unable to write to $DEST"; break 1; }
|
||||
break 2
|
||||
;;
|
||||
r|R) mv "$1" "${1##$REJECTED_DIR}" || { info "unable to restore ${1##$REJECTED_DIR}"; break 1; }
|
||||
break 2
|
||||
;;
|
||||
d|D) rm -f "$1"
|
||||
break 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
file_menu() {
|
||||
while true; do
|
||||
info "$1"
|
||||
@ -253,9 +279,9 @@ main() {
|
||||
for REJECTED_FILE in $(find $REJECTED_DIR ! -type d); do
|
||||
INSTALLED_FILE="$REJMERGE_ROOT${REJECTED_FILE##$REJECTED_DIR}"
|
||||
|
||||
# Remove rejected file if there is no installed version
|
||||
# If there is no copy on sysroot, the file is probably stale
|
||||
if [ ! -e "$INSTALLED_FILE" ]; then
|
||||
rm -f "$REJECTED_FILE"
|
||||
relic_menu "$REJECTED_FILE"
|
||||
continue
|
||||
fi
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user