# # # patch "cmd_diff_log.cc" # from [b95267396272bf66f1c4c17b19659cc4e734213a] # to [d28d87896dfc0b4daf974de3b33fbedeaa016871] # # patch "cmd_merging.cc" # from [5ebc0d909d0ea52fd29bcb5177a9df5595b97121] # to [c6da9a3ef28bf0c6fa8e4bb15917acc1079f5f3b] # # patch "cmd_ws_commit.cc" # from [978acabdbea5739e0b18c7a4187255b7c6343d47] # to [7bf89bc93737f48a23e7aafe729b09aa99264f42] # # patch "revision.cc" # from [f65fbe7ba0fe0508668a5b353f1e5b532e096402] # to [b262b0ff0aaed2a707704268a57ba9ccf5d97a24] # # patch "roster.cc" # from [e36b1e83bf7a5a3538f0a882feaccb9f32250118] # to [113187ebdf575e645f20efa657db7517d349636c] # # patch "roster.hh" # from [2a6c8163373bb6edd8ad291fc333c007e364b194] # to [d9a92727756deb5917cede674ff95c44e933f0ff] # ============================================================ --- cmd_diff_log.cc b95267396272bf66f1c4c17b19659cc4e734213a +++ cmd_diff_log.cc d28d87896dfc0b4daf974de3b33fbedeaa016871 @@ -358,7 +358,7 @@ prepare_diff(cset & included, if (app.opts.revision_selectors.size() == 0) { - roster_t new_roster, old_roster; + roster_t old_roster, restricted_roster, new_roster; revision_id old_rid; parent_map parents; @@ -379,16 +379,19 @@ prepare_diff(cset & included, old_roster, new_roster, app); app.work.update_current_roster_from_filesystem(new_roster, mask); - make_restricted_csets(old_roster, new_roster, - included, excluded, mask); - check_restricted_cset(old_roster, included); + make_restricted_roster(old_roster, new_roster, restricted_roster, + mask); + + make_cset(old_roster, restricted_roster, included); + make_cset(restricted_roster, new_roster, excluded); + new_is_archived = false; header << "# old_revision [" << old_rid << "]\n"; } else if (app.opts.revision_selectors.size() == 1) { - roster_t new_roster, old_roster; + roster_t old_roster, restricted_roster, new_roster; revision_id r_old_id; complete(app, idx(app.opts.revision_selectors, 0)(), r_old_id); @@ -404,16 +407,19 @@ prepare_diff(cset & included, old_roster, new_roster, app); app.work.update_current_roster_from_filesystem(new_roster, mask); - make_restricted_csets(old_roster, new_roster, - included, excluded, mask); - check_restricted_cset(old_roster, included); + make_restricted_roster(old_roster, new_roster, restricted_roster, + mask); + + make_cset(old_roster, restricted_roster, included); + make_cset(restricted_roster, new_roster, excluded); + new_is_archived = false; header << "# old_revision [" << r_old_id << "]\n"; } else if (app.opts.revision_selectors.size() == 2) { - roster_t new_roster, old_roster; + roster_t old_roster, restricted_roster, new_roster; revision_id r_old_id, r_new_id; complete(app, idx(app.opts.revision_selectors, 0)(), r_old_id); @@ -454,9 +460,11 @@ prepare_diff(cset & included, // (which fails for paths with @'s in them) or possibly //rev/file // since versioned paths are required to be relative. - make_restricted_csets(old_roster, new_roster, - included, excluded, mask); - check_restricted_cset(old_roster, included); + make_restricted_roster(old_roster, new_roster, restricted_roster, + mask); + + make_cset(old_roster, restricted_roster, included); + make_cset(restricted_roster, new_roster, excluded); new_is_archived = true; } ============================================================ --- cmd_merging.cc 5ebc0d909d0ea52fd29bcb5177a9df5595b97121 +++ cmd_merging.cc c6da9a3ef28bf0c6fa8e4bb15917acc1079f5f3b @@ -938,10 +938,13 @@ CMD(pluck, "pluck", "", CMD_REF(workspac args_to_paths(app.opts.exclude_patterns), app.opts.depth, *from_roster, to_true_roster, app); - make_restricted_csets(*from_roster, to_true_roster, - from_to_to, from_to_to_excluded, - mask); - check_restricted_cset(*from_roster, from_to_to); + + roster_t restricted_roster; + make_restricted_roster(*from_roster, to_true_roster, + restricted_roster, mask); + + make_cset(*from_roster, restricted_roster, from_to_to); + make_cset(restricted_roster, to_true_roster, from_to_to_excluded); } N(!from_to_to.empty(), F("no changes to be applied")); // ...and use it to create the TO roster ============================================================ --- cmd_ws_commit.cc 978acabdbea5739e0b18c7a4187255b7c6343d47 +++ cmd_ws_commit.cc 7bf89bc93737f48a23e7aafe729b09aa99264f42 @@ -200,9 +200,13 @@ CMD(revert, "revert", "", CMD_REF(worksp old_roster, new_roster, app); } - make_restricted_csets(old_roster, new_roster, - included, excluded, mask); - + roster_t restricted_roster; + make_restricted_roster(old_roster, new_roster, restricted_roster, + mask); + + make_cset(old_roster, restricted_roster, included); + make_cset(restricted_roster, new_roster, excluded); + // The included cset will be thrown away (reverted) leaving the // excluded cset pending in MTN/work which must be valid against the // old roster. ============================================================ --- revision.cc f65fbe7ba0fe0508668a5b353f1e5b532e096402 +++ revision.cc b262b0ff0aaed2a707704268a57ba9ccf5d97a24 @@ -714,15 +714,16 @@ make_restricted_revision(parent_map cons revision_t & rev) { edge_map edges; - cset dummy; for (parent_map::const_iterator i = old_rosters.begin(); i != old_rosters.end(); i++) { shared_ptr included(new cset()); - make_restricted_csets(parent_roster(i), new_roster, - *included, dummy, mask); - check_restricted_cset(parent_roster(i), *included); + roster_t restricted_roster; + + make_restricted_roster(parent_roster(i), new_roster, + restricted_roster, mask); + make_cset(parent_roster(i), restricted_roster, *included); safe_insert(edges, make_pair(parent_id(i), included)); } @@ -744,9 +745,12 @@ make_restricted_revision(parent_map cons i++) { shared_ptr included(new cset()); - make_restricted_csets(parent_roster(i), new_roster, - *included, excluded, mask); - check_restricted_cset(parent_roster(i), *included); + roster_t restricted_roster; + + make_restricted_roster(parent_roster(i), new_roster, + restricted_roster, mask); + make_cset(parent_roster(i), restricted_roster, *included); + make_cset(restricted_roster, new_roster, excluded); safe_insert(edges, make_pair(parent_id(i), included)); if (!excluded.empty()) no_excludes = false; ============================================================ --- roster.cc e36b1e83bf7a5a3538f0a882feaccb9f32250118 +++ roster.cc 113187ebdf575e645f20efa657db7517d349636c @@ -2175,19 +2175,17 @@ equal_up_to_renumbering(roster_t const & return true; } - -void make_restricted_csets(roster_t const & from, roster_t const & to, - cset & included, cset & excluded, - node_restriction const & mask) +static void +select_restricted_nodes(roster_t const & from, roster_t const & to, + node_restriction const & mask, + map & selected) { - included.clear(); - excluded.clear(); - - L(FL("building restricted csets")); + selected.clear(); parallel::iter i(from.all_nodes(), to.all_nodes()); while (i.next()) { MM(i); + switch (i.state()) { case parallel::invalid: @@ -2195,50 +2193,130 @@ void make_restricted_csets(roster_t cons case parallel::in_left: // deleted - if (mask.includes(from, i.left_key())) - { - delta_only_in_from(from, i.left_key(), i.left_data(), included); - L(FL("included left %d") % i.left_key()); - } - else - { - delta_only_in_from(from, i.left_key(), i.left_data(), excluded); - L(FL("excluded left %d") % i.left_key()); - } + if (!mask.includes(from, i.left_key())) + selected.insert(make_pair(i.left_key(), i.left_data())); break; case parallel::in_right: // added if (mask.includes(to, i.right_key())) - { - delta_only_in_to(to, i.right_key(), i.right_data(), included); - L(FL("included right %d") % i.right_key()); - } - else - { - delta_only_in_to(to, i.right_key(), i.right_data(), excluded); - L(FL("excluded right %d") % i.right_key()); - } + selected.insert(make_pair(i.right_key(), i.right_data())); break; case parallel::in_both: // moved/renamed/patched/attribute changes - if (mask.includes(from, i.left_key()) || mask.includes(to, i.right_key())) + if (mask.includes(from, i.left_key()) || + mask.includes(to, i.right_key())) + selected.insert(make_pair(i.right_key(), i.right_data())); + else + selected.insert(make_pair(i.left_key(), i.left_data())); + break; + } + } +} + +void +make_restricted_roster(roster_t const & from, roster_t const & to, + roster_t & restricted, + node_restriction const & mask) +{ + MM(from); + MM(to); + MM(restricted); + + I(restricted.all_nodes().empty()); + + map selected; + + select_restricted_nodes(from, to, mask, selected); + + int problems = 0; + + while (!selected.empty()) + { + map::const_iterator n = selected.begin(), p; + + L(FL("selected node %d %s parent %d") + % n->second->self + % n->second->name + % n->second->parent); + + while (!null_node(n->second->parent) && + !restricted.has_node(n->second->parent)) + { + // we can't add this node until its parent has been added + + L(FL("deferred node %d %s parent %d") + % n->second->self + % n->second->name + % n->second->parent); + + p = selected.find(n->second->parent); + + if (p != selected.end()) { - delta_in_both(i.left_key(), from, i.left_data(), to, i.right_data(), included); - L(FL("in both %d %d") % i.left_key() % i.right_key()); + n = p; // see if we can add the parent + I(is_dir_t(n->second)); } else + break; + } + + if (p != selected.end()) + { + L(FL("adding node %d %s parent %d") + % n->second->self + % n->second->name + % n->second->parent); + + if (is_file_t(n->second)) { - delta_in_both(i.left_key(), from, i.left_data(), to, i.right_data(), excluded); - L(FL("in both %d %d") % i.left_key() % i.right_key()); + file_t const f = downcast_to_file_t(n->second); + restricted.create_file_node(f->content, f->self); } - break; + else + restricted.create_dir_node(n->second->self); + + node_t added = restricted.get_node(n->second->self); + added->attrs = n->second->attrs; + + restricted.attach_node(n->second->self, n->second->parent, n->second->name); } + else if (from.has_node(n->second->parent) && !to.has_node(n->second->parent)) + { + // included a delete that must be excluded + file_path self, parent; + from.get_name(n->second->self, self); + from.get_name(n->second->parent, parent); + W(F("restriction includes deletion of '%s' " + "but excludes deletion of '%s'") + % parent % self); + problems++; + } + else if (!from.has_node(n->second->parent) && to.has_node(n->second->parent)) + { + // excluded an add that must be included + file_path self, parent; + to.get_name(n->second->self, self); + to.get_name(n->second->parent, parent); + W(F("restriction excludes addition of '%s' " + "but includes addition of '%s'") + % parent % self); + problems++; + } + else + I(false); // something we missed?!? + + selected.erase(n->first); } + N(problems == 0, F("invalid restriction")); + + // TODO: add some sanity checks here... restricted.check_sane()? } + +// TODO: possibly delete all this checking stuff class editable_roster_for_check : public editable_roster_base { @@ -2339,6 +2417,15 @@ editable_roster_for_check::attach_node(n } } + +// TODO: delete this ?!? +// it may still be needed for revert which has to check that the excluded cset +// still makes sense against the *old* roster +// before revert: +// old roster restricted roster new roster +// after revert: +// old roster new roster + void check_restricted_cset(roster_t const & roster, cset const & cs) { ============================================================ --- roster.hh 2a6c8163373bb6edd8ad291fc333c007e364b194 +++ roster.hh d9a92727756deb5917cede674ff95c44e933f0ff @@ -196,7 +196,6 @@ public: node_id_source & nis); void create_file_node(file_id const & content, node_id nid); - void insert_node(node_t n); void attach_node(node_id nid, file_path const & dst); void attach_node(node_id nid, node_id parent, path_component name); void apply_delta(file_path const & pth, @@ -364,9 +363,9 @@ void class node_restriction; void -make_restricted_csets(roster_t const & from, roster_t const & to, - cset & included, cset & excluded, - node_restriction const & mask); +make_restricted_roster(roster_t const & from, roster_t const & to, + roster_t & restricted, + node_restriction const & mask); void check_restricted_cset(roster_t const & roster, cset const & cs);