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: Stephen Leake
Subject: Re: [Monotone-devel] Updated Issue 209 - support drop/modified conflict
Date: Wed, 13 Jun 2012 08:39:58 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (windows-nt)

Markus Wanner <address@hidden> writes:

> On 06/09/2012 04:47 PM, Stephen Leake wrote:
>> So we need some way to tell monotone what our permanent decision is.
>
> Agreed.
> ...
> 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.

Yes.

>> 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.

Merging doesn't care about branches, but we are mostly talking about the
user interface to the merge process, and that does care about branches
for this use case (upstream vs local).

> 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.

Ok. Let's find another solution.

> 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.

I'd have to see a complete proposal for that. Sounds like a lot of work,
although possibly less than full suturing.

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

Ok, good.

>>> 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. 

With multiple files, potentially each with its own persisting conflict,
requiring independent persisting resolution.

> 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"

Ah, different resolutions depending on the branch being merged from.
That is more complicated. 

Is that a real use case? Let's not try to solve problems we don't
actually have.

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

One premise of the upstream/local use case is that we never merge from
local to upstream.

In any case, the user can delete or modify the attribute before any
specific merge; that should handle these other cases.

>>> 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.

Ah! Excellent point :).

>> Why a file name, instead of a node id? Ah, because the node doesn't exist.
>
> ..and because you cannot netsync node ids.

I was thinking we could convert the node id to a file name at the time
of sync, but there is no file with that node id in that revision.

I think that kills this idea.

>> 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 "..."
>
> ...

But we are still stuck with how to specify an attribute that says how to
handle a file that does not exist in the revision. A file name is not
adequate, since it could be renamed in the other branch. Renaming seems
likely in the upstream/local use case, since we are talking about a
persisting situation.

Hmm. We need a way to uniquely identify a file, so we can track renames.
'file <name> in revision <rev_id>' works; we can get a node id for that,
and then trace renames to the current revision being merged.

>> 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.

Yes, if people want to use this feature of mtn 1.1 locally, they must
also use a mtn 1.1 server. But they can use mtn 1.1 locally with a mtn
1.0 server, as long as they don't use this feature.

> 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).

I think that's too restrictive. 

I could see a global option that disables this by default, that people
can turn on if they are using a 1.1 server.

-- 
-- Stephe



reply via email to

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