# # patch "git_import.cc" # from [e2c2ea2a1169502bb7425593ad6548543999c101] # to [9d648116debe417ff84863d988e0712c2e4c2315] # # patch "revision.cc" # from [cc5f95abbde0913cda381575bc9fe7f4bb714150] # to [9c5112ad4d29e25d14a7d2c6db90a7baf75f5e80] # # patch "revision.hh" # from [75914f980a90359e6560fdd5b801ab0aa5095cda] # to [f58cbe88b1869e6418dddd44f5d107a70d15540c] # ======================================================================== --- git_import.cc e2c2ea2a1169502bb7425593ad6548543999c101 +++ git_import.cc 9d648116debe417ff84863d988e0712c2e4c2315 @@ -386,6 +386,7 @@ bool header = true; revision_set rev; edge_map edges; + vector parents; manifest_map manifest; // XXX: it might be user policy decision whether to take author @@ -461,41 +462,7 @@ } else if (keyword == "parent") { - revision_id parent_rev; - manifest_id parent_mid; - - // given the topo order, we ought to have the parent hashed - except - // for incremental imports - map - >::const_iterator i = git.commitmap.find(param); - if (i != git.commitmap.end()) - { - parent_rev = i->second.first; - parent_mid = i->second.second; - } - else - { - historical_gitrev_to_monorev(git.branch, &git.commitmap, app, param, parent_rev); - app.db.get_revision_manifest(parent_rev, parent_mid); - } - - manifest_map parent_man; - L(F("parent revision '%s'") % parent_rev.inner()); - L(F("parent manifest '%s', loading...") % parent_mid.inner()); - app.db.get_manifest(parent_mid, parent_man); - - boost::shared_ptr changes(new change_set()); - - // complete_change_set(parent_man, manifest, *changes); - full_change_set(parent_man, manifest, *changes); - - { - data cset; - write_change_set(*changes, cset); - L(F("Changeset:\n%s") % cset()); - } - - edges.insert(make_pair(parent_rev, make_pair(parent_mid, changes))); + parents.push_back(revision_id(param)); } else if (keyword == "committer") { @@ -507,6 +474,60 @@ } } + + // Add edges to parents: + + for (unsigned i = 0; i < parents.size(); i++) + { + revision_id parent_rev; + manifest_id parent_mid; + + // given the topo order, we ought to have the parent hashed - except + // for incremental imports + map + >::const_iterator cm = git.commitmap.find(parents[i].inner()); + if (cm != git.commitmap.end()) + { + parent_rev = cm->second.first; + parent_mid = cm->second.second; + } + else + { + historical_gitrev_to_monorev(git.branch, &git.commitmap, app, parents[i].inner(), parent_rev); + app.db.get_revision_manifest(parent_rev, parent_mid); + } + + L(F("parent revision '%s'") % parent_rev.inner()); + L(F("parent manifest '%s', loading...") % parent_mid.inner()); + + boost::shared_ptr changes(new change_set()); + + if (parents.size() == 2) + { + // A merge. See the huge comment in + // anc_graph::construct_revision_from_ancestry() if you want to + // know why are we bothering with this stuff. + + change_set_for_merge(app, parents[i], parents[unsigned(1 - i)], parent_mid, rev.new_manifest, *changes); + + } else { + manifest_map parent_man; + app.db.get_manifest(parent_mid, parent_man); + // Nothing to see here, please move along. + // complete_change_set(parent_man, manifest, *changes); + full_change_set(parent_man, manifest, *changes); + } + + { + data cset; + write_change_set(*changes, cset); + L(F("Changeset:\n%s") % cset()); + } + + edges.insert(make_pair(parent_rev, make_pair(parent_mid, changes))); + } + + // Connect with the ancestry: edge_map::const_iterator e = edges.begin(); ======================================================================== --- revision.cc cc5f95abbde0913cda381575bc9fe7f4bb714150 +++ revision.cc 9c5112ad4d29e25d14a7d2c6db90a7baf75f5e80 @@ -1078,7 +1078,7 @@ // real enough error case that we need support code for it. -static void +static void analyze_manifest_changes(app_state & app, manifest_id const & parent, manifest_id const & child, @@ -1127,7 +1127,31 @@ } } +void +change_set_for_merge(app_state &app, revision_id const &parent_rid, revision_id const &other_parent_rid, + manifest_id const &parent_man, manifest_id const &child_man, change_set &cs) +{ + // this is stupidly inefficient, in that we do this whole expensive + // changeset finding thing twice in a row. oh well. + revision_id lca; + std::set need_killing_files; + if (find_least_common_ancestor(parent_rid, other_parent_rid, lca, app)) + { + change_set parent_cs, other_parent_cs; + calculate_composite_change_set(lca, other_parent_rid, app, other_parent_cs); + calculate_composite_change_set(lca, parent_rid, app, parent_cs); + std::set_difference(other_parent_cs.rearrangement.deleted_files.begin(), + other_parent_cs.rearrangement.deleted_files.end(), + parent_cs.rearrangement.deleted_files.begin(), + parent_cs.rearrangement.deleted_files.end(), + std::inserter(need_killing_files, + need_killing_files.begin())); + } + analyze_manifest_changes(app, parent_man, child_man, need_killing_files, cs); +} + + struct anc_graph { anc_graph(bool existing, app_state & a) : @@ -1540,32 +1564,13 @@ u64 other_parent = idx(others, i); L(F("processing edge from child %d -> parent %d\n") % child % parent); - revision_id parent_rid = node_to_new_rev.find(parent)->second; - revision_id other_parent_rid = node_to_new_rev.find(other_parent)->second; - // this is stupidly inefficient, in that we do this whole expensive - // changeset finding thing twice in a row. oh well. - revision_id lca; - std::set need_killing_files; - if (find_least_common_ancestor(parent_rid, other_parent_rid, lca, app)) - { - change_set parent_cs, other_parent_cs; - calculate_composite_change_set(lca, other_parent_rid, app, other_parent_cs); - calculate_composite_change_set(lca, parent_rid, app, parent_cs); - std::set_difference(other_parent_cs.rearrangement.deleted_files.begin(), - other_parent_cs.rearrangement.deleted_files.end(), - parent_cs.rearrangement.deleted_files.begin(), - parent_cs.rearrangement.deleted_files.end(), - std::inserter(need_killing_files, - need_killing_files.begin())); - } - - L(F("parent node %d = revision %s\n") % parent % parent_rid); manifest_id parent_man; get_node_manifest(parent, parent_man); boost::shared_ptr cs(new change_set()); - analyze_manifest_changes(app, parent_man, child_man, need_killing_files, - *cs); - rev.edges.insert(std::make_pair(parent_rid, + change_set_for_merge(app, node_to_new_rev.find(parent)->second, + node_to_new_rev.find(other_parent)->second, + parent_man, child_man, *cs); + rev.edges.insert(std::make_pair(node_to_new_rev.find(parent)->second, std::make_pair(parent_man, cs))); } } ======================================================================== --- revision.hh 75914f980a90359e6560fdd5b801ab0aa5095cda +++ revision.hh f58cbe88b1869e6418dddd44f5d107a70d15540c @@ -167,6 +167,14 @@ app_state & app, change_set & composed); +void +change_set_for_merge(app_state &app, + revision_id const &parent_rid, + revision_id const &other_parent_rid, + manifest_id const &parent_man, + manifest_id const &child_man, + change_set &cs); + void build_changesets_from_manifest_ancestry(app_state & app);