monotone-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Monotone-devel] Updated Issue 209 - support drop/modified conflict


From: Markus Wanner
Subject: Re: [Monotone-devel] Updated Issue 209 - support drop/modified conflict
Date: Mon, 11 Jun 2012 20:21:16 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0.4) Gecko/20120510 Icedove/10.0.4

Hi,

On 06/09/2012 04:47 PM, Stephen Leake wrote:
> So we need some way to tell monotone what our permanent decision is.

Agreed.

>>> But it's easier to use directories and build directives to achieve that
>>> result, so I'm back to thinking this is not a valid use case.
>>
>> Here, you need to elaborate. How can directories and build directives be
>> a replacement for a thing as simple as a file deletion.
> 
> See the current monotone system for win32 and unix; much simpler than
> dealing with multiple projects.

Uh.. you were the one who proposed to split into multiple projects in
that use case.

Anyway, we seem to agree that there *is* a use case for wanting to
permanently delete a file, disregarding concurrent modifications to it
on other "branches" of the revision tree.

> So you need a 'pure' upstream branch, an 'annotated' upstream branch
> (with the delete attributes), and a 'local' branch. Then the update
> process would be:

So, taking branches out of the equation (merging doesn't care about
branch certs), that effectively means adding a helper revision to store
the merge preferences.

I dislike it being on the upstream side, which adds quite a bit of
complexity compared to being able to store it in the line of revisions
that performed the delete. But well...

> An attribute would eliminate the mtn 1.0 warning, so it would be a
> better solution to your use case.

It would suppress the warning, which is helpful. However, I doubt
somewhat that's worth a separate "annotated branch". Too much work for
the user to maintain that. Too much that can go wrong.

>>> Note that file suture is no help in this case.
>>
>> Agreed.
>>
>> Proper file resurrection could be, though. 
> 
> I don't see that.

By "proper file resurrection" I mean approaches like tracking file
liveliness, which could refer to the original node id for "undeleting"
the file.

With such a thing in place, you don't need to suture anything, because
it's just one node id. No matter how many renames and liveness changes.

>> At least when thinking of deleted files as "moved to some unreachable
>> place, contents intact". There once was such a proposal for tracking
>> (and properly merging) a files liveliness.
> 
> That makes sense. CVS has an internal Attic directory for deleted files.

Well, it only makes sense for the analogy of "unlinking", "throwing
away" user model, as opposed to "truncating" or "destroying" before
dropping. That's because modifications don't conflict with drops in that
case (at least not without changing that part of the merge code,
compared to monotone-1.0).

>> I read through your suture documentation and noticed you trapped into
>> the same fallacy of trying to identify files by their file names. 
> 
> That was not the intent. I'm sure it uses file names when trying to
> resolve conflicts.

Huh? "Using file names when trying to resolve conflicts" is what I'm
saying is the wrong thing to do. Only node ids have a chance of reliably
referencing what the user considers to be the same file across revisions
(in the face of possible renames).

>> IMO sutures must not depend on file names. Instead, it should well be
>> possible to suture two files with different paths.
> 
> That was one use case covered in the sutures doc.

Okay, good.

> I don't see how that patch would be useful. Let's put this in a use
> case:
> 
>      A
>     / \
>    M1  D    -- D change list includes patch to zero length, and delete
>    | \ |
>    M2  P    -- how is that information used here?
>     \ /
>      Q      -- or here?
> 
> 
> If the node is just gone in D and P, how do we notice the patch?

Oh, right, that doesn't work. Sorry, my brain fart. Thanks for putting
that straight.

> Right. So a general 'conflict resolution' attribute might be appropriate.

Agreed.

>> Complicating things, I don't think it's a file specific decision. Maybe
>> there exist use cases where you want to ignore modifications from the
>> parent project, but at least want to see a warning, or even better a
>> real conflict, if somebody else from your project tried to modify the
>> file "before" seeing your deletion.
> 
> I don't follow this. It's still per file. Although, for the win32/unix
> example, it could be per directory. 

We were assuming a single upstream branch. However, there can well be
multiple different branches propagated from.

I was trying to say that it might not suffice to store:

  for file "foo", prefer dropping, in case the drop conflicts
  against any modification.

Instead, I was thinking about something like:

  for file "foo", prefer dropping, in case the drop conflicts
  with a modification from branch "upstream"

This would allow modifications from other branches (including the target
branch itself, for example) to still raise a drop/modify conflict.

(Of course, the meaning might need to get turned around in case we store
such a thing in an annotated upstream branch instead of the branch that
drops the file.)

>> My gut feeling is that such decisions should be stored per branch. I.e.
>> assuming branches "parent" and "child", a file "foo" existing in
>> "parent" and propagated to "child", but then deleted there. Once a
>> conflict with a modification of "foo" in "parent" arises, the user can
>> choose to:
>>
>>  - keep ignoring modifications from branch "parent" to file "foo"
>>  - continue to get conflicts for mods from branch "parent" to file
>>  "foo"
> 
> But what about file "bar"? There could easily be some files that want
> one resolution, others that want another.

One attribute per file is the minimum required granularity, yes. I'm
advocating one attribute per (file * branch). However, the requirement
of an annotate branch kind of solves this already, because you'd have to
create such an annotated branch per "upstream" you propagate from.

(Also note that "branch" cannot really mean branch certs, because merges
simply don't care about certs. And it could all happen within revisions
tagged by the same branch cert. However, the reasoning applies just as
well to "branches" of the revision tree.)

> Why a file name, instead of a node id? Ah, because the node doesn't exist.

..and because you cannot netsync node ids.

> But actually, that's ok; this information is only used when merging with
> revs where that node _does_ exist. And in that case, a node id is much
> better; it allows for renames.

No, that won't work. Node ids are only ever useful within the single
database of their origin. They don't match across databases. (I don't
even think they survive a recreation of the rosters).

> Storing on the root node does eliminate the requirement for the
> annotated branch. 

Yeah, I dislike that option as well. Maybe new "revision" attributes? As
a generally usable feature?

> On the other hand, it complicates renaming the root node.
> 
> We need a place to store information in revision A that describes what
> to do when merging with revision B that has nodes that don't exist in A.
> There's no reason to attach that information to the root node;

Agreed.

I'd simply use the existing "attributes" mechanism and allow a revision
to have attributes, just like nodes do. In terms of a basic_io
representation of a manifest, this could look like:

format_version "1"

attr "sample_key" "value"
attr "second_key" "true"

dir ""

file    "foo"
content "..."

...

> Implementing that change does not require a flag day; I had the same
> problem in the sutures branch, and someone suggested a nifty way to
> solve it. You have a predicate that decides if any revision needs the
> 'rev annotations' structure (in this case, that's simple; "did the user
> specify any?"). If the predicate returns false, the structure is not
> stored with the rev; that means all revs prior to 1.0 don't change
> structure (or, more importantly, rev id), and most revs post 1.0 also
> wont have the rev annotations structure.

Well, attributes already work that way. No "attr" line is ever stored
for files that don't have any. However, it doesn't help the case of
monotone-1.0 (and older) not being able to parse a revision that
*contains* a new struct/attribute/unknown thing.

IMO the best thing we can do is to add the functionality, but only
enable it, when we can be pretty sure nobody is using 1.0 anymore
(either by time or by announcing a flag day).

Regards

Markus Wanner



reply via email to

[Prev in Thread] Current Thread [Next in Thread]