You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/09/27 23:29:22 UTC
svn commit: r1527088 - /subversion/trunk/subversion/libsvn_fs_x/tree.c
Author: stefan2
Date: Fri Sep 27 21:29:22 2013
New Revision: 1527088
URL: http://svn.apache.org/r1527088
Log:
Sync FSX fs_move code with latest FSFS changes.
* subversion/libsvn_fs_x/tree.c
(is_changed_node): new utility
(copy_helper): allow moving from older revisions if there were
no intermittent changes
Modified:
subversion/trunk/subversion/libsvn_fs_x/tree.c
Modified: subversion/trunk/subversion/libsvn_fs_x/tree.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/tree.c?rev=1527088&r1=1527087&r2=1527088&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/tree.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/tree.c Fri Sep 27 21:29:22 2013
@@ -132,6 +132,12 @@ static svn_error_t *make_txn_root(svn_fs
apr_uint32_t flags,
apr_pool_t *pool);
+static svn_error_t *x_closest_copy(svn_fs_root_t **root_p,
+ const char **path_p,
+ svn_fs_root_t *root,
+ const char *path,
+ apr_pool_t *pool);
+
/*** Node Caching ***/
@@ -2344,6 +2350,65 @@ typedef enum copy_type_t
copy_type_move
} copy_type_t;
+/* Set CHANGES to TRUE if PATH in ROOT is unchanged in REVISION if the
+ same files system. If the content is identical, parent path copies and
+ deletions still count as changes. Use POOL for temporary allocations.
+ Not that we will return an error if PATH does not exist in ROOT or
+ REVISION- */
+static svn_error_t *
+is_changed_node(svn_boolean_t *changed,
+ svn_fs_root_t *root,
+ const char *path,
+ svn_revnum_t revision,
+ apr_pool_t *pool)
+{
+ dag_node_t *node, *rev_node;
+ svn_fs_root_t *rev_root;
+ svn_fs_root_t *copy_from_root1, *copy_from_root2;
+ const char *copy_from_path1, *copy_from_path2;
+
+ SVN_ERR(svn_fs_x__revision_root(&rev_root, root->fs, revision, pool));
+
+ /* Get the NODE for FROM_PATH in FROM_ROOT.*/
+ SVN_ERR(get_dag(&node, root, path, TRUE, pool));
+ SVN_ERR(get_dag(&rev_node, rev_root, path, TRUE, pool));
+
+ /* different ID -> got changed */
+ if (!svn_fs_fs__id_eq(svn_fs_fs__dag_get_id(node),
+ svn_fs_fs__dag_get_id(rev_node)))
+ {
+ *changed = TRUE;
+ return SVN_NO_ERROR;
+ }
+
+ /* same node. might still be a lazy copy with separate history */
+ SVN_ERR(x_closest_copy(©_from_root1, ©_from_path1, root,
+ path, pool));
+ SVN_ERR(x_closest_copy(©_from_root2, ©_from_path2, rev_root,
+ path, pool));
+
+ if (copy_from_root1 == NULL && copy_from_root2 == NULL)
+ {
+ /* never copied -> same line of history */
+ *changed = FALSE;
+ }
+ else if (copy_from_root1 != NULL && copy_from_root2 != NULL)
+ {
+ /* both got copied. At the same time & location? */
+ *changed = (copy_from_root1->rev != copy_from_root2->rev)
+ || strcmp(copy_from_path1, copy_from_path2);
+ }
+ else
+ {
+ /* one is a copy while the other one is not
+ * -> different lines of history */
+ *changed = TRUE;
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
/* Copy the node at FROM_PATH under FROM_ROOT to TO_PATH under
TO_ROOT. COPY_TYPE determines whether then the copy is recorded in
the copies table and whether it is being marked as a move.
@@ -2381,10 +2446,36 @@ copy_helper(svn_fs_root_t *from_root,
(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
_("Copy immutable tree not supported"));
- if (copy_type == copy_type_move && from_root->rev != txn_id->revision)
- return svn_error_create
- (SVN_ERR_UNSUPPORTED_FEATURE, NULL,
- _("Move from non-HEAD revision not currently supported"));
+ /* move support comes with a number of conditions ... */
+ if (copy_type == copy_type_move)
+ {
+ /* if we don't copy from the TXN's base rev, check that the path has
+ not been touched in that revision range */
+ if (from_root->rev != txn_id->revision)
+ {
+ svn_boolean_t changed = TRUE;
+ svn_error_t *err = is_changed_node(&changed, from_root,
+ from_path, txn_id->revision,
+ pool);
+
+ /* Only "not found" is considered to be caused by out-of-date-ness.
+ Everything else means something got very wrong ... */
+ if (err && err->apr_err != SVN_ERR_FS_NOT_FOUND)
+ return svn_error_trace(err);
+
+ /* here error means "out of data" */
+ if (err || changed)
+ {
+ svn_error_clear(err);
+ return svn_error_create(SVN_ERR_FS_OUT_OF_DATE, NULL,
+ _("Move-from node is out-of-date"));
+ }
+
+ /* always move from the txn's base rev */
+ SVN_ERR(svn_fs_fs__revision_root(&from_root, from_root->fs,
+ txn_id->revision, pool));
+ }
+ }
/* Get the NODE for FROM_PATH in FROM_ROOT.*/
SVN_ERR(get_dag(&from_node, from_root, from_path, TRUE, pool));