else if (!installed && o_upgrade)
throw runtime_error("package " + package.first + " not previously installed (skip -u to install)");
+ set<string> non_install_files = apply_install_rules(package.first, package.second, config_rules);
set<string> conflicting_files = db_find_conflicts(package.first, package.second);
if (!conflicting_files.empty()) {
db_add_pkg(package.first, package.second);
db_commit();
- pkg_install(o_package, keep_list);
+ pkg_install(o_package, keep_list, non_install_files);
ldconfig();
}
}
if (sscanf(line.c_str(), "%s %s %s %s", event, pattern, action, dummy) != 3)
throw runtime_error(filename + ":" + itos(linecount) + ": wrong number of arguments, aborting");
- if (!strcmp(event, "UPGRADE")) {
+ if (!strcmp(event, "UPGRADE") || !strcmp(event, "INSTALL")) {
rule_t rule;
- rule.event = UPGRADE;
+ rule.event = strcmp(event, "UPGRADE") ? INSTALL : UPGRADE;
rule.pattern = pattern;
if (!strcmp(action, "YES")) {
rule.action = true;
return keep_list;
}
+set<string> pkgadd::apply_install_rules(const string& name, pkginfo_t& info, const vector<rule_t>& rules)
+{
+ // TODO: better algo(?)
+ set<string> install_set;
+ set<string> non_install_set;
+ vector<rule_t> found;
+
+ find_rules(rules, INSTALL, found);
+
+ for (set<string>::const_iterator i = info.files.begin(); i != info.files.end(); i++) {
+ bool install_file = true;
+
+ for (vector<rule_t>::reverse_iterator j = found.rbegin(); j != found.rend(); j++) {
+ if (rule_applies_to_file(*j, *i)) {
+ install_file = (*j).action;
+ break;
+ }
+ }
+
+ if (install_file)
+ install_set.insert(install_set.end(), *i);
+ else
+ non_install_set.insert(*i);
+ }
+
+ info.files.clear();
+ info.files = install_set;
+
+#ifndef NDEBUG
+ cerr << "Install set:" << endl;
+ for (set<string>::iterator j = info.files.begin(); j != info.files.end(); j++) {
+ cerr << " " << (*j) << endl;
+ }
+ cerr << endl;
+
+ cerr << "Non-Install set:" << endl;
+ for (set<string>::iterator j = non_install_set.begin(); j != non_install_set.end(); j++) {
+ cerr << " " << (*j) << endl;
+ }
+ cerr << endl;
+#endif
+
+ return non_install_set;
+}
+
void pkgadd::find_rules(const vector<rule_t>& rules, rule_event_t event, vector<rule_t>& found) const
{
for (vector<rule_t>::const_iterator i = rules.begin(); i != rules.end(); i++)
#define PKGADD_CONF_MAXLINE 1024
enum rule_event_t {
- UPGRADE
+ UPGRADE,
+ INSTALL
};
struct rule_t {
private:
vector<rule_t> read_config() const;
set<string> make_keep_list(const set<string>& files, const vector<rule_t>& rules) const;
+ set<string> apply_install_rules(const string& name, pkginfo_t& info, const vector<rule_t>& rules);
void find_rules(const vector<rule_t>& rules, rule_event_t event, vector<rule_t>& found) const;
bool rule_applies_to_file(const rule_t& rule, const string& file) const;
};
return result;
}
-void pkgutil::pkg_install(const string& filename, const set<string>& keep_list) const
+void pkgutil::pkg_install(const string& filename, const set<string>& keep_list, const set<string>& non_install_list) const
{
TAR* t;
unsigned int i;
string original_filename = trim_filename(root + string("/") + archive_filename);
string real_filename = original_filename;
+ // Check if file is filtered out via INSTALL
+ if (non_install_list.find(archive_filename) != non_install_list.end()) {
+ if (TH_ISREG(t))
+ tar_skip_regfile(t);
+
+ continue;
+ }
+
// Check if file should be rejected
if (file_exists(real_filename) && keep_list.find(archive_filename) != keep_list.end())
real_filename = trim_filename(reject_dir + string("/") + archive_filename);