[Extension] Dirty hack of 'shelve' and 'unshelve' command

Aaron Bentley aaron.bentley at utoronto.ca
Thu May 19 14:59:22 BST 2005


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Martin Pool wrote:
| On 19 May 2005, Michael Ellerman <michael at ellerman.id.au> wrote:
|>Basically you can run 'bzr shelve' and it will prompt you which hunks
you want
|>to 'place on the shelf', ie. put away for the moment. You can then
make sure
|>your tree still builds, run any tests, and then use the regular 'bzr
commit'.
|
|
| That sounds interesting; this is like tla's undo/redo commands, except
| that they don't let you choose hunks (and are prone to break when you
| need them most.)

I'm definitely a fan of this approach, in fact I have other code that
implements selected-hunk-undo for Arch in my Fai tool.  (But it's
heavily Arch-based, so it probably wouldn't have been a useful starting
point.)

Martin had some hesitations about my implementation last time we
discussed it.  It came down to the fact that hunk-level granularity
isn't always appropriate.

What's great about hunk granularity is it allows you to remove a change
completely, and have no spurious changes to whitespace, syntax, etc.
What sucks about hunk granularity is it can be too coarse, and not allow
you to remove only one of a set of two overlapping changes.

I spent some time thinking about how to get finer granularity, but it
didn't really go anywhere.  Today, I'm thinking: use a text editor,
silly! (especially vimdiff)(hey, we need better vimdiff support)

So here's a proposal.  The interface for shelve can stay the same,
though an option to skip manual hunk selection might be nice.  For
unshelve, I'd like to add the guarantee that no matter what manual
changes you make to your tree between shelve and unshelve, 'unshelve'
will restore the tree to the state it was in when you issued the
'shelve' command.  This means if 'per-hunk' will do the job, you can use
it.  But if you need to touch it up with an editor, you can do that,
too.  So it won't fail just when you need it most.

Also, I think it would be cool if commit automatically invoked unshelf
after committing, so the user doesn't forget.

Shelf implementation:
1. take a snapshot of the working tree (don't worry about space yet)
2. generate a patch from basis to working tree
3. remove any hunks the user wants to keep in the tree
4. reverse-apply the patch

Unshelf implementation:
1. use 'merge' to convert the working tree into the snapshot
(i.e. "merge $SNAPSHOT .")

Storing the snapshot efficiently

a) The simplest way to take a snapshot is to copy all the files.  This
is suboptimal for kernel-sized trees.

b) We could also make a hard-linked copy, but that:
~  1. would be too unixy
~  2. would risk corruption

c) We could also make a diff of the basis tree and store that.  This
doesn't solve everything, because we still need to recreate the files at
some point (unless we get fancy), in order to do the merge.  Also, you
lose renames, etc.

d) We could make a revision that is not part of the revision history.
This would bloat the store, but probably not severely, and it's
proportional to the number of files changed, which is a desirable
property.  Removing unneeded revisions is easy.  Removing unneeded
text-ids is tricky, because we need to do reference-counting.  Or maybe
we could segregate the temporary ids somehow.

e) We could invent a hybrid tree type: any file with contents uses those
contents.  Any missing file uses the basis-tree contents.

f) Inside the branch, we could make a hard-linked copy of the branch,
itself.  We take the snapshot as a revision of the copy, and then throw
the copy away afterward.  This is too unixy and probably too slow, but
doesn't risk corruption.

I think d) is probably the best option.

What do you guys think?  Is this all sleep-deprived crack?

Aaron

P.S. my patch parser is fairly strict about the input it will accept, so
it may behave badly if the user specifies their own diff.  (Currently,
even diff -u -p will give it fits)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFCjJu60F+nu1YWqI0RAvXOAJ4olwQiNL1cPrfocppzfjqSEMp6eACfRXfs
kmKANECMZuwqkwB+n50JaI0=
=s2fB
-----END PGP SIGNATURE-----




More information about the bazaar mailing list