# # # patch "ChangeLog" # from [92ddf54713dd2c652b83058905f3fa453af756d0] # to [4197ec0785e53d59a0a66583a6782b6bd0d5bd9d] # # patch "merge.cc" # from [a7ae4085f45df539b091156d211d7e1f4c0cadda] # to [6b32ab65201a1b475b64af515bb8edf6481eca46] # # patch "roster_merge.cc" # from [890ca37b82f4b4de03680cb660a40db17ae97664] # to [4dec4aecf9c67f0ba369c9430bb492a3d93170bf] # # patch "roster_merge.hh" # from [ed68adf1d012e2a3689168d7367bfd5bd3b7be20] # to [e9c290f799091e5ecb70e291daae0bff72df2d48] # ============================================================ --- ChangeLog 92ddf54713dd2c652b83058905f3fa453af756d0 +++ ChangeLog 4197ec0785e53d59a0a66583a6782b6bd0d5bd9d @@ -1,5 +1,16 @@ 2006-02-02 Emile Snyder + * merge.cc (resolve_merge_conflicts): If the merge has non-content + conflicts warn the user and abort before making them do content + merges. Move logging/warning of conflicts to methods in the + roster_merge_result struct. + + * roster_merge.{cc,hh} (log_conflicts, + warn_non_content_conflicts): New methods to do the busy work of + logging or warning. + +2006-02-02 Emile Snyder + * netsync.cc (run_netsync_protocol): Print a warning if either the include or the exclude branch pattern have a ' or a " character anywhere in them. Hopefully will help users running in a Windows ============================================================ --- merge.cc a7ae4085f45df539b091156d211d7e1f4c0cadda +++ merge.cc 6b32ab65201a1b475b64af515bb8edf6481eca46 @@ -1,3 +1,4 @@ +// -*- mode: C++; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2 -*- // copyright (C) 2005 nathaniel smith // copyright (C) 2005 graydon hoare // all rights reserved. @@ -48,60 +49,17 @@ // line-merger on content conflicts. Other classes of conflict will // cause an invariant to trip below. Probably just a bunch of lua // hooks for remaining conflict types will be ok. - + if (!result.is_clean()) - { - L(FL("unclean mark-merge: %d name conflicts, %d content conflicts, %d attr conflicts, " - "%d orphaned node conflicts, %d rename target conflicts, %d directory loop conflicts\n") - % result.node_name_conflicts.size() - % result.file_content_conflicts.size() - % result.node_attr_conflicts.size() - % result.orphaned_node_conflicts.size() - % result.rename_target_conflicts.size() - % result.directory_loop_conflicts.size()); + result.log_conflicts(); - for (size_t i = 0; i < result.node_name_conflicts.size(); ++i) - L(FL("name conflict on node %d: [parent %d, self %s] vs. [parent %d, self %s]\n") - % result.node_name_conflicts[i].nid - % result.node_name_conflicts[i].left.first - % result.node_name_conflicts[i].left.second - % result.node_name_conflicts[i].right.first - % result.node_name_conflicts[i].right.second); - - for (size_t i = 0; i < result.file_content_conflicts.size(); ++i) - L(FL("content conflict on node %d: [%s] vs. [%s]\n") - % result.file_content_conflicts[i].nid - % result.file_content_conflicts[i].left - % result.file_content_conflicts[i].right); - - for (size_t i = 0; i < result.node_attr_conflicts.size(); ++i) - L(FL("attribute conflict on node %d, key %s: [%d, %s] vs. [%d, %s]\n") - % result.node_attr_conflicts[i].nid - % result.node_attr_conflicts[i].key - % result.node_attr_conflicts[i].left.first - % result.node_attr_conflicts[i].left.second - % result.node_attr_conflicts[i].right.first - % result.node_attr_conflicts[i].right.second); - - for (size_t i = 0; i < result.orphaned_node_conflicts.size(); ++i) - L(FL("orphaned node conflict on node %d, dead parent %d, name %s") - % result.orphaned_node_conflicts[i].nid - % result.orphaned_node_conflicts[i].parent_name.first - % result.orphaned_node_conflicts[i].parent_name.second); - - for (size_t i = 0; i < result.rename_target_conflicts.size(); ++i) - L(FL("rename target conflict: nodes %d, %d, both want parent %d, name %s") - % result.rename_target_conflicts[i].nid1 - % result.rename_target_conflicts[i].nid2 - % result.rename_target_conflicts[i].parent_name.first - % result.rename_target_conflicts[i].parent_name.second); - - for (size_t i = 0; i < result.directory_loop_conflicts.size(); ++i) - L(FL("directory loop conflict: node %d, wanted parent %d, name %s") - % result.directory_loop_conflicts[i].nid - % result.directory_loop_conflicts[i].parent_name.first - % result.directory_loop_conflicts[i].parent_name.second); - + if (!result.is_clean_except_for_content()) + { + result.warn_non_content_conflicts(); + W(F("resolve non-content conflicts and then try again.")); + } + else + { // Attempt to auto-resolve any content conflicts using the line-merger. // To do this requires finding a merge ancestor. if (!result.file_content_conflicts.empty()) ============================================================ --- roster_merge.cc 890ca37b82f4b4de03680cb660a40db17ae97664 +++ roster_merge.cc 4dec4aecf9c67f0ba369c9430bb492a3d93170bf @@ -1,3 +1,4 @@ +// -*- mode: C++; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2 -*- // copyright (C) 2005 nathaniel smith // all rights reserved. // licensed to the public under the terms of the GNU GPL (>= 2) @@ -21,7 +22,112 @@ && directory_loop_conflicts.empty(); } +bool +roster_merge_result::is_clean_except_for_content() +{ + return node_name_conflicts.empty() + && node_attr_conflicts.empty() + && orphaned_node_conflicts.empty() + && rename_target_conflicts.empty() + && directory_loop_conflicts.empty(); +} + void +roster_merge_result::log_conflicts() +{ + L(FL("unclean mark-merge: %d name conflicts, %d content conflicts, %d attr conflicts, " + "%d orphaned node conflicts, %d rename target conflicts, %d directory loop conflicts\n") + % node_name_conflicts.size() + % file_content_conflicts.size() + % node_attr_conflicts.size() + % orphaned_node_conflicts.size() + % rename_target_conflicts.size() + % directory_loop_conflicts.size()); + + for (size_t i = 0; i < node_name_conflicts.size(); ++i) + L(FL("name conflict on node %d: [parent %d, self %s] vs. [parent %d, self %s]\n") + % node_name_conflicts[i].nid + % node_name_conflicts[i].left.first + % node_name_conflicts[i].left.second + % node_name_conflicts[i].right.first + % node_name_conflicts[i].right.second); + + for (size_t i = 0; i < file_content_conflicts.size(); ++i) + L(FL("content conflict on node %d: [%s] vs. [%s]\n") + % file_content_conflicts[i].nid + % file_content_conflicts[i].left + % file_content_conflicts[i].right); + + for (size_t i = 0; i < node_attr_conflicts.size(); ++i) + L(FL("attribute conflict on node %d, key %s: [%d, %s] vs. [%d, %s]\n") + % node_attr_conflicts[i].nid + % node_attr_conflicts[i].key + % node_attr_conflicts[i].left.first + % node_attr_conflicts[i].left.second + % node_attr_conflicts[i].right.first + % node_attr_conflicts[i].right.second); + + for (size_t i = 0; i < orphaned_node_conflicts.size(); ++i) + L(FL("orphaned node conflict on node %d, dead parent %d, name %s") + % orphaned_node_conflicts[i].nid + % orphaned_node_conflicts[i].parent_name.first + % orphaned_node_conflicts[i].parent_name.second); + + for (size_t i = 0; i < rename_target_conflicts.size(); ++i) + L(FL("rename target conflict: nodes %d, %d, both want parent %d, name %s") + % rename_target_conflicts[i].nid1 + % rename_target_conflicts[i].nid2 + % rename_target_conflicts[i].parent_name.first + % rename_target_conflicts[i].parent_name.second); + + for (size_t i = 0; i < directory_loop_conflicts.size(); ++i) + L(FL("directory loop conflict: node %d, wanted parent %d, name %s") + % directory_loop_conflicts[i].nid + % directory_loop_conflicts[i].parent_name.first + % directory_loop_conflicts[i].parent_name.second); +} + +void +roster_merge_result::warn_non_content_conflicts() +{ + for (size_t i = 0; i < node_name_conflicts.size(); ++i) + W(F("name conflict on node %d: [parent %d, self %s] vs. [parent %d, self %s]\n") + % node_name_conflicts[i].nid + % node_name_conflicts[i].left.first + % node_name_conflicts[i].left.second + % node_name_conflicts[i].right.first + % node_name_conflicts[i].right.second); + + for (size_t i = 0; i < node_attr_conflicts.size(); ++i) + W(F("attribute conflict on node %d, key %s: [%d, %s] vs. [%d, %s]\n") + % node_attr_conflicts[i].nid + % node_attr_conflicts[i].key + % node_attr_conflicts[i].left.first + % node_attr_conflicts[i].left.second + % node_attr_conflicts[i].right.first + % node_attr_conflicts[i].right.second); + + for (size_t i = 0; i < orphaned_node_conflicts.size(); ++i) + W(F("orphaned node conflict on node %d, dead parent %d, name %s") + % orphaned_node_conflicts[i].nid + % orphaned_node_conflicts[i].parent_name.first + % orphaned_node_conflicts[i].parent_name.second); + + for (size_t i = 0; i < rename_target_conflicts.size(); ++i) + W(F("rename target conflict: nodes %d, %d, both want parent %d, name %s") + % rename_target_conflicts[i].nid1 + % rename_target_conflicts[i].nid2 + % rename_target_conflicts[i].parent_name.first + % rename_target_conflicts[i].parent_name.second); + + for (size_t i = 0; i < directory_loop_conflicts.size(); ++i) + W(F("directory loop conflict: node %d, wanted parent %d, name %s") + % directory_loop_conflicts[i].nid + % directory_loop_conflicts[i].parent_name.first + % directory_loop_conflicts[i].parent_name.second); +} + +void roster_merge_result::clear() { node_attr_conflicts.clear(); ============================================================ --- roster_merge.hh ed68adf1d012e2a3689168d7367bfd5bd3b7be20 +++ roster_merge.hh e9c290f799091e5ecb70e291daae0bff72df2d48 @@ -1,3 +1,4 @@ +// -*- mode: C++; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2 -*- #ifndef __ROSTER_MERGE_HH__ #define __ROSTER_MERGE_HH__ @@ -107,6 +108,9 @@ // this roster is sane if is_clean() returns true roster_t roster; bool is_clean(); + bool is_clean_except_for_content(); + void log_conflicts(); + void warn_non_content_conflicts(); void clear(); };