# # # patch "paths.cc" # from [dde6659e387c8890c96278ea29e3196bdf588139] # to [627323156040102f40923eaf1fee80e16f3f310c] # # patch "paths.hh" # from [f0d9aab30593dfde43c6fc6f999619211184f9ed] # to [bf930a1546fb00d9dd95c25fa8b3f0612c626f78] # # patch "work.cc" # from [0ef66673796d2a408587d70530944a5a8747d488] # to [04462308709ee929fb10ab635240551c3e1e74ff] # ============================================================ --- paths.cc dde6659e387c8890c96278ea29e3196bdf588139 +++ paths.cc 627323156040102f40923eaf1fee80e16f3f310c @@ -721,6 +721,15 @@ bookkeeping_path::operator /(path_compon + to_append(), 0, string::npos); } +bookkeeping_path +bookkeeping_path::operator /(file_path const & to_append) const +{ + I(!to_append.empty()); + I(!empty()); + return bookkeeping_path(((*(data.end() - 1) == '/') ? data : data + "/") + + to_append.as_internal(), 0, string::npos); +} + system_path system_path::operator /(path_component const & to_append) const { ============================================================ --- paths.hh f0d9aab30593dfde43c6fc6f999619211184f9ed +++ paths.hh bf930a1546fb00d9dd95c25fa8b3f0612c626f78 @@ -299,6 +299,7 @@ public: bookkeeping_path(std::string const &); bookkeeping_path operator /(char const *) const; bookkeeping_path operator /(path_component const &) const; + bookkeeping_path operator /(file_path const & to_append) const; // exposed for the use of walk_tree and friends static bool internal_string_is_bookkeeping_path(utf8 const & path); ============================================================ --- work.cc 0ef66673796d2a408587d70530944a5a8747d488 +++ work.cc 04462308709ee929fb10ab635240551c3e1e74ff @@ -825,18 +825,18 @@ addition_builder::visit_dir(file_path co { if (!recursive) { bool warn = false; - + // If the db can ever be stored in a dir // then revisit this logic I(!db.is_dbfile(path)); - + if (!respect_ignore) warn = !directory_empty(path); else if (respect_ignore && !work.ignore_file(path)) { vector children; read_directory(path, children, children); - + for (vector::const_iterator i = children.begin(); i != children.end(); ++i) { @@ -857,12 +857,12 @@ addition_builder::visit_dir(file_path co } } } - + if (warn) W(F("Non-recursive add: Files in the directory '%s' " "will not be added automatically.") % path); } - + this->visit_file(path); return true; } @@ -930,11 +930,11 @@ struct simulated_working_tree : public e node_id_source & nis; set blocked_paths; + set leftover_paths; map nid_map; - int conflicts; simulated_working_tree(roster_t & r, temp_node_id_source & n) - : workspace(r), nis(n), conflicts(0) {} + : workspace(r), nis(n) {} virtual node_id detach_node(file_path const & src); virtual void drop_detached_node(node_id nid); @@ -1173,8 +1173,10 @@ simulated_working_tree::drop_detached_no { map::const_iterator i = nid_map.find(nid); I(i != nid_map.end()); - W(F("cannot drop non-empty directory '%s'") % i->second); - conflicts++; + L(FL("directory '%s' should be dropped, but is not empty") % i->second); + for (dir_map::const_iterator j = dir->children.begin(); + j != dir->children.end(); ++j) + leftover_paths.insert(i->second / j->first); } } } @@ -1203,9 +1205,9 @@ simulated_working_tree::attach_node(node if (workspace.has_node(dst)) { - W(F("attach node %d blocked by unversioned path '%s'") % nid % dst); + L(FL("attach node %d blocked by unversioned path '%s'") % nid % dst); blocked_paths.insert(dst); - conflicts++; + leftover_paths.insert(dst); } else if (dst.empty()) { @@ -1221,7 +1223,7 @@ simulated_working_tree::attach_node(node workspace.attach_node(nid, dst); else { - W(F("attach node %d blocked by blocked parent '%s'") + L(FL("attach node %d blocked by blocked parent '%s'") % nid % parent); blocked_paths.insert(dst); } @@ -1253,7 +1255,40 @@ simulated_working_tree::commit() void simulated_working_tree::commit() { - N(conflicts == 0, F("%d workspace conflicts") % conflicts); + // if we have found paths during the test-run which will conflict with newly + // attached or to-be-dropped nodes, move these paths out of the way into + // _MTN/leftover while keeping the path to these paths intact in case the + // user wants them back + if (leftover_paths.size() > 0) + { + string now = date_t::now().as_iso_8601_extended(); + bookkeeping_path leftover_path = bookkeeping_root / "leftover" / now.data(); + require_path_is_nonexistent(leftover_path, + F("cannot move left-over paths - " + "base path %s already exists") % leftover_path); + + mkdir_p(leftover_path); + + for (set::const_iterator i = leftover_paths.begin(); + i != leftover_paths.end(); ++i) + { + L(FL("processing %s") % *i); + + file_path basedir = (*i).dirname(); + if (!basedir.empty()) + mkdir_p(leftover_path / basedir); + + bookkeeping_path new_path = leftover_path / *i; + if (directory_exists(*i)) + move_dir(*i, new_path); + else if (file_exists(*i)) + move_file(*i, new_path); + else + I(false); + + P(F("moved left-over path %s to %s") % *i % new_path); + } + } } simulated_working_tree::~simulated_working_tree()