Status and overview of tree-conflicts work. Tree conflict handling spans the following areas: [DETECT] - detect tree conflicts during update/switch/merge [RECORD] - record them in the WC [DISPLAY] - display them (e.g. in "svn status") [COMMIT] - disallow commits while conflicts exist [RESOLVING] - help the user to resolve the conflict [RESOLVED] - enable the user to un-mark the conflict when resolved [DETECT] ======== Purpose: Determine whether each incoming change conflicts with the state of the WC receiving the change. If so, record the fact and ensure that sufficient information is preserved to enable the user to resolve the conflict. Allow the operation to continue on to process other items that are not affected by this conflict. Status: incomplete As far as is currently tested by tree_conflict_tests.py, the status is: Detection of file conflicts: complete Detection of directory conflicts: 2 cases incomplete: - test 8: update add onto add (this is not a primary use case) - test 14: merge del onto changed (this is a primary use case) Primary APIs: For update/switch: svn_delta_editor_t For merge: svn_wc_diff_callbacks3_t Implemented in: For update/switch: subversion/libsvn_wc/update_editor.c (caution: the same code is also used for checkout) For merge: subversion/libsvn_client/merge.c To do: * Fix test 14: merge deletes a changed dir. Needs to compare the dir currently in the target with the dir that was deleted from the merge-left source. If identical, allow the deletion. If not, conflict. * When raising a tree conflict on a dir victim, skip processing everything inside that dir. Check that files don't need similar "skip" handling, or are already getting it. * Check that a dir conflict on the root of an update/switch/merge is handled OK. It need not be handled the same as other dir conflicts, because there is no parent dir available. It just needs to fail in some reasonable way. * Pre-existing obstructions (status "~") or missing items ("!") should be detected first, before attempting to apply the change, and abort the operation. * Unversioned obstructions encountered while applying the change should be handled as a kind of tree conflict. (Given the pre-screening of obstructions to versioned items, this can only occur during add.) Behaviour no longer wanted: Merge: "skipped missing target '...'". As a general principle, I'm wondering if it is no longer acceptable for a merge to skip anything without leaving a persistent record of what it did and why. If the target to be modified by the merge is missing from the target WC in the sense of no longer being under version control, we should instead raise a tree conflict. (If it's missing due to a known and already recorded reason, such as a shallow WC, that might be a bit different.) [RECORD] ======== Purpose: A mechanism for recording, in the WC, what tree conflicts presently exist, and enough information to describe them to the user. Note: This is not the same as recording enough information in the WC to be able to resolve the conflict in any desired way without contacting the repository or source of the merge. For example, for a victim that is a directory, we might need to store or have access to both versions of the whole victim sub-tree. This problem comes under the [RESOLVING] section. Status: complete enough to use. Primary APIs: svn_wc_conflict_description_t /** * Read tree conflict descriptions from @a dir_entry. * Append pointers to newly allocated svn_wc_conflict_description_t * objects to the array pointed to by @a conflicts. * Do all allocations in @a pool. * * @since New in 1.6. */ svn_error_t * svn_wc_read_tree_conflicts_from_entry(apr_array_header_t *conflicts, const svn_wc_entry_t *dir_entry, apr_pool_t *pool); /** * Add a tree conflict to the directory entry belonging to @a adm_access. * Pass a description of the new tree conflict in @a conflict. * Do all allocations in @a pool. * * @since New in 1.6. */ svn_error_t * svn_wc_add_tree_conflict_data(svn_wc_conflict_description_t *conflict, svn_wc_adm_access_t *adm_access, apr_pool_t *pool); To do: Record enough information to be able to reconstruct the "old", "mine" and "theirs" versions of the item, and possibly also a complete local copy of them. Notes: Special case: The root of the WC is the victim of a tree conflict. (This can only happen with a merge, as there can be no tree change scheduled locally for an update to conflict with.) Problem: There is no parent directory in which to store the conflict info. Solution: Abort with an error, and don't change the WC. [DISPLAY] ========= Status: complete enough to use, but wants improvement. "svn info" mechanism complete but ugly "svn status" mechanism complete "svn up/sw/merge" (progress notifications) mechanism complete Primary APIs: "svn info" "svn status" "svn up/sw/merge" (progress notifications) To do: * Design: conceptually, do we want to see conflicts on the parent directory or on the victims? Due to what falls out of the early implementation, we were heading for a concept of resolving the parent directory... but I don't feel that's right. See also [RESOLVED]. * Clean up the "svn info" text: make it much less verbose. * Consider whether "svn st ITEM" should show conflict on victim ITEM. Notes: * Making the information available to be displayed is part of [DETECT]. [COMMIT] ======== Status: incomplete When parent and victim are included: complete? When only the parent is included: complete? When only the victim is included: incomplete Purpose: Disallow commits while conflicts exist in the items proposed for commit. When directory D has a tree conflict on one or more children, what does that mean for (a) a child that is a victim? (b) a child that is not a victim? (c) the directory D, when treated as non-recursively (depth 0)? Answer: (a) Each victim is in conflict and cannot be committed, even if the "conflict" status information is stored in the parent D. (b) Each non-victim child is fine and can be committed independently of its parent. (c) NOT SURE... Could work either way. To do: * Make commits fail when tree conflicts exist, even when the victim's parent is not part of the requested commit. [RESOLVING] =========== Purpose: 1. Provide metadata about what happened. - See [DISPLAY]. 2. Provide access to all data involved in the conflict. - Incomplete. 3. Enable the user to resolve the conflict by creating a desired working version (including the desired scheduling). - Is possible. No assistance is provided. Needs evaluation. - Not sure what's needed here. 4. Enable the user to mark the conflict as resolved. - Incomplete. Design: * Keep all of the merge-left + merge-right + working data locally. (Ideally, by analogy with text conflicts. May not be necessary for a first pass.) * Ensure user has suitable and obvious commands for resolving. - may include merge, delete, copy, etc. - may require hints or documentation on what commands should be used. * Interactive resolution should recognise tree conflicts and provide basic and common resolutions. * Ability to use "svn resolved" to say "the conflict on victim V is resolved". * Ability to use "svn resolve --accept=..." to say "resolve the conflict on victim V by choosing ...". Status: incomplete * Mark as resolved, by command: the basic "svn resolved PARENT" works to some extent, but needs attention. Issue #3145 * Mark as resolved, interactively: not started. Issue #3144 To do: * Design: conceptually, do we want to "resolve" the parent directory or the victims? Due to what falls out of the early implementation, we were heading for a concept of resolving the parent directory... but I don't feel that's right. See also [DISPLAY]. * Ensure the basic "resolved"/"resolve --accept=" works on a whole directory. * Allow individual victims to be marked as "resolved".