Provide a unified API for reading any locally stored version of a given
node's text or properties: the "base" or "working" version, or one of three
conflict artifact versions "old"/"theirs"/"mine".
Formerly, inconsistent APIs were available for reading a file's text and no
APIs were available for the conflict artifacts other than to get the names
of the files.
Store property conflict artifacts (the old/theirs/mine versions) in the WC
admin area when conflicts occur, and provide access through this mechanism.
### WORK IN PROGRESS. Some tests are broken: at least update_tests 34.
*** Interface via svn_opt_revision_t ***
* subversion/include/svn_opt.h
(svn_opt_revision_kind): Add revision kinds 'old', 'theirs' and 'mine'.
* subversion/libsvn_subr/opt.c
(revision_from_word): Add revision kinds 'old', 'theirs' and 'mine'.
* subversion/libsvn_client/revisions.c
(svn_client__get_revision_number): Add revision kinds 'old', 'theirs' and
'mine'.
### Unfinished: rev numbers not yet stored in entry.
*** WC interface via svn_wc_rev_kind_t ***
* subversion/include/svn_wc.h
(svn_wc_rev_kind_t): New type.
(svn_wc_prop_list2, svn_wc_prop_get2, svn_wc_get_diff_editor5a,
svn_wc_diff5a): New functions, like their predecessors but with
svn_wc_rev_kind_t arguments specifying which version of the source file
to read from.
(svn_wc_get_text_path): New function.
*** WC Library ***
* subversion/libsvn_wc/adm_files.c
(svn_wc__text_path): New function.
(svn_wc__text_base_path, svn_wc__text_revert_path): Use svn_wc__text_path().
(svn_wc__prop_path): Support old/theirs/mine.
* subversion/libsvn_wc/adm_files.h
(svn_wc__text_path): New function.
* subversion/libsvn_wc/adm_ops.c
(revert_admin_things):
### Placeholder for where we should remove prop conflict artifact files.
(svn_wc_get_text_path): New function.
* subversion/libsvn_wc/diff.c
(edit_baton): Add a wc_rev_kind field to support old/theirs/mine.
(make_editor_baton): Support old/theirs/mine.
### The previous field is deprecated. Check fully supported, or remove it.
(svn_wc_get_diff_editor5a): New version of svn_wc_get_diff_editor5 to support
old/theirs/mine.
### Combine with svn_wc_get_diff_editor5().
(svn_wc_diff5a): New version of svn_wc_diff5 to support old/theirs/mine.
### Combine with svn_wc_diff5().
* subversion/libsvn_wc/props.c
(svn_wc__load_props2): New function, like svn_wc__load_props() but supporting
old/theirs/mine.
(svn_wc__load_props): Re-implement as a wrapper around svn_wc__load_props2().
(maybe_generate_propconflict): Improve doc string.
(install_prop_conflict_files): New function.
(svn_wc__merge_props): When raising a conflict, save the old/theirs/mine
versions of the properties.
(svn_wc_prop_list2): New function, like svn_wc_prop_list() but supporting
old/theirs/mine.
(svn_wc_prop_list): Re-implement as a wrapper around svn_wc_prop_list2().
* subversion/libsvn_wc/props.h
(svn_wc__props_kind_t): Add enumerators for old/theirs/mine.
(svn_wc__load_props2): New function.
### Should just update svn_wc__load_props. No need to rev it.
* subversion/libsvn_wc/wc.h
(SVN_WC__CNFL_OLD_EXT, SVN_WC__CNFL_NEW_EXT, SVN_WC__CNFL_MINE_EXT,
SVN_WC__ADM_DIR_PROP_CNFL_OLD, SVN_WC__ADM_DIR_PROP_CNFL_NEW,
SVN_WC__ADM_DIR_PROP_CNFL_MINE): New macros.
*** Client Library ***
* subversion/libsvn_client/cat.c
(cat_local_file): Support old/theirs/mine.
### Doesn't use the right status and mod-time for old/theirs/mine.
* subversion/libsvn_client/diff.c
(check_paths): Allow old/theirs/mine.
(diff_wc_wc): Allow diffs between pairs of WC revisions other than just
base:working.
* subversion/libsvn_client/export.c
(copy_one_versioned_file): Allow copying from old/theirs/mine.
### Doesn't use the right status and mod-time for old/theirs/mine.
* subversion/libsvn_client/mergeinfo.c
(svn_client__parse_mergeinfo): Allow old/theirs/mine.
(svn_client__get_wc_or_repos_mergeinfo): Adjust the call accordingly.
* subversion/libsvn_client/prop_commands.c
(pristine_or_working_props, pristine_or_working_propval):
Allow old/theirs/mine.
### Function names are now poor.
(propget_walk_baton, proplist_walk_baton, propget_walk_cb, proplist_walk_cb,
svn_client__get_prop_from_wc): Allow old/theirs/mine.
(svn_client_propget3, svn_client_proplist3): Use
svn_cl__rev_default_to_head_or_base() and
SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(), and thereby allow old/theirs/mine.
* subversion/libsvn_client/util.c
(svn_cl__item_exists_in_local_revision, svn_cl__wc_rev_kind_from_rev):
New functions.
* subversion/libsvn_client/client.h
(svn_client__get_prop_from_wc): Change "pristine" parameter to "revision".
(SVN_CLIENT__REVKIND_NEEDS_WC, SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC):
Add revision kinds 'old', 'theirs' and 'mine'.
(svn_cl__item_exists_in_local_revision, svn_cl__wc_rev_kind_from_rev):
New functions.
*** Command-Line Client ***
* subversion/svn/diff-cmd.c
(svn_cl__diff): Support old/theirs/mine.
Index: subversion/include/svn_opt.h
===================================================================
--- subversion/include/svn_opt.h (revision 32317)
+++ subversion/include/svn_opt.h (working copy)
@@ -346,7 +346,16 @@ enum svn_opt_revision_kind {
svn_opt_revision_working,
/** repository youngest */
- svn_opt_revision_head
+ svn_opt_revision_head,
+
+ /** conflict artifact: old/left version of incoming change */
+ svn_opt_revision_old,
+
+ /** conflict artifact: new/right version of incoming change */
+ svn_opt_revision_theirs,
+
+ /** conflict artifact: pre-conflict working version */
+ svn_opt_revision_mine
};
/**
Index: subversion/include/svn_wc.h
===================================================================
--- subversion/include/svn_wc.h (revision 32317)
+++ subversion/include/svn_wc.h (working copy)
@@ -1145,6 +1145,8 @@ typedef struct svn_wc_conflict_descripti
* property values are technically binary values, and thus can't
* always be merged.)
*/
+ /* ### These three may be obsoleted by ability to request
+ * wrk/base/old/theirs/mine from any WC functions. */
const char *base_file; /* common ancestor of the two files being merged */
/** their version of the file */
@@ -1592,6 +1594,7 @@ svn_wc_check_wc(const char *path,
svn_error_t *
svn_wc_has_binary_prop(svn_boolean_t *has_binary_prop,
const char *path,
+ /* ### want svn_wc_rev_kind_t? */
svn_wc_adm_access_t *adm_access,
apr_pool_t *pool);
@@ -2667,6 +2670,7 @@ svn_wc_status_set_repos_locks(void *set_
*/
svn_error_t *
svn_wc_copy2(const char *src,
+ /* ### want svn_wc_rev_kind_t? */
svn_wc_adm_access_t *dst_parent,
const char *dst_basename,
svn_cancel_func_t cancel_func,
@@ -3658,12 +3662,42 @@ svn_wc_get_switch_editor(svn_revnum_t *t
* difference.
*/
+/* 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/left/base side */
+ svn_wc_rev_kind_conflict_new, /* the incoming change's new/right/theirs */
+ svn_wc_rev_kind_conflict_wrk /* the pre-conflict working/mine version */
+} 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 path. Allocate the table, names, and values in @a pool.
+ * If the @a rev_kind version of the node exists and has no properties,
+ * return an empty hash.
+ * If the @a rev_kind version of the node does not logically exist (for
+ * example, is scheduled for deletion, or is the base of an item scheduled
+ * for addition, or is a conflict artifact of an item not in conflict),
+ * 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.
*/
svn_error_t *
svn_wc_prop_list(apr_hash_t **props,
@@ -3677,6 +3711,19 @@ svn_wc_prop_list(apr_hash_t **props,
* @a name may be a regular or wc property; if it is an entry property,
* return the error @c SVN_ERR_BAD_PROP_KIND. @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_get2(const svn_string_t **value,
+ const char *name,
+ 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_get2() except only the working properties can be
+ * obtained.
*/
svn_error_t *
svn_wc_prop_get(const svn_string_t **value,
@@ -3826,8 +3873,8 @@ svn_wc_canonicalize_svn_prop(const svn_s
* @a ignore_ancestry is @c FALSE, then any discontinuous node ancestry will
* result in the diff given as a full delete followed by an add.
*
- * If @a use_text_base is TRUE, then compare the repository against
- * the working copy's text-base files, rather than the working files.
+ * Compare the repository against the working copy version specified by
+ * @a wc_rev_kind.
*
* Normally, the difference from repository->working_copy is shown.
* If @a reverse_order is TRUE, then show working_copy->repository diffs.
@@ -3844,6 +3891,22 @@ svn_wc_canonicalize_svn_prop(const svn_s
* @since New in 1.6.
*/
svn_error_t *
+svn_wc_get_diff_editor5a(svn_wc_adm_access_t *anchor,
+ const char *target,
+ const svn_wc_diff_callbacks3_t *callbacks,
+ void *callback_baton,
+ svn_depth_t depth,
+ svn_boolean_t ignore_ancestry,
+ svn_wc_rev_kind_t rev_kind,
+ svn_boolean_t reverse_order,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ const apr_array_header_t *changelists,
+ const svn_delta_editor_t **editor,
+ void **edit_baton,
+ apr_pool_t *pool);
+/* ### In v1.6, combine svn_wc_get_diff_editor5a() with ...5() as ...5(). */
+svn_error_t *
svn_wc_get_diff_editor5(svn_wc_adm_access_t *anchor,
const char *target,
const svn_wc_diff_callbacks3_t *callbacks,
@@ -3950,10 +4013,14 @@ svn_wc_get_diff_editor(svn_wc_adm_access
/**
- * Compare working copy against the text-base.
+ * Compare one version of a WC node against another version of it, sending
+ * the results through the svn_wc_diff_callbacks3_t callback interface.
*
* @a anchor/@a target represent the base of the hierarchy to be compared.
*
+ * @a rev_kind_from and @a rev_kind_to specify the left and right side of
+ * the diff respectively.
+ *
* @a callbacks/@a callback_baton is the callback table to use when two
* files are to be compared.
*
@@ -3979,6 +4046,18 @@ svn_wc_get_diff_editor(svn_wc_adm_access
* @since New in 1.6.
*/
svn_error_t *
+svn_wc_diff5a(svn_wc_adm_access_t *anchor,
+ const char *target,
+ svn_wc_rev_kind_t rev_kind_from,
+ svn_wc_rev_kind_t rev_kind_to,
+ const svn_wc_diff_callbacks3_t *callbacks,
+ void *callback_baton,
+ svn_depth_t depth,
+ svn_boolean_t ignore_ancestry,
+ const apr_array_header_t *changelists,
+ apr_pool_t *pool);
+/* ### In v1.6, combine svn_wc_diff5a() with ...5() as ...5(). */
+svn_error_t *
svn_wc_diff5(svn_wc_adm_access_t *anchor,
const char *target,
const svn_wc_diff_callbacks3_t *callbacks,
@@ -3990,7 +4069,8 @@ svn_wc_diff5(svn_wc_adm_access_t *anchor
/**
* Similar to svn_wc_diff5(), but with a @c svn_wc_diff_callbacks2_t argument
- * instead of @c svn_wc_diff_callbacks3_t.
+ * instead of @c svn_wc_diff_callbacks3_t, and the left and right side of
+ * the diff being BASE and WORKING respectively.
*
* @deprecated Provided for backward compatibility with the 1.5 API.
*/
@@ -4070,6 +4150,7 @@ svn_error_t *
svn_wc_get_prop_diffs(apr_array_header_t **propchanges,
apr_hash_t **original_props,
const char *path,
+ /* ### want svn_wc_rev_kind_t? */
svn_wc_adm_access_t *adm_access,
apr_pool_t *pool);
@@ -4301,6 +4382,23 @@ svn_wc_get_pristine_copy_path(const char
const char **pristine_path,
apr_pool_t *pool);
+/** Given a @a path to a wc file, set @a text_path to the path of the
+ * version of the file specified by @a rev_kind.
+ * If the specified version is a conflict version, and the file is not in
+ * conflict, return an error.
+ * If the specified version does not exist, set @a text_path to NULL.
+ * @a adm_access is an access baton for @a path.
+ * Perform all allocations in @a pool.
+ *
+ * ### Need to specify which way the file should be translated?
+ */
+svn_error_t *
+svn_wc_get_text_path(const char **text_path,
+ const char *path,
+ svn_wc_rev_kind_t rev_kind,
+ svn_wc_adm_access_t *adm_access,
+ apr_pool_t *pool);
+
/**
* Recurse from @a path, cleaning up unfinished log business. Perform
Index: subversion/libsvn_client/cat.c
===================================================================
--- subversion/libsvn_client/cat.c (revision 32317)
+++ subversion/libsvn_client/cat.c (working copy)
@@ -39,9 +39,9 @@
/*** Code. ***/
-/* Helper function to handle copying a potentially translated version of
- local file PATH to OUTPUT. REVISION must be one of the following: BASE,
- COMMITTED, WORKING. Uses POOL for temporary allocations. */
+/* Copy a potentially translated version of local file PATH to OUTPUT.
+ * REVISION must be of a kind that the WC can provide locally, and must not
+ * be UNSPECIFIED. Use POOL for temporary allocations. */
static svn_error_t *
cat_local_file(const char *path,
svn_stream_t *output,
@@ -60,8 +60,10 @@ cat_local_file(const char *path,
apr_time_t tm;
apr_file_t *input_file;
svn_stream_t *input;
+ svn_wc_rev_kind_t wc_rev_kind;
SVN_ERR_ASSERT(SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(revision->kind));
+ wc_rev_kind = svn_cl__wc_rev_kind_from_rev(revision);
SVN_ERR(svn_wc__entry_versioned(&entry, path, adm_access, FALSE, pool));
@@ -70,17 +72,21 @@ cat_local_file(const char *path,
_("'%s' refers to a directory"),
svn_path_local_style(path, pool));
- if (revision->kind != svn_opt_revision_working)
- {
- SVN_ERR(svn_wc_get_pristine_copy_path(path, &base, pool));
- SVN_ERR(svn_wc_get_prop_diffs(NULL, &props, path, adm_access, pool));
- }
- else
+ /* Get the text and properties */
+ SVN_ERR(svn_wc_get_text_path(&base, path, wc_rev_kind, adm_access, pool));
+ if (base == NULL)
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("'%s' does not exist at that version"),
+ path);
+ SVN_ERR(svn_wc_prop_list2(&props, path, wc_rev_kind, adm_access, pool));
+
+ /* Find out whether we're looking at a locally modified version. (If so,
+ * then we won't know the author or revision number.) */
+ /* ### Update for svn_opt_revision_old/new/mine */
+ if (revision->kind == svn_opt_revision_working)
{
svn_wc_status2_t *status;
- base = path;
- SVN_ERR(svn_wc_prop_list(&props, path, adm_access, pool));
SVN_ERR(svn_wc_status2(&status, path, adm_access, pool));
if (status->text_status != svn_wc_status_normal)
local_mod = TRUE;
@@ -98,7 +104,7 @@ cat_local_file(const char *path,
if (local_mod && (! special))
{
- /* Use the modified time from the working copy if
+ /* Use the modified time from the working copy of
the file */
SVN_ERR(svn_io_file_affected_time(&tm, path, pool));
}
Index: subversion/libsvn_client/client.h
===================================================================
--- subversion/libsvn_client/client.h (revision 32317)
+++ subversion/libsvn_client/client.h (working copy)
@@ -322,7 +322,7 @@ svn_error_t *
svn_client__get_prop_from_wc(apr_hash_t *props,
const char *propname,
const char *target,
- svn_boolean_t pristine,
+ const svn_opt_revision_t *revision,
const svn_wc_entry_t *entry,
svn_wc_adm_access_t *adm_access,
svn_depth_t depth,
@@ -1057,14 +1057,20 @@ svn_client__ensure_revprop_table(apr_has
((kind) == svn_opt_revision_base || \
(kind) == svn_opt_revision_previous || \
(kind) == svn_opt_revision_working || \
- (kind) == svn_opt_revision_committed) \
+ (kind) == svn_opt_revision_committed || \
+ (kind) == svn_opt_revision_old || \
+ (kind) == svn_opt_revision_theirs || \
+ (kind) == svn_opt_revision_mine)
/* Return true if KIND is a revision kind that the WC can supply without
* contacting the repository. Otherwise, return false. */
#define SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(kind) \
((kind) == svn_opt_revision_base || \
(kind) == svn_opt_revision_working || \
- (kind) == svn_opt_revision_committed)
+ (kind) == svn_opt_revision_committed || \
+ (kind) == svn_opt_revision_old || \
+ (kind) == svn_opt_revision_theirs || \
+ (kind) == svn_opt_revision_mine)
/* Return REVISION unless its kind is 'unspecified' in which case return
* a pointer to a statically allocated revision structure of kind 'head'
@@ -1086,6 +1092,18 @@ const svn_opt_revision_t *
svn_cl__rev_default_to_peg(const svn_opt_revision_t *revision,
const svn_opt_revision_t *peg_revision);
+/* Return true iff the item *ENTRY is scheduled to logically exists in the
+ * version specified by *REVISION (which must be of a "local" kind). */
+svn_boolean_t
+svn_cl__item_exists_in_local_revision(const svn_wc_entry_t *entry,
+ const svn_opt_revision_t *revision);
+
+/* Return the WC revision kind corresponding to *REVISION which must be of
+ * a kind that the WC can supply, as determined
+ * by SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(). */
+svn_wc_rev_kind_t
+svn_cl__wc_rev_kind_from_rev(const svn_opt_revision_t *revision);
+
#ifdef __cplusplus
}
Index: subversion/libsvn_client/diff.c
===================================================================
--- subversion/libsvn_client/diff.c (revision 32317)
+++ subversion/libsvn_client/diff.c (working copy)
@@ -908,9 +908,11 @@ check_paths(const struct diff_parameters
is_local_rev1 =
((params->revision1->kind == svn_opt_revision_base)
|| (params->revision1->kind == svn_opt_revision_working));
+ /* ### SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(params->revision1->kind) ? */
is_local_rev2 =
((params->revision2->kind == svn_opt_revision_base)
|| (params->revision2->kind == svn_opt_revision_working));
+ /* ### SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(params->revision2->kind) ? */
if (params->peg_revision->kind != svn_opt_revision_unspecified)
{
@@ -1132,14 +1134,12 @@ diff_wc_wc(const char *path1,
/* Currently we support only the case where path1 and path2 are the
same path. */
- if ((strcmp(path1, path2) != 0)
- || (! ((revision1->kind == svn_opt_revision_base)
- && (revision2->kind == svn_opt_revision_working))))
+ if (strcmp(path1, path2) != 0)
return unsupported_diff_error
(svn_error_create
(SVN_ERR_INCORRECT_PARAMS, NULL,
- _("Only diffs between a path's text-base "
- "and its working files are supported at this time")));
+ _("Diffs between different working copy paths "
+ "are not supported at this time")));
SVN_ERR(svn_wc_adm_open_anchor(&adm_access, &target_access, &target,
path1, FALSE, levels_to_lock,
@@ -1151,8 +1151,11 @@ diff_wc_wc(const char *path1,
(&callback_baton->revnum1, NULL, NULL, revision1, path1, pool));
callback_baton->revnum2 = SVN_INVALID_REVNUM; /* WC */
- SVN_ERR(svn_wc_diff5(adm_access, target, callbacks, callback_baton,
- depth, ignore_ancestry, changelists, pool));
+ SVN_ERR(svn_wc_diff5a(adm_access, target,
+ svn_cl__wc_rev_kind_from_rev(revision1),
+ svn_cl__wc_rev_kind_from_rev(revision2),
+ callbacks, callback_baton,
+ depth, ignore_ancestry, changelists, pool));
SVN_ERR(svn_wc_adm_close(adm_access));
return SVN_NO_ERROR;
}
Index: subversion/libsvn_client/export.c
===================================================================
--- subversion/libsvn_client/export.c (revision 32317)
+++ subversion/libsvn_client/export.c (working copy)
@@ -107,38 +107,31 @@ copy_one_versioned_file(const char *from
const char *eol = NULL;
svn_boolean_t local_mod = FALSE;
apr_time_t tm;
+ svn_wc_rev_kind_t wc_rev_kind;
+
+ wc_rev_kind = svn_cl__wc_rev_kind_from_rev(revision);
SVN_ERR(svn_wc_entry(&entry, from, adm_access, FALSE, pool));
- /* Only export 'added' files when the revision is WORKING.
- Otherwise, skip the 'added' files, since they didn't exist
- in the BASE revision and don't have an associated text-base.
-
- Don't export 'deleted' files and directories unless it's a
- revision other than WORKING. These files and directories
- don't really exist in WORKING. */
- if ((revision->kind != svn_opt_revision_working &&
- entry->schedule == svn_wc_schedule_add) ||
- (revision->kind == svn_opt_revision_working &&
- entry->schedule == svn_wc_schedule_delete))
+ /* Don't export the 'working' version of an item that is scheduled for
+ deletion, or the 'base' version of an item that is scheduled for
+ addition, as these versions are not deemed to really exist. */
+ if (! svn_cl__item_exists_in_local_revision(entry, revision))
return SVN_NO_ERROR;
- if (revision->kind != svn_opt_revision_working)
- {
- SVN_ERR(svn_wc_get_pristine_copy_path(from, &base,
- pool));
- SVN_ERR(svn_wc_get_prop_diffs(NULL, &props, from,
- adm_access, pool));
- }
- else
+ /* Get the text and properties */
+ SVN_ERR(svn_wc_get_text_path(&base, from, wc_rev_kind, adm_access, pool));
+ if (base == NULL)
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("'%s' does not exist at that version"),
+ from);
+ SVN_ERR(svn_wc_prop_list2(&props, from, wc_rev_kind, adm_access, pool));
+ /* ### Update for svn_opt_revision_old/new/mine */
+ if (revision->kind == svn_opt_revision_working)
{
svn_wc_status2_t *status;
- base = from;
- SVN_ERR(svn_wc_prop_list(&props, from,
- adm_access, pool));
- SVN_ERR(svn_wc_status2(&status, from,
- adm_access, pool));
+ SVN_ERR(svn_wc_status2(&status, from, adm_access, pool));
if (status->text_status != svn_wc_status_normal)
local_mod = TRUE;
}
@@ -231,17 +224,10 @@ copy_versioned_files(const char *from,
SVN_ERR(svn_wc__entry_versioned(&entry, from, adm_access, FALSE, pool));
- /* Only export 'added' files when the revision is WORKING.
- Otherwise, skip the 'added' files, since they didn't exist
- in the BASE revision and don't have an associated text-base.
-
- Don't export 'deleted' files and directories unless it's a
- revision other than WORKING. These files and directories
- don't really exist in WORKING. */
- if ((revision->kind != svn_opt_revision_working &&
- entry->schedule == svn_wc_schedule_add) ||
- (revision->kind == svn_opt_revision_working &&
- entry->schedule == svn_wc_schedule_delete))
+ /* Don't export the 'working' version of an item that is scheduled for
+ deletion, or the 'base' version of an item that is scheduled for
+ addition, as these versions are not deemed to really exist. */
+ if (! svn_cl__item_exists_in_local_revision(entry, revision))
return SVN_NO_ERROR;
if (entry->kind == svn_node_dir)
Index: subversion/libsvn_client/mergeinfo.c
===================================================================
--- subversion/libsvn_client/mergeinfo.c (revision 32317)
+++ subversion/libsvn_client/mergeinfo.c (working copy)
@@ -53,12 +53,16 @@ svn_client__parse_mergeinfo(svn_mergeinf
{
apr_hash_t *props = apr_hash_make(pool);
const svn_string_t *propval;
+ /* ### Shouldn't be here. Make the caller pass in a revision. */
+ static const svn_opt_revision_t base_rev = { svn_opt_revision_base, { 0 }};
+ static const svn_opt_revision_t wrk_rev = { svn_opt_revision_working, { 0 }};
/* ### Use svn_wc_prop_get() would actually be sufficient for now.
### 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 ? &base_rev : &wrk_rev,
+ entry, adm_access,
svn_depth_empty, NULL, ctx, pool));
propval = apr_hash_get(props, wcpath, APR_HASH_KEY_STRING);
if (propval)
@@ -363,6 +367,8 @@ svn_client__get_wc_or_repos_mergeinfo(sv
if (entry->schedule != svn_wc_schedule_add)
{
apr_hash_t *props = apr_hash_make(pool);
+ static const svn_opt_revision_t base_rev
+ = { svn_opt_revision_base, { 0 }};
/* Get the pristine SVN_PROP_MERGEINFO.
If it exists, then it should have been deleted by the local
@@ -370,7 +376,7 @@ 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, &base_rev, 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 32317)
+++ subversion/libsvn_client/prop_commands.c (working copy)
@@ -22,6 +22,8 @@
/*** Includes. ***/
+#include
+
#define APR_WANT_STRFUNC
#include
@@ -552,8 +554,9 @@ 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.
+/* 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 ### or return an error.
*
* The keys of *PROPS will be 'const char *' property names, and the
* values 'const svn_string_t *' property values. Allocate *PROPS
@@ -562,43 +565,33 @@ svn_client_revprop_set(const char *propn
static svn_error_t *
pristine_or_working_props(apr_hash_t **props,
const char *path,
+ const svn_opt_revision_t *revision,
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;
+ svn_wc_rev_kind_t wc_rev_kind = svn_cl__wc_rev_kind_from_rev(revision);
+ 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 ### or return an error.
+ * 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,
+ const svn_opt_revision_t *revision,
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, revision, 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 +601,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. */
+ const svn_opt_revision_t *revision; /* Which version of the 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 +612,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
@@ -642,8 +635,7 @@ propget_walk_cb(const char *path,
return SVN_NO_ERROR;
/* 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))
+ if (! svn_cl__item_exists_in_local_revision(entry, wb->revision))
return SVN_NO_ERROR;
/* If our entry doesn't pass changelist filtering, get outta here. */
@@ -651,7 +643,7 @@ propget_walk_cb(const char *path,
return SVN_NO_ERROR;
SVN_ERR(pristine_or_working_propval(&propval, wb->propname, path,
- wb->base_access, wb->pristine,
+ wb->base_access, wb->revision,
pool));
if (propval)
@@ -811,7 +803,7 @@ svn_error_t *
svn_client__get_prop_from_wc(apr_hash_t *props,
const char *propname,
const char *target,
- svn_boolean_t pristine,
+ const svn_opt_revision_t *revision,
const svn_wc_entry_t *entry,
svn_wc_adm_access_t *adm_access,
svn_depth_t depth,
@@ -836,7 +828,7 @@ svn_client__get_prop_from_wc(apr_hash_t
depth = svn_depth_infinity;
wb.propname = propname;
- wb.pristine = pristine;
+ wb.revision = revision;
wb.base_access = adm_access;
wb.changelist_hash = changelist_hash;
wb.props = props;
@@ -886,7 +878,6 @@ svn_client_propget3(apr_hash_t **props,
{
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,
@@ -899,12 +890,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,
+ revision, node, adm_access,
depth, changelists, ctx, pool));
SVN_ERR(svn_wc_adm_close(adm_access));
@@ -1155,7 +1142,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. */
+ const svn_opt_revision_t *revision; /* Which version of the 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. */
@@ -1167,7 +1154,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,
@@ -1186,8 +1173,7 @@ proplist_walk_cb(const char *path,
return SVN_NO_ERROR;
/* 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))
+ if (! svn_cl__item_exists_in_local_revision(entry, wb->revision))
return SVN_NO_ERROR;
/* If our entry doesn't pass changelist filtering, get outta here. */
@@ -1196,8 +1182,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->revision,
+ wb->base_access, pool));
SVN_ERR(call_receiver(path, hash, wb->receiver, wb->receiver_baton,
pool));
@@ -1231,7 +1217,6 @@ svn_client_proplist3(const char *path_or
&& SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(peg_revision->kind)
&& SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(revision->kind))
{
- svn_boolean_t pristine;
int levels_to_lock = SVN_WC__LEVELS_TO_LOCK_FROM_DEPTH(depth);
const svn_wc_entry_t *entry;
apr_hash_t *changelist_hash = NULL;
@@ -1243,16 +1228,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));
@@ -1265,7 +1240,7 @@ svn_client_proplist3(const char *path_or
struct proplist_walk_baton wb;
wb.base_access = adm_access;
- wb.pristine = pristine;
+ wb.revision = revision;
wb.changelist_hash = changelist_hash;
wb.receiver = receiver;
wb.receiver_baton = receiver_baton;
@@ -1279,8 +1254,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, revision,
+ adm_access, pool));
SVN_ERR(call_receiver(path_or_url, hash,
receiver, receiver_baton, pool));
Index: subversion/libsvn_client/revisions.c
===================================================================
--- subversion/libsvn_client/revisions.c (revision 32317)
+++ subversion/libsvn_client/revisions.c (working copy)
@@ -73,6 +73,9 @@ svn_client__get_revision_number(svn_revn
case svn_opt_revision_working:
case svn_opt_revision_base:
case svn_opt_revision_previous:
+ case svn_opt_revision_old:
+ case svn_opt_revision_theirs:
+ case svn_opt_revision_mine:
{
svn_wc_adm_access_t *adm_access;
const svn_wc_entry_t *ent;
@@ -92,7 +95,40 @@ svn_client__get_revision_number(svn_revn
{
*revnum = ent->revision;
}
- else
+ else if (revision->kind == svn_opt_revision_old)
+ {
+ SVN_ERR_MALFUNCTION();
+ /* ###
+ if (! SVN_IS_VALID_REVNUM(ent->old_rev))
+ return svn_error_createf(SVN_ERR_CLIENT_BAD_REVISION, NULL,
+ _("Path '%s' has no conflict-old "
+ "revision"), path);
+ *revnum = ent->old_rev;
+ */
+ }
+ else if (revision->kind == svn_opt_revision_theirs)
+ {
+ SVN_ERR_MALFUNCTION();
+ /* ###
+ if (! SVN_IS_VALID_REVNUM(ent->new_rev))
+ return svn_error_createf(SVN_ERR_CLIENT_BAD_REVISION, NULL,
+ _("Path '%s' has no conflict-theirs "
+ "revision"), path);
+ *revnum = ent->new_rev;
+ */
+ }
+ else if (revision->kind == svn_opt_revision_mine)
+ {
+ SVN_ERR_MALFUNCTION();
+ /* ###
+ if (! SVN_IS_VALID_REVNUM(ent->wrk_rev))
+ return svn_error_createf(SVN_ERR_CLIENT_BAD_REVISION, NULL,
+ _("Path '%s' has no conflict-mine "
+ "revision"), path);
+ *revnum = ent->wrk_rev;
+ */
+ }
+ else /* committed / previous */
{
if (! SVN_IS_VALID_REVNUM(ent->cmt_rev))
return svn_error_createf(SVN_ERR_CLIENT_BAD_REVISION, NULL,
Index: subversion/libsvn_client/util.c
===================================================================
--- subversion/libsvn_client/util.c (revision 32317)
+++ subversion/libsvn_client/util.c (working copy)
@@ -348,3 +348,51 @@ svn_cl__rev_default_to_peg(const svn_opt
return peg_revision;
return revision;
}
+
+svn_boolean_t
+svn_cl__item_exists_in_local_revision(const svn_wc_entry_t *entry,
+ const svn_opt_revision_t *revision)
+{
+ switch (revision->kind)
+ {
+ case svn_opt_revision_working:
+ return (entry->schedule != svn_wc_schedule_delete);
+ case svn_opt_revision_base:
+ return (entry->schedule != svn_wc_schedule_add);
+ case svn_opt_revision_old:
+ return (entry->conflict_old != NULL);
+ case svn_opt_revision_theirs:
+ return (entry->conflict_new != NULL);
+ case svn_opt_revision_mine:
+ return (entry->conflict_wrk != NULL);
+ default:
+ return FALSE;
+ }
+}
+
+svn_wc_rev_kind_t
+svn_cl__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:
+ case svn_opt_revision_unspecified:
+ return svn_wc_rev_kind_working;
+
+ case svn_opt_revision_old:
+ return svn_wc_rev_kind_conflict_old;
+
+ case svn_opt_revision_theirs:
+ return svn_wc_rev_kind_conflict_new;
+
+ case svn_opt_revision_mine:
+ return svn_wc_rev_kind_conflict_wrk;
+
+ default:
+ assert(FALSE);
+ }
+}
Index: subversion/libsvn_subr/opt.c
===================================================================
--- subversion/libsvn_subr/opt.c (revision 32317)
+++ subversion/libsvn_subr/opt.c (working copy)
@@ -550,6 +550,12 @@ svn_opt_subcommand_help(const char *subc
*
* - For "committed", set REVISION->kind to svn_opt_revision_committed.
*
+ * - For "old", set REVISION->kind to svn_opt_revision_old.
+ *
+ * - For "theirs", set REVISION->kind to svn_opt_revision_theirs.
+ *
+ * - For "mine", set REVISION->kind to svn_opt_revision_mine.
+ *
* If match, return 0, else return -1 and don't touch REVISION.
*/
static int
@@ -571,6 +577,18 @@ revision_from_word(svn_opt_revision_t *r
{
revision->kind = svn_opt_revision_committed;
}
+ else if (svn_cstring_casecmp(word, "old") == 0)
+ {
+ revision->kind = svn_opt_revision_old;
+ }
+ else if (svn_cstring_casecmp(word, "theirs") == 0)
+ {
+ revision->kind = svn_opt_revision_theirs;
+ }
+ else if (svn_cstring_casecmp(word, "mine") == 0)
+ {
+ revision->kind = svn_opt_revision_mine;
+ }
else
return -1;
Index: subversion/libsvn_wc/adm_files.c
===================================================================
--- subversion/libsvn_wc/adm_files.c (revision 32317)
+++ subversion/libsvn_wc/adm_files.c (working copy)
@@ -366,20 +366,56 @@ svn_wc__sync_text_base(const char *path,
}
const char *
-svn_wc__text_base_path(const char *path,
- svn_boolean_t tmp,
- apr_pool_t *pool)
+svn_wc__text_path(const char *path,
+ svn_wc_adm_access_t *adm_access,
+ svn_wc__props_kind_t kind,
+ svn_boolean_t tmp,
+ apr_pool_t *pool)
{
const char *newpath, *base_name;
+ const svn_wc_entry_t *entry;
+ const char *extension;
+
+ switch (kind)
+ {
+ case svn_wc__props_base:
+ extension = SVN_WC__BASE_EXT;
+ break;
+ case svn_wc__props_revert:
+ extension = SVN_WC__REVERT_EXT;
+ break;
+
+ case svn_wc__props_working:
+ assert(! tmp);
+ return path;
+
+ case svn_wc__props_conflict_old:
+ /* SVN_ERR( */ svn_wc_entry(&entry, path, adm_access, TRUE, pool);
+ return entry->conflict_old;
+ case svn_wc__props_conflict_new:
+ /* SVN_ERR( */ svn_wc_entry(&entry, path, adm_access, TRUE, pool);
+ return entry->conflict_new;
+ case svn_wc__props_conflict_wrk:
+ /* SVN_ERR( */ svn_wc_entry(&entry, path, adm_access, TRUE, pool);
+ return entry->conflict_wrk;
+
+ case svn_wc__props_wcprop:
+ default:
+ assert(FALSE);
+ }
svn_path_split(path, &newpath, &base_name, pool);
- return extend_with_adm_name(newpath,
- SVN_WC__BASE_EXT,
- tmp,
- pool,
- SVN_WC__ADM_TEXT_BASE,
- base_name,
- NULL);
+
+ return extend_with_adm_name(newpath, extension, tmp, pool,
+ SVN_WC__ADM_TEXT_BASE, base_name, NULL);
+}
+
+const char *
+svn_wc__text_base_path(const char *path,
+ svn_boolean_t tmp,
+ apr_pool_t *pool)
+{
+ return svn_wc__text_path(path, NULL, svn_wc__props_base, tmp, pool);
}
const char *
@@ -387,16 +423,7 @@ svn_wc__text_revert_path(const char *pat
svn_boolean_t tmp,
apr_pool_t *pool)
{
- const char *newpath, *base_name;
-
- svn_path_split(path, &newpath, &base_name, pool);
- return extend_with_adm_name(newpath,
- SVN_WC__REVERT_EXT,
- tmp,
- pool,
- SVN_WC__ADM_TEXT_BASE,
- base_name,
- NULL);
+ return svn_wc__text_path(path, NULL, svn_wc__props_revert, tmp, pool);
}
svn_error_t *
@@ -413,7 +440,10 @@ svn_wc__prop_path(const char **prop_path
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_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_WRK /* svn_wc__props_conflict_wrk */
};
*prop_path = extend_with_adm_name
@@ -430,14 +460,20 @@ svn_wc__prop_path(const char **prop_path
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__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_WRK_EXT /* svn_wc__props_conflict_wrk */
};
static const char * dirs[] = {
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_PROPS, /* svn_wc__props_working */
+ SVN_WC__ADM_PROPS, /* svn_wc__props_conflict_old */
+ SVN_WC__ADM_PROPS, /* svn_wc__props_conflict_new */
+ SVN_WC__ADM_PROPS, /* svn_wc__props_conflict_wrk */
};
const char *base_name;
Index: subversion/libsvn_wc/adm_files.h
===================================================================
--- subversion/libsvn_wc/adm_files.h (revision 32317)
+++ subversion/libsvn_wc/adm_files.h (working copy)
@@ -100,6 +100,19 @@ svn_wc__text_revert_path(const char *pat
apr_pool_t *pool);
+/* Return the path to PATH's KIND file. KIND may not be the 'wcprop' kind.
+ * If TMP is true, return a path to a temporary file of this kind rather than
+ * the permanent one.
+ * If KIND is the 'working' kind, then TMP may not be true.
+ * ### TODO: KIND is designed for properties, and being abused for this. */
+const char *
+svn_wc__text_path(const char *path,
+ svn_wc_adm_access_t *adm_access,
+ svn_wc__props_kind_t kind,
+ svn_boolean_t tmp,
+ apr_pool_t *pool);
+
+
/* Set *PROP_PATH to PATH's PROPS_KIND properties file.
If TMP is set, return a path to the tmp working property file.
PATH can be a directory or file, and even have changed w.r.t. the
Index: subversion/libsvn_wc/adm_ops.c
===================================================================
--- subversion/libsvn_wc/adm_ops.c (revision 32317)
+++ subversion/libsvn_wc/adm_ops.c (working copy)
@@ -1900,7 +1900,8 @@ revert_admin_things(svn_wc_adm_access_t
}
/* Remove the property conflict file if the entry lists one (and it
- exists) */
+ exists). Also in this case remove the property conflict artifact
+ files. */
if (entry->prejfile)
{
flags |= SVN_WC__ENTRY_MODIFY_PREJFILE;
@@ -1909,6 +1910,14 @@ revert_admin_things(svn_wc_adm_access_t
(&log_accum, adm_access,
svn_path_join(svn_wc_adm_access_path(adm_access),
entry->prejfile, pool), pool));
+#if 0 /* ### unfinished */
+ SVN_ERR(svn_wc__loggy_remove
+ (&log_accum, adm_access,
+ svn_path_join(svn_wc_adm_access_path(adm_access),
+ entry->pconflict_old, pool), pool));
+ ..._new
+ ..._wrk
+#endif
}
/* Clean up the copied state if this is a replacement. */
@@ -2348,6 +2357,27 @@ svn_wc_get_pristine_copy_path(const char
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_wc_get_text_path(const char **text_path,
+ const char *path,
+ svn_wc_rev_kind_t rev_kind,
+ svn_wc_adm_access_t *adm_access,
+ apr_pool_t *pool)
+{
+ static svn_wc__props_kind_t kinds[] =
+ {
+ svn_wc__props_base, /* svn_wc_rev_kind_pristine */
+ svn_wc__props_working, /* svn_wc_rev_kind_working */
+ svn_wc__props_conflict_old, /* svn_wc_rev_kind_conflict_old */
+ svn_wc__props_conflict_new, /* svn_wc_rev_kind_conflict_new */
+ svn_wc__props_conflict_wrk /* svn_wc_rev_kind_conflict_wrk */
+ };
+
+ *text_path = svn_wc__text_path(path, adm_access, kinds[rev_kind], FALSE,
+ pool);
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_wc_remove_from_revision_control(svn_wc_adm_access_t *adm_access,
Index: subversion/libsvn_wc/diff.c
===================================================================
--- subversion/libsvn_wc/diff.c (revision 32317)
+++ subversion/libsvn_wc/diff.c (working copy)
@@ -146,7 +146,8 @@ struct edit_baton {
svn_boolean_t ignore_ancestry;
/* Possibly diff repos against text-bases instead of working files. */
- svn_boolean_t use_text_base;
+ svn_boolean_t use_text_base; /* ### deprecated in favour of: */
+ svn_wc_rev_kind_t wc_rev_kind;
/* Possibly show the diffs backwards. */
svn_boolean_t reverse_order;
@@ -260,7 +261,7 @@ make_editor_baton(struct edit_baton **ed
void *callback_baton,
svn_depth_t depth,
svn_boolean_t ignore_ancestry,
- svn_boolean_t use_text_base,
+ svn_wc_rev_kind_t wc_rev_kind,
svn_boolean_t reverse_order,
const apr_array_header_t *changelists,
apr_pool_t *pool)
@@ -279,7 +280,9 @@ make_editor_baton(struct edit_baton **ed
eb->callback_baton = callback_baton;
eb->depth = depth;
eb->ignore_ancestry = ignore_ancestry;
- eb->use_text_base = use_text_base;
+ eb->use_text_base = (wc_rev_kind == svn_wc_rev_kind_pristine); /* ### deprecated */
+ SVN_ERR_ASSERT(wc_rev_kind == svn_wc_rev_kind_pristine || wc_rev_kind == svn_wc_rev_kind_working); /* ### */
+ eb->wc_rev_kind = wc_rev_kind,
eb->reverse_order = reverse_order;
eb->changelist_hash = changelist_hash;
eb->pool = pool;
@@ -1776,13 +1779,13 @@ callbacks2_wrap(const svn_wc_diff_callba
/* Create a diff editor and baton. */
svn_error_t *
-svn_wc_get_diff_editor5(svn_wc_adm_access_t *anchor,
+svn_wc_get_diff_editor5a(svn_wc_adm_access_t *anchor,
const char *target,
const svn_wc_diff_callbacks3_t *callbacks,
void *callback_baton,
svn_depth_t depth,
svn_boolean_t ignore_ancestry,
- svn_boolean_t use_text_base,
+ svn_wc_rev_kind_t wc_rev_kind,
svn_boolean_t reverse_order,
svn_cancel_func_t cancel_func,
void *cancel_baton,
@@ -1797,7 +1800,7 @@ svn_wc_get_diff_editor5(svn_wc_adm_acces
const svn_delta_editor_t *inner_editor;
SVN_ERR(make_editor_baton(&eb, anchor, target, callbacks, callback_baton,
- depth, ignore_ancestry, use_text_base,
+ depth, ignore_ancestry, wc_rev_kind,
reverse_order, changelists, pool));
tree_editor = svn_delta_default_editor(eb->pool);
@@ -1838,6 +1841,29 @@ svn_wc_get_diff_editor5(svn_wc_adm_acces
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_wc_get_diff_editor5(svn_wc_adm_access_t *anchor,
+ const char *target,
+ const svn_wc_diff_callbacks3_t *callbacks,
+ void *callback_baton,
+ svn_depth_t depth,
+ svn_boolean_t ignore_ancestry,
+ svn_boolean_t use_text_base,
+ svn_boolean_t reverse_order,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ const apr_array_header_t *changelists,
+ const svn_delta_editor_t **editor,
+ void **edit_baton,
+ apr_pool_t *pool)
+{
+ return svn_wc_get_diff_editor5a(anchor, target, callbacks, callback_baton,
+ depth, ignore_ancestry,
+ use_text_base ? svn_wc_rev_kind_pristine
+ : svn_wc_rev_kind_working,
+ reverse_order, cancel_func, cancel_baton,
+ changelists, editor, edit_baton, pool);
+}
svn_error_t *
svn_wc_get_diff_editor4(svn_wc_adm_access_t *anchor,
@@ -1948,10 +1974,12 @@ svn_wc_get_diff_editor(svn_wc_adm_access
}
-/* Compare working copy against the text-base. */
+/* Compare one WC version against another WC version of the same node. */
svn_error_t *
-svn_wc_diff5(svn_wc_adm_access_t *anchor,
+svn_wc_diff5a(svn_wc_adm_access_t *anchor,
const char *target,
+ svn_wc_rev_kind_t rev_kind_from,
+ svn_wc_rev_kind_t rev_kind_to,
const svn_wc_diff_callbacks3_t *callbacks,
void *callback_baton,
svn_depth_t depth,
@@ -1965,9 +1993,14 @@ svn_wc_diff5(svn_wc_adm_access_t *anchor
const char *target_path;
svn_wc_adm_access_t *adm_access;
+ if (rev_kind_from != svn_wc_rev_kind_pristine
+ || rev_kind_to != svn_wc_rev_kind_working)
+ return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+ "Diff in WC can only be BASE->WORKING as yet");
+
SVN_ERR(make_editor_baton(&eb, anchor, target, callbacks, callback_baton,
- depth, ignore_ancestry, FALSE, FALSE,
- changelists, pool));
+ depth, ignore_ancestry, svn_wc_rev_kind_working,
+ FALSE, changelists, pool));
target_path = svn_path_join(svn_wc_adm_access_path(anchor), target,
eb->pool);
@@ -1987,6 +2020,22 @@ svn_wc_diff5(svn_wc_adm_access_t *anchor
return SVN_NO_ERROR;
}
+/* Compare working copy against the text-base. */
+svn_error_t *
+svn_wc_diff5(svn_wc_adm_access_t *anchor,
+ const char *target,
+ const svn_wc_diff_callbacks3_t *callbacks,
+ void *callback_baton,
+ svn_depth_t depth,
+ svn_boolean_t ignore_ancestry,
+ const apr_array_header_t *changelists,
+ apr_pool_t *pool)
+{
+ return svn_wc_diff5a(anchor, target, svn_wc_rev_kind_pristine,
+ svn_wc_rev_kind_working, callbacks, callback_baton,
+ depth, ignore_ancestry, changelists, pool);
+}
+
svn_error_t *
svn_wc_diff4(svn_wc_adm_access_t *anchor,
const char *target,
Index: subversion/libsvn_wc/props.c
===================================================================
--- subversion/libsvn_wc/props.c (revision 32317)
+++ subversion/libsvn_wc/props.c (working copy)
@@ -254,12 +254,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 =
@@ -270,6 +273,8 @@ svn_wc__load_props(apr_hash_t **base_pro
SVN_ERR(svn_wc_entry(&entry, path, adm_access, FALSE, pool));
/* If there is no entry, we just return empty hashes, since the
property merging can use this function when there is no entry. */
+ /* ### Huh? Explain in terms of API promise, not by
+ * allusion to what something else does. */
if (! entry)
{
if (base_props_p)
@@ -278,6 +283,12 @@ svn_wc__load_props(apr_hash_t **base_pro
*props_p = apr_hash_make(pool);
if (revert_props_p)
*revert_props_p = apr_hash_make(pool);
+ if (conflict_old_props_p)
+ *conflict_old_props_p = apr_hash_make(pool);
+ if (conflict_new_props_p)
+ *conflict_new_props_p = apr_hash_make(pool);
+ if (conflict_mine_props_p)
+ *conflict_mine_props_p = apr_hash_make(pool);
return SVN_NO_ERROR;
}
@@ -331,9 +342,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_wrk, 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);
+}
+
/*---------------------------------------------------------------------*/
@@ -1227,10 +1281,15 @@ write_tmp_file(const char **new_path,
/* Helper function for the three apply_* functions below, used when
- * merging properties together.
+ * merging properties together. Handle a conflict on one property by using
+ * the resolver callback function (if provided) to get the desired result
+ * into WORKING_PROPS. If successful, set *CONFLICT_REMAINS to false. If the
+ * resolver function is not provided or does not resolve the conflict then
+ * set *CONFLICT_REMAINS to true.
*
* Given property PROPNAME on PATH, and four possible property values,
- * generate four tmpfiles and pass them to CONFLICT_FUNC callback.
+ * put three of them in temporary files and pass those and a temporary file
+ * for the merged result to the 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.)
@@ -1244,7 +1303,9 @@ write_tmp_file(const char **new_path,
* '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.
*
*/
@@ -1324,7 +1385,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;
@@ -1838,6 +1899,31 @@ apply_single_prop_change(svn_wc_notify_s
}
+/* Install into the administrative area given by ADM_ACCESS three property
+ * hash files containing the conflict artifact property sets OLD_PROPHASH,
+ * NEW_PROPHASH and MINE_PROPHASH for the WC item PATH.
+ * Use POOL for temporary allocations. */
+static svn_error_t *
+install_prop_conflict_files(svn_wc_adm_access_t *adm_access,
+ const char *path,
+ apr_hash_t *old_prophash,
+ apr_hash_t *new_prophash,
+ apr_hash_t *mine_prophash,
+ apr_pool_t *pool)
+{
+ svn_stringbuf_t *log_accum;
+
+ SVN_ERR(install_props_file(&log_accum, adm_access, path, old_prophash,
+ svn_wc__props_conflict_old, pool));
+ SVN_ERR(install_props_file(&log_accum, adm_access, path, new_prophash,
+ svn_wc__props_conflict_new, pool));
+ SVN_ERR(install_props_file(&log_accum, adm_access, path, mine_prophash,
+ svn_wc__props_conflict_wrk, pool));
+ SVN_ERR(svn_wc__write_log(adm_access, 0, log_accum, pool));
+ SVN_ERR(svn_wc__run_log(adm_access, NULL, pool));
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_wc__merge_props(svn_wc_notify_state_t *state,
svn_wc_adm_access_t *adm_access,
@@ -1859,6 +1945,7 @@ svn_wc__merge_props(svn_wc_notify_state_
const char *reject_path = NULL;
apr_file_t *reject_tmp_fp = NULL; /* the temporary conflicts file */
const char *reject_tmp_path = NULL;
+ apr_hash_t *server_newprops; /* the new, complete set on the server side */
if (! svn_path_is_child(svn_wc_adm_access_path(adm_access), path, NULL))
is_dir = TRUE;
@@ -1871,7 +1958,10 @@ svn_wc__merge_props(svn_wc_notify_state_
working_props ? NULL : &working_props,
NULL, adm_access, path, pool));
if (!server_baseprops)
- server_baseprops = base_props;
+ server_baseprops = apr_hash_copy(pool, base_props); /* shallow copy */
+
+ /* Make SERVER_NEWPROPS from the old ones, and modify by each of the changes. */
+ server_newprops = apr_hash_copy(pool, server_baseprops); /* shallow copy */
if (state)
{
@@ -1882,7 +1972,12 @@ svn_wc__merge_props(svn_wc_notify_state_
*state = svn_wc_notify_state_unchanged;
}
- /* Looping over the array of incoming propchanges we want to apply: */
+ /* Looping over the array of incoming propchanges we want to apply:
+ * Don't modify SERVER_BASEPROPS.
+ * Populate SERVER_NEWPROPS.
+ * Update BASE_PROPS if this is a "base merge".
+ * Merge changes into WORKING_PROPS.
+ */
for (i = 0; i < propchanges->nelts; i++)
{
const char *propname;
@@ -1902,6 +1997,8 @@ svn_wc__merge_props(svn_wc_notify_state_
working_val = apr_hash_get(working_props, propname, APR_HASH_KEY_STRING);
base_val = apr_hash_get(base_props, propname, APR_HASH_KEY_STRING);
+ apr_hash_set(server_newprops, propname, APR_HASH_KEY_STRING, to_val);
+
if (base_merge)
apr_hash_set(base_props, propname, APR_HASH_KEY_STRING, to_val);
@@ -2022,6 +2119,10 @@ svn_wc__merge_props(svn_wc_notify_state_
pool));
}
+ /* Save the old/new/mine conflict artifact files. */
+ SVN_ERR(install_prop_conflict_files(adm_access, path,
+ server_baseprops, server_newprops,
+ working_props, pool));
} /* if (reject_tmp_fp) */
return SVN_NO_ERROR;
@@ -2206,10 +2307,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;
@@ -2229,7 +2331,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_wrk:
+ SVN_ERR(svn_wc__load_props2(NULL, NULL, NULL, NULL, NULL, props,
+ adm_access, path, pool));
+ break;
+ default:
+ SVN_ERR_MALFUNCTION();
+ }
+ 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 32317)
+++ 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_wrk
} svn_wc__props_kind_t;
@@ -216,6 +219,23 @@ svn_wc__load_props(apr_hash_t **base_pro
const char *path,
apr_pool_t *pool);
+/* Load the base, working, revert, old, new, mine props for PATH in ADM_ACCESS,
+ * returning them in *BASE_PROPS_P, *PROPS_P, *REVERT_PROPS_P,
+ * *CONFLICT_OLD_PROPS_, *CONFLICT_NEW_PROPS_PP, *CONFLICT_MINE_PROPS_P
+ * respectively. Any of these may be null.
+ * If any requested set of properties is not available, ###?
+ * 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 32317)
+++ subversion/libsvn_wc/wc.h (working copy)
@@ -38,6 +38,9 @@ extern "C" {
#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__CNFL_OLD_EXT ".svn-c-old"
+#define SVN_WC__CNFL_NEW_EXT ".svn-c-new"
+#define SVN_WC__CNFL_WRK_EXT ".svn-c-wrk"
@@ -145,6 +148,9 @@ struct svn_wc_traversal_info_t
#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-c-old"
+#define SVN_WC__ADM_DIR_PROP_CNFL_NEW "dir-prop-c-new"
+#define SVN_WC__ADM_DIR_PROP_CNFL_WRK "dir-prop-c-wrk"
#define SVN_WC__ADM_ALL_WCPROPS "all-wcprops"
#define SVN_WC__ADM_LOG "log"
#define SVN_WC__ADM_KILLME "KILLME"
Index: subversion/svn/diff-cmd.c
===================================================================
--- subversion/svn/diff-cmd.c (revision 32317)
+++ subversion/svn/diff-cmd.c (working copy)
@@ -296,9 +296,15 @@ svn_cl__diff(apr_getopt_t *os,
/* Determine if we need to do pegged diffs. */
if ((opt_state->start_revision.kind != svn_opt_revision_base
- && opt_state->start_revision.kind != svn_opt_revision_working)
+ && opt_state->start_revision.kind != svn_opt_revision_working
+ && opt_state->start_revision.kind != svn_opt_revision_old
+ && opt_state->start_revision.kind != svn_opt_revision_theirs
+ && opt_state->start_revision.kind != svn_opt_revision_mine)
|| (opt_state->end_revision.kind != svn_opt_revision_base
- && opt_state->end_revision.kind != svn_opt_revision_working))
+ && opt_state->end_revision.kind != svn_opt_revision_working
+ && opt_state->end_revision.kind != svn_opt_revision_old
+ && opt_state->end_revision.kind != svn_opt_revision_theirs
+ && opt_state->end_revision.kind != svn_opt_revision_mine))
pegged_diff = TRUE;
}