[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: allowing multiple conflicts in storage

From: Julian Foad <julian.foad_at_wandisco.com>
Date: Wed, 31 Mar 2010 13:44:23 +0100

On Tue, 2010-03-30, Stefan Sperling wrote:
> On Tue, Mar 30, 2010 at 05:56:54PM +0100, Julian Foad wrote:
> >
> > > Conflict meta data storage in wc-ng
> > > ===================================
[...]
I'm putting the last paragraph first for clarity.

> > I don't think
> > it is right to call "patch conflict" in the same space as those others.
> > A patch is a potential *source* of the change that conflicts, not a kind
> > of conflict.
>
> Well, I think the terminology has misled you.
> Maybe we should just toss that name and call it "reject conflict" instead.

Ah, yes, you've got it. That would help.

> I guess calling it "patch conflict" is confusing because "patch" is also
> the name of an operation. An operation always uses potential sources of
> conflicts (be it a delta to be merged, a property to be updated,
> or a patch to be applied). But that is not why we need this new conflict
> type. We need it because 'svn patch' added a new type of conflict that
> didn't exist before. [...]

It added a new way of recording a text conflict; I find it confusing to
call that a new "type of conflict".

We need to clearly distinguish the source of the incoming change from
the description of which part(s) of the node is/are affected by this
conflict. For example, a patch will (later) be able to make changes to
properties and to tree structure. In that sense, a patch file is a
source of changes (and not just the name of an operation), and we need a
way to refer to this source of changes that is independent from saying
"this conflict affects the file's text" versus "this conflict affects
the node's properties" versus "this conflict affects the tree
structure".

The Source of the Incoming Change
=================================

I suggest something like (? means an optional field):

  * A diff between nodes that have a location in a repository.

      left=(repo, rev, relpath, sha1?)
      right=(repo, rev, relpath, sha1?)

      # This source description is normally from merge/up/sw.
      # Full texts are (at least in principle) available.

  * A Patch File

      patch-file=(path, (info to identify which part of the
                         patch file applies to this node - e.g. byte
                         offsets or other info)?)
      reported-left=(repo?, rev?, relpath?)
      reported-right=(repo?, rev?, relpath?)

      # This source description is normally from operation 'patch'.
      # The reported-{left,right} are taken from info in the patch
      # file if available: e.g. from "+++ foo (r1000)" we can fill
      # in at least 'rev' and maybe 'relpath'. These cannot be
      # considered trustworthy even when given, as patch files can
      # be constructed and edited at will.

  * A diff between nodes that don't have a repository.
      # e.g. a merge from a diff between two locally-modified WCs.
      # We have no need of this yet (not supported) but we should
      # expect to support this kind of source of change some time.

A Change Affects the Whole Node
===============================

It is important to record the whole-node source of the change, as far as
possible, even when only one property conflicts, because I want to be
able to see what the other properties and text were on {left, right,
mine} to help me resolve the conflict. So we must not think of "a
property conflict" as being a fundamental thing: the fundamental thing
is "a change to this node conflicts with another change to this node".
The assumption that all properties are independent from each other and
independent from the text is a high-level approximation which the client
makes, to be more convenient in simple cases, but not a fundamental
truth, and we must not tie the conflict storage design to only
supporting this assumption.

In the same way, when we record a tree conflict, we want to record the
{left, right, mine} versions of the whole node. We don't have the
infrastructure to do this yet - we don't have a pristine store for sets
of properties, let alone for directory trees - but we could do in
principle and I hope we will do in practice one day.

The Part(s) of the Node Affected By The Change
==============================================

Briefly: the WC probably needs to know only "this node is in conflict"
or perhaps tree-conflict versus content-conflict, and no more detail
than that. By "know" I mean what the WC layer itself needs to
understand and use. It needs to be able to *supply* much more detail,
of course, to the client layer, but that can (and should) be in a blob
whose content is opaque to libsvn_wc. Layering is Good (unless the
layers are too many, too thin; but the WC layer can hardly be accused of
that).

So I think it IS important to have a common part of the info that
libsvn_wc understands itself, and a detailed part that libsvn_wc simply
reports to libsvn_client and which libsvn_client composes and
decomposes. Of course this means that libsvn_client has to be
responsible for making, reverting and resolving individual prop changes
and file text changes, and then calling libsvn_wc with updated conflict
info, rather than calling a WC function that does both the change and
updates the conflict info. Is that sane? Yes, I believe so. Is it
easy to get there from here? Maybe not too bad: the present libsvn_wc
"revert the node"/"resolve the node" functions can simply set the whole
conflict info to nil without needing to know the details.

> > > There are five types of conflicts (text conflicts, property conflicts,
> > > tree conflicts, patch conflicts, and obstructions).
> >
> > Whoa. A patch can cause a text conflict
>
> No. It cannot cause a text conflict. It causes a "reject" instead.

A reject is one way to record that some text change could not be applied
because it did not match the text found in the target file. That is
logically a text conflict, but recorded in a different way, and with
less information about which lines of text go where. It is certainly a
conflict of text rather than of properties or of tree structure.

So, we could have said:

  There are five types of conflict *description* (text conflict with
full texts, text conflict from a patch, property conflict, tree
conflict, and obstruction).

But property and tree conflicts can (later) come from a patch, so:

  There are seven types of conflict *description* (text conflict with
full texts, text conflict from a patch, property conflict with full
sources, property conflict from a patch, tree conflict with full
sources, tree conflict from a patch, and obstruction).

But in my opinion that not good. As I said above, it's better to
distinguish the source of change from the kind of change as two separate
dimensions.

> > Sources of a conflict are:
> >
> > That's all for now.
>
> Did you mean to make a list sources but Evolution wouldn't let you?

Oops, no, it was just a left-over fragment from my editing.

- Julian
Received on 2010-03-31 14:45:02 CEST

This is an archived mail posted to the Subversion Dev mailing list.