On Tue, 2008-07-15 at 13:21 -0400, Karl Fogel wrote:
> You know, I kind of think the way to go about this is to propose the API
> *first*, and then worry about where we're going to store the property
> conflicts afterwards. The API is the key thing here.
OK...
Libsvn_wc presently stores two "versions" or "revision kinds" of a given
node locally:
* pristine base version (read-only)
* working version (read-write)
and provides APIs for accessing these versions of a file's text ...
case svn_opt_revision_base:
SVN_ERR(svn_wc_get_pristine_copy_path(wc_path, &base_path, pool));
case svn_opt_revision_working:
working_path = wc_path; /* no API as such: we know the path */
... and its properties:
case svn_opt_revision_base:
SVN_ERR(svn_wc_get_prop_diffs(NULL, &base_props, wc_path, adm...);
case svn_opt_revision_working:
SVN_ERR(svn_wc_prop_list(&working_props, path, adm_access, pool));
(ugh, look: that's two different APIs).
Let libsvn_wc store three additional versions of a given node when a
conflict (any kind of conflict) occurs:
* "old" or "merge-left" version (read-only)
* "new" or "merge-right" or "their" version (read-only)
* previous-working or "my" version (read-only)
Let libsvn_wc provide a uniform API for operations that can be common
across all five versions:
> /* A type to select one of the versions that the WC holds of a node. Types
> * 'pristine' and 'working' are meaningful unless the node is schedule-add
> * or schedule-delete respectively. The three 'conflict_*' types are
> * meaningful only while the node is in a state of conflict. */
> typedef enum svn_wc_rev_kind_t
> {
> svn_wc_rev_kind_pristine, /* the 'pristine' or 'base' version */
> svn_wc_rev_kind_working, /* the version that can be locally edited */
> svn_wc_rev_kind_conflict_old, /* the incoming change's 'old' or 'left' side */
> svn_wc_rev_kind_conflict_new, /* the incoming change's 'new' or 'right' side */
> svn_wc_rev_kind_conflict_mine /* what was 'working' before the conflict */
> } svn_wc_rev_kind_t;
>
> /** Set @a *props to a hash table mapping <tt>char *</tt> names onto
> * <tt>svn_string_t *</tt> values for all the regular properties of
> * @a path. Allocate the table, names, and values in @a pool.
> * If the node has no properties, return an empty hash.
> * If the node does not exist in the working copy, return an error.
> * @a adm_access is an access baton set that contains @a path.
> * @a rev_kind specifies which version of the node to access: the pristine base,
> * the working version, or one of the conflict artifacts.
> */
> svn_error_t *
> svn_wc_prop_list2(apr_hash_t **props,
> const char *path,
> svn_wc_rev_kind_t rev_kind,
> svn_wc_adm_access_t *adm_access,
> apr_pool_t *pool);
>
> /** Like svn_wc_prop_list2() except that only the working properties can be
> * obtained, and if the node does not exist in the working copy then an
> * empty hash is returned.
> *
> * @deprecated ...
> */
> svn_error_t *
> svn_wc_prop_list(apr_hash_t **props,
> const char *path,
> svn_wc_adm_access_t *adm_access,
> apr_pool_t *pool);
... and likewise for propget, and similarly for the various diff
functions ...
> /* Get an editor to describe the differences between the WC-local
> * version @a rev_kind and a repository version of the target. ...
> */
> svn_error_t *
> svn_wc_get_diff_editor5(svn_wc_adm_access_t *anchor,
> const char *target,
> [...]
> svn_wc_rev_kind_t rev_kind,
> [...]);
>
> /* @deprecated ... */
> svn_error_t *
> svn_wc_get_diff_editor4(svn_wc_adm_access_t *anchor,
> const char *target,
> [...]
> svn_boolean_t use_text_base,
> [...]);
... and similarly for svn_wc_diff5() to diff between two arbitrary
WC-local versions, where the present version only does base to working.
I'm pretty confident of the part of this approach that is saying:
"libsvn_wc, for this node, give me access to a version that you I know
you're holding that's identified by this parameter REV_KIND."
I'm less certain that the type of the parameter REV_KIND should be an
enum of these particular values.
The "theirs" and "old" versions are normally (always, in present svn
client) going to be repository versions, so we could instead use
repository version numbers (which we can get by querying the conflict
ibnfo) to request access to these versions, either via the WC API or via
the repository access API. But the special-identifier way is consistent
with how we request "base": we don't look up the corresponding
repository rev number and then pass that to the (WC or RA) APIs.
The "mine" version is like "working" in that it often doesn't have a
repository equivalent, as it may contain local mods, so it has to have a
special identifier. (The identifier could possibly be something that is
dynamically generated by libsvn_wc rather than a fixed constant, looking
forward to a time when it may be able to store more than one
work-in-progress per node, but that seems premature.)
I think this achieves:
* An improvement in WC API self-consistency, and thereby a
simplification of calling code in users such as svn_client_cat() and
svn_client_propget().
* A way to access text conflict artifact files that is consistent with
how we access text base files.
* A way to access property conflict artifacts which we will want to
store soon, however we choose to store them, that is consistent with how
we access base and working properties.
* An identification mechanism that we can also apply to tree conflict
artifacts. Although difficult-to-resolve tree conflicts may occur less
often than "normal" conflicts, when it does occur the need to access
these things through a consistent programmatic interface may be greater
than the need currently is for text and prop conflicts.
I'd like to know what folks think is right and wrong with this :-)
- Julian
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe_at_subversion.tigris.org
For additional commands, e-mail: dev-help_at_subversion.tigris.org
Received on 2008-07-21 15:55:34 CEST