|  | -*- text -*- | 
|  |  | 
|  | This file is a scratch pad for working out current and expected | 
|  | behaviors for various tree-conflict situations.  It may be considered | 
|  | unfinished at best -- scatterbrained is more like it. | 
|  |  | 
|  | NOTE:  As Subversion does not actually have real 'move' functionality, | 
|  | please try to express move-ish use-cases in terms of deletes and | 
|  | adds-with-history (copies). | 
|  |  | 
|  |  | 
|  | =================== | 
|  | BACKGROUND THOUGHTS | 
|  | =================== | 
|  |  | 
|  | This whole thing is, I think, basically about ensuring that the | 
|  | history of a file isn't allowed to fork and then suffer the | 
|  | unceremonious death of one of the two resulting lines of history when | 
|  | the streams are rejoined. | 
|  |  | 
|  | When doing an update, we don't have to worry that the working copy | 
|  | base file has deviated from the line of history that's being deleted | 
|  | -- other processes prevent this from happening (you can't commit | 
|  | to a deleted file; you can't delete a file that's been modified since | 
|  | you last updated).  But you do have to worry about local mods, which | 
|  | are a "different path" in the file's line of history than the path | 
|  | that led to its deletion. | 
|  |  | 
|  | When doing a merge, though, stuff gets really complicated.  Now you | 
|  | have an arbitrary line of history as the source which you are trying to | 
|  | "lay down" overtop the line of history of the stuff in your | 
|  | repository, and the goal remains the same: don't assume that | 
|  | deviations in those lines should be resolved by disregarding one side | 
|  | of the fork or the other -- that's ungood.  In the best case you are | 
|  | trying to append segments of one fork in the history road to the | 
|  | other, and hopefully you don't leave gaps or cause deviations.  In the | 
|  | worst case, though, you're dealing with a "line of history" that's | 
|  | made up on-the-fly (due to your left- and right-side merge sources | 
|  | being unrelated, or only related as second cousins twice removed, or | 
|  | something).  This is where the "merge = diff + patch" paradigm really | 
|  | starts to show its weaknesses (and maybe, just maybe, should have been | 
|  | a use-case that Subversion disallowed ... if only it weren't so darned | 
|  | useful for vendor branches...). | 
|  |  | 
|  | Anyway, there appear to me to be some pretty clear goals: | 
|  |  | 
|  | * Conflicting operations should be marked as such and require user | 
|  | interaction to resolve | 
|  |  | 
|  | * In such a conflicting situation, users would like to be able to | 
|  | easily do the following: | 
|  |  | 
|  | - determine what local mods they've made | 
|  | - apply those mods elsewhere if necessary | 
|  | - determine what mods conflict with the ones with they | 
|  | - overrule the conflict and make their changes anyway | 
|  |  | 
|  | * Tree conflicts appear to be something special, and should be | 
|  | annotated as such. | 
|  |  | 
|  | So a tree conflict is really just a conflict on the content of a | 
|  | directory, much like a regular conflict is on the content of a file, | 
|  | and a prop conflict is on the properties of a file or directory.  To | 
|  | annotate a tree conflict, we recycle the 'conflict-new' conflict file | 
|  | slot pointing to a dropped file named dir_contents.trej.  It's | 
|  | contents can note the details of the tree conflict.  [### TODO: Do we | 
|  | need to be able to mark files as tree-conflicted, too?] | 
|  |  | 
|  |  | 
|  | =================== | 
|  | SCENARIO PLAYGROUND | 
|  | =================== | 
|  |  | 
|  | 'svn update' pulls file deletion atop file with local text mods | 
|  |  | 
|  | NOW:  File is silently unversioned. | 
|  |  | 
|  | NEW:  File is marked as added-with-history (as of the revision | 
|  | previously in the working copy), and placed into a state of | 
|  | conflict.  There are no conflict markers, but the .trej file | 
|  | notes that our file was deleted in the repository.  User can | 
|  | see mods with 'svn diff'; revert still works; resolved+commit | 
|  | undoes the deletion and commits the users's mods. | 
|  |  | 
|  | 'svn update' pulls text mods onto schedule-delete file | 
|  |  | 
|  | NOW:  Text mods are silently merged into file's text-base and file | 
|  | remains scheduled for deletion. | 
|  |  | 
|  | NEW:  File remains scheduled for deletion, text-base is up-to-date, | 
|  | but file is marked as conflict, and .trej file notes that | 
|  | the file was modified in the repository. | 
|  |  | 
|  | QUESTION: Should .trej file contain the diff of those mods | 
|  | from the repository? | 
|  |  | 
|  | 'svn update' pulls dir deletion atop dir containing deep text mods | 
|  |  | 
|  | NOW:  Directory is removed save for modified files (left | 
|  | unversioned). | 
|  |  | 
|  | NEW:  Modified files are marked as added-with-history (as of their | 
|  | working copy revisions), placed into a state of conflict, with | 
|  | .trej files noting the deletion of the parent directory. | 
|  | Intermediate directories are marked as added (no history) and | 
|  | in conflict, with their .trej files noting the deletion of the | 
|  | directory. | 
|  |  | 
|  | 'svn update' pulls file replacement atop modified file | 
|  |  | 
|  | NOW:  Behaves as a two-step action: delete over modified file (see | 
|  | above), then file add over existing file (which is obstructed | 
|  | unless --force is provided. | 
|  |  | 
|  | NEW:  If the 'delete' step goes as recommended above, we'll wind up | 
|  | in a state of conflict already with a schedule-added file. | 
|  | Once the 'add' step hits, the operation will be obstructed | 
|  | even if --force is provided. | 
|  |  | 
|  | QUESTION:  Is this desirable?  What's the final state of the | 
|  | file after the failed update?  How do the recovery options | 
|  | play out from here?  For example, we wouldn't want the file | 
|  | scheduled for add-with-history because that commit can't | 
|  | succeed (another file already exists in the repository at | 
|  | that location). | 
|  |  | 
|  | 'svn update' pulls dir replacement atop deep-modified directory | 
|  |  | 
|  | 'svn update' pulls file-to-dir replacement atop modified file | 
|  |  | 
|  | NOW:  Behaves as a two-step action: delete over modified file (see | 
|  | above), then directory add over existing file (which is | 
|  | disallowed, even if --force is supplied). | 
|  |  | 
|  | NEW: | 
|  |  | 
|  | 'svn update' pulls dir-to-file replacement atop deep-modified directory | 
|  |  | 
|  | NOW:  Behaves as a two-step action: delete over deep-modified | 
|  | directory (see above), then file add over existing directory | 
|  | left over from delete step (which fails). | 
|  |  | 
|  | NEW: | 
|  |  | 
|  | 'svn merge' pulls file deletion | 
|  |  | 
|  | NOW:  If there's nothing at the target location to delete, the | 
|  | target is "skipped" (?); otherwise the target is removed from | 
|  | version control and, if not locally modified, deleted. | 
|  |  | 
|  | NEW:  All file deletions that would affect a local file and that come | 
|  | via merge get sanity-checked, with the client pulling the | 
|  | left-side source version of the file down and comparing its | 
|  | contents with the to-be-deleted working file.  If they are | 
|  | equivalent and there are no local mods to the file, it is | 
|  | removed from version control.  Otherwise, we have two sets of | 
|  | data we'd like to keep easy track of:  diffs between | 
|  | deleted-source and wc base file, and diffs between wc base and | 
|  | wc working files. | 
|  | NOTE:  Need more thinkin' 'round these parts... | 
|  |  | 
|  | 'svn merge' pulls file modification atop schedule-delete file | 
|  |  | 
|  | NOW:  "Skipped missing target" message. | 
|  |  | 
|  | NEW:  File remains scheduled for deletion, but working file is | 
|  | restored (if missing), marked as conflicted, and contents | 
|  | carry conflict info. | 
|  |  | 
|  | 'svn merge' pulls file modification atop missing file | 
|  |  | 
|  | NOW:  "Skipped missing target" message. | 
|  |  | 
|  | NEW: | 
|  |  | 
|  | 'svn merge' pulls file modification atop added file | 
|  |  | 
|  | NOW:  Conflict! | 
|  |  | 
|  | NEW:  Conflict! |