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

Re: Conflict storage for WC-NG

From: Julian Foad <julianfoad_at_btopenworld.com>
Date: Wed, 30 Sep 2009 17:13:56 +0100

On Wed, 2009-09-30 at 01:20 +0100, Julian Foad wrote:
> On Tue, 2009-09-29, Julian Foad wrote:
> > Bert and others,
> >
> > I've been having a think, and this is how I think conflict info should
> > be logically structured in the WC. It's an attempt to unify tree
> > conflicts with other conflicts to the extent that it makes sense to do
> > so, and to provide enough info to fill in the old
> > svn_wc_conflict_description_t.
> >
> > APIs for setting and retrieving this info are not specified here. (I
> > haven't thought of them.)
> Greg mentioned it should also provide for changes made by "svn patch".
> Here's an update.

And after further IRC conversation...

1. Operation/action/reason are basically client-level human-readable
indications (not expected to be used by e.g. an automatic resolver
function), so at the low level DB storage we can treat that tuple as an
opaque blob of "user data".

2. The semantic distinction of how a node can be in either tree conflict
or (text and/or one-or-more-props) conflict does not need to be explicit
at the DB level: the DB could store per node-path a list of conflicts,
each of which is either tree or text or (one) prop, and the higher
layers can deal with the relationship between them. If this is done,
much of the info per conflict should be the same for all conflicts on a
node: I do not want to allow the node to have two conflicts at the same
time that result from different incoming changes. (And the high-level
code already aims to prevent this.)

3. In the reference to each node-version (source-left, source-right,
target-mine) we should store the text checksum, so as to be able to
retrieve the node's text from the DB.

4. We discussed granularity. Presently we keep track of conflicts on
individual properties, and conflicts in the text (marked with conflict
marker lines). I would like always to be able to recall the incoming
change to the whole node, not just the parts of it that weren't
auto-merged, because the user may well find this info useful or
necessary in order to resolve the conflict. Ultimately (like in
Subversion 2.0), I would like to keep track of the whole incoming tree
change, so that if changes to one file conflict semantically with
changes to another file, the user can choose to revert to "my" version
of the entire tree. But that's for another time.

As a part-way step, if any conflict results from merge/up/sw, I want to
store (or rather be able to retrieve) each relevant version of the whole
node (its text and properties; maybe also the list of children, for a
directory), even if it was only one property that conflicted. If the
incoming change is from "svn patch", then the corresponding thing is to
store the portion of the patch that applies to the whole node.

5. We also mentioned that the files that are presently created on disk,
for the various versions text and property values that conflict, should
be retrieved from the DB on demand. (Compatibility code can then
recreate those "foo.r1234", "foo.mine" etc. files.) In particular, we
should store a copy of "Mine" (the old ACTUAL version of the node)
before starting to merge changes into ACTUAL.

- Julian

> [[[
> This is the information that needs to be stored in the WC to represent
> the conflict state of a node.
> Conflict state is per node-path. A path is in conflict or not in
> conflict. If it is in conflict, it is either in "tree conflict" or in
> "content conflict" which means text and/or one or more properties
> conflict. When a tree conflict is resolved, or when the text conflict
> (if any) and all property conflicts (if any) are resolved, then the path
> is no longer in conflict.
> A path can be in conflict (tree conflict) even if no BASE node is
> present and the node is not even scheduled for addition. The node's
> parent dir must exist in the target for this to happen, otherwise a tree
> conflict would be raised higher up the tree instead. This happens when a
> merge attempts to modify/replace/delete a node that does not exist in
> the target. Then a tree conflict exists on the path, reason = missing.
> The version of the node in which conflict resolution is performed, is
> the (new) ACTUAL version.
> When this conflict information has been made available, the BASE will
> have already been updated (in an up/sw) and the ACTUAL will have already
> been modified (if the up/sw/merge was able to partially complete its
> merge), possibly leaving conflict markers in it.
> /* The conflict state of a specific path.
> * If this info exists on a path, the path is in conflict,
> * else the path is not in conflict. */
> struct conflict_state
> {
> /* What kind of conflict?
> * At this level, it's just "tree" or "content". */
> enum { tree_conflict, content_conflict }
> /* Why is there a conflict (in broad, woolly terms)? */
> operation
> action
> reason
> /* References to the incoming change and the local version that it
> * conflicts with. We do not mandate here whether the WC stores a
> * copy of any or all such changes or nodes, or just metadata about
> * them. The API should be able to retrieve the details and content
> * of all relevant nodes when possible. */
> incoming_change
> tgt_mine_version /* = old ACTUAL */
> /* A place for the client to remember which parts of the conflict it
> * considers have been resolved. "In conflict" means "not resolved".
> * For a tree conflict, these shall be initially all true. */
> is_text_in_conflict
> is_prop_in_conflict{keyed by prop name}
> }
> enum operation:
> { merge, update, switch, patch }
> enum action:
> { edit, add, del, replace }
> enum reason:
> /* For up/sw: */
> { edited, added, deleted, replaced }
> /* For merge: */
> { different, obstructed, missing, wrong_kind }
> /* ### Have a single enum with all eight values? The present
> * merge code is a bit muddled about reasons - like "added"
> * vs. "obstructed". Need to choose one clear set of reasons. */
> incoming_change:
> patch_data /* iff operation = patch */
> or
> src_left_version /* for up/sw, = old BASE */
> src_right_version /* for up/sw, = new BASE; aka THEIRS */
> patch_data:
> /* A reference to, or more likely a copy of, the patch applied to
> * this node. A patch may contain some src_left/right metadata. */
> src_left_version, src_right_version:
> /* Identify a node-rev in a repository.
> * API must be able to retrieve the node's content (text or children,
> * and props) from this info. */
> svn_wc_conflict_version_t
> tgt_mine_version:
> /* Identify a node of which we definitely can have the full content.
> * The node might be a node-rev in a repository (if merging into a
> * clean WC), in which case record a reference to this node-rev.
> * Must be able to retrieve text or children, and props. */
> svn_wc_conflict_version_t
> ]]]
> > We need a bit of work on the svn_wc_conflict_version_t to make it
> > possible to retrieve the text/children/props through it, and to make it
> > defined for an unversioned node as well as a versioned node.
> - Julian
> ------------------------------------------------------
> http://subversion.tigris.org/ds/viewMessage.do?dsForumId=462&dsMessageId=2401826

Received on 2009-09-30 18:14:17 CEST

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

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.