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

Reply via email to