# # patch "commands.cc" # from [e1dec5c24b9716e26504b76091f7954d68985f40] # to [af9078ec98297982cd41e7a8b0cea758e9a9df6c] # # patch "merge.cc" # from [635075b4158cb7a383660663cd9347d667d658f5] # to [b0b447f677a2e152f0d9cf15afeee01ee23c88c4] # # patch "revision.cc" # from [e0469a524455b86a3867af582fd4e7149553374c] # to [660a3bf2779b462955c45cc154e37639e23eb6a3] # # patch "revision.hh" # from [a0449ad6861f9f989c1baab0aae2dfe9d47e9466] # to [3bd95a5f0eeee3f31b8e6f835046d757b4b63488] # ======================================================================== --- commands.cc e1dec5c24b9716e26504b76091f7954d68985f40 +++ commands.cc af9078ec98297982cd41e7a8b0cea758e9a9df6c @@ -2285,9 +2285,7 @@ get_working_revision_and_rosters(app, args, rs, old_roster, new_roster, excluded_work); calculate_ident(rs, rid); - N(!(rs.edges.size() == 0 || - edge_changes(rs.edges.begin()).empty()), - F("no changes to commit\n")); + N(rs.is_nontrivial(), F("no changes to commit\n")); cert_value branchname; I(rs.edges.size() == 1); ======================================================================== --- merge.cc 635075b4158cb7a383660663cd9347d667d658f5 +++ merge.cc b0b447f677a2e152f0d9cf15afeee01ee23c88c4 @@ -10,6 +10,7 @@ #include "merge.hh" #include "roster_merge.hh" #include "packet.hh" +#include "safe_map.hh" void interactive_merge_and_store(revision_id const & left_rid, ======================================================================== --- revision.cc e0469a524455b86a3867af582fd4e7149553374c +++ revision.cc 660a3bf2779b462955c45cc154e37639e23eb6a3 @@ -40,36 +40,33 @@ void revision_set::check_sane() const { -/* -// FIXME_ROSTERS: disabled until rewritten to use rosters I(!null_id(new_manifest)); - - manifest_map fragment; - for (edge_map::const_iterator i = edges.begin(); i != edges.end(); ++i) + if (edges.size() == 1) { - change_set const & cs = edge_changes(i); - cs.check_sane(); - if (!global_sanity.relaxed) + // null revision is allowed iff there is a null manifest + I(null_id(edge_old_revision(edges.begin())) + == null_id(edge_old_manifest(edges.begin()))); + } + else if (edges.size() == 2) + { + // merge nodes cannot have null revisions or null manifests, ever + for (edge_map::const_iterator i = edges.begin(); i != edges.end(); ++i) { - // null old revisions come with null old manifests - I(!null_id(edge_old_revision(i)) || null_id(edge_old_manifest(i))); + I(!null_id(edge_old_revision(i))); + I(!null_id(edge_old_manifest(i))); + if (!(new_manifest == edge_old_manifest(i))) + I(!edge_changes(i).empty()); } - for (change_set::delta_map::const_iterator j = cs.deltas.begin(); j != cs.deltas.end(); ++j) - { - manifest_map::const_iterator k = fragment.find(delta_entry_path(j)); - if (k == fragment.end()) - fragment.insert(std::make_pair(delta_entry_path(j), - delta_entry_dst(j))); - else - { - if (!global_sanity.relaxed) - { - I(delta_entry_dst(j) == manifest_entry_id(k)); - } - } - } } -*/ + else + // revisions must always have either 1 or 2 edges + I(false); + + // we used to also check that if there were multiple edges that had patches + // for the same file, then the new hashes on each edge matched each other. + // this is not ported over to roster-style revisions because it's an + // inadequate check, and the real check, that the new manifest id is correct + // (done in put_revision, for instance) covers this case automatically. } bool @@ -78,6 +75,19 @@ return edges.size() > 1; } +bool +revision_set::is_nontrivial() const +{ + check_sane(); + // merge revisions are never trivial, because even if the resulting node + // happens to be identical to both parents, the merge is still recording + // that fact. + if (is_merge_node()) + return true; + else + return !edge_changes(edges.begin()).empty(); +} + revision_set::revision_set(revision_set const & other) { /* behave like normal constructor if other is empty */ ======================================================================== --- revision.hh a0449ad6861f9f989c1baab0aae2dfe9d47e9466 +++ revision.hh 3bd95a5f0eeee3f31b8e6f835046d757b4b63488 @@ -56,6 +56,9 @@ { void check_sane() const; bool is_merge_node() const; + // trivial revisions are ones that have no effect -- e.g., commit should + // refuse to commit them, saying that there are no changes to commit. + bool is_nontrivial() const; revision_set() {} revision_set(revision_set const & other); revision_set const & operator=(revision_set const & other); @@ -164,10 +167,10 @@ // frontier set of shared_ptrs, while traversing history. void select_nodes_modified_by_rev(revision_id const & rid, - revision_set const & rev, - std::set & nodes_changed, - std::set & nodes_born, - app_state & app); + revision_set const & rev, + std::set & nodes_changed, + std::set & nodes_born, + app_state & app); /* void