[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Monotone-devel] use case
From: |
graydon hoare |
Subject: |
Re: [Monotone-devel] use case |
Date: |
22 Jul 2003 23:47:47 -0400 |
User-agent: |
Gnus/5.09 (Gnus v5.9.0) Emacs/21.2 |
Tom Tromey <address@hidden> writes:
> The ideal situation would be that if somebody writes a Classpath
> change, and we like it for libgcj, a libgcj could simply sign it and
> it would appear in the libgcj tree. Even more ideally, the same could
> be done for changes to files that have a required divergence --
> monotone would try to merge the changes into the destination tree.
some of that can happen magically, but possibly not all, and certainly
not yet. maybe we can wedge it into place. what happens currently is
this:
1. when the classpath person makes some edit and commits it to
foo/bar.java, monotone scans the current manifest and 'work file'
(a list of adds and deletes), notices that there's no adds or
deletes but there is a change in SHA1 for the foo/bar.java entry,
say from id1 -> id2. it'll save the new tree state and queue up
a bunch of packets for transmission:
- an fdelta packet describing how to build id2 from id1
(which consists of whatever edit the user made)
- an mdelta packet describing the change to the manifest
(which consists of changing id1 -> id2 in the manifest)
- an mcert packet describing the ancestry relationship between
the new manifest and the old one.
- an mcert packet asserting that the new manifest is in the
classpath branch
- an mcert packet asserting that address@hidden was the
author of the new manifest
- an mcert packet asserting that the new manifest was written
on the current date
- an mcert packet associating a changelog with the new manifest
2. when the gcj person receives those 7 packets, they'll have a bunch
of options as to what to do. the storage system will learn how to
construct id2 from id1, and how to construct the new manifest from
the old one, but it will not have associated these new versions
with the gcj branch (presumably it has a different name) so there
will be no attempted merging.
3. the most obvious thing to do if you want the new version id2 of the
file to show up in the gcj branch under some new pathname
baz/bar.java is to cd to a checked out version of the gcj tree and
type:
$ monotone cat file id2 >baz/bar.java
$ monotone commit
of course, that's a bit tedious and error prone, not much better
than CVS really; it would be nicer if monotone could associate the
files "naturally"; I can think of two things we'd need to add --
nothing fundamentally novel -- to support it.
first, we'd need to really support "union" branches, or more
generally branches defined by a lua hook function. this will
produce the correct manifest merge obligation between the gcj
versions and the classpath versions; it's a feature I'm entirely
planning to add, just haven't gotten around to.
second, we'd need to add some means of extending the manifest merge
heuristic. keep in mind that monotone starts merges up at the
manifest level, and only bothers with byte-level merges of file
contents when it thinks there's been conflicting changes to the
"same" file. if changes happen to different files, or files are
added/deleted, the relevant manifest entries are merged set-wise
at the manifest level, and there's no fiddling with byte merging.
so we'd need some way of telling the manifest merger "look, these
files have different names but you have to consider them the same
for the sake of performing this merge".
we could do that either with a lua hook or a special type of fcert,
or some combination thereof. I haven't thought deeply about the
implications of either, but I don't think it'll break the design
much in any case.
> I didn't see any info in the FAQ or the manual about renaming files.
> It seems to me that for monotone to recognize a rename, you'd have to
> do a rename as a separate commit, before making any changes to the
> renamed file. But this turns out to be an unusual approach... for
> instance, in Java it may result in an unbuildable tree (if you are
> refactoring).
for it to *recognize* a rename, yeah. but failure to recognize a
rename is not the worst possible fate; it just degrades into a
delete+add, which is operationally quite similar. here are the two
scenarios:
1. rename recognized: monotone transmits an mdelta packet describing
the rename, plus an fdelta packet containing any changes to the
file contents.
2. rename not recognized: monotone transmits an mdelta packet
describing the rename, plus an fdata packet containing the entire
contents of the "new" file.
more data is sent in the second case, but it's not fatal by any
means. and the two cases can coexist; multiple reconstruction paths in
the database are harmless, and packet receipt is idempotent. anyways,
I suspect the solution to "how to associate 2 different paths with a
file" will make the recognizing more likely anyways.
the easiest thing is to add a work file entry called 'rename' (in
addition to 'add' and 'delete') which gives the commit routine a hint
that it should queue the fdelta packet, not the fdata one. that I can
have working in very little time, but you'd need to explicitly
"monotone rename foo bar" to get it to record such a thing in the work
file. there's only so much we can infer :)
> One idea for the classpath scenario would be to change the build set
> up a bit. We could have a directory, gcc/classpath, which is a branch
> of the classpath repository (checked out in the gcc source tree).
> That way we wouldn't have to worry about the renaming problem.
yeah, something like that is certainly the easiest, but not always
best; I don't mind batting this idea around a bit and seeing if any
good improvements fall out.
-graydon