Store property conflicts in the WC in the same way that we store text
conflicts - with separate old/theirs/mine files and API access to them -
for better automation support.
Index: subversion/include/svn_wc.h
===================================================================
--- subversion/include/svn_wc.h (revision 31940)
+++ subversion/include/svn_wc.h (working copy)
@@ -3752,6 +3752,35 @@ svn_wc_prop_list(apr_hash_t **props,
svn_wc_adm_access_t *adm_access,
apr_pool_t *pool);
+/* A type to specify which of the versions held in the WC. Types 'pristine'
+ * and 'working' are always meaningful (though they may be in the
+ * "nonexistent" state), whereas types 'conflict_*' are only valid when the WC
+ * item 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 char * names onto
+ * svn_string_t * values for all the regular properties of
+ * @a path. Allocate the table, names, and values in @a pool. If
+ * the node has no properties, or does not exist in the working copy,
+ * then an empty hash is returned. @a adm_access is an access baton
+ * set that contains @a path.
+ * @a rev_kind specified whether to access the pristine or working or
+ * one of the conflict artifact versions of this WC item.
+ */
+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);
+
/** Set @a *value to the value of property @a name for @a path, allocating
* @a *value in @a pool. If no such prop, set @a *value to @c NULL.
Index: subversion/libsvn_client/client.h
===================================================================
--- subversion/libsvn_client/client.h (revision 31940)
+++ subversion/libsvn_client/client.h (working copy)
@@ -333,7 +333,7 @@ svn_error_t *
svn_client__get_prop_from_wc(apr_hash_t *props,
const char *propname,
const char *target,
- svn_boolean_t pristine,
+ svn_wc_rev_kind_t wc_rev_kind,
const svn_wc_entry_t *entry,
svn_wc_adm_access_t *adm_access,
svn_depth_t depth,
@@ -1062,15 +1062,21 @@ svn_client__ensure_revprop_table(apr_has
apr_pool_t *pool);
-/** Return TRUE iff revision kind is dependent on the working copy.
- * Otherwise, return FALSE.
- */
-#define SVN_CLIENT__REVKIND_NEEDS_WC(kind) \
- (((kind) == svn_opt_revision_base || \
- (kind) == svn_opt_revision_previous || \
- (kind) == svn_opt_revision_working || \
- (kind) == svn_opt_revision_committed) \
- ? TRUE : FALSE)
+/** Return true iff *REVISION is of a kind that is dependent on the working
+ * copy. The result is unspecified if REVISION->kind is 'unspecified'. */
+#define SVN_CLIENT__REVKIND_NEEDS_WC(revision) \
+ ((revision)->kind == svn_opt_revision_base || \
+ (revision)->kind == svn_opt_revision_previous || \
+ (revision)->kind == svn_opt_revision_working || \
+ (revision)->kind == svn_opt_revision_committed)
+
+/* Return true iff *REVISION is of a kind that the WC can supply without
+ * reference to the repository.
+ * The result is unspecified if REVISION->kind is 'unspecified'. */
+#define SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(revision) \
+ ((revision)->kind == svn_opt_revision_base || \
+ (revision)->kind == svn_opt_revision_working || \
+ (revision)->kind == svn_opt_revision_committed)
#ifdef __cplusplus
Index: subversion/libsvn_client/copy.c
===================================================================
--- subversion/libsvn_client/copy.c (revision 31940)
+++ subversion/libsvn_client/copy.c (working copy)
@@ -1732,7 +1732,7 @@ setup_copy(svn_commit_info_t **commit_in
((svn_client_copy_source_t **) (sources->elts))[i];
if (svn_path_is_url(source->path)
- && (SVN_CLIENT__REVKIND_NEEDS_WC(source->peg_revision->kind)))
+ && (SVN_CLIENT__REVKIND_NEEDS_WC(source->peg_revision)))
return svn_error_create
(SVN_ERR_CLIENT_BAD_REVISION, NULL,
_("Revision type requires a working copy path, not a URL"));
Index: subversion/libsvn_client/log.c
===================================================================
--- subversion/libsvn_client/log.c (revision 31940)
+++ subversion/libsvn_client/log.c (working copy)
@@ -326,9 +326,9 @@ svn_client_log4(const apr_array_header_t
/* Use the passed URL, if there is one. */
if (svn_path_is_url(url_or_path))
{
- if (SVN_CLIENT__REVKIND_NEEDS_WC(peg_revision->kind) ||
- SVN_CLIENT__REVKIND_NEEDS_WC(start->kind) ||
- SVN_CLIENT__REVKIND_NEEDS_WC(end->kind))
+ if (SVN_CLIENT__REVKIND_NEEDS_WC(peg_revision) ||
+ SVN_CLIENT__REVKIND_NEEDS_WC(start) ||
+ SVN_CLIENT__REVKIND_NEEDS_WC(end))
return svn_error_create
(SVN_ERR_CLIENT_BAD_REVISION, NULL,
@@ -433,7 +433,7 @@ svn_client_log4(const apr_array_header_t
/* If this is a revision type that requires access to the working copy,
* we use our initial target path to figure out where to root the RA
* session, otherwise we use our URL. */
- if (SVN_CLIENT__REVKIND_NEEDS_WC(peg_revision->kind))
+ if (SVN_CLIENT__REVKIND_NEEDS_WC(peg_revision))
SVN_ERR(svn_path_condense_targets(&ra_target, NULL, targets, TRUE, pool));
else
ra_target = url_or_path;
Index: subversion/libsvn_client/mergeinfo.c
===================================================================
--- subversion/libsvn_client/mergeinfo.c (revision 31940)
+++ subversion/libsvn_client/mergeinfo.c (working copy)
@@ -58,7 +58,10 @@ svn_client__parse_mergeinfo(svn_mergeinf
### DannyB thinks that later we'll need behavior more like
### svn_client__get_prop_from_wc(). */
SVN_ERR(svn_client__get_prop_from_wc(props, SVN_PROP_MERGEINFO,
- wcpath, pristine, entry, adm_access,
+ wcpath, pristine
+ ? svn_wc_rev_kind_pristine
+ : svn_wc_rev_kind_working,
+ entry, adm_access,
svn_depth_empty, NULL, ctx, pool));
propval = apr_hash_get(props, wcpath, APR_HASH_KEY_STRING);
if (propval)
@@ -370,7 +373,9 @@ svn_client__get_wc_or_repos_mergeinfo(sv
assume the mergeinfo to be NULL.
*/
SVN_ERR(svn_client__get_prop_from_wc(props, SVN_PROP_MERGEINFO,
- target_wcpath, TRUE, entry,
+ target_wcpath,
+ svn_wc_rev_kind_pristine,
+ entry,
adm_access, svn_depth_empty,
NULL, ctx, pool));
if (apr_hash_get(props, target_wcpath, APR_HASH_KEY_STRING) == NULL)
Index: subversion/libsvn_client/prop_commands.c
===================================================================
--- subversion/libsvn_client/prop_commands.c (revision 31940)
+++ subversion/libsvn_client/prop_commands.c (working copy)
@@ -24,6 +24,7 @@
#define APR_WANT_STRFUNC
#include
+#include
#include "svn_error.h"
#include "svn_client.h"
@@ -552,8 +553,27 @@ svn_client_revprop_set(const char *propn
}
-/* Set *PROPS to the pristine (base) properties at PATH, if PRISTINE
- * is true, or else the working value if PRISTINE is false.
+/* ### (Assumes *REVISION is of a kind that the WC can supply. No error handling.) */
+static svn_wc_rev_kind_t
+wc_rev_kind_from_rev(const svn_opt_revision_t *revision)
+{
+ switch (revision->kind)
+ {
+ case svn_opt_revision_committed:
+ case svn_opt_revision_base:
+ return svn_wc_rev_kind_pristine;
+
+ case svn_opt_revision_working:
+ return svn_wc_rev_kind_working;
+
+ default:
+ return svn_wc_rev_kind_conflict_new; /* ### not really, just for testing */
+ }
+}
+
+/* Set *PROPS to the pristine/working/conflicted version of the properties
+ * at PATH, according to the value of WC_REV_KIND. If PATH has no such version,
+ * then set *PROPS to null.
*
* The keys of *PROPS will be 'const char *' property names, and the
* values 'const svn_string_t *' property values. Allocate *PROPS
@@ -562,43 +582,32 @@ svn_client_revprop_set(const char *propn
static svn_error_t *
pristine_or_working_props(apr_hash_t **props,
const char *path,
+ svn_wc_rev_kind_t wc_rev_kind,
svn_wc_adm_access_t *adm_access,
- svn_boolean_t pristine,
apr_pool_t *pool)
{
- if (pristine)
- SVN_ERR(svn_wc_get_prop_diffs(NULL, props, path, adm_access, pool));
- else
- SVN_ERR(svn_wc_prop_list(props, path, adm_access, pool));
-
- return SVN_NO_ERROR;
+ return svn_wc_prop_list2(props, path, wc_rev_kind, adm_access, pool);
}
-/* Set *PROPVAL to the pristine (base) value of property PROPNAME at
- * PATH, if PRISTINE is true, or else the working value if PRISTINE is
- * false. Allocate *PROPVAL in POOL.
+/* Set *PROPVAL to the pristine/working/conflicted value of property PROPNAME
+ * at PATH, according to the value of WC_REV_KIND. If PATH does not exist at the
+ * revision kind WC_REV_KIND then set *PROPVAL to null.
+ * Allocate *PROPVAL in POOL.
*/
static svn_error_t *
pristine_or_working_propval(const svn_string_t **propval,
const char *propname,
const char *path,
svn_wc_adm_access_t *adm_access,
- svn_boolean_t pristine,
+ svn_wc_rev_kind_t wc_rev_kind,
apr_pool_t *pool)
{
- if (pristine)
- {
- apr_hash_t *pristine_props;
+ apr_hash_t *props;
- SVN_ERR(svn_wc_get_prop_diffs(NULL, &pristine_props, path, adm_access,
+ SVN_ERR(pristine_or_working_props(&props, path, wc_rev_kind, adm_access,
pool));
- *propval = apr_hash_get(pristine_props, propname, APR_HASH_KEY_STRING);
- }
- else /* get the working revision */
- {
- SVN_ERR(svn_wc_prop_get(propval, propname, path, adm_access, pool));
- }
+ *propval = apr_hash_get(props, propname, APR_HASH_KEY_STRING);
return SVN_NO_ERROR;
}
@@ -608,7 +617,7 @@ pristine_or_working_propval(const svn_st
struct propget_walk_baton
{
const char *propname; /* The name of the property to get. */
- svn_boolean_t pristine; /* Select base rather than working props. */
+ svn_wc_rev_kind_t wc_rev_kind; /* Select base rather than working props. */
svn_wc_adm_access_t *base_access; /* Access for the tree being walked. */
apr_hash_t *changelist_hash; /* Keys are changelists to filter on. */
apr_hash_t *props; /* Out: mapping of (path:propval). */
@@ -619,7 +628,7 @@ struct propget_walk_baton
* For the path given by PATH and ENTRY,
* populate wb->PROPS with the values of property wb->PROPNAME,
* where "wb" is the WALK_BATON of type "struct propget_walk_baton *".
- * If wb->PRISTINE is true, use the base value, else use the working value.
+ * Get the pristine/working/conflict values, according to wb->WC_REV_KIND.
*
* The keys of wb->PROPS will be 'const char *' paths, rooted at the
* path svn_wc_adm_access_path(ADM_ACCESS), and the values are
@@ -641,17 +650,19 @@ propget_walk_cb(const char *path,
&& (strcmp(entry->name, SVN_WC_ENTRY_THIS_DIR) != 0))
return SVN_NO_ERROR;
+#if 0
/* Ignore the entry if it does not exist at the time of interest. */
if (entry->schedule
== (wb->pristine ? svn_wc_schedule_add : svn_wc_schedule_delete))
return SVN_NO_ERROR;
+#endif
/* If our entry doesn't pass changelist filtering, get outta here. */
if (! SVN_WC__CL_MATCH(wb->changelist_hash, entry))
return SVN_NO_ERROR;
SVN_ERR(pristine_or_working_propval(&propval, wb->propname, path,
- wb->base_access, wb->pristine,
+ wb->base_access, wb->wc_rev_kind,
pool));
if (propval)
@@ -811,7 +822,7 @@ svn_error_t *
svn_client__get_prop_from_wc(apr_hash_t *props,
const char *propname,
const char *target,
- svn_boolean_t pristine,
+ svn_wc_rev_kind_t wc_rev_kind,
const svn_wc_entry_t *entry,
svn_wc_adm_access_t *adm_access,
svn_depth_t depth,
@@ -836,7 +847,7 @@ svn_client__get_prop_from_wc(apr_hash_t
depth = svn_depth_infinity;
wb.propname = propname;
- wb.pristine = pristine;
+ wb.wc_rev_kind = wc_rev_kind;
wb.base_access = adm_access;
wb.changelist_hash = changelist_hash;
wb.props = props;
@@ -857,7 +868,18 @@ svn_client__get_prop_from_wc(apr_hash_t
return SVN_NO_ERROR;
}
-/* Note: this implementation is very similar to svn_client_proplist. */
+/* Return REVISION unless its kind is 'unspecified' in which case return
+ * a pointer to a statically allocated revision structure of kind 'base'. */
+static const svn_opt_revision_t *
+rev_default_to_base(const svn_opt_revision_t *revision)
+{
+ static svn_opt_revision_t base_revision = { svn_opt_revision_base, { 0 } };
+
+ return ((revision->kind == svn_opt_revision_unspecified)
+ ? &base_revision : revision);
+}
+
+/* Note: this implementation is very similar to svn_client_proplist3(). */
svn_error_t *
svn_client_propget3(apr_hash_t **props,
const char *propname,
@@ -877,18 +899,12 @@ svn_client_propget3(apr_hash_t **props,
*props = apr_hash_make(pool);
if (! svn_path_is_url(path_or_url)
- && (peg_revision->kind == svn_opt_revision_base
- || peg_revision->kind == svn_opt_revision_working
- || peg_revision->kind == svn_opt_revision_committed
- || peg_revision->kind == svn_opt_revision_unspecified)
- && (revision->kind == svn_opt_revision_base
- || revision->kind == svn_opt_revision_working
- || revision->kind == svn_opt_revision_committed
- || revision->kind == svn_opt_revision_unspecified))
+ && SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(rev_default_to_base(peg_revision))
+ && SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(rev_default_to_base(revision)))
{
+ svn_wc_rev_kind_t wc_rev_kind = wc_rev_kind_from_rev(revision);
svn_wc_adm_access_t *adm_access;
const svn_wc_entry_t *node;
- svn_boolean_t pristine;
int adm_lock_level = SVN_WC__LEVELS_TO_LOCK_FROM_DEPTH(depth);
SVN_ERR(svn_wc_adm_probe_open3(&adm_access, NULL, path_or_url,
@@ -901,12 +917,8 @@ svn_client_propget3(apr_hash_t **props,
SVN_ERR(svn_client__get_revision_number
(&revnum, NULL, NULL, revision, path_or_url, pool));
- /* If FALSE, we must want the working revision. */
- pristine = (revision->kind == svn_opt_revision_committed
- || revision->kind == svn_opt_revision_base);
-
SVN_ERR(svn_client__get_prop_from_wc(*props, propname, path_or_url,
- pristine, node, adm_access,
+ wc_rev_kind, node, adm_access,
depth, changelists, ctx, pool));
SVN_ERR(svn_wc_adm_close(adm_access));
@@ -1157,7 +1169,7 @@ remote_proplist(const char *target_prefi
/* A baton for proplist_walk_cb. */
struct proplist_walk_baton
{
- svn_boolean_t pristine; /* Select base rather than working props. */
+ svn_wc_rev_kind_t wc_rev_kind; /* Select base rather than working props. */
svn_wc_adm_access_t *base_access; /* Access for the tree being walked. */
apr_hash_t *changelist_hash; /* Keys are changelists to filter on. */
svn_proplist_receiver_t receiver; /* Proplist receiver to call. */
@@ -1169,7 +1181,7 @@ struct proplist_walk_baton
* For the path given by PATH and ENTRY,
* populate wb->PROPS with a svn_client_proplist_item_t for each path,
* where "wb" is the WALK_BATON of type "struct proplist_walk_baton *".
- * If wb->PRISTINE is true, use the base values, else use the working values.
+ * Get the pristine/working/conflict values, according to wb->WC_REV_KIND.
*/
static svn_error_t *
proplist_walk_cb(const char *path,
@@ -1187,10 +1199,12 @@ proplist_walk_cb(const char *path,
&& (strcmp(entry->name, SVN_WC_ENTRY_THIS_DIR) != 0))
return SVN_NO_ERROR;
+#if 0
/* Ignore the entry if it does not exist at the time of interest. */
if (entry->schedule
== (wb->pristine ? svn_wc_schedule_add : svn_wc_schedule_delete))
return SVN_NO_ERROR;
+#endif
/* If our entry doesn't pass changelist filtering, get outta here. */
if (! SVN_WC__CL_MATCH(wb->changelist_hash, entry))
@@ -1198,8 +1212,8 @@ proplist_walk_cb(const char *path,
path = apr_pstrdup(pool, path);
- SVN_ERR(pristine_or_working_props(&hash, path, wb->base_access,
- wb->pristine, pool));
+ SVN_ERR(pristine_or_working_props(&hash, path, wb->wc_rev_kind,
+ wb->base_access, pool));
SVN_ERR(call_receiver(path, hash, wb->receiver, wb->receiver_baton,
pool));
@@ -1207,6 +1221,7 @@ proplist_walk_cb(const char *path,
}
+/* Note: this implementation is very similar to svn_client_propget3(). */
svn_error_t *
svn_client_proplist3(const char *path_or_url,
const svn_opt_revision_t *peg_revision,
@@ -1225,16 +1240,10 @@ svn_client_proplist3(const char *path_or
depth = svn_depth_empty;
if (! svn_path_is_url(path_or_url)
- && (peg_revision->kind == svn_opt_revision_base
- || peg_revision->kind == svn_opt_revision_working
- || peg_revision->kind == svn_opt_revision_committed
- || peg_revision->kind == svn_opt_revision_unspecified)
- && (revision->kind == svn_opt_revision_base
- || revision->kind == svn_opt_revision_working
- || revision->kind == svn_opt_revision_committed
- || revision->kind == svn_opt_revision_unspecified))
+ && SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(rev_default_to_base(peg_revision))
+ && SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(rev_default_to_base(revision)))
{
- svn_boolean_t pristine;
+ svn_wc_rev_kind_t wc_rev_kind = wc_rev_kind_from_rev(revision);
int levels_to_lock = SVN_WC__LEVELS_TO_LOCK_FROM_DEPTH(depth);
const svn_wc_entry_t *entry;
apr_hash_t *changelist_hash = NULL;
@@ -1246,16 +1255,6 @@ svn_client_proplist3(const char *path_or
SVN_ERR(svn_wc__entry_versioned(&entry, path_or_url, adm_access,
FALSE, pool));
- if ((revision->kind == svn_opt_revision_committed)
- || (revision->kind == svn_opt_revision_base))
- {
- pristine = TRUE;
- }
- else /* must be the working revision */
- {
- pristine = FALSE;
- }
-
if (changelists && changelists->nelts)
SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash,
changelists, pool));
@@ -1268,7 +1267,7 @@ svn_client_proplist3(const char *path_or
struct proplist_walk_baton wb;
wb.base_access = adm_access;
- wb.pristine = pristine;
+ wb.wc_rev_kind = wc_rev_kind;
wb.changelist_hash = changelist_hash;
wb.receiver = receiver;
wb.receiver_baton = receiver_baton;
@@ -1282,8 +1281,8 @@ svn_client_proplist3(const char *path_or
{
apr_hash_t *hash;
- SVN_ERR(pristine_or_working_props(&hash, path_or_url, adm_access,
- pristine, pool));
+ SVN_ERR(pristine_or_working_props(&hash, path_or_url, wc_rev_kind,
+ adm_access, pool));
SVN_ERR(call_receiver(path_or_url, hash,
receiver, receiver_baton, pool));
@@ -1345,7 +1344,6 @@ proplist_receiver_cb(void *baton,
return SVN_NO_ERROR;
}
-/* Note: this implementation is very similar to svn_client_propget. */
svn_error_t *
svn_client_proplist2(apr_array_header_t **props,
const char *target,
Index: subversion/libsvn_wc/adm_files.c
===================================================================
--- subversion/libsvn_wc/adm_files.c (revision 31940)
+++ subversion/libsvn_wc/adm_files.c (working copy)
@@ -410,10 +410,13 @@ svn_wc__prop_path(const char **prop_path
if (node_kind == svn_node_dir) /* It's a working copy dir */
{
static const char * names[] = {
- SVN_WC__ADM_DIR_PROP_BASE, /* prop_path_kind_base */
- SVN_WC__ADM_DIR_PROP_REVERT, /* prop_path_kind_revert */
- SVN_WC__ADM_DIR_WCPROPS, /* prop_path_kind_wcprop */
- SVN_WC__ADM_DIR_PROPS /* prop_path_kind_working */
+ SVN_WC__ADM_DIR_PROP_BASE, /* svn_wc__props_base */
+ SVN_WC__ADM_DIR_PROP_REVERT, /* svn_wc__props_revert */
+ SVN_WC__ADM_DIR_WCPROPS, /* svn_wc__props_wcprop */
+ SVN_WC__ADM_DIR_PROPS, /* svn_wc__props_working */
+ SVN_WC__ADM_DIR_PROP_CNFL_OLD, /* svn_wc__props_conflict_old */
+ SVN_WC__ADM_DIR_PROP_CNFL_NEW, /* svn_wc__props_conflict_new */
+ SVN_WC__ADM_DIR_PROP_CNFL_MINE /* svn_wc__props_conflict_mine */
};
*prop_path = extend_with_adm_name
@@ -427,17 +430,23 @@ svn_wc__prop_path(const char **prop_path
else /* It's a file */
{
static const char * extensions[] = {
- SVN_WC__BASE_EXT, /* prop_path_kind_base */
- SVN_WC__REVERT_EXT, /* prop_path_kind_revert */
- SVN_WC__WORK_EXT, /* prop_path_kind_wcprop */
- SVN_WC__WORK_EXT /* prop_path_kind_working */
+ SVN_WC__BASE_EXT, /* svn_wc__props_base */
+ SVN_WC__REVERT_EXT, /* svn_wc__props_revert */
+ SVN_WC__WORK_EXT, /* svn_wc__props_wcprop */
+ SVN_WC__WORK_EXT, /* svn_wc__props_working */
+ SVN_WC__CNFL_OLD_EXT, /* svn_wc__props_conflict_old */
+ SVN_WC__CNFL_NEW_EXT, /* svn_wc__props_conflict_new */
+ SVN_WC__CNFL_MINE_EXT /* svn_wc__props_conflict_mine */
};
static const char * dirs[] = {
- SVN_WC__ADM_PROP_BASE, /* prop_path_kind_base */
- SVN_WC__ADM_PROP_BASE, /* prop_path_kind_revert */
- SVN_WC__ADM_WCPROPS, /* prop_path_kind_wcprop */
- SVN_WC__ADM_PROPS /* prop_path_kind_working */
+ SVN_WC__ADM_PROP_BASE, /* svn_wc__props_base */
+ SVN_WC__ADM_PROP_BASE, /* svn_wc__props_revert */
+ SVN_WC__ADM_WCPROPS, /* svn_wc__props_wcprop */
+ SVN_WC__ADM_PROPS, /* svn_wc__props_working */
+ SVN_WC__ADM_PROP_CNFL_OLD, /* svn_wc__props_conflict_old */
+ SVN_WC__ADM_PROP_CNFL_NEW, /* svn_wc__props_conflict_new */
+ SVN_WC__ADM_PROP_CNFL_MINE /* svn_wc__props_conflict_mine */
};
const char *base_name;
Index: subversion/libsvn_wc/props.c
===================================================================
--- subversion/libsvn_wc/props.c (revision 31940)
+++ subversion/libsvn_wc/props.c (working copy)
@@ -198,7 +198,7 @@ append_prop_conflict(apr_file_t *fp,
}
-/* Look up the entry NAME within ADM_ACCESS and see if it has a `current'
+/* Look up the entry for PATH within ADM_ACCESS and see if it has a `current'
reject file describing a state of conflict. Set *REJECT_FILE to the
name of that file, or to NULL if no such file exists. */
static svn_error_t *
@@ -253,12 +253,15 @@ build_present_props(apr_hash_t *props, a
/*** Loading regular properties. ***/
svn_error_t *
-svn_wc__load_props(apr_hash_t **base_props_p,
- apr_hash_t **props_p,
- apr_hash_t **revert_props_p,
- svn_wc_adm_access_t *adm_access,
- const char *path,
- apr_pool_t *pool)
+svn_wc__load_props2(apr_hash_t **base_props_p,
+ apr_hash_t **props_p,
+ apr_hash_t **revert_props_p,
+ apr_hash_t **conflict_old_props_p,
+ apr_hash_t **conflict_new_props_p,
+ apr_hash_t **conflict_mine_props_p,
+ svn_wc_adm_access_t *adm_access,
+ const char *path,
+ apr_pool_t *pool)
{
svn_node_kind_t kind;
svn_boolean_t has_propcaching =
@@ -330,9 +333,52 @@ svn_wc__load_props(apr_hash_t **base_pro
}
}
+ if (conflict_old_props_p)
+ {
+ const char *prop_file_path;
+
+ *conflict_old_props_p = apr_hash_make(pool);
+ SVN_ERR(svn_wc__prop_path(&prop_file_path, path, kind,
+ svn_wc__props_conflict_old, FALSE, pool));
+ SVN_ERR(load_prop_file(prop_file_path, *conflict_old_props_p, pool));
+ }
+
+ if (conflict_new_props_p)
+ {
+ const char *prop_file_path;
+
+ *conflict_new_props_p = apr_hash_make(pool);
+ SVN_ERR(svn_wc__prop_path(&prop_file_path, path, kind,
+ svn_wc__props_conflict_new, FALSE, pool));
+ SVN_ERR(load_prop_file(prop_file_path, *conflict_new_props_p, pool));
+ }
+
+ if (conflict_mine_props_p)
+ {
+ const char *prop_file_path;
+
+ *conflict_mine_props_p = apr_hash_make(pool);
+ SVN_ERR(svn_wc__prop_path(&prop_file_path, path, kind,
+ svn_wc__props_conflict_mine, FALSE, pool));
+ SVN_ERR(load_prop_file(prop_file_path, *conflict_mine_props_p, pool));
+ }
+
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_wc__load_props(apr_hash_t **base_props_p,
+ apr_hash_t **props_p,
+ apr_hash_t **revert_props_p,
+ svn_wc_adm_access_t *adm_access,
+ const char *path,
+ apr_pool_t *pool)
+{
+ return svn_wc__load_props2(base_props_p, props_p, revert_props_p,
+ NULL, NULL, NULL,
+ adm_access, path, pool);
+}
+
/*---------------------------------------------------------------------*/
@@ -1188,10 +1234,15 @@ set_prop_merge_state(svn_wc_notify_state
/* Helper function for the three apply_* functions below, used when
- * merging properties together.
+ * merging properties together. Either resolve the conflict (using the
+ * resolver callback function) into WORKING_PROPS or set
+ * *CONFLICT_REMAINS to true.
+ *
+ * ### TODO: If a conflict remains, record the four input values in the
+ * WC to help with later resolution.
*
* Given property PROPNAME on PATH, and four possible property values,
- * generate four tmpfiles and pass them to CONFLICT_FUNC callback.
+ * generate four (not corresponding) tmpfiles and pass them to CONFLICT_FUNC callback.
* This gives the client an opportunity to interactively resolve the
* property conflict. (ADM_ACCESS provides the ability to examine
* PATH's entries.)
@@ -1205,7 +1256,9 @@ set_prop_merge_state(svn_wc_notify_state
* 'choose_postpone', then set *CONFLICT_REMAINS to true and return.
*
* If the callback responds with a choice of 'base', 'theirs', 'mine',
- * or 'merged', then install the proper value into WORKING_PROPS and
+ * or 'merged', then install the proper value (OLD_VAL, NEW_VAL,
+ * WORKING_VAL, or the merged value provided by the callback, respectively;
+ * note two different meanings of "base") into WORKING_PROPS and
* set *CONFLICT_REMAINS to false.
*
*/
@@ -1312,7 +1365,7 @@ maybe_generate_propconflict(svn_boolean_
HOWEVER: we can still pass one of the two base values as
'base_file' to the callback anyway. It's still useful to
present the working and new values to the user to
- compare. */
+ compare. ### AARGH! Vague wooly spec. */
if (working_val && svn_string_compare(base_val, working_val))
the_val = old_val;
@@ -1387,13 +1440,7 @@ maybe_generate_propconflict(svn_boolean_
/* Invoke the interactive conflict callback. */
SVN_ERR(conflict_func(&result, cdesc, conflict_baton, pool));
- if (result == NULL)
- {
- *conflict_remains = TRUE;
- return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE,
- NULL, _("Conflict callback violated API:"
- " returned no results."));
- }
+ assert(result);
switch (result->choice)
{
@@ -1428,26 +1475,19 @@ maybe_generate_propconflict(svn_boolean_
}
case svn_wc_conflict_choose_merged:
{
- if (!cdesc->merged_file && !result->merged_file)
- return svn_error_create
- (SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE,
- NULL, _("Conflict callback violated API:"
- " returned no merged file."));
- else
- {
- svn_stringbuf_t *merged_stringbuf;
- svn_string_t *merged_string;
+ svn_stringbuf_t *merged_stringbuf;
+ svn_string_t *merged_string;
- SVN_ERR(svn_stringbuf_from_file2(&merged_stringbuf,
- result->merged_file ?
- result->merged_file :
- cdesc->merged_file,
- pool));
- merged_string = svn_string_create_from_buf(merged_stringbuf, pool);
- apr_hash_set(working_props, propname,
- APR_HASH_KEY_STRING, merged_string);
- *conflict_remains = FALSE;
- }
+ assert(cdesc->merged_file || result->merged_file);
+ SVN_ERR(svn_stringbuf_from_file2(&merged_stringbuf,
+ result->merged_file ?
+ result->merged_file :
+ cdesc->merged_file,
+ pool));
+ merged_string = svn_string_create_from_buf(merged_stringbuf, pool);
+ apr_hash_set(working_props, propname,
+ APR_HASH_KEY_STRING, merged_string);
+ *conflict_remains = FALSE;
break;
}
}
@@ -2202,10 +2242,11 @@ svn_wc__wcprop_set(const char *name,
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)
+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)
{
const svn_wc_entry_t *entry;
@@ -2225,7 +2266,42 @@ svn_wc_prop_list(apr_hash_t **props,
SVN_ERR(svn_wc_adm_retrieve(&adm_access, adm_access,
svn_path_dirname(path, pool), pool));
- return svn_wc__load_props(NULL, props, NULL, adm_access, path, pool);
+ switch (rev_kind)
+ {
+ case svn_wc_rev_kind_pristine:
+ SVN_ERR(svn_wc__load_props2(props, NULL, NULL, NULL, NULL, NULL,
+ adm_access, path, pool));
+ break;
+ case svn_wc_rev_kind_working:
+ SVN_ERR(svn_wc__load_props2(NULL, props, NULL, NULL, NULL, NULL,
+ adm_access, path, pool));
+ break;
+ case svn_wc_rev_kind_conflict_old:
+ SVN_ERR(svn_wc__load_props2(NULL, NULL, NULL, props, NULL, NULL,
+ adm_access, path, pool));
+ break;
+ case svn_wc_rev_kind_conflict_new:
+ SVN_ERR(svn_wc__load_props2(NULL, NULL, NULL, NULL, props, NULL,
+ adm_access, path, pool));
+ break;
+ case svn_wc_rev_kind_conflict_mine:
+ SVN_ERR(svn_wc__load_props2(NULL, NULL, NULL, NULL, NULL, props,
+ adm_access, path, pool));
+ break;
+ default:
+ assert(0);
+ }
+ return SVN_NO_ERROR;
+}
+
+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)
+{
+ return svn_wc_prop_list2(props, path, svn_wc_rev_kind_working, adm_access,
+ pool);
}
/* Determine if PROPNAME is contained in the list of space separated
Index: subversion/libsvn_wc/props.h
===================================================================
--- subversion/libsvn_wc/props.h (revision 31940)
+++ subversion/libsvn_wc/props.h (working copy)
@@ -35,7 +35,10 @@ typedef enum svn_wc__props_kind_t
svn_wc__props_base = 0,
svn_wc__props_revert,
svn_wc__props_wcprop,
- svn_wc__props_working
+ svn_wc__props_working,
+ svn_wc__props_conflict_old,
+ svn_wc__props_conflict_new,
+ svn_wc__props_conflict_mine
} svn_wc__props_kind_t;
@@ -215,6 +218,21 @@ svn_wc__load_props(apr_hash_t **base_pro
const char *path,
apr_pool_t *pool);
+/* Load the base, working and revert props for PATH in ADM_ACCESS returning
+ them in *BASE_PROPS_P, *PROPS_P and *REVERT_PROPS_P respectively.
+ Any of BASE_PROPS, PROPS and REVERT_PROPS may be null.
+ Do all allocations in POOL. */
+svn_error_t *
+svn_wc__load_props2(apr_hash_t **base_props_p,
+ apr_hash_t **props_p,
+ apr_hash_t **revert_props_p,
+ apr_hash_t **conflict_old_props_p,
+ apr_hash_t **conflict_new_props_p,
+ apr_hash_t **conflict_mine_props_p,
+ svn_wc_adm_access_t *adm_access,
+ const char *path,
+ apr_pool_t *pool);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Index: subversion/libsvn_wc/wc.h
===================================================================
--- subversion/libsvn_wc/wc.h (revision 31940)
+++ subversion/libsvn_wc/wc.h (working copy)
@@ -36,8 +36,10 @@ extern "C" {
#define SVN_WC__PROP_REJ_EXT ".prej"
#define SVN_WC__BASE_EXT ".svn-base" /* for text and prop bases */
#define SVN_WC__WORK_EXT ".svn-work" /* for working propfiles */
-#define SVN_WC__REVERT_EXT ".svn-revert" /* for reverting a replaced
- file */
+#define SVN_WC__REVERT_EXT ".svn-revert" /* for reverting a replaced file */
+#define SVN_WC__CNFL_OLD_EXT ".old"
+#define SVN_WC__CNFL_NEW_EXT ".new"
+#define SVN_WC__CNFL_MINE_EXT ".mine"
@@ -140,11 +142,17 @@ struct svn_wc_traversal_info_t
#define SVN_WC__ADM_TEXT_BASE "text-base"
#define SVN_WC__ADM_PROPS "props"
#define SVN_WC__ADM_PROP_BASE "prop-base"
+#define SVN_WC__ADM_WCPROPS "wcprops"
+#define SVN_WC__ADM_PROP_CNFL_OLD "prop-cnfl-old"
+#define SVN_WC__ADM_PROP_CNFL_NEW "prop-cnfl-new"
+#define SVN_WC__ADM_PROP_CNFL_MINE "prop-cnfl-mine"
#define SVN_WC__ADM_DIR_PROPS "dir-props"
#define SVN_WC__ADM_DIR_PROP_BASE "dir-prop-base"
#define SVN_WC__ADM_DIR_PROP_REVERT "dir-prop-revert"
-#define SVN_WC__ADM_WCPROPS "wcprops"
#define SVN_WC__ADM_DIR_WCPROPS "dir-wcprops"
+#define SVN_WC__ADM_DIR_PROP_CNFL_OLD "dir-prop-cnfl-old"
+#define SVN_WC__ADM_DIR_PROP_CNFL_NEW "dir-prop-cnfl-new"
+#define SVN_WC__ADM_DIR_PROP_CNFL_MINE "dir-prop-cnfl-mine"
#define SVN_WC__ADM_ALL_WCPROPS "all-wcprops"
#define SVN_WC__ADM_LOG "log"
#define SVN_WC__ADM_KILLME "KILLME"