On Sat, Nov 23, 2024 at 5:26 AM Timofei Zhakov <t...@chemodax.net> wrote:
> Hi! > > I am using patches frequently, however, 'svn diff' and 'svn patch' > commands currently have several limitations: > > 1. They do not track tree changes (like copies and moves) > 2. Binary file modifications are not tracked in plain-text patches > 3. Unidiff patches use 2-way merge instead of 3-way merge, so in case > of conflict, the patch/hunk/file/directory will be rejected. > > The ideas I would suggest to solve these problems will be explained below: > > 1. Add `svn diff --xpatch` for creating binary patches. > 2. Add `svn merge --xpatch FILENAME` for applying them onto a working copy. > 3. Optionally, we can also implement several commands to browse xpatch > files using the command-line interface. For example, previewing them > as unidiff or showing the diff-summary. > > In my opinion, the best way to save the changes is to write them to an > XML file/stream (btw, this is why I would name this feature as > "[x]patch"). I will explain the format in detail soon. > > Recently, I was doing research about how the merge works and about the > ways to reuse its implementation for creating some kind of binary > patches. > > It is currently implemented using a svn_diff_tree_processor, which > applies the differences, resolves conflicts. I.e. it edits the working > copy and resolves the conflict cases. > > However, there are some technical limitations in the current merge > implementation, which prohibit it to be used outside of the merge > command, but the merge implementation can be split onto two files; the > merge itself and the "apply" tree-processor. > > I have a prototype of factoring-out the "apply" tree-processor from > merge. In general it seems to be working with most test cases passing. > Additionally, as you might already have seen, I committed some > improvements a while ago, which are related to this. > > I am planning to do the following to implement binary patches: > > 1. Factor-out "apply" tree-processor from merge.c to another file of > private client API. > 2. Do some preparations for xpatching in the 'trunk'. > 3. Create a branch for the xpatch feature. > 4. Implement writer and parser for xpatch files in the branch. > 5. Add`svn diff -–xpatch` and `svn merge -–xpatch` commands by > connecting diff driver, xpatch file routines, and "apply" > tree-processor together in the same branch. > > I have a working prototype of xpatch file writer and parser, but it > seems to be far from ready. > > -- > Timofei Zhakov > Much of this sounds good so far. I have quite a few times been frustrated by the limitations of the current diff and patch functionality, as I'm sure others have been as well. I'll wait to hear your thoughts about your proposed XML format before I express an opinion about that part of it. Meanwhile I'd like to point out that much of what you discuss above reminds me of issues that were discussed when shelving was implemented a few years ago. I think it will be extremely valuable to look into this: Shelving was released as an 'experimental' feature in 1.10 and then subsequently improved in the following releases. There were in total 3 versions of shelving implemented in different ways. There are 2 different implementations available now but hidden behind an environment variable. The original, referred to as shelving v1, was basically a convenience wrapper around 'svn diff' and 'svn patch' with exactly the four limitations you describe for the current patch format and its apply logic. Nevertheless it was useful and there was positive feedback from users who tried it. I think this version doesn't exist in the codebase anymore; at least it isn't accessible through the command line client. The ultimate desire was to be able to shelve any kind of committable changes, whether file, property, or tree changes, and to be able to unshelve them later, with full merge and conflict resolution possible. Then, it would also be possible to have a sequence of shelved changes (checkpointing), functioning somewhat like a local branch. Shelving v2 and v3 are both attempts to overcome the diff/patch limitations by not using patch files. Shelving v2 is "better" than v1 in that v2 can handle binary files and a few more things, but not tree changes. It's not better in terms of storage space as it stores a full copy of the before and after states of each changed file, since those are needed for the three-way merge to overcome the same issues you talked about. Shelving v3 is even "better" than v2 in that (modulo some bugs) it can shelve and unshelve any kind of committable changes. It uses the same delta editor logic that is used for transferring changes between the repository and working copy. This version in its current state uses potentially a lot of unnecessary storage space because it creates a full working copy base per shelve; I'll call it a "shadow" WC. I remember people complaining about that. The intention was to eventually reduce the storage space usage by using (the equivalent of) '--set-depth' to only store needed parts of that shadow WC tree, but work on shelving and checkpointing stopped around that time. One of the biggest ways that patches are used is precisely for saving changes that aren't ready to be committed (shelving), which may be a sequence of such changes (checkpointing), and sharing with others (e.g., by email), so I think you can see how these subjects are related. I think it will be valuable to read the CWIKI page: Shelving v1/v2/v3 Development Review: https://cwiki.apache.org/confluence/x/MxbcC and the 1.14 release notes have more information as well as links to additional CWIKI pages: https://subversion.apache.org/docs/release-notes/1.14.html#shelving Would your proposed new feature make it possible to implement shelving that has the advantages of v3 (can shelve/unshelve any committable changes, with proper merging and conflict resolution) while using minimal storage space by storing its data somewhat like v1 (in 'xpatch' files)? Would it make sense to do so? Cheers, Nathan