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/10/16 01:44:46 UTC
svn commit: r1532597 [5/10] - in /subversion/branches/log-addressing: ./
build/ac-macros/ build/generator/ build/generator/templates/ build/win32/
contrib/client-side/emacs/ notes/ subversion/bindings/javahl/native/
subversion/bindings/javahl/src/org/a...
Modified: subversion/branches/log-addressing/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_fs/tree.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_fs/tree.c Tue Oct 15 23:44:41 2013
@@ -60,6 +60,7 @@
#include "pack.h"
#include "temp_serializer.h"
#include "transaction.h"
+#include "util.h"
#include "private/svn_mergeinfo_private.h"
#include "private/svn_subr_private.h"
@@ -132,6 +133,12 @@ static svn_error_t *make_txn_root(svn_fs
apr_uint32_t flags,
apr_pool_t *pool);
+static svn_error_t *fs_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 ***/
@@ -2244,7 +2251,7 @@ fs_dir_optimal_order(apr_array_header_t
{
*ordered_p
= svn_fs_fs__order_dir_entries(root->fs, entries,
- svn_fs_revision_root_revision(root),
+ root->rev,
pool);
return SVN_NO_ERROR;
@@ -2388,15 +2395,89 @@ fs_same_p(svn_boolean_t *same_p,
return SVN_NO_ERROR;
}
+/* Type to select the various behavioral modes of copy_helper.
+ */
+typedef enum copy_type_t
+{
+ /* add without history */
+ copy_type_plain_add,
+
+ /* add with history */
+ copy_type_add_with_history,
+
+ /* move (always with history) */
+ 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_fs__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(fs_closest_copy(©_from_root1, ©_from_path1, root,
+ path, pool));
+ SVN_ERR(fs_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. If PRESERVE_HISTORY is set, then the copy is recorded in
- the copies table. Perform temporary allocations in POOL. */
+ TO_ROOT. COPY_TYPE determines whether then the copy is recorded in
+ the copies table and whether it is being marked as a move.
+ Perform temporary allocations in POOL. */
static svn_error_t *
copy_helper(svn_fs_root_t *from_root,
const char *from_path,
svn_fs_root_t *to_root,
const char *to_path,
- svn_boolean_t preserve_history,
+ copy_type_t copy_type,
apr_pool_t *pool)
{
dag_node_t *from_node;
@@ -2413,11 +2494,52 @@ copy_helper(svn_fs_root_t *from_root,
_("Cannot copy between two different filesystems ('%s' and '%s')"),
from_root->fs->path, to_root->fs->path);
+ /* more things that we can't do ATM */
if (from_root->is_txn_root)
return svn_error_create
(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
_("Copy from mutable tree not currently supported"));
+ if (! to_root->is_txn_root)
+ return svn_error_create
+ (SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+ _("Copy immutable tree not 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));
+ }
+
+ /* does the FS support moves at all? */
+ if (!svn_fs_fs__supports_move(to_root->fs))
+ copy_type = copy_type_add_with_history;
+ }
+
/* Get the NODE for FROM_PATH in FROM_ROOT.*/
SVN_ERR(get_dag(&from_node, from_root, from_path, TRUE, pool));
@@ -2454,14 +2576,20 @@ copy_helper(svn_fs_root_t *from_root,
operation is a replacement, not an addition. */
if (to_parent_path->node)
{
- kind = svn_fs_path_change_replace;
+ kind = copy_type == copy_type_move
+ ? svn_fs_path_change_movereplace
+ : svn_fs_path_change_replace;
+
if (svn_fs_fs__fs_supports_mergeinfo(to_root->fs))
SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_start,
to_parent_path->node));
}
else
{
- kind = svn_fs_path_change_add;
+ kind = copy_type == copy_type_move
+ ? svn_fs_path_change_move
+ : svn_fs_path_change_add;
+
mergeinfo_start = 0;
}
@@ -2479,12 +2607,12 @@ copy_helper(svn_fs_root_t *from_root,
SVN_ERR(svn_fs_fs__dag_copy(to_parent_path->parent->node,
to_parent_path->entry,
from_node,
- preserve_history,
+ copy_type != copy_type_plain_add,
from_root->rev,
from_canonpath,
txn_id, pool));
- if (kind == svn_fs_path_change_replace)
+ if (kind != svn_fs_path_change_add)
SVN_ERR(dag_node_cache_invalidate(to_root,
parent_path_path(to_parent_path,
pool), pool));
@@ -2541,7 +2669,7 @@ fs_copy(svn_fs_root_t *from_root,
to_root,
svn_fs__canonicalize_abspath(to_path,
pool),
- TRUE, pool));
+ copy_type_add_with_history, pool));
}
@@ -2559,7 +2687,29 @@ fs_revision_link(svn_fs_root_t *from_roo
path = svn_fs__canonicalize_abspath(path, pool);
return svn_error_trace(copy_helper(from_root, path, to_root, path,
- FALSE, pool));
+ copy_type_plain_add, pool));
+}
+
+
+/* Create a copy of FROM_PATH in FROM_ROOT named TO_PATH in TO_ROOT and mark
+ it as a Move. If FROM_PATH is a directory, copy it recursively.
+ Temporary allocations are from POOL.*/
+static svn_error_t *
+fs_move(svn_fs_root_t *from_root,
+ const char *from_path,
+ svn_fs_root_t *to_root,
+ const char *to_path,
+ apr_pool_t *pool)
+{
+ SVN_ERR(check_newline(to_path, pool));
+
+ return svn_error_trace(copy_helper(from_root,
+ svn_fs__canonicalize_abspath(from_path,
+ pool),
+ to_root,
+ svn_fs__canonicalize_abspath(to_path,
+ pool),
+ copy_type_move, pool));
}
@@ -4134,6 +4284,9 @@ static root_vtable_t root_vtable = {
fs_node_origin_rev,
fs_node_created_path,
fs_delete_node,
+ fs_copy,
+ fs_revision_link,
+ fs_move,
fs_copied_from,
fs_closest_copy,
fs_node_prop,
@@ -4143,8 +4296,6 @@ static root_vtable_t root_vtable = {
fs_dir_entries,
fs_dir_optimal_order,
fs_make_dir,
- fs_copy,
- fs_revision_link,
fs_file_length,
fs_file_checksum,
fs_file_contents,
@@ -4326,19 +4477,28 @@ verify_node(dag_node_t *node,
{
svn_fs_dirent_t *dirent = svn__apr_hash_index_val(hi);
dag_node_t *child;
- svn_revnum_t child_rev;
apr_int64_t child_mergeinfo;
svn_pool_clear(iterpool);
/* Compute CHILD_REV. */
- SVN_ERR(svn_fs_fs__dag_get_node(&child, fs, dirent->id, iterpool));
- SVN_ERR(svn_fs_fs__dag_get_revision(&child_rev, child, iterpool));
-
- if (child_rev == rev)
- SVN_ERR(verify_node(child, rev, iterpool));
+ if (svn_fs_fs__id_rev(dirent->id) == rev)
+ {
+ SVN_ERR(svn_fs_fs__dag_get_node(&child, fs, dirent->id,
+ iterpool));
+ SVN_ERR(verify_node(child, rev, iterpool));
+ SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&child_mergeinfo,
+ child));
+ }
+ else
+ {
+ /* access mergeinfo counter with minimal overhead */
+ node_revision_t *noderev;
+ SVN_ERR(svn_fs_fs__get_node_revision(&noderev, fs, dirent->id,
+ iterpool));
+ child_mergeinfo = noderev->mergeinfo_count;
+ }
- SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&child_mergeinfo, child));
children_mergeinfo += child_mergeinfo;
}
Modified: subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.c Tue Oct 15 23:44:41 2013
@@ -637,3 +637,11 @@ svn_fs_fs__use_log_addressing(svn_fs_t *
return ffd->min_log_addressing_rev != SVN_INVALID_REVNUM
&& ffd->min_log_addressing_rev <= rev;
}
+
+svn_boolean_t
+svn_fs_fs__supports_move(svn_fs_t *fs)
+{
+ fs_fs_data_t *ffd = fs->fsap_data;
+
+ return ffd->format >= SVN_FS_FS__MIN_MOVE_SUPPORT_FORMAT;
+}
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.h?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.h (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.h Tue Oct 15 23:44:41 2013
@@ -385,4 +385,8 @@ svn_boolean_t
svn_fs_fs__use_log_addressing(svn_fs_t *fs,
svn_revnum_t rev);
-#endif
+/* Return TRUE if FS's format supports moves to be recorded natively. */
+svn_boolean_t
+svn_fs_fs__supports_move(svn_fs_t *fs);
+
+#endif
\ No newline at end of file
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_fs/verify.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_fs/verify.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
Merged /subversion/trunk/subversion/libsvn_fs_x:r1516632-1532579
Merged /subversion/branches/fsfs-improvements/subversion/libsvn_fs_x:r1499981-1509278,1516645-1532583
Modified: subversion/branches/log-addressing/subversion/libsvn_fs_x/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_x/cached_data.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_x/cached_data.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_x/cached_data.c Tue Oct 15 23:44:41 2013
@@ -413,6 +413,57 @@ svn_fs_x__get_node_revision(node_revisio
svn_error_t *
+svn_fs_x__get_mergeinfo_count(apr_int64_t *count,
+ svn_fs_t *fs,
+ const svn_fs_id_t *id,
+ apr_pool_t *pool)
+{
+ node_revision_t *noderev;
+
+ /* If we want a full acccess log, we need to provide full data and
+ cannot take shortcuts here. */
+#if !defined(SVN_FS_X__LOG_ACCESS)
+
+ /* First, try a noderevs container cache lookup. */
+ if (! svn_fs_x__id_is_txn(id))
+ {
+ /* noderevs in rev / pack files can be cached */
+ const svn_fs_x__id_part_t *rev_item = svn_fs_x__id_rev_item(id);
+ fs_x_data_t *ffd = fs->fsap_data;
+
+ if ( svn_fs_x__is_packed_rev(fs, rev_item->revision)
+ && ffd->noderevs_container_cache)
+ {
+ pair_cache_key_t key;
+ apr_off_t offset;
+ apr_uint32_t sub_item;
+ svn_boolean_t is_cached;
+
+ SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs,
+ rev_item->revision, NULL,
+ rev_item->number, pool));
+ key.revision = svn_fs_x__packed_base_rev(fs, rev_item->revision);
+ key.second = offset;
+
+ SVN_ERR(svn_cache__get_partial((void **)count, &is_cached,
+ ffd->noderevs_container_cache, &key,
+ svn_fs_x__mergeinfo_count_get_func,
+ &sub_item, pool));
+ if (is_cached)
+ return SVN_NO_ERROR;
+ }
+ }
+#endif
+
+ /* fallback to the naive implementation handling all edge cases */
+ SVN_ERR(svn_fs_x__get_node_revision(&noderev, fs, id, pool));
+ *count = noderev->mergeinfo_count;
+
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
svn_fs_x__rev_get_root(svn_fs_id_t **root_id_p,
svn_fs_t *fs,
svn_revnum_t rev,
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/cached_data.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/branches/log-addressing/subversion/libsvn_fs_x/cached_data.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_x/cached_data.h?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_x/cached_data.h (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_x/cached_data.h Tue Oct 15 23:44:41 2013
@@ -39,6 +39,14 @@ svn_fs_x__get_node_revision(node_revisio
const svn_fs_id_t *id,
apr_pool_t *pool);
+/* Set *COUNT to the value of the mergeinfo_count member of the node-
+ revision for the node ID in FS. Do any allocations in POOL. */
+svn_error_t *
+svn_fs_x__get_mergeinfo_count(apr_int64_t *count,
+ svn_fs_t *fs,
+ const svn_fs_id_t *id,
+ apr_pool_t *pool);
+
/* Set *ROOT_ID to the node-id for the root of revision REV in
filesystem FS. Do any allocations in POOL. */
svn_error_t *
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/cached_data.h
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/branches/log-addressing/subversion/libsvn_fs_x/changes.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_x/changes.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_x/changes.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_x/changes.c Tue Oct 15 23:44:41 2013
@@ -60,6 +60,8 @@
#define CHANGE_KIND_DELETE 0x00040
#define CHANGE_KIND_REPLACE 0x00060
#define CHANGE_KIND_RESET 0x00080
+#define CHANGE_KIND_MOVE 0x000A0
+#define CHANGE_KIND_MOVEREPLACE 0x000C0
/* Our internal representation of a change */
typedef struct binary_change_t
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/changes.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/changes.h
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/branches/log-addressing/subversion/libsvn_fs_x/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_x/fs.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_x/fs.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_x/fs.c Tue Oct 15 23:44:41 2013
@@ -229,10 +229,13 @@ initialize_fs_struct(svn_fs_t *fs)
/* This implements the fs_library_vtable_t.create() API. Create a new
fsx-backed Subversion filesystem at path PATH and link it into
*FS. Perform temporary allocations in POOL, and fs-global allocations
- in COMMON_POOL. */
+ in COMMON_POOL. The latter must be serialized using COMMON_POOL_LOCK. */
static svn_error_t *
-x_create(svn_fs_t *fs, const char *path, apr_pool_t *pool,
- apr_pool_t *common_pool)
+x_create(svn_fs_t *fs,
+ const char *path,
+ svn_mutex__t *common_pool_lock,
+ apr_pool_t *pool,
+ apr_pool_t *common_pool)
{
SVN_ERR(svn_fs__check_fs(fs, FALSE));
@@ -241,7 +244,10 @@ x_create(svn_fs_t *fs, const char *path,
SVN_ERR(svn_fs_x__create(fs, path, pool));
SVN_ERR(svn_fs_x__initialize_caches(fs, pool));
- return x_serialized_init(fs, common_pool, pool);
+ SVN_MUTEX__WITH_LOCK(common_pool_lock,
+ x_serialized_init(fs, common_pool, pool));
+
+ return SVN_NO_ERROR;
}
@@ -251,17 +257,26 @@ x_create(svn_fs_t *fs, const char *path,
/* This implements the fs_library_vtable_t.open() API. Open an FSX
Subversion filesystem located at PATH, set *FS to point to the
correct vtable for the filesystem. Use POOL for any temporary
- allocations, and COMMON_POOL for fs-global allocations. */
+ allocations, and COMMON_POOL for fs-global allocations.
+ The latter must be serialized using COMMON_POOL_LOCK. */
static svn_error_t *
-x_open(svn_fs_t *fs, const char *path, apr_pool_t *pool,
- apr_pool_t *common_pool)
+x_open(svn_fs_t *fs,
+ const char *path,
+ svn_mutex__t *common_pool_lock,
+ apr_pool_t *pool,
+ apr_pool_t *common_pool)
{
+ SVN_ERR(svn_fs__check_fs(fs, FALSE));
+
SVN_ERR(initialize_fs_struct(fs));
SVN_ERR(svn_fs_x__open(fs, path, pool));
SVN_ERR(svn_fs_x__initialize_caches(fs, pool));
- return x_serialized_init(fs, common_pool, pool);
+ SVN_MUTEX__WITH_LOCK(common_pool_lock,
+ x_serialized_init(fs, common_pool, pool));
+
+ return SVN_NO_ERROR;
}
@@ -270,7 +285,9 @@ x_open(svn_fs_t *fs, const char *path, a
static svn_error_t *
x_open_for_recovery(svn_fs_t *fs,
const char *path,
- apr_pool_t *pool, apr_pool_t *common_pool)
+ svn_mutex__t *common_pool_lock,
+ apr_pool_t *pool,
+ apr_pool_t *common_pool)
{
/* Recovery for FSX is currently limited to recreating the 'current'
file from the latest revision. */
@@ -288,7 +305,7 @@ x_open_for_recovery(svn_fs_t *fs,
"0 1 1\n", pool));
/* Now open the filesystem properly by calling the vtable method directly. */
- return x_open(fs, path, pool, common_pool);
+ return x_open(fs, path, common_pool_lock, pool, common_pool);
}
@@ -301,14 +318,11 @@ x_upgrade(svn_fs_t *fs,
void *notify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
+ svn_mutex__t *common_pool_lock,
apr_pool_t *pool,
apr_pool_t *common_pool)
{
- SVN_ERR(svn_fs__check_fs(fs, FALSE));
- SVN_ERR(initialize_fs_struct(fs));
- SVN_ERR(svn_fs_x__open(fs, path, pool));
- SVN_ERR(svn_fs_x__initialize_caches(fs, pool));
- SVN_ERR(x_serialized_init(fs, common_pool, pool));
+ SVN_ERR(x_open(fs, path, common_pool_lock, pool, common_pool));
return svn_fs_x__upgrade(fs, notify_func, notify_baton,
cancel_func, cancel_baton, pool);
}
@@ -321,14 +335,11 @@ x_verify(svn_fs_t *fs, const char *path,
void *notify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
+ svn_mutex__t *common_pool_lock,
apr_pool_t *pool,
apr_pool_t *common_pool)
{
- SVN_ERR(svn_fs__check_fs(fs, FALSE));
- SVN_ERR(initialize_fs_struct(fs));
- SVN_ERR(svn_fs_x__open(fs, path, pool));
- SVN_ERR(svn_fs_x__initialize_caches(fs, pool));
- SVN_ERR(x_serialized_init(fs, common_pool, pool));
+ SVN_ERR(x_open(fs, path, common_pool_lock, pool, common_pool));
return svn_fs_x__verify(fs, start, end, notify_func, notify_baton,
cancel_func, cancel_baton, pool);
}
@@ -340,14 +351,11 @@ x_pack(svn_fs_t *fs,
void *notify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
+ svn_mutex__t *common_pool_lock,
apr_pool_t *pool,
apr_pool_t *common_pool)
{
- SVN_ERR(svn_fs__check_fs(fs, FALSE));
- SVN_ERR(initialize_fs_struct(fs));
- SVN_ERR(svn_fs_x__open(fs, path, pool));
- SVN_ERR(svn_fs_x__initialize_caches(fs, pool));
- SVN_ERR(x_serialized_init(fs, common_pool, pool));
+ SVN_ERR(x_open(fs, path, common_pool_lock, pool, common_pool));
return svn_fs_x__pack(fs, notify_func, notify_baton,
cancel_func, cancel_baton, pool);
}
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/hotcopy.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/hotcopy.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/index.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/index.h
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/branches/log-addressing/subversion/libsvn_fs_x/low_level.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_x/low_level.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_x/low_level.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_x/low_level.c Tue Oct 15 23:44:41 2013
@@ -53,6 +53,8 @@
#define ACTION_DELETE "delete"
#define ACTION_REPLACE "replace"
#define ACTION_RESET "reset"
+#define ACTION_MOVE "move"
+#define ACTION_MOVEREPLACE "movereplace"
/* True and False flags. */
#define FLAG_TRUE "true"
@@ -828,6 +830,14 @@ read_change(change_t **change_p,
{
info->change_kind = svn_fs_path_change_reset;
}
+ else if (strcmp(str, ACTION_MOVE) == 0)
+ {
+ info->change_kind = svn_fs_path_change_move;
+ }
+ else if (strcmp(str, ACTION_MOVEREPLACE) == 0)
+ {
+ info->change_kind = svn_fs_path_change_movereplace;
+ }
else
{
return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
@@ -961,6 +971,12 @@ write_change_entry(svn_stream_t *stream,
case svn_fs_path_change_reset:
change_string = ACTION_RESET;
break;
+ case svn_fs_path_change_move:
+ change_string = ACTION_MOVE;
+ break;
+ case svn_fs_path_change_movereplace:
+ change_string = ACTION_MOVEREPLACE;
+ break;
default:
return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
_("Invalid change type %d"),
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/low_level.h
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/branches/log-addressing/subversion/libsvn_fs_x/noderevs.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_x/noderevs.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_x/noderevs.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_x/noderevs.c Tue Oct 15 23:44:41 2013
@@ -1014,3 +1014,25 @@ svn_fs_x__noderevs_get_func(void **out,
return SVN_NO_ERROR;
}
+
+svn_error_t *
+svn_fs_x__mergeinfo_count_get_func(void **out,
+ const void *data,
+ apr_size_t data_len,
+ void *baton,
+ apr_pool_t *pool)
+{
+ binary_noderev_t *binary_noderev;
+ apr_array_header_t noderevs;
+
+ apr_uint32_t idx = *(apr_uint32_t *)baton;
+ const svn_fs_x__noderevs_t *container = data;
+
+ /* Resolve all container pointers */
+ resolve_apr_array_header(&noderevs, container, &container->noderevs);
+ binary_noderev = &APR_ARRAY_IDX(&noderevs, idx, binary_noderev_t);
+
+ *(apr_int64_t *)out = binary_noderev->mergeinfo_count;
+
+ return SVN_NO_ERROR;
+}
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/noderevs.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/branches/log-addressing/subversion/libsvn_fs_x/noderevs.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_x/noderevs.h?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_x/noderevs.h (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_x/noderevs.h Tue Oct 15 23:44:41 2013
@@ -127,4 +127,15 @@ svn_fs_x__noderevs_get_func(void **out,
void *baton,
apr_pool_t *pool);
+/* Implements svn_cache__partial_getter_func_t for the mergeinfo_count in
+ * the stored noderevs, setting *OUT to the apr_int64_t counter value of
+ * the noderev selected by the apr_uint32_t index passed in as *BATON.
+ */
+svn_error_t *
+svn_fs_x__mergeinfo_count_get_func(void **out,
+ const void *data,
+ apr_size_t data_len,
+ void *baton,
+ apr_pool_t *pool);
+
#endif
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/noderevs.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/pack.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/pack.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/recovery.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/recovery.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/reps.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/reps.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/revprops.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/string_table.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/string_table.h
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/branches/log-addressing/subversion/libsvn_fs_x/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_x/transaction.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_x/transaction.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_x/transaction.c Tue Oct 15 23:44:41 2013
@@ -646,6 +646,33 @@ unparse_dir_entries(apr_hash_t **str_ent
return SVN_NO_ERROR;
}
+/* Copy the contents of NEW_CHANGE into OLD_CHANGE assuming that both
+ belong to the same path. Allocate copies in POOL.
+ */
+static void
+replace_change(svn_fs_path_change2_t *old_change,
+ const svn_fs_path_change2_t *new_change,
+ apr_pool_t *pool)
+{
+ /* An add at this point must be following a previous delete,
+ so treat it just like a replace. */
+ old_change->node_kind = new_change->node_kind;
+ old_change->node_rev_id = svn_fs_x__id_copy(new_change->node_rev_id, pool);
+ old_change->text_mod = new_change->text_mod;
+ old_change->prop_mod = new_change->prop_mod;
+ if (new_change->copyfrom_rev == SVN_INVALID_REVNUM)
+ {
+ old_change->copyfrom_rev = SVN_INVALID_REVNUM;
+ old_change->copyfrom_path = NULL;
+ }
+ else
+ {
+ old_change->copyfrom_rev = new_change->copyfrom_rev;
+ old_change->copyfrom_path = apr_pstrdup(pool,
+ new_change->copyfrom_path);
+ }
+}
+
/* Merge the internal-use-only CHANGE into a hash of public-FS
svn_fs_path_change2_t CHANGES, collapsing multiple changes into a
single summarical (is that real word?) change per path. Also keep
@@ -683,11 +710,13 @@ fold_change(apr_hash_t *changes,
_("Invalid change ordering: new node revision ID "
"without delete"));
- /* Sanity check: an add, replacement, or reset must be the first
+ /* Sanity check: an add, replacement, move, or reset must be the first
thing to follow a deletion. */
if ((old_change->change_kind == svn_fs_path_change_delete)
&& (! ((info->change_kind == svn_fs_path_change_replace)
|| (info->change_kind == svn_fs_path_change_reset)
+ || (info->change_kind == svn_fs_path_change_movereplace)
+ || (info->change_kind == svn_fs_path_change_move)
|| (info->change_kind == svn_fs_path_change_add))))
return svn_error_create
(SVN_ERR_FS_CORRUPT, NULL,
@@ -712,7 +741,8 @@ fold_change(apr_hash_t *changes,
break;
case svn_fs_path_change_delete:
- if (old_change->change_kind == svn_fs_path_change_add)
+ if ((old_change->change_kind == svn_fs_path_change_add)
+ || (old_change->change_kind == svn_fs_path_change_move))
{
/* If the path was introduced in this transaction via an
add, and we are deleting it, just remove the path
@@ -734,22 +764,16 @@ fold_change(apr_hash_t *changes,
case svn_fs_path_change_replace:
/* An add at this point must be following a previous delete,
so treat it just like a replace. */
+ replace_change(old_change, info, pool);
old_change->change_kind = svn_fs_path_change_replace;
- old_change->node_rev_id = svn_fs_x__id_copy(info->node_rev_id,
- pool);
- old_change->text_mod = info->text_mod;
- old_change->prop_mod = info->prop_mod;
- if (info->copyfrom_rev == SVN_INVALID_REVNUM)
- {
- old_change->copyfrom_rev = SVN_INVALID_REVNUM;
- old_change->copyfrom_path = NULL;
- }
- else
- {
- old_change->copyfrom_rev = info->copyfrom_rev;
- old_change->copyfrom_path = apr_pstrdup(pool,
- info->copyfrom_path);
- }
+ break;
+
+ case svn_fs_path_change_move:
+ case svn_fs_path_change_movereplace:
+ /* A move at this point must be following a previous delete,
+ so treat it just like a replacing move. */
+ replace_change(old_change, info, pool);
+ old_change->change_kind = svn_fs_path_change_movereplace;
break;
case svn_fs_path_change_modify:
@@ -816,7 +840,8 @@ process_changes(apr_hash_t *changed_path
*/
if ((change->info.change_kind == svn_fs_path_change_delete)
- || (change->info.change_kind == svn_fs_path_change_replace))
+ || (change->info.change_kind == svn_fs_path_change_replace)
+ || (change->info.change_kind == svn_fs_path_change_movereplace))
{
apr_hash_index_t *hi;
@@ -2655,25 +2680,37 @@ write_final_rev(const svn_fs_id_t **new_
return SVN_NO_ERROR;
}
-/* Write the changed path info from transaction TXN_ID in filesystem
- FS to the permanent rev-file FILE. *OFFSET_P is set the to offset
- in the file of the beginning of this information. Perform
- temporary allocations in POOL. */
+/* Write the changed path info CHANGED_PATHS of transaction TXN_ID to the
+ permanent rev-file FILE representing NEW_REV in filesystem FS. *OFFSET_P
+ is set the to offset in the file of the beginning of this information.
+ Perform temporary allocations in POOL. */
static svn_error_t *
write_final_changed_path_info(apr_off_t *offset_p,
apr_file_t *file,
svn_fs_t *fs,
const svn_fs_x__id_part_t *txn_id,
+ apr_hash_t *changed_paths,
+ svn_revnum_t new_rev,
apr_pool_t *pool)
{
- apr_hash_t *changed_paths;
apr_off_t offset;
+ apr_hash_index_t *hi;
svn_fs_x__p2l_entry_t entry;
svn_fs_x__id_part_t rev_item
= {SVN_INVALID_REVNUM, SVN_FS_X__ITEM_INDEX_CHANGES};
SVN_ERR(svn_fs_x__get_file_offset(&offset, file, pool));
- SVN_ERR(svn_fs_x__txn_changes_fetch(&changed_paths, fs, txn_id, pool));
+
+ /* all moves specify the "copy-from-rev" as REV-1 */
+ for (hi = apr_hash_first(pool, changed_paths); hi; hi = apr_hash_next(hi))
+ {
+ svn_fs_path_change2_t *change;
+ apr_hash_this(hi, NULL, NULL, (void **)&change);
+
+ if (change->change_kind == svn_fs_path_change_move)
+ change->copyfrom_rev = new_rev - 1;
+ }
+
SVN_ERR(svn_fs_x__write_changes(svn_stream_from_aprfile2(file, TRUE, pool),
fs, changed_paths, TRUE, pool));
@@ -2814,6 +2851,163 @@ verify_locks(svn_fs_t *fs,
return SVN_NO_ERROR;
}
+/* If CHANGE is move, verify that there is no other move with the same
+ copy-from path in SOURCE_PATHS already (parent or sub-node moves are fine).
+ Add the source path to SOURCE_PATHS after successful verification. */
+static svn_error_t *
+check_for_duplicate_move_source(apr_hash_t *source_paths,
+ change_t *change)
+{
+ if ( change->info.change_kind == svn_fs_path_change_move
+ || change->info.change_kind == svn_fs_path_change_movereplace)
+ if (change->info.copyfrom_path)
+ {
+ if (apr_hash_get(source_paths, change->info.copyfrom_path,
+ APR_HASH_KEY_STRING))
+ return svn_error_createf(SVN_ERR_FS_AMBIGUOUS_MOVE, NULL,
+ _("Path '%s' has been moved to more than one target"),
+ change->info.copyfrom_path);
+
+ apr_hash_set(source_paths, change->info.copyfrom_path,
+ APR_HASH_KEY_STRING, change->info.copyfrom_path);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* Verify that the moves we are about to commit with TXN_ID in FS are unique
+ and the respective copy sources have been deleted. OLD_REV is the last
+ committed revision. CHANGED_PATHS is the list of changes paths in this
+ txn. Use POOL for temporary allocations. */
+static svn_error_t *
+verify_moves(svn_fs_t *fs,
+ const svn_fs_x__id_part_t *txn_id,
+ svn_revnum_t old_rev,
+ apr_hash_t *changed_paths,
+ apr_pool_t *pool)
+{
+ apr_hash_t *source_paths = apr_hash_make(pool);
+ svn_revnum_t revision;
+ apr_pool_t *iter_pool = svn_pool_create(pool);
+ apr_hash_index_t *hi;
+ int i;
+ apr_array_header_t *moves
+ = apr_array_make(pool, 16, sizeof(svn_sort__item_t));
+ apr_array_header_t *deletions
+ = apr_array_make(pool, 16, sizeof(const char *));
+
+ /* extract moves and deletions from the current txn's change list */
+
+ for (hi = apr_hash_first(pool, changed_paths); hi; hi = apr_hash_next(hi))
+ {
+ const char *path;
+ apr_ssize_t len;
+ change_t *change;
+ apr_hash_this(hi, (const void**)&path, &len, (void**)&change);
+
+ if ( change->info.copyfrom_path
+ && ( change->info.change_kind == svn_fs_path_change_move
+ || change->info.change_kind == svn_fs_path_change_movereplace))
+ {
+ svn_sort__item_t *item = apr_array_push(moves);
+ item->key = path;
+ item->klen = len;
+ item->value = change;
+ }
+
+ if ( change->info.change_kind == svn_fs_path_change_delete
+ || change->info.change_kind == svn_fs_path_change_replace
+ || change->info.change_kind == svn_fs_path_change_movereplace)
+ APR_ARRAY_PUSH(deletions, const char *) = path;
+ }
+
+ /* no moves? -> done here */
+
+ if (moves->nelts == 0)
+ return SVN_NO_ERROR;
+
+ /* correct the deletions that refer to moved paths and make them refer to
+ the paths in OLD_REV */
+
+ qsort(moves->elts, moves->nelts, moves->elt_size,
+ svn_sort_compare_paths);
+
+ for (i = 0; i < deletions->nelts; ++i)
+ {
+ const char *deleted_path = APR_ARRAY_IDX(deletions, i, const char*);
+ int closest_move_idx
+ = svn_sort__bsearch_lower_bound(deleted_path, moves,
+ svn_sort_compare_paths);
+
+ if (closest_move_idx < moves->nelts)
+ {
+ svn_sort__item_t *closest_move_item
+ = &APR_ARRAY_IDX(moves, closest_move_idx, svn_sort__item_t);
+ const char *relpath
+ = svn_dirent_skip_ancestor(closest_move_item->key,
+ deleted_path);
+ if (relpath)
+ {
+ change_t *closed_move = closest_move_item->value;
+ APR_ARRAY_IDX(deletions, i, const char*)
+ = svn_dirent_join(closed_move->info.copyfrom_path, relpath,
+ pool);
+ }
+ }
+ }
+
+ qsort(deletions->elts, deletions->nelts, deletions->elt_size,
+ svn_sort_compare_paths);
+
+ /* The _same_ source paths must never occur more than once in any move
+ since our base revision. */
+
+ for (i = 0; moves->nelts; ++i)
+ SVN_ERR(check_for_duplicate_move_source (source_paths,
+ APR_ARRAY_IDX(moves, i, svn_sort__item_t).value));
+
+ for (revision = txn_id->revision + 1; revision <= old_rev; ++revision)
+ {
+ apr_array_header_t *changes;
+ change_t **changes_p;
+
+ svn_pool_clear(iter_pool);
+ svn_fs_x__get_changes(&changes, fs, revision, iter_pool);
+
+ changes_p = (change_t **)&changes->elts;
+ for (i = 0; i < changes->nelts; ++i)
+ SVN_ERR(check_for_duplicate_move_source(source_paths, changes_p[i]));
+ }
+
+ /* The move source paths must been deleted in this txn. */
+
+ for (i = 0; i < moves->nelts; ++i)
+ {
+ change_t *change = APR_ARRAY_IDX(moves, i, svn_sort__item_t).value;
+
+ /* there must be a deletion of move's copy-from path
+ (or any of its parents) */
+
+ int closest_deletion_idx
+ = svn_sort__bsearch_lower_bound(change->info.copyfrom_path, deletions,
+ svn_sort_compare_paths);
+ if (closest_deletion_idx < deletions->nelts)
+ {
+ const char *closest_deleted_path
+ = APR_ARRAY_IDX(deletions, closest_deletion_idx, const char *);
+ if (!svn_dirent_is_ancestor(closest_deleted_path,
+ change->info.copyfrom_path))
+ return svn_error_createf(SVN_ERR_FS_INCOMPLETE_MOVE, NULL,
+ _("Path '%s' has been moved without being deleted"),
+ change->info.copyfrom_path);
+ }
+ }
+
+ svn_pool_destroy(iter_pool);
+
+ return SVN_NO_ERROR;
+}
+
/* Baton used for commit_body below. */
struct commit_baton {
svn_revnum_t *new_rev_p;
@@ -2846,6 +3040,7 @@ commit_body(void *baton, apr_pool_t *poo
apr_array_header_t *txnprop_list;
svn_prop_t prop;
const svn_fs_x__id_part_t *txn_id = svn_fs_x__txn_get_id(cb->txn);
+ apr_hash_t *changed_paths;
/* Get the current youngest revision. */
SVN_ERR(svn_fs_x__youngest_rev(&old_rev, cb->fs, pool));
@@ -2862,6 +3057,13 @@ commit_body(void *baton, apr_pool_t *poo
discovered locks. */
SVN_ERR(verify_locks(cb->fs, txn_id, pool));
+ /* we need the changes list for verification as well as for writing it
+ to the final rev file */
+ SVN_ERR(svn_fs_x__txn_changes_fetch(&changed_paths, cb->fs, txn_id,
+ pool));
+
+ SVN_ERR(verify_moves(cb->fs, txn_id, old_rev, changed_paths, pool));
+
/* We are going to be one better than this puny old revision. */
new_rev = old_rev + 1;
@@ -2879,7 +3081,8 @@ commit_body(void *baton, apr_pool_t *poo
/* Write the changed-path information. */
SVN_ERR(write_final_changed_path_info(&changed_path_offset, proto_file,
- cb->fs, txn_id, pool));
+ cb->fs, txn_id, changed_paths,
+ new_rev, pool));
SVN_ERR(svn_io_file_flush_to_disk(proto_file, pool));
SVN_ERR(svn_io_file_close(proto_file, pool));
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/transaction.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/transaction.h
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/branches/log-addressing/subversion/libsvn_fs_x/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_x/tree.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_x/tree.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_x/tree.c Tue Oct 15 23:44:41 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 ***/
@@ -2330,15 +2336,89 @@ x_same_p(svn_boolean_t *same_p,
return SVN_NO_ERROR;
}
+/* Type to select the various behavioral modes of copy_helper.
+ */
+typedef enum copy_type_t
+{
+ /* add without history */
+ copy_type_plain_add,
+
+ /* add with history */
+ copy_type_add_with_history,
+
+ /* move (always with history) */
+ 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_x__id_eq(svn_fs_x__dag_get_id(node),
+ svn_fs_x__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. If PRESERVE_HISTORY is set, then the copy is recorded in
- the copies table. Perform temporary allocations in POOL. */
+ TO_ROOT. COPY_TYPE determines whether then the copy is recorded in
+ the copies table and whether it is being marked as a move.
+ Perform temporary allocations in POOL. */
static svn_error_t *
copy_helper(svn_fs_root_t *from_root,
const char *from_path,
svn_fs_root_t *to_root,
const char *to_path,
- svn_boolean_t preserve_history,
+ copy_type_t copy_type,
apr_pool_t *pool)
{
dag_node_t *from_node;
@@ -2355,11 +2435,48 @@ copy_helper(svn_fs_root_t *from_root,
_("Cannot copy between two different filesystems ('%s' and '%s')"),
from_root->fs->path, to_root->fs->path);
+ /* more things that we can't do ATM */
if (from_root->is_txn_root)
return svn_error_create
(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
_("Copy from mutable tree not currently supported"));
+ if (! to_root->is_txn_root)
+ return svn_error_create
+ (SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+ _("Copy immutable tree not 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_x__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));
@@ -2396,13 +2513,19 @@ copy_helper(svn_fs_root_t *from_root,
operation is a replacement, not an addition. */
if (to_parent_path->node)
{
- kind = svn_fs_path_change_replace;
+ kind = copy_type == copy_type_move
+ ? svn_fs_path_change_movereplace
+ : svn_fs_path_change_replace;
+
SVN_ERR(svn_fs_x__dag_get_mergeinfo_count(&mergeinfo_start,
to_parent_path->node));
}
else
{
- kind = svn_fs_path_change_add;
+ kind = copy_type == copy_type_move
+ ? svn_fs_path_change_move
+ : svn_fs_path_change_add;
+
mergeinfo_start = 0;
}
@@ -2418,12 +2541,12 @@ copy_helper(svn_fs_root_t *from_root,
SVN_ERR(svn_fs_x__dag_copy(to_parent_path->parent->node,
to_parent_path->entry,
from_node,
- preserve_history,
+ copy_type != copy_type_plain_add,
from_root->rev,
from_canonpath,
txn_id, pool));
- if (kind == svn_fs_path_change_replace)
+ if (kind != svn_fs_path_change_add)
SVN_ERR(dag_node_cache_invalidate(to_root,
parent_path_path(to_parent_path,
pool), pool));
@@ -2477,7 +2600,7 @@ x_copy(svn_fs_root_t *from_root,
to_root,
svn_fs__canonicalize_abspath(to_path,
pool),
- TRUE, pool));
+ copy_type_add_with_history, pool));
}
@@ -2495,7 +2618,27 @@ x_revision_link(svn_fs_root_t *from_root
path = svn_fs__canonicalize_abspath(path, pool);
return svn_error_trace(copy_helper(from_root, path, to_root, path,
- FALSE, pool));
+ copy_type_plain_add, pool));
+}
+
+
+/* Create a copy of FROM_PATH in FROM_ROOT named TO_PATH in TO_ROOT and mark
+ it as a Move. If FROM_PATH is a directory, copy it recursively.
+ Temporary allocations are from POOL.*/
+static svn_error_t *
+x_move(svn_fs_root_t *from_root,
+ const char *from_path,
+ svn_fs_root_t *to_root,
+ const char *to_path,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(copy_helper(from_root,
+ svn_fs__canonicalize_abspath(from_path,
+ pool),
+ to_root,
+ svn_fs__canonicalize_abspath(to_path,
+ pool),
+ copy_type_move, pool));
}
@@ -4061,6 +4204,9 @@ static root_vtable_t root_vtable = {
x_node_origin_rev,
x_node_created_path,
x_delete_node,
+ x_copy,
+ x_revision_link,
+ x_move,
x_copied_from,
x_closest_copy,
x_node_prop,
@@ -4070,8 +4216,6 @@ static root_vtable_t root_vtable = {
x_dir_entries,
x_dir_optimal_order,
x_make_dir,
- x_copy,
- x_revision_link,
x_file_length,
x_file_checksum,
x_file_contents,
@@ -4253,19 +4397,25 @@ verify_node(dag_node_t *node,
{
svn_fs_dirent_t *dirent = svn__apr_hash_index_val(hi);
dag_node_t *child;
- svn_revnum_t child_rev;
apr_int64_t child_mergeinfo;
svn_pool_clear(iterpool);
/* Compute CHILD_REV. */
- SVN_ERR(svn_fs_x__dag_get_node(&child, fs, dirent->id, iterpool));
- SVN_ERR(svn_fs_x__dag_get_revision(&child_rev, child, iterpool));
-
- if (child_rev == rev)
- SVN_ERR(verify_node(child, rev, iterpool));
+ if (svn_fs_x__id_rev(dirent->id) == rev)
+ {
+ SVN_ERR(svn_fs_x__dag_get_node(&child, fs, dirent->id,
+ iterpool));
+ SVN_ERR(verify_node(child, rev, iterpool));
+ SVN_ERR(svn_fs_x__dag_get_mergeinfo_count(&child_mergeinfo,
+ child));
+ }
+ else
+ {
+ SVN_ERR(svn_fs_x__get_mergeinfo_count(&child_mergeinfo, fs,
+ dirent->id, iterpool));
+ }
- SVN_ERR(svn_fs_x__dag_get_mergeinfo_count(&child_mergeinfo, child));
children_mergeinfo += child_mergeinfo;
}
Propchange: subversion/branches/log-addressing/subversion/libsvn_fs_x/util.h
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/branches/log-addressing/subversion/libsvn_ra/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra/compat.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra/compat.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra/compat.c Tue Oct 15 23:44:41 2013
@@ -363,8 +363,9 @@ svn_ra__locations_from_log(svn_ra_sessio
Notice that we always run on the youngest rev of the 3 inputs. */
targets = apr_array_make(pool, 1, sizeof(const char *));
APR_ARRAY_PUSH(targets, const char *) = path;
- SVN_ERR(svn_ra_get_log2(session, targets, youngest, oldest, 0,
+ SVN_ERR(svn_ra_get_log3(session, targets, youngest, oldest, 0,
TRUE, FALSE, FALSE,
+ svn_move_behavior_explicit_moves,
apr_array_make(pool, 0, sizeof(const char *)),
log_receiver, &lrb, pool));
@@ -585,8 +586,9 @@ svn_ra__location_segments_from_log(svn_r
Notice that we always run on the youngest rev of the 3 inputs. */
targets = apr_array_make(pool, 1, sizeof(const char *));
APR_ARRAY_PUSH(targets, const char *) = path;
- SVN_ERR(svn_ra_get_log2(session, targets, peg_revision, end_rev, 0,
+ SVN_ERR(svn_ra_get_log3(session, targets, peg_revision, end_rev, 0,
TRUE, FALSE, FALSE,
+ svn_move_behavior_explicit_moves,
apr_array_make(pool, 0, sizeof(const char *)),
gls_log_receiver, &lrb, pool));
@@ -684,10 +686,11 @@ svn_ra__file_revs_from_log(svn_ra_sessio
/* Accumulate revision metadata by walking the revisions
backwards; this allows us to follow moves/copies
correctly. */
- SVN_ERR(svn_ra_get_log2(ra_session,
+ SVN_ERR(svn_ra_get_log3(ra_session,
condensed_targets,
end, start, 0, /* no limit */
TRUE, FALSE, FALSE,
+ svn_move_behavior_explicit_moves,
NULL, fr_log_message_receiver, &lmb,
pool));
@@ -853,8 +856,9 @@ svn_ra__get_deleted_rev_from_log(svn_ra_
/* Examine the logs of SESSION's URL to find when DELETED_PATH was first
deleted or replaced. */
- SVN_ERR(svn_ra_get_log2(session, NULL, peg_revision, end_revision, 0,
+ SVN_ERR(svn_ra_get_log3(session, NULL, peg_revision, end_revision, 0,
TRUE, TRUE, FALSE,
+ svn_move_behavior_explicit_moves,
apr_array_make(pool, 0, sizeof(char *)),
log_path_del_receiver, &log_path_deleted_baton,
pool));
Modified: subversion/branches/log-addressing/subversion/libsvn_ra/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra/deprecated.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra/deprecated.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra/deprecated.c Tue Oct 15 23:44:41 2013
@@ -292,6 +292,25 @@ svn_error_t *svn_ra_do_diff(svn_ra_sessi
versus_url, diff_editor, diff_baton, pool);
}
+svn_error_t *svn_ra_get_log2(svn_ra_session_t *session,
+ const apr_array_header_t *paths,
+ svn_revnum_t start,
+ svn_revnum_t end,
+ int limit,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_boolean_t include_merged_revisions,
+ const apr_array_header_t *revprops,
+ svn_log_entry_receiver_t receiver,
+ void *receiver_baton,
+ apr_pool_t *pool)
+{
+ return svn_ra_get_log3(session, paths, start, end, limit,
+ discover_changed_paths, strict_node_history,
+ include_merged_revisions, svn_move_behavior_no_moves,
+ revprops, receiver, receiver_baton, pool);
+}
+
svn_error_t *svn_ra_get_log(svn_ra_session_t *session,
const apr_array_header_t *paths,
svn_revnum_t start,
Modified: subversion/branches/log-addressing/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra/ra_loader.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra/ra_loader.c Tue Oct 15 23:44:41 2013
@@ -877,7 +877,7 @@ svn_error_t *svn_ra_do_diff3(svn_ra_sess
diff_baton, pool);
}
-svn_error_t *svn_ra_get_log2(svn_ra_session_t *session,
+svn_error_t *svn_ra_get_log3(svn_ra_session_t *session,
const apr_array_header_t *paths,
svn_revnum_t start,
svn_revnum_t end,
@@ -885,6 +885,7 @@ svn_error_t *svn_ra_get_log2(svn_ra_sess
svn_boolean_t discover_changed_paths,
svn_boolean_t strict_node_history,
svn_boolean_t include_merged_revisions,
+ svn_move_behavior_t move_behavior,
const apr_array_header_t *revprops,
svn_log_entry_receiver_t receiver,
void *receiver_baton,
@@ -905,8 +906,8 @@ svn_error_t *svn_ra_get_log2(svn_ra_sess
return session->vtable->get_log(session, paths, start, end, limit,
discover_changed_paths, strict_node_history,
- include_merged_revisions, revprops,
- receiver, receiver_baton, pool);
+ include_merged_revisions, move_behavior,
+ revprops, receiver, receiver_baton, pool);
}
svn_error_t *svn_ra_check_path(svn_ra_session_t *session,
Modified: subversion/branches/log-addressing/subversion/libsvn_ra/ra_loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra/ra_loader.h?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra/ra_loader.h (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra/ra_loader.h Tue Oct 15 23:44:41 2013
@@ -194,6 +194,7 @@ typedef struct svn_ra__vtable_t {
svn_boolean_t discover_changed_paths,
svn_boolean_t strict_node_history,
svn_boolean_t include_merged_revisions,
+ svn_move_behavior_t move_behavior,
const apr_array_header_t *revprops,
svn_log_entry_receiver_t receiver,
void *receiver_baton,
Modified: subversion/branches/log-addressing/subversion/libsvn_ra/wrapper_template.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra/wrapper_template.h?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra/wrapper_template.h (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra/wrapper_template.h Tue Oct 15 23:44:41 2013
@@ -395,6 +395,7 @@ static svn_error_t *compat_get_log(void
return VTBL.get_log(session_baton, paths, start, end, 0, /* limit */
discover_changed_paths, strict_node_history,
FALSE, /* include_merged_revisions */
+ svn_move_behavior_no_moves,
svn_compat_log_revprops_in(pool), /* revprops */
receiver2, receiver2_baton, pool);
}
Modified: subversion/branches/log-addressing/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra_local/ra_plugin.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra_local/ra_plugin.c Tue Oct 15 23:44:41 2013
@@ -989,6 +989,7 @@ svn_ra_local__get_log(svn_ra_session_t *
svn_boolean_t discover_changed_paths,
svn_boolean_t strict_node_history,
svn_boolean_t include_merged_revisions,
+ svn_move_behavior_t move_behavior,
const apr_array_header_t *revprops,
svn_log_entry_receiver_t receiver,
void *receiver_baton,
@@ -1017,7 +1018,7 @@ svn_ra_local__get_log(svn_ra_session_t *
receiver = log_receiver_wrapper;
receiver_baton = &lb;
- return svn_repos_get_logs4(sess->repos,
+ return svn_repos_get_logs5(sess->repos,
abs_paths,
start,
end,
@@ -1025,6 +1026,7 @@ svn_ra_local__get_log(svn_ra_session_t *
discover_changed_paths,
strict_node_history,
include_merged_revisions,
+ move_behavior,
revprops,
NULL, NULL,
receiver,
Modified: subversion/branches/log-addressing/subversion/libsvn_ra_local/split_url.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra_local/split_url.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra_local/split_url.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra_local/split_url.c Tue Oct 15 23:44:41 2013
@@ -39,6 +39,7 @@ svn_ra_local__split_URL(svn_repos_t **re
const char *repos_dirent;
const char *repos_root_dirent;
svn_stringbuf_t *urlbuf;
+ apr_size_t root_end;
SVN_ERR(svn_uri_get_dirent_from_file_url(&repos_dirent, URL, pool));
@@ -65,10 +66,17 @@ svn_ra_local__split_URL(svn_repos_t **re
"/",
svn_dirent_skip_ancestor(repos_root_dirent, repos_dirent),
(const char *)NULL); */
- *fs_path = &repos_dirent[strlen(repos_root_dirent)];
-
- if (**fs_path == '\0')
+ root_end = strlen(repos_root_dirent);
+ if (! repos_dirent[root_end])
*fs_path = "/";
+ else if (repos_dirent[root_end] == '/')
+ *fs_path = &repos_dirent[root_end];
+ else
+ {
+ /* On Windows "C:/" is the parent directory of "C:/dir" */
+ *fs_path = &repos_dirent[root_end-1];
+ SVN_ERR_ASSERT((*fs_path)[0] == '/');
+ }
/* Remove the path components after the root dirent from the original URL,
to get a URL to the repository root.
Modified: subversion/branches/log-addressing/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra_serf/commit.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra_serf/commit.c Tue Oct 15 23:44:41 2013
@@ -1933,7 +1933,18 @@ add_file(const char *path,
if (handler->sline.code != 404)
{
- return svn_error_createf(SVN_ERR_RA_DAV_ALREADY_EXISTS, NULL,
+ if (handler->sline.code != 200)
+ {
+ svn_error_t *err;
+
+ err = svn_ra_serf__error_on_status(handler->sline,
+ handler->path,
+ handler->location);
+
+ SVN_ERR(err);
+ }
+
+ return svn_error_createf(SVN_ERR_FS_ALREADY_EXISTS, NULL,
_("File '%s' already exists"), path);
}
}
@@ -2168,8 +2179,8 @@ close_file(void *file_baton,
{
proppatch_context_t *proppatch;
- proppatch = apr_pcalloc(ctx->pool, sizeof(*proppatch));
- proppatch->pool = ctx->pool;
+ proppatch = apr_pcalloc(scratch_pool, sizeof(*proppatch));
+ proppatch->pool = scratch_pool;
proppatch->relpath = ctx->relpath;
proppatch->path = ctx->url;
proppatch->commit = ctx->commit;
@@ -2177,7 +2188,7 @@ close_file(void *file_baton,
proppatch->removed_props = ctx->removed_props;
proppatch->base_revision = ctx->base_revision;
- SVN_ERR(proppatch_resource(proppatch, ctx->commit, ctx->pool));
+ SVN_ERR(proppatch_resource(proppatch, ctx->commit, scratch_pool));
}
return SVN_NO_ERROR;
Modified: subversion/branches/log-addressing/subversion/libsvn_ra_serf/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra_serf/log.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra_serf/log.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra_serf/log.c Tue Oct 15 23:44:41 2013
@@ -76,6 +76,7 @@ typedef struct log_context_t {
svn_boolean_t changed_paths;
svn_boolean_t strict_node_history;
svn_boolean_t include_merged_revisions;
+ svn_move_behavior_t move_behavior;
const apr_array_header_t *revprops;
int nest_level; /* used to track mergeinfo nesting levels */
int count; /* only incremented when nest_level == 0 */
@@ -451,6 +452,14 @@ create_log_body(serf_bucket_t **body_bkt
alloc);
}
+ if (log_ctx->move_behavior != svn_move_behavior_no_moves)
+ {
+ svn_ra_serf__add_tag_buckets(buckets,
+ "S:move-behavior",
+ apr_ltoa(pool, log_ctx->move_behavior),
+ alloc);
+ }
+
if (log_ctx->revprops)
{
int i;
@@ -507,6 +516,7 @@ svn_ra_serf__get_log(svn_ra_session_t *r
svn_boolean_t discover_changed_paths,
svn_boolean_t strict_node_history,
svn_boolean_t include_merged_revisions,
+ svn_move_behavior_t move_behavior,
const apr_array_header_t *revprops,
svn_log_entry_receiver_t receiver,
void *receiver_baton,
@@ -532,6 +542,7 @@ svn_ra_serf__get_log(svn_ra_session_t *r
log_ctx->changed_paths = discover_changed_paths;
log_ctx->strict_node_history = strict_node_history;
log_ctx->include_merged_revisions = include_merged_revisions;
+ log_ctx->move_behavior = move_behavior;
log_ctx->revprops = revprops;
log_ctx->nest_level = 0;
Modified: subversion/branches/log-addressing/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra_serf/ra_serf.h?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra_serf/ra_serf.h Tue Oct 15 23:44:41 2013
@@ -429,6 +429,10 @@ typedef struct svn_ra_serf__handler_t {
enabled. */
svn_boolean_t custom_accept_encoding;
+ /* If TRUE then default DAV: capabilities request headers is not configured
+ for request. */
+ svn_boolean_t no_dav_headers;
+
/* Has the request/response been completed? */
svn_boolean_t done;
@@ -1494,6 +1498,7 @@ svn_ra_serf__get_log(svn_ra_session_t *s
svn_boolean_t discover_changed_paths,
svn_boolean_t strict_node_history,
svn_boolean_t include_merged_revisions,
+ svn_move_behavior_t move_behavior,
const apr_array_header_t *revprops,
svn_log_entry_receiver_t receiver,
void *receiver_baton,
Modified: subversion/branches/log-addressing/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra_serf/update.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra_serf/update.c Tue Oct 15 23:44:41 2013
@@ -1574,6 +1574,7 @@ fetch_file(report_context_t *ctx, report
handler->session = ctx->sess;
handler->custom_accept_encoding = TRUE;
+ handler->no_dav_headers = TRUE;
handler->header_delegate = headers_fetch;
handler->header_delegate_baton = fetch_ctx;
@@ -3705,6 +3706,7 @@ svn_ra_serf__get_file(svn_ra_session_t *
handler->session = session;
handler->custom_accept_encoding = TRUE;
+ handler->no_dav_headers = TRUE;
handler->header_delegate = headers_fetch;
handler->header_delegate_baton = stream_ctx;
Modified: subversion/branches/log-addressing/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra_serf/util.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra_serf/util.c Tue Oct 15 23:44:41 2013
@@ -705,6 +705,9 @@ apr_status_t svn_ra_serf__handle_client_
*
* If CONTENT_TYPE is not-NULL, it will be sent as the Content-Type header.
*
+ * If DAV_HEADERS is non-zero, it will add standard DAV capabilites headers
+ * to request.
+ *
* REQUEST_POOL should live for the duration of the request. Serf will
* construct this and provide it to the request_setup callback, so we
* should just use that one.
@@ -717,6 +720,7 @@ setup_serf_req(serf_request_t *request,
const char *method, const char *url,
serf_bucket_t *body_bkt, const char *content_type,
const char *accept_encoding,
+ svn_boolean_t dav_headers,
apr_pool_t *request_pool,
apr_pool_t *scratch_pool)
{
@@ -783,12 +787,15 @@ setup_serf_req(serf_request_t *request,
serf_bucket_headers_setn(*hdrs_bkt, "Accept-Encoding", accept_encoding);
}
- /* These headers need to be sent with every request; see issue #3255
- ("mod_dav_svn does not pass client capabilities to start-commit
- hooks") for why. */
- serf_bucket_headers_setn(*hdrs_bkt, "DAV", SVN_DAV_NS_DAV_SVN_DEPTH);
- serf_bucket_headers_setn(*hdrs_bkt, "DAV", SVN_DAV_NS_DAV_SVN_MERGEINFO);
- serf_bucket_headers_setn(*hdrs_bkt, "DAV", SVN_DAV_NS_DAV_SVN_LOG_REVPROPS);
+ /* These headers need to be sent with every request except GET; see
+ issue #3255 ("mod_dav_svn does not pass client capabilities to
+ start-commit hooks") for why. */
+ if (dav_headers)
+ {
+ serf_bucket_headers_setn(*hdrs_bkt, "DAV", SVN_DAV_NS_DAV_SVN_DEPTH);
+ serf_bucket_headers_setn(*hdrs_bkt, "DAV", SVN_DAV_NS_DAV_SVN_MERGEINFO);
+ serf_bucket_headers_setn(*hdrs_bkt, "DAV", SVN_DAV_NS_DAV_SVN_LOG_REVPROPS);
+ }
return SVN_NO_ERROR;
}
@@ -2241,7 +2248,8 @@ setup_request(serf_request_t *request,
SVN_ERR(setup_serf_req(request, req_bkt, &headers_bkt,
handler->session, handler->method, handler->path,
body_bkt, handler->body_type, accept_encoding,
- request_pool, scratch_pool));
+ !handler->no_dav_headers, request_pool,
+ scratch_pool));
if (handler->header_delegate)
{
@@ -2251,7 +2259,7 @@ setup_request(serf_request_t *request,
request_pool));
}
- return APR_SUCCESS;
+ return SVN_NO_ERROR;
}
/* Implements the serf_request_setup_t interface (which sets up both a
Modified: subversion/branches/log-addressing/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra_svn/client.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra_svn/client.c Tue Oct 15 23:44:41 2013
@@ -561,14 +561,42 @@ static svn_error_t *parse_url(const char
return SVN_NO_ERROR;
}
+/* This structure is used as a baton for the pool cleanup function to
+ store tunnel parameters used by the close-tunnel callback. */
+struct tunnel_data_t {
+ void *tunnel_context;
+ void *tunnel_baton;
+ const char *tunnel_name;
+ const char *user;
+ const char *hostname;
+ int port;
+ svn_ra_close_tunnel_func_t close_tunnel;
+};
+
+/* Pool cleanup function that invokes the close-tunel callback. */
+static apr_status_t close_tunnel_cleanup(void *baton)
+{
+ const struct tunnel_data_t *const td = baton;
+ svn_error_t *const err =
+ svn_error_root_cause(td->close_tunnel(td->tunnel_context, td->tunnel_baton,
+ td->tunnel_name, td->user,
+ td->hostname, td->port));
+ const apr_status_t ret = (err ? err->apr_err : 0);
+ svn_error_clear(err);
+ return ret;
+}
+
/* Open a session to URL, returning it in *SESS_P, allocating it in POOL.
URI is a parsed version of URL. CALLBACKS and CALLBACKS_BATON
- are provided by the caller of ra_svn_open. If tunnel_argv is non-null,
- it points to a program argument list to use when invoking the tunnel agent.
+ are provided by the caller of ra_svn_open. If TUNNEL_NAME is not NULL,
+ it is the name of the tunnel type parsed from the URL scheme.
+ If TUNNEL_ARGV is not NULL, it points to a program argument list to use
+ when invoking the tunnel agent.
*/
static svn_error_t *open_session(svn_ra_svn__session_baton_t **sess_p,
const char *url,
const apr_uri_t *uri,
+ const char *tunnel_name,
const char **tunnel_argv,
const svn_ra_callbacks2_t *callbacks,
void *callbacks_baton,
@@ -583,19 +611,52 @@ static svn_error_t *open_session(svn_ra_
sess = apr_palloc(pool, sizeof(*sess));
sess->pool = pool;
- sess->is_tunneled = (tunnel_argv != NULL);
+ sess->is_tunneled = (tunnel_name != NULL);
sess->url = apr_pstrdup(pool, url);
sess->user = uri->user;
sess->hostname = uri->hostname;
sess->realm_prefix = apr_psprintf(pool, "<svn://%s:%d>", uri->hostname,
uri->port);
+ sess->tunnel_name = tunnel_name;
sess->tunnel_argv = tunnel_argv;
sess->callbacks = callbacks;
sess->callbacks_baton = callbacks_baton;
sess->bytes_read = sess->bytes_written = 0;
- if (tunnel_argv)
- SVN_ERR(make_tunnel(tunnel_argv, &conn, pool));
+ if (tunnel_name)
+ {
+ if (tunnel_argv)
+ SVN_ERR(make_tunnel(tunnel_argv, &conn, pool));
+ else
+ {
+ void *tunnel_context;
+ apr_file_t *request;
+ apr_file_t *response;
+ SVN_ERR(callbacks->open_tunnel_func(
+ &request, &response, &tunnel_context,
+ callbacks->tunnel_baton, tunnel_name,
+ uri->user, uri->hostname, uri->port,
+ pool));
+ if (callbacks->close_tunnel_func)
+ {
+ struct tunnel_data_t *const td = apr_palloc(pool, sizeof(*td));
+ td->tunnel_context = tunnel_context;
+ td->tunnel_baton = callbacks->tunnel_baton;
+ td->tunnel_name = apr_pstrdup(pool, tunnel_name);
+ td->user = apr_pstrdup(pool, uri->user);
+ td->hostname = apr_pstrdup(pool, uri->hostname);
+ td->port = uri->port;
+ td->close_tunnel = callbacks->close_tunnel_func;
+ apr_pool_cleanup_register(pool, td, close_tunnel_cleanup,
+ apr_pool_cleanup_null);
+ }
+
+ conn = svn_ra_svn_create_conn3(NULL, response, request,
+ SVN_DELTA_COMPRESSION_LEVEL_DEFAULT,
+ 0, 0, pool);
+ SVN_ERR(svn_ra_svn__skip_leading_garbage(conn, pool));
+ }
+ }
else
{
SVN_ERR(make_connection(uri->hostname, uri->port, &sock, pool));
@@ -738,7 +799,14 @@ static svn_error_t *ra_svn_open(svn_ra_s
parse_tunnel(url, &tunnel, pool);
- if (tunnel)
+ /* Use the default tunnel implementation if we got a tunnel name,
+ but either do not have tunnel handler callbacks installed, or
+ the handlers don't like the tunnel name. */
+ if (tunnel
+ && (!callbacks->open_tunnel_func
+ || (callbacks->check_tunnel_func && callbacks->open_tunnel_func
+ && !callbacks->check_tunnel_func(callbacks->tunnel_baton,
+ tunnel))))
SVN_ERR(find_tunnel_agent(tunnel, uri.hostinfo, &tunnel_argv, config,
pool));
else
@@ -755,7 +823,7 @@ static svn_error_t *ra_svn_open(svn_ra_s
/* We open the session in a subpool so we can get rid of it if we
reparent with a server that doesn't support reparenting. */
- SVN_ERR(open_session(&sess, url, &uri, tunnel_argv,
+ SVN_ERR(open_session(&sess, url, &uri, tunnel, tunnel_argv,
callbacks, callback_baton, sess_pool));
session->priv = sess;
@@ -791,7 +859,7 @@ static svn_error_t *ra_svn_reparent(svn_
sess_pool = svn_pool_create(ra_session->pool);
err = parse_url(url, &uri, sess_pool);
if (! err)
- err = open_session(&new_sess, url, &uri, sess->tunnel_argv,
+ err = open_session(&new_sess, url, &uri, sess->tunnel_name, sess->tunnel_argv,
sess->callbacks, sess->callbacks_baton, sess_pool);
/* We destroy the new session pool on error, since it is allocated in
the main session pool. */
@@ -1487,6 +1555,7 @@ perform_ra_svn_log(svn_error_t **outer_e
svn_boolean_t discover_changed_paths,
svn_boolean_t strict_node_history,
svn_boolean_t include_merged_revisions,
+ svn_move_behavior_t move_behavior,
const apr_array_header_t *revprops,
svn_log_entry_receiver_t receiver,
void *receiver_baton,
@@ -1536,11 +1605,13 @@ perform_ra_svn_log(svn_error_t **outer_e
else
want_custom_revprops = TRUE;
}
- SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!))"));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!)n)",
+ (apr_uint64_t) move_behavior));
}
else
{
- SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!w())", "all-revprops"));
+ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!w()n)", "all-revprops",
+ (apr_uint64_t) move_behavior));
want_author = TRUE;
want_date = TRUE;
@@ -1712,6 +1783,7 @@ ra_svn_log(svn_ra_session_t *session,
svn_boolean_t discover_changed_paths,
svn_boolean_t strict_node_history,
svn_boolean_t include_merged_revisions,
+ svn_move_behavior_t move_behavior,
const apr_array_header_t *revprops,
svn_log_entry_receiver_t receiver,
void *receiver_baton, apr_pool_t *pool)
@@ -1726,7 +1798,7 @@ ra_svn_log(svn_ra_session_t *session,
discover_changed_paths,
strict_node_history,
include_merged_revisions,
- revprops,
+ move_behavior, revprops,
receiver, receiver_baton,
pool));
return svn_error_trace(
Propchange: subversion/branches/log-addressing/subversion/libsvn_ra_svn/deprecated.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/branches/log-addressing/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra_svn/marshal.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra_svn/marshal.c Tue Oct 15 23:44:41 2013
@@ -1017,7 +1017,7 @@ static svn_error_t *read_string(svn_ra_s
/* Given the first non-whitespace character FIRST_CHAR, read an item
* into the already allocated structure ITEM. LEVEL should be set
- * to 0 for the first call and is used to enforce a recurssion limit
+ * to 0 for the first call and is used to enforce a recursion limit
* on the parser. */
static svn_error_t *read_item(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
svn_ra_svn_item_t *item, char first_char,
Modified: subversion/branches/log-addressing/subversion/libsvn_ra_svn/protocol
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra_svn/protocol?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra_svn/protocol (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra_svn/protocol Tue Oct 15 23:44:41 2013
@@ -382,11 +382,13 @@ second place for auth-request point as n
[ end-rev:number ] changed-paths:bool strict-node:bool
? limit:number
? include-merged-revisions:bool
- all-revprops | revprops ( revprop:string ... ) )
+ all-revprops | revprops ( revprop:string ... )
+ ? move-behavior:number )
Before sending response, server sends log entries, ending with "done".
If a client does not want to specify a limit, it should send 0 as the
limit parameter. rev-props excludes author, date, and log; they are
sent separately for backwards-compatibility.
+ Move-behavior is encoded like enum svn_move_behavior_t.
log-entry: ( ( change:changed-path-entry ... ) rev:number
[ author:string ] [ date:string ] [ message:string ]
? has-children:bool invalid-revnum:bool