> -----Original Message----- > From: s...@apache.org [mailto:s...@apache.org] > Sent: donderdag 14 augustus 2014 21:23 > To: comm...@subversion.apache.org > Subject: svn commit: r1618024 - in /subversion/trunk/subversion: > libsvn_client/merge.c libsvn_wc/tree_conflicts.c > > Author: stsp > Date: Thu Aug 14 19:22:30 2014 > New Revision: 1618024
At your request, a review of this change. I found a small issue around replacement detection, see inline. > > URL: http://svn.apache.org/r1618024 > Log: > For tree conflicts flagged during merges, record the proper node kinds > of the the versions of nodes involved in the conflict (the local working > copy node kind, the merge-left node kind, and the merge-right node kind). > > Before this change misleading node kind information was recorded., > For example, nodes which are deleted at the merge-right side of the > incoming > change would produce the following conflict information: > > Tree conflict: local file edit, incoming file delete or move upon merge > Source left: (file) ^/trunk/beta@1 > Source right: (file) ^/branch/beta@3 > > This is misleading since ^/branche/betas does not exist in r3 since it > was deleted in r2. With this change, the recorded node kind is 'none': > > Tree conflict: local file edit, incoming file delete or move upon merge > Source left: (file) ^/trunk/beta@1 > Source right: (none) ^/branch/beta@3 > > * subversion/libsvn_client/merge.c > (make_conflict_versions): Expect two node kinds, for the left and right > side of the merge source, instead of just one. > (merge_dir_baton_t, merge_file_baton_t): Add fields to store node kind > information for tree conflict victims: tree_conflict_local_node_kind, > tree_conflict_merge_left_node_kind, and > tree_conflict_merge_right_node_kind. > (record_tree_conflict): Add two node kind parameters for a total of three > and > rename the existing 'node_kind' parameter to 'local_node_kind'. > Create conflict versions with merge-left/merge-right node kinds. The local > node kind is used as the victim's node kind in the conflict description. > (mark_dir_edited, mark_file_edited): Propagate node kind information > stored > in the dir/file baton to record_tree_conflict(). > (merge_file_opened, merge_dir_opened): Fill in all three node kinds > involved > in the conflict. > (merge_file_changed): Pass merge-left/merge-right node kinds to the > make_conflict_versions() function. For file edits both are svn_node_file. > (merge_file_deleted, merge_dir_deleted): Pass all three node kinds > involved > in the conflict to record_tree_conflict(). > > * subversion/libsvn_wc/tree_conflicts.c > (svn_wc__serialize_conflict): 'none' is a legal node kind for tree > conflicts. > Adjust an assertion accordingly. > > Modified: > subversion/trunk/subversion/libsvn_client/merge.c > subversion/trunk/subversion/libsvn_wc/tree_conflicts.c > > Modified: subversion/trunk/subversion/libsvn_client/merge.c > URL: > http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/m > erge.c?rev=1618024&r1=1618023&r2=1618024&view=diff > ========================================================== > ==================== > --- subversion/trunk/subversion/libsvn_client/merge.c (original) > +++ subversion/trunk/subversion/libsvn_client/merge.c Thu Aug 14 19:22:30 > 2014 <snip> > @@ -1903,12 +1934,11 @@ merge_file_opened(void **new_file_baton, > && ((pdb && pdb->added) || fb->add_is_replace))) > { > svn_wc_notify_state_t obstr_state; > - svn_node_kind_t kind; > svn_boolean_t is_deleted; > > SVN_ERR(perform_obstruction_check(&obstr_state, &is_deleted, > NULL, > - &kind, NULL, > - merge_b, local_abspath, > + > &fb->tree_conflict_local_node_kind, > + NULL, merge_b, local_abspath, > scratch_pool)); > > if (obstr_state != svn_wc_notify_state_inapplicable) > @@ -1918,7 +1948,8 @@ merge_file_opened(void **new_file_baton, > fb->tree_conflict_reason = CONFLICT_REASON_SKIP; > fb->skip_reason = obstr_state; > } > - else if (kind != svn_node_none && !is_deleted) > + else if (fb->tree_conflict_local_node_kind != svn_node_none > + && !is_deleted) > { > /* Set a tree conflict */ > fb->shadowed = TRUE; > @@ -1997,7 +2028,8 @@ merge_file_changed(const char *relpath, > scratch_pool, scratch_pool)); > > SVN_ERR(make_conflict_versions(&left, &right, local_abspath, > - svn_node_file, &merge_b->merge_source, > merge_b- > >target, > + svn_node_file, svn_node_file, > + &merge_b->merge_source, merge_b->target, > scratch_pool, scratch_pool)); > > /* Do property merge now, if we are not going to perform a text merge */ > @@ -2422,6 +2454,10 @@ merge_file_deleted(const char *relpath, > */ > SVN_ERR(record_tree_conflict(merge_b, local_abspath, fb- > >parent_baton, > svn_node_file, > + svn_node_file, > + fb->add_is_replace > + ? svn_node_file > + : svn_node_none, At this place inside merge_file_deleted() we are still in the delete part of the merge, so fb->add_is_replace is aways FALSE. Only in the add that follows the delete we know that we have a replacement. (That is why the variable is called add_is_replace instead of delete_is_replace) > svn_wc_conflict_action_delete, > svn_wc_conflict_reason_edited, > NULL, TRUE, > @@ -2472,6 +2508,16 @@ merge_dir_opened(void **new_dir_baton, > > *new_dir_baton = db; > > + if (left_source) > + db->tree_conflict_merge_left_node_kind = svn_node_dir; > + else > + db->tree_conflict_merge_left_node_kind = svn_node_none; > + > + if (right_source) > + db->tree_conflict_merge_right_node_kind = svn_node_dir; > + else > + db->tree_conflict_merge_right_node_kind = svn_node_none; > + > if (pdb) > { > db->parent_baton = pdb; > @@ -2488,7 +2534,6 @@ merge_dir_opened(void **new_dir_baton, > else if (left_source != NULL) > { > /* Node is expected to be a directory. */ > - svn_node_kind_t kind; > svn_boolean_t is_deleted; > svn_boolean_t excluded; > svn_depth_t parent_depth; > @@ -2500,9 +2545,9 @@ merge_dir_opened(void **new_dir_baton, > { > svn_wc_notify_state_t obstr_state; > SVN_ERR(perform_obstruction_check(&obstr_state, &is_deleted, > &excluded, > - &kind, &parent_depth, > - merge_b, local_abspath, > - scratch_pool)); > + &db->tree_conflict_local_node_kind, > + &parent_depth, merge_b, > + local_abspath, scratch_pool)); > > if (obstr_state != svn_wc_notify_state_inapplicable) > { > @@ -2537,10 +2582,10 @@ merge_dir_opened(void **new_dir_baton, > } > > if (is_deleted) > - kind = svn_node_none; > + db->tree_conflict_local_node_kind = svn_node_none; > } > > - if (kind == svn_node_none) > + if (db->tree_conflict_local_node_kind == svn_node_none) > { > db->shadowed = TRUE; > > @@ -2576,7 +2621,7 @@ merge_dir_opened(void **new_dir_baton, > return SVN_NO_ERROR; > /* ### /avoid breaking tests */ > } > - else if (kind != svn_node_dir) > + else if (db->tree_conflict_local_node_kind != svn_node_dir) > { > db->shadowed = TRUE; > > @@ -2667,6 +2712,8 @@ merge_dir_opened(void **new_dir_baton, > > /* Update the tree conflict to store that this is a replace */ > SVN_ERR(record_tree_conflict(merge_b, local_abspath, pdb, > + old_tc->local_node_kind, > + svn_node_none, > svn_node_dir, > db->tree_conflict_action, > db->tree_conflict_reason, > @@ -2681,12 +2728,11 @@ merge_dir_opened(void **new_dir_baton, > && ((pdb && pdb->added) || db->add_is_replace))) > { > svn_wc_notify_state_t obstr_state; > - svn_node_kind_t kind; > svn_boolean_t is_deleted; > > SVN_ERR(perform_obstruction_check(&obstr_state, &is_deleted, > NULL, > - &kind, NULL, > - merge_b, local_abspath, > + > &db->tree_conflict_local_node_kind, > + NULL, merge_b, local_abspath, > scratch_pool)); > > /* In this case of adding a directory, we have an exception to the > @@ -2696,7 +2742,8 @@ merge_dir_opened(void **new_dir_baton, > * versioned but unexpectedly missing from disk, or is unversioned > * but obstructed by a node of the wrong kind. */ > if (obstr_state == svn_wc_notify_state_obstructed > - && (is_deleted || kind == svn_node_none)) > + && (is_deleted || > + db->tree_conflict_local_node_kind == svn_node_none)) > { > svn_node_kind_t disk_kind; > > @@ -2717,7 +2764,8 @@ merge_dir_opened(void **new_dir_baton, > db->tree_conflict_reason = CONFLICT_REASON_SKIP; > db->skip_reason = obstr_state; > } > - else if (kind != svn_node_none && !is_deleted) > + else if (db->tree_conflict_local_node_kind != svn_node_none > + && !is_deleted) > { > /* Set a tree conflict */ > db->shadowed = TRUE; > @@ -2796,6 +2844,8 @@ merge_dir_opened(void **new_dir_baton, > { > /* ### Should be atomic with svn_wc_add(4|_from_disk2)() */ > SVN_ERR(record_tree_conflict(merge_b, local_abspath, pdb, > + old_tc->local_node_kind, > + svn_node_none, > svn_node_dir, > db->tree_conflict_action, > db->tree_conflict_reason, > @@ -2864,7 +2914,8 @@ merge_dir_changed(const char *relpath, > svn_wc_notify_state_t prop_state; > > SVN_ERR(make_conflict_versions(&left, &right, local_abspath, > - svn_node_dir, &merge_b->merge_source, > + svn_node_dir, svn_node_dir, > + &merge_b->merge_source, > merge_b->target, > scratch_pool, scratch_pool)); > > @@ -3212,6 +3263,8 @@ merge_dir_deleted(const char *relpath, > */ > SVN_ERR(record_tree_conflict(merge_b, local_abspath, db- > >parent_baton, > svn_node_dir, > + svn_node_dir, > + svn_node_none, This is exactly the same case as discussed above for files. > svn_wc_conflict_action_delete, > svn_wc_conflict_reason_edited, > NULL, TRUE, > > Modified: subversion/trunk/subversion/libsvn_wc/tree_conflicts.c > URL: > http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/tree > _conflicts.c?rev=1618024&r1=1618023&r2=1618024&view=diff > ========================================================== > ==================== > --- subversion/trunk/subversion/libsvn_wc/tree_conflicts.c (original) > +++ subversion/trunk/subversion/libsvn_wc/tree_conflicts.c Thu Aug 14 > 19:22:30 2014 > @@ -367,7 +367,8 @@ svn_wc__serialize_conflict(svn_skel_t ** > > /* node_kind */ > SVN_ERR_ASSERT(conflict->local_node_kind == svn_node_dir > - || conflict->local_node_kind == svn_node_file); > + || conflict->local_node_kind == svn_node_file > + || conflict->local_node_kind == svn_node_none); > skel_prepend_enum(c_skel, node_kind_map, conflict->local_node_kind, > result_pool); > >