You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2011/08/22 17:21:15 UTC
svn commit: r1160299 [2/3] - in /subversion/branches/fs-py: ./ build/ notes/
subversion/bindings/ctypes-python/test/ subversion/bindings/javahl/native/
subversion/bindings/javahl/src/org/apache/subversion/javahl/
subversion/bindings/javahl/src/org/tigr...
Modified: subversion/branches/fs-py/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_client/status.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_client/status.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_client/status.c Mon Aug 22 15:21:13 2011
@@ -85,12 +85,22 @@ tweak_status(void *baton,
/* If the status item has an entry, but doesn't belong to one of the
changelists our caller is interested in, we filter out this status
transmission. */
- if (sb->changelist_hash
- && (! status->changelist
- || ! apr_hash_get(sb->changelist_hash, status->changelist,
- APR_HASH_KEY_STRING)))
+ if (sb->changelist_hash)
{
- return SVN_NO_ERROR;
+ if (status->changelist)
+ {
+ /* Skip unless the caller requested this changelist. */
+ if (! apr_hash_get(sb->changelist_hash, status->changelist,
+ APR_HASH_KEY_STRING))
+ return SVN_NO_ERROR;
+ }
+ else
+ {
+ /* Skip unless the caller requested changelist-lacking items. */
+ if (! apr_hash_get(sb->changelist_hash, "",
+ APR_HASH_KEY_STRING))
+ return SVN_NO_ERROR;
+ }
}
/* If we know that the target was deleted in HEAD of the repository,
@@ -570,10 +580,6 @@ svn_client_status_dup(const svn_client_s
if (status->moved_to_abspath)
st->moved_to_abspath = apr_pstrdup(result_pool, status->moved_to_abspath);
- if (status->moved_to_op_root_abspath)
- st->moved_to_op_root_abspath =
- apr_pstrdup(result_pool, status->moved_to_op_root_abspath);
-
return st;
}
@@ -680,7 +686,6 @@ svn_client__create_status(svn_client_sta
(*cst)->moved_from_abspath = status->moved_from_abspath;
(*cst)->moved_to_abspath = status->moved_to_abspath;
- (*cst)->moved_to_op_root_abspath = status->moved_to_op_root_abspath;
return SVN_NO_ERROR;
}
Modified: subversion/branches/fs-py/subversion/libsvn_ra_serf/blame.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_ra_serf/blame.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_ra_serf/blame.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_ra_serf/blame.c Mon Aug 22 15:21:13 2011
@@ -159,8 +159,7 @@ create_propval(blame_info_t *info)
info->prop_attr_len + 1);
}
- /* Include the null term. */
- s = svn_string_ncreate(info->prop_attr, info->prop_attr_len + 1, info->pool);
+ s = svn_string_ncreate(info->prop_attr, info->prop_attr_len, info->pool);
if (info->prop_base64)
{
s = svn_base64_decode_string(s, info->pool);
Modified: subversion/branches/fs-py/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_ra_serf/commit.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_ra_serf/commit.c Mon Aug 22 15:21:13 2011
@@ -94,7 +94,7 @@ typedef struct commit_context_t {
typedef struct proppatch_context_t {
apr_pool_t *pool;
- const char *name;
+ const char *relpath;
const char *path;
commit_context_t *commit;
@@ -146,7 +146,10 @@ typedef struct dir_context_t {
/* Our parent */
struct dir_context_t *parent_dir;
- /* The directory name; if NULL, we're the 'root' */
+ /* The directory name; if "", we're the 'root' */
+ const char *relpath;
+
+ /* The basename of the directory. "" for the 'root' */
const char *name;
/* The base revision of the dir. */
@@ -178,6 +181,7 @@ typedef struct file_context_t {
dir_context_t *parent_dir;
+ const char *relpath;
const char *name;
/* The checked out context for this file. */
@@ -311,44 +315,6 @@ handle_checkout(serf_request_t *request,
return err;
}
-/* Return the relative path from DIR's topmost parent to DIR, in
- Subversion's internal path style, allocated in POOL. Use POOL for
- temporary work as well. */
-static const char *
-relative_dir_path(dir_context_t *dir, apr_pool_t *pool)
-{
- const char *rel_path = "";
- apr_array_header_t *components;
- dir_context_t *dir_ptr = dir;
- int i;
-
- components = apr_array_make(pool, 1, sizeof(const char *));
-
- for (dir_ptr = dir; dir_ptr; dir_ptr = dir_ptr->parent_dir)
- APR_ARRAY_PUSH(components, const char *) = dir_ptr->name;
-
- for (i = 0; i < components->nelts; i++)
- {
- rel_path = svn_relpath_join(rel_path,
- APR_ARRAY_IDX(components, i, const char *),
- pool);
- }
-
- return rel_path;
-}
-
-
-/* Return the relative path from FILE's topmost parent to FILE, in
- Subversion's internal path style, allocated in POOL. Use POOL for
- temporary work as well. */
-static const char *
-relative_file_path(file_context_t *f, apr_pool_t *pool)
-{
- const char *dir_path = relative_dir_path(f->parent_dir, pool);
- return svn_relpath_join(dir_path, f->name, pool);
-}
-
-
static svn_error_t *
checkout_dir(dir_context_t *dir)
{
@@ -375,8 +341,7 @@ checkout_dir(dir_context_t *dir)
dir->checkout->activity_url = dir->commit->activity_url;
dir->checkout->resource_url =
svn_path_url_add_component2(dir->parent_dir->checkout->resource_url,
- svn_relpath_basename(dir->name, NULL),
- dir->pool);
+ dir->name, dir->pool);
return SVN_NO_ERROR;
}
@@ -428,8 +393,7 @@ checkout_dir(dir_context_t *dir)
if (err->apr_err == SVN_ERR_FS_CONFLICT)
SVN_ERR_W(err, apr_psprintf(dir->pool,
_("Directory '%s' is out of date; try updating"),
- svn_dirent_local_style(relative_dir_path(dir, dir->pool),
- dir->pool)));
+ svn_dirent_local_style(dir->relpath, dir->pool)));
return err;
}
@@ -563,8 +527,8 @@ checkout_file(file_context_t *file)
file->checkout->activity_url = file->commit->activity_url;
file->checkout->resource_url =
svn_path_url_add_component2(parent_dir->checkout->resource_url,
- svn_relpath__is_child(parent_dir->name,
- file->name,
+ svn_relpath__is_child(parent_dir->relpath,
+ file->relpath,
file->pool),
file->pool);
return SVN_NO_ERROR;
@@ -585,7 +549,7 @@ checkout_file(file_context_t *file)
SVN_ERR(get_version_url(&(file->checkout->checkout_url),
file->commit->session, file->commit->conn,
- file->name, file->base_revision,
+ file->relpath, file->base_revision,
NULL, file->pool));
handler->body_delegate = create_checkout_body;
@@ -611,8 +575,7 @@ checkout_file(file_context_t *file)
if (err->apr_err == SVN_ERR_FS_CONFLICT)
SVN_ERR_W(err, apr_psprintf(file->pool,
_("File '%s' is out of date; try updating"),
- svn_dirent_local_style(relative_file_path(file, file->pool),
- file->pool)));
+ svn_dirent_local_style(file->relpath, file->pool)));
return err;
}
@@ -839,11 +802,11 @@ setup_proppatch_headers(serf_bucket_t *h
proppatch->base_revision));
}
- if (proppatch->name && proppatch->commit->lock_tokens)
+ if (proppatch->relpath && proppatch->commit->lock_tokens)
{
const char *token;
- token = apr_hash_get(proppatch->commit->lock_tokens, proppatch->name,
+ token = apr_hash_get(proppatch->commit->lock_tokens, proppatch->relpath,
APR_HASH_KEY_STRING);
if (token)
@@ -1061,7 +1024,7 @@ setup_put_headers(serf_bucket_t *headers
{
const char *token;
- token = apr_hash_get(ctx->commit->lock_tokens, ctx->name,
+ token = apr_hash_get(ctx->commit->lock_tokens, ctx->relpath,
APR_HASH_KEY_STRING);
if (token)
@@ -1118,9 +1081,8 @@ setup_copy_dir_headers(serf_bucket_t *he
else
{
uri.path = (char *)svn_path_url_add_component2(
- dir->parent_dir->checkout->resource_url,
- svn_relpath_basename(dir->name, pool),
- pool);
+ dir->parent_dir->checkout->resource_url,
+ dir->name, pool);
}
absolute_uri = apr_uri_unparse(pool, &uri, 0);
@@ -1398,6 +1360,7 @@ open_root(void *edit_baton,
dir->pool = dir_pool;
dir->commit = ctx;
dir->base_revision = base_revision;
+ dir->relpath = "";
dir->name = "";
dir->changed_props = apr_hash_make(dir->pool);
dir->removed_props = apr_hash_make(dir->pool);
@@ -1479,12 +1442,13 @@ open_root(void *edit_baton,
dir->pool = dir_pool;
dir->commit = ctx;
dir->base_revision = base_revision;
+ dir->relpath = "";
dir->name = "";
dir->changed_props = apr_hash_make(dir->pool);
dir->removed_props = apr_hash_make(dir->pool);
SVN_ERR(get_version_url(&dir->url, dir->commit->session,
- dir->commit->conn, dir->name,
+ dir->commit->conn, dir->relpath,
dir->base_revision, ctx->checked_in_url,
dir->pool));
ctx->checked_in_url = dir->url;
@@ -1563,7 +1527,7 @@ delete_entry(const char *path,
SVN_ERR(checkout_dir(dir));
delete_target = svn_path_url_add_component2(dir->checkout->resource_url,
svn_relpath_basename(path,
- pool),
+ NULL),
pool);
}
@@ -1658,7 +1622,8 @@ add_directory(const char *path,
dir->base_revision = SVN_INVALID_REVNUM;
dir->copy_revision = copyfrom_revision;
dir->copy_path = copyfrom_path;
- dir->name = apr_pstrdup(dir->pool, path);
+ dir->relpath = apr_pstrdup(dir->pool, path);
+ dir->name = svn_relpath_basename(dir->relpath, NULL);
dir->changed_props = apr_hash_make(dir->pool);
dir->removed_props = apr_hash_make(dir->pool);
@@ -1674,11 +1639,10 @@ add_directory(const char *path,
SVN_ERR(checkout_dir(parent));
dir->url = svn_path_url_add_component2(parent->commit->checked_in_url,
- path, dir->pool);
+ dir->name, dir->pool);
mkcol_target = svn_path_url_add_component2(
parent->checkout->resource_url,
- svn_relpath_basename(path, dir->pool),
- dir->pool);
+ dir->name, dir->pool);
}
handler = apr_pcalloc(dir->pool, sizeof(*handler));
@@ -1772,7 +1736,8 @@ open_directory(const char *path,
dir->added = FALSE;
dir->base_revision = base_revision;
- dir->name = apr_pstrdup(dir->pool, path);
+ dir->relpath = apr_pstrdup(dir->pool, path);
+ dir->name = svn_relpath_basename(dir->relpath, NULL);
dir->changed_props = apr_hash_make(dir->pool);
dir->removed_props = apr_hash_make(dir->pool);
@@ -1785,7 +1750,7 @@ open_directory(const char *path,
{
SVN_ERR(get_version_url(&dir->url,
dir->commit->session, dir->commit->conn,
- dir->name, dir->base_revision,
+ dir->relpath, dir->base_revision,
dir->commit->checked_in_url, dir->pool));
}
*child_baton = dir;
@@ -1863,7 +1828,7 @@ close_directory(void *dir_baton,
proppatch_ctx->pool = pool;
proppatch_ctx->progress.pool = pool;
proppatch_ctx->commit = dir->commit;
- proppatch_ctx->name = dir->name;
+ proppatch_ctx->relpath = dir->relpath;
proppatch_ctx->changed_props = dir->changed_props;
proppatch_ctx->removed_props = dir->removed_props;
proppatch_ctx->base_revision = dir->base_revision;
@@ -1902,7 +1867,8 @@ add_file(const char *path,
new_file->parent_dir = dir;
new_file->commit = dir->commit;
- new_file->name = apr_pstrdup(new_file->pool, path);
+ new_file->relpath = apr_pstrdup(new_file->pool, path);
+ new_file->name = svn_relpath_basename(new_file->relpath, NULL);
new_file->added = TRUE;
new_file->base_revision = SVN_INVALID_REVNUM;
new_file->copy_path = copy_path;
@@ -1925,8 +1891,7 @@ add_file(const char *path,
new_file->url =
svn_path_url_add_component2(dir->checkout->resource_url,
- svn_relpath_basename(path, new_file->pool),
- new_file->pool);
+ new_file->name, new_file->pool);
}
while (deleted_parent && deleted_parent[0] != '\0')
@@ -1992,7 +1957,8 @@ open_file(const char *path,
new_file->parent_dir = parent;
new_file->commit = parent->commit;
- new_file->name = apr_pstrdup(new_file->pool, path); /* TODO: basename? */
+ new_file->relpath = apr_pstrdup(new_file->pool, path);
+ new_file->name = svn_relpath_basename(new_file->relpath, NULL);
new_file->added = FALSE;
new_file->base_revision = base_revision;
new_file->changed_props = apr_hash_make(new_file->pool);
@@ -2213,7 +2179,7 @@ close_file(void *file_baton,
proppatch = apr_pcalloc(ctx->pool, sizeof(*proppatch));
proppatch->pool = ctx->pool;
proppatch->progress.pool = pool;
- proppatch->name = ctx->name;
+ proppatch->relpath = ctx->relpath;
proppatch->path = ctx->url;
proppatch->commit = ctx->commit;
proppatch->changed_props = ctx->changed_props;
Modified: subversion/branches/fs-py/subversion/libsvn_ra_serf/locks.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_ra_serf/locks.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_ra_serf/locks.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_ra_serf/locks.c Mon Aug 22 15:21:13 2011
@@ -580,6 +580,8 @@ svn_ra_serf__lock(svn_ra_session_t *ra_s
subpool = svn_pool_create(pool);
+ /* ### TODO for issue 2263: Send all the locks over the wire at once. This
+ loop is just a temporary shim. */
for (hi = apr_hash_first(pool, path_revs); hi; hi = apr_hash_next(hi))
{
svn_ra_serf__handler_t *handler;
@@ -683,6 +685,8 @@ svn_ra_serf__unlock(svn_ra_session_t *ra
subpool = svn_pool_create(pool);
+ /* ### TODO for issue 2263: Send all the locks over the wire at once. This
+ loop is just a temporary shim. */
for (hi = apr_hash_first(pool, path_tokens); hi; hi = apr_hash_next(hi))
{
svn_ra_serf__handler_t *handler;
Modified: subversion/branches/fs-py/subversion/libsvn_subr/validate.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_subr/validate.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_subr/validate.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_subr/validate.c Mon Aug 22 15:21:13 2011
@@ -45,6 +45,7 @@ svn_mime_type_validate(const char *mime_
specification, e.g., "text/html; charset=UTF-8", make sure we're
only looking at the media type here. */
const apr_size_t len = strcspn(mime_type, "; ");
+ const apr_size_t len2 = strlen(mime_type);
const char *const slash_pos = strchr(mime_type, '/');
apr_size_t i;
const char *tspecials = "()<>@,;:\\\"/[]?=";
@@ -69,7 +70,19 @@ svn_mime_type_validate(const char *mime_
|| (strchr(tspecials, mime_type[i]) != NULL)))
return svn_error_createf
(SVN_ERR_BAD_MIME_TYPE, NULL,
- _("MIME type '%s' contains invalid character '%c'"),
+ _("MIME type '%s' contains invalid character '%c' "
+ "in media type"),
+ mime_type, mime_type[i]);
+ }
+
+ /* Check the whole string for unsafe characters. (issue #2872) */
+ for (i = 0; i < len2; i++)
+ {
+ if (svn_ctype_iscntrl(mime_type[i]) && mime_type[i] != '\t')
+ return svn_error_createf(
+ SVN_ERR_BAD_MIME_TYPE, NULL,
+ _("MIME type '%s' contains invalid character '0x%02x' "
+ "in postfix"),
mime_type, mime_type[i]);
}
Modified: subversion/branches/fs-py/subversion/libsvn_wc/adm_ops.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_wc/adm_ops.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_wc/adm_ops.c Mon Aug 22 15:21:13 2011
@@ -29,6 +29,7 @@
#include <string.h>
+#include <stdlib.h>
#include <apr_pools.h>
#include <apr_tables.h>
@@ -1291,6 +1292,136 @@ remove_conflict_file(svn_boolean_t *noti
}
+/* Sort copied children obtained from the revert list based on
+ * their paths in descending order (longest paths first). */
+static int
+compare_revert_list_copied_children(const void *a, const void *b)
+{
+ const svn_wc__db_revert_list_copied_child_info_t *ca = a;
+ const svn_wc__db_revert_list_copied_child_info_t *cb = b;
+ int i;
+
+ i = svn_path_compare_paths(ca->abspath, cb->abspath);
+
+ /* Reverse the result of svn_path_compare_paths() to achieve
+ * descending order. */
+ return -i;
+}
+
+
+/* Remove all reverted copied children from the directory at LOCAL_ABSPATH.
+ * If REMOVE_SELF is TRUE, try to remove LOCAL_ABSPATH itself (REMOVE_SELF
+ * should be set if LOCAL_ABSPATH is itself a reverted copy).
+ *
+ * If REMOVED_SELF is not NULL, indicate in *REMOVED_SELF whether
+ * LOCAL_ABSPATH itself was removed.
+ *
+ * All reverted copied file children are removed from disk. Reverted copied
+ * directories left empty as a result are also removed from disk.
+ */
+static svn_error_t *
+revert_restore_handle_copied_dirs(svn_boolean_t *removed_self,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ svn_boolean_t remove_self,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
+{
+ const apr_array_header_t *copied_children;
+ svn_wc__db_revert_list_copied_child_info_t *child_info;
+ int i;
+ svn_node_kind_t on_disk;
+ apr_pool_t *iterpool;
+ svn_error_t *err;
+
+ if (removed_self)
+ *removed_self = FALSE;
+
+ SVN_ERR(svn_wc__db_revert_list_read_copied_children(&copied_children,
+ db, local_abspath,
+ scratch_pool,
+ scratch_pool));
+ iterpool = svn_pool_create(scratch_pool);
+
+ /* Remove all copied file children. */
+ for (i = 0; i < copied_children->nelts; i++)
+ {
+ child_info = APR_ARRAY_IDX(
+ copied_children, i,
+ svn_wc__db_revert_list_copied_child_info_t *);
+
+ if (cancel_func)
+ SVN_ERR(cancel_func(cancel_baton));
+
+ if (child_info->kind != svn_wc__db_kind_file)
+ continue;
+
+ svn_pool_clear(iterpool);
+
+ /* Make sure what we delete from disk is really a file. */
+ SVN_ERR(svn_io_check_path(child_info->abspath, &on_disk, iterpool));
+ if (on_disk != svn_node_file)
+ continue;
+
+ SVN_ERR(svn_io_remove_file2(child_info->abspath, TRUE, iterpool));
+ }
+
+ /* Delete every empty child directory.
+ * We cannot delete children recursively since we want to keep any files
+ * that still exist on disk (e.g. unversioned files within the copied tree).
+ * So sort the children list such that longest paths come first and try to
+ * remove each child directory in order. */
+ qsort(copied_children->elts, copied_children->nelts,
+ sizeof(svn_wc__db_revert_list_copied_child_info_t *),
+ compare_revert_list_copied_children);
+ for (i = 0; i < copied_children->nelts; i++)
+ {
+ child_info = APR_ARRAY_IDX(
+ copied_children, i,
+ svn_wc__db_revert_list_copied_child_info_t *);
+
+ if (cancel_func)
+ SVN_ERR(cancel_func(cancel_baton));
+
+ if (child_info->kind != svn_wc__db_kind_dir)
+ continue;
+
+ svn_pool_clear(iterpool);
+
+ err = svn_io_dir_remove_nonrecursive(child_info->abspath, iterpool);
+ if (err)
+ {
+ if (APR_STATUS_IS_ENOENT(err->apr_err) ||
+ SVN__APR_STATUS_IS_ENOTDIR(err->apr_err) ||
+ APR_STATUS_IS_ENOTEMPTY(err->apr_err))
+ svn_error_clear(err);
+ else
+ return svn_error_trace(err);
+ }
+ }
+
+ if (remove_self)
+ {
+ /* Delete LOCAL_ABSPATH itself if no children are left. */
+ err = svn_io_dir_remove_nonrecursive(local_abspath, iterpool);
+ if (err)
+ {
+ if (APR_STATUS_IS_ENOTEMPTY(err->apr_err))
+ svn_error_clear(err);
+ else
+ return svn_error_trace(err);
+ }
+ else if (removed_self)
+ *removed_self = TRUE;
+ }
+
+ svn_pool_destroy(iterpool);
+
+ return SVN_NO_ERROR;
+}
+
+
/* Make the working tree under LOCAL_ABSPATH to depth DEPTH match the
versioned tree. This function is called after svn_wc__db_op_revert
has done the database revert and created the revert list. Notifies
@@ -1321,6 +1452,8 @@ revert_restore(svn_wc__db_t *db,
#ifdef HAVE_SYMLINK
svn_boolean_t special;
#endif
+ svn_boolean_t copied_here;
+ svn_wc__db_kind_t reverted_kind;
if (cancel_func)
SVN_ERR(cancel_func(cancel_baton));
@@ -1328,6 +1461,7 @@ revert_restore(svn_wc__db_t *db,
SVN_ERR(svn_wc__db_revert_list_read(¬ify_required,
&conflict_old, &conflict_new,
&conflict_working, &prop_reject,
+ &copied_here, &reverted_kind,
db, local_abspath,
scratch_pool, scratch_pool));
@@ -1342,17 +1476,31 @@ revert_restore(svn_wc__db_t *db,
{
svn_error_clear(err);
- if (notify_func && notify_required)
- notify_func(notify_baton,
- svn_wc_create_notify(local_abspath, svn_wc_notify_revert,
- scratch_pool),
- scratch_pool);
-
- if (notify_func)
- SVN_ERR(svn_wc__db_revert_list_notify(notify_func, notify_baton,
- db, local_abspath,
- scratch_pool));
- return SVN_NO_ERROR;
+ if (!copied_here)
+ {
+ if (notify_func && notify_required)
+ notify_func(notify_baton,
+ svn_wc_create_notify(local_abspath,
+ svn_wc_notify_revert,
+ scratch_pool),
+ scratch_pool);
+
+ if (notify_func)
+ SVN_ERR(svn_wc__db_revert_list_notify(notify_func, notify_baton,
+ db, local_abspath,
+ scratch_pool));
+ return SVN_NO_ERROR;
+ }
+ else
+ {
+ /* ### Initialise to values which prevent the code below from
+ * ### trying to restore anything to disk.
+ * ### 'status' should be status_unknown but that doesn't exist. */
+ status = svn_wc__db_status_normal;
+ kind = svn_wc__db_kind_unknown;
+ recorded_size = SVN_INVALID_FILESIZE;
+ recorded_mod_time = 0;
+ }
}
else if (err)
return svn_error_trace(err);
@@ -1387,6 +1535,27 @@ revert_restore(svn_wc__db_t *db,
#endif
}
+ if (copied_here)
+ {
+ /* The revert target itself is the op-root of a copy. */
+ if (reverted_kind == svn_wc__db_kind_file && on_disk == svn_node_file)
+ {
+ SVN_ERR(svn_io_remove_file2(local_abspath, TRUE, scratch_pool));
+ on_disk = svn_node_none;
+ }
+ else if (reverted_kind == svn_wc__db_kind_dir && on_disk == svn_node_dir)
+ {
+ svn_boolean_t removed;
+
+ SVN_ERR(revert_restore_handle_copied_dirs(&removed, db,
+ local_abspath, TRUE,
+ cancel_func, cancel_baton,
+ scratch_pool));
+ if (removed)
+ on_disk = svn_node_none;
+ }
+ }
+
/* If we expect a versioned item to be present then check that any
item on disk matches the versioned item, if it doesn't match then
fix it or delete it. */
@@ -1567,6 +1736,10 @@ revert_restore(svn_wc__db_t *db,
const apr_array_header_t *children;
int i;
+ SVN_ERR(revert_restore_handle_copied_dirs(NULL, db, local_abspath, FALSE,
+ cancel_func, cancel_baton,
+ iterpool));
+
SVN_ERR(svn_wc__db_read_children_of_working_node(&children, db,
local_abspath,
scratch_pool,
@@ -2327,9 +2500,11 @@ svn_wc__internal_changelist_match(svn_wc
return FALSE;
}
+ /* The empty changelist name is special-cased. */
return (changelist
- && apr_hash_get((apr_hash_t *)clhash, changelist,
- APR_HASH_KEY_STRING) != NULL);
+ ? apr_hash_get((apr_hash_t *)clhash, changelist, APR_HASH_KEY_STRING)
+ : apr_hash_get((apr_hash_t *)clhash, "", APR_HASH_KEY_STRING)
+ ) != NULL;
}
Modified: subversion/branches/fs-py/subversion/libsvn_wc/diff_local.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_wc/diff_local.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_wc/diff_local.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_wc/diff_local.c Mon Aug 22 15:21:13 2011
@@ -474,8 +474,29 @@ diff_status_callback(void *baton,
SVN_ERR(file_diff(eb, local_abspath, path, scratch_pool));
}
}
- else
+ else /* it's a directory */
{
+ const char *path = svn_dirent_skip_ancestor(eb->anchor_abspath,
+ local_abspath);
+
+ /* Report the directory as deleted and/or opened or added. */
+ if (status->node_status == svn_wc_status_deleted
+ || status->node_status == svn_wc_status_replaced)
+ SVN_ERR(eb->callbacks->dir_deleted(NULL, NULL, path,
+ eb->callback_baton, scratch_pool));
+
+ if (status->node_status == svn_wc_status_added
+ || status->node_status == svn_wc_status_replaced)
+ SVN_ERR(eb->callbacks->dir_added(NULL, NULL, NULL, NULL,
+ path, status->revision,
+ path, status->revision /* ### ? */,
+ eb->callback_baton, scratch_pool));
+ else
+ SVN_ERR(eb->callbacks->dir_opened(NULL, NULL, NULL,
+ path, status->revision,
+ eb->callback_baton, scratch_pool));
+
+ /* Report the prop change. */
/* ### This case should probably be extended for git-diff, but this
is what the old diff code provided */
if (status->node_status == svn_wc_status_deleted
@@ -484,9 +505,6 @@ diff_status_callback(void *baton,
{
apr_array_header_t *propchanges;
apr_hash_t *baseprops;
- const char *path = svn_dirent_skip_ancestor(eb->anchor_abspath,
- local_abspath);
-
SVN_ERR(svn_wc__internal_propdiff(&propchanges, &baseprops,
eb->db, local_abspath,
@@ -498,6 +516,15 @@ diff_status_callback(void *baton,
eb->callback_baton,
scratch_pool));
}
+
+ /* Close the dir.
+ * ### This should be done after all children have been processed, not
+ * yet. The current Subversion-internal callers don't care. */
+ SVN_ERR(eb->callbacks->dir_closed(
+ NULL, NULL, NULL, path,
+ (status->node_status == svn_wc_status_added
+ || status->node_status == svn_wc_status_replaced),
+ eb->callback_baton, scratch_pool));
}
return SVN_NO_ERROR;
}
Modified: subversion/branches/fs-py/subversion/libsvn_wc/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_wc/status.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_wc/status.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_wc/status.c Mon Aug 22 15:21:13 2011
@@ -273,6 +273,68 @@ read_info(const struct svn_wc__db_info_t
&mtb->lock, NULL, NULL,
db, local_abspath,
result_pool, scratch_pool));
+
+ if (mtb->status == svn_wc__db_status_deleted)
+ {
+ const char *moved_to_abspath;
+ const char *moved_to_op_root_abspath;
+
+ /* NOTE: we can't use op-root-ness as a condition here since a base
+ * node can be the root of a move and still not be an explicit
+ * op-root (having a working node with op_depth == pathelements).
+ *
+ * Both these (almost identical) situations showcase this:
+ * svn mv a/b bb
+ * svn del a
+ * and
+ * svn mv a aa
+ * svn mv aa/b bb
+ * In both, 'bb' is moved from 'a/b', but 'a/b' has no op_depth>0
+ * node at all, as its parent 'a' is locally deleted. */
+
+ SVN_ERR(svn_wc__db_scan_deletion(NULL,
+ &moved_to_abspath,
+ NULL,
+ &moved_to_op_root_abspath,
+ db, local_abspath,
+ scratch_pool, scratch_pool));
+ if (moved_to_abspath != NULL
+ && moved_to_op_root_abspath != NULL
+ && strcmp(moved_to_abspath, moved_to_op_root_abspath) == 0)
+ {
+ mtb->moved_to_abspath = apr_pstrdup(result_pool,
+ moved_to_abspath);
+ }
+ /* ### ^^^ THIS SUCKS. For at least two reasons:
+ * 1) We scan the node deletion and that's technically not necessary.
+ * We'd be fine to know if this is an actual root of a move.
+ * 2) From the elaborately calculated results, we backwards-guess
+ * whether this is a root.
+ * It works ok, and this code only gets called when a node is an
+ * explicit target of a 'status'. But it would be better to do this
+ * differently.
+ * We could return moved-to via svn_wc__db_base_get_info() (called
+ * just above), but as moved-to is only intended to be returned for
+ * roots of a move, that doesn't fit too well. */
+ }
+ }
+
+ /* ### svn_wc__db_read_info() could easily return the moved-here flag. But
+ * for now... (The per-dir query for recursive status is far more optimal.)
+ * Note that this actually scans around to get the full path, for a bool.
+ * This bool then gets returned, later is evaluated, and if true leads to
+ * the same paths being scanned again. We'd want to obtain this bool here as
+ * cheaply as svn_wc__db_read_children_info() does. */
+ if (mtb->status == svn_wc__db_status_added)
+ {
+ const char *moved_from_abspath = NULL;
+ SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ &moved_from_abspath,
+ NULL,
+ db, local_abspath,
+ result_pool, scratch_pool));
+ mtb->moved_here = (moved_from_abspath != NULL);
}
mtb->has_checksum = (checksum != NULL);
@@ -404,8 +466,6 @@ assemble_status(svn_wc_status3_t **statu
const char *repos_root_url;
const char *repos_uuid;
const char *moved_from_abspath = NULL;
- const char *moved_to_abspath = NULL;
- const char *moved_to_op_root_abspath = NULL;
svn_filesize_t filesize = (dirent && (dirent->kind == svn_node_file))
? dirent->filesize
: SVN_INVALID_FILESIZE;
@@ -426,17 +486,13 @@ assemble_status(svn_wc_status3_t **statu
/* A node is switched if it doesn't have the implied repos_relpath */
const char *name = svn_relpath_skip_ancestor(parent_repos_relpath,
info->repos_relpath);
- switched_p = !name || (strcmp(name, svn_dirent_basename(local_abspath, NULL)) != 0);
+ switched_p = !name || (strcmp(name,
+ svn_dirent_basename(local_abspath, NULL))
+ != 0);
}
- /* Examine whether our target is missing or obstructed.
-
- While we are not completely in single-db mode yet, data about
- obstructed or missing nodes might be incomplete here. This is
- reported by svn_wc_db_status_obstructed_XXXX. In single-db
- mode these obstructions are no longer reported and we have
- to detect obstructions by looking at the on disk status in DIRENT.
- */
+ /* Examine whether our target is missing or obstructed. To detect
+ * obstructions, we have to look at the on-disk status in DIRENT. */
if (info->kind == svn_wc__db_kind_dir)
{
if (info->status == svn_wc__db_status_incomplete)
@@ -608,26 +664,18 @@ assemble_status(svn_wc_status3_t **statu
else if (schedule == svn_wc_schedule_replace)
node_status = svn_wc_status_replaced;
}
+
+ /* Get moved-from info (only for potential op-roots of a move). */
+ if (info->moved_here && info->op_root)
+ SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ &moved_from_abspath,
+ NULL,
+ db, local_abspath,
+ result_pool, scratch_pool));
}
}
- /* Get moved-to info. */
- if (info->status == svn_wc__db_status_deleted)
- SVN_ERR(svn_wc__db_scan_deletion(NULL,
- &moved_to_abspath,
- NULL,
- &moved_to_op_root_abspath,
- db, local_abspath,
- result_pool, scratch_pool));
-
- /* Get moved-from info. */
- if (info->status == svn_wc__db_status_added)
- SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- &moved_from_abspath,
- NULL,
- db, local_abspath,
- result_pool, scratch_pool));
if (node_status == svn_wc_status_normal)
node_status = text_status;
@@ -722,8 +770,7 @@ assemble_status(svn_wc_status3_t **statu
stat->repos_uuid = repos_uuid;
stat->moved_from_abspath = moved_from_abspath;
- stat->moved_to_abspath = moved_to_abspath;
- stat->moved_to_op_root_abspath = moved_to_op_root_abspath;
+ stat->moved_to_abspath = info->moved_to_abspath;
*status = stat;
@@ -1082,8 +1129,8 @@ get_dir_status(const struct walk_status_
don't all map the same types, but only the keys of the result
hash are subsequently used. */
SVN_ERR(svn_wc__db_read_children_info(&nodes, &conflicts,
- wb->db, local_abspath,
- subpool, iterpool));
+ wb->db, local_abspath,
+ subpool, iterpool));
all_children = apr_hash_overlay(subpool, nodes, dirents);
if (apr_hash_count(conflicts) > 0)
@@ -2624,10 +2671,6 @@ svn_wc_dup_status3(const svn_wc_status3_
new_stat->moved_to_abspath
= apr_pstrdup(pool, orig_stat->moved_to_abspath);
- if (orig_stat->moved_to_op_root_abspath)
- new_stat->moved_to_op_root_abspath
- = apr_pstrdup(pool, orig_stat->moved_to_op_root_abspath);
-
/* Return the new hotness. */
return new_stat;
}
Modified: subversion/branches/fs-py/subversion/libsvn_wc/tree_conflicts.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_wc/tree_conflicts.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_wc/tree_conflicts.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_wc/tree_conflicts.c Mon Aug 22 15:21:13 2011
@@ -76,6 +76,8 @@ const svn_token_map_t svn_wc__conflict_r
{ "added", svn_wc_conflict_reason_added },
{ "replaced", svn_wc_conflict_reason_replaced },
{ "unversioned", svn_wc_conflict_reason_unversioned },
+ { "moved-here", svn_wc_conflict_reason_moved_here },
+ { "moved-away", svn_wc_conflict_reason_moved_away },
{ NULL }
};
Modified: subversion/branches/fs-py/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_wc/update_editor.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_wc/update_editor.c Mon Aug 22 15:21:13 2011
@@ -1272,7 +1272,8 @@ create_tree_conflict(svn_wc_conflict_des
/* Get the source-left information, i.e. the local state of the node
* before any changes were made to the working copy, i.e. the state the
* node would have if it was reverted. */
- if (reason == svn_wc_conflict_reason_added)
+ if (reason == svn_wc_conflict_reason_added ||
+ reason == svn_wc_conflict_reason_moved_here)
{
svn_wc__db_status_t added_status;
@@ -1327,6 +1328,7 @@ create_tree_conflict(svn_wc_conflict_des
* and that other case should also be handled. */
SVN_ERR_ASSERT(reason == svn_wc_conflict_reason_edited
|| reason == svn_wc_conflict_reason_deleted
+ || reason == svn_wc_conflict_reason_moved_away
|| reason == svn_wc_conflict_reason_replaced
|| reason == svn_wc_conflict_reason_obstructed);
@@ -1364,7 +1366,8 @@ create_tree_conflict(svn_wc_conflict_des
/* This is an 'update', so REPOS_RELPATH would be the same as for
* source-left. However, we don't have a source-left for locally
* added files. */
- right_repos_relpath = (reason == svn_wc_conflict_reason_added ?
+ right_repos_relpath = ((reason == svn_wc_conflict_reason_added ||
+ reason == svn_wc_conflict_reason_moved_here) ?
added_repos_relpath : left_repos_relpath);
if (! right_repos_relpath)
right_repos_relpath = their_relpath;
@@ -1496,7 +1499,18 @@ check_tree_conflict(svn_wc_conflict_desc
* would not have been called in the first place. */
SVN_ERR_ASSERT(action == svn_wc_conflict_action_add);
- reason = svn_wc_conflict_reason_added;
+ /* Scan the addition in case our caller didn't. */
+ if (working_status == svn_wc__db_status_added)
+ SVN_ERR(svn_wc__db_scan_addition(&working_status, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ eb->db, local_abspath,
+ scratch_pool, scratch_pool));
+
+ if (working_status == svn_wc__db_status_moved_here)
+ reason = svn_wc_conflict_reason_moved_here;
+ else
+ reason = svn_wc_conflict_reason_added;
}
else
{
@@ -1507,8 +1521,20 @@ check_tree_conflict(svn_wc_conflict_desc
case svn_wc__db_status_deleted:
- /* The node is locally deleted. */
- reason = svn_wc_conflict_reason_deleted;
+ {
+ const char *moved_to_abspath;
+
+ /* The node is locally deleted. Check if it was moved away.
+ * ### should scan_deletion return status_moved_away, like
+ * ### scan_addition returns status_moved_here? */
+ SVN_ERR(svn_wc__db_scan_deletion(NULL, &moved_to_abspath, NULL,
+ NULL, eb->db, local_abspath,
+ scratch_pool, scratch_pool));
+ if (moved_to_abspath)
+ reason = svn_wc_conflict_reason_moved_away;
+ else
+ reason = svn_wc_conflict_reason_deleted;
+ }
break;
case svn_wc__db_status_incomplete:
@@ -1573,6 +1599,7 @@ check_tree_conflict(svn_wc_conflict_desc
* would not have been called in the first place.*/
if (reason == svn_wc_conflict_reason_edited
|| reason == svn_wc_conflict_reason_deleted
+ || reason == svn_wc_conflict_reason_moved_away
|| reason == svn_wc_conflict_reason_replaced)
/* When the node existed before (it was locally deleted, replaced or
* edited), then 'update' cannot add it "again". So it can only send
@@ -1580,7 +1607,8 @@ check_tree_conflict(svn_wc_conflict_desc
SVN_ERR_ASSERT(action == svn_wc_conflict_action_edit
|| action == svn_wc_conflict_action_delete
|| action == svn_wc_conflict_action_replace);
- else if (reason == svn_wc_conflict_reason_added)
+ else if (reason == svn_wc_conflict_reason_added ||
+ reason == svn_wc_conflict_reason_moved_here)
/* When the node did not exist before (it was locally added), then 'update'
* cannot want to modify it in any way. It can only send _action_add. */
SVN_ERR_ASSERT(action == svn_wc_conflict_action_add);
@@ -1835,6 +1863,7 @@ delete_entry(const char *path,
keeping a not-present marker */
}
else if (tree_conflict->reason == svn_wc_conflict_reason_deleted
+ || tree_conflict->reason == svn_wc_conflict_reason_moved_away
|| tree_conflict->reason == svn_wc_conflict_reason_replaced)
{
/* The item does not exist locally because it was already shadowed.
@@ -2355,6 +2384,7 @@ open_directory(const char *path,
/* Other modifications wouldn't be a tree conflict */
SVN_ERR_ASSERT(
tree_conflict->reason == svn_wc_conflict_reason_deleted ||
+ tree_conflict->reason == svn_wc_conflict_reason_moved_away ||
tree_conflict->reason == svn_wc_conflict_reason_replaced);
/* Continue updating BASE */
@@ -3349,6 +3379,7 @@ open_file(const char *path,
/* Other modifications wouldn't be a tree conflict */
SVN_ERR_ASSERT(
tree_conflict->reason == svn_wc_conflict_reason_deleted ||
+ tree_conflict->reason == svn_wc_conflict_reason_moved_away||
tree_conflict->reason == svn_wc_conflict_reason_replaced);
/* Continue updating BASE */
Modified: subversion/branches/fs-py/subversion/libsvn_wc/wc-metadata.sql
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_wc/wc-metadata.sql?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_wc/wc-metadata.sql (original)
+++ subversion/branches/fs-py/subversion/libsvn_wc/wc-metadata.sql Mon Aug 22 15:21:13 2011
@@ -316,8 +316,8 @@ CREATE TABLE NODES (
BASE node, the location of the initial checkout.
When op_depth != 0, they indicate where this node was copied/moved from.
- In this case, the fields are set only on the root of the operation,
- and are NULL for all children. */
+ In this case, the fields are set for the root of the operation and for all
+ children. */
repos_id INTEGER REFERENCES REPOSITORY (id),
repos_path TEXT,
revision INTEGER,
@@ -384,7 +384,8 @@ CREATE TABLE NODES (
perhaps add a column called "moved_from". */
/* Boolean value, specifying if this node was moved here (rather than just
- copied). The source of the move is specified in copyfrom_*. */
+ copied). The source of the move is implied by a different node with
+ a moved_to column pointing at this node. */
moved_here INTEGER,
/* If the underlying node was moved away (rather than just deleted), this
@@ -392,8 +393,8 @@ CREATE TABLE NODES (
This is set only on the root of a move, and is NULL for all children.
Note that moved_to never refers to *this* node. It always refers
- to the "underlying" node, whether that is BASE or a child node
- implied from a parent's move/copy. */
+ to the "underlying" node in the BASE tree. A non-NULL moved_to column
+ is only valid in rows where op_depth == 0. */
moved_to TEXT,
Modified: subversion/branches/fs-py/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_wc/wc-queries.sql?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/fs-py/subversion/libsvn_wc/wc-queries.sql Mon Aug 22 15:21:13 2011
@@ -37,8 +37,11 @@ ORDER BY op_depth DESC
-- STMT_SELECT_NODE_INFO_WITH_LOCK
SELECT op_depth, nodes.repos_id, nodes.repos_path, presence, kind, revision,
checksum, translated_size, changed_revision, changed_date, changed_author,
- depth, symlink_target, last_mod_time, properties, lock_token, lock_owner,
- lock_comment, lock_date, moved_here
+ depth, symlink_target, last_mod_time, properties, moved_here,
+ /* All the columns until now must match those returned by
+ STMT_SELECT_NODE_INFO. The implementation of svn_wc__db_read_info()
+ assumes that these columns are followed by the lock information) */
+ lock_token, lock_owner, lock_comment, lock_date
FROM nodes
LEFT OUTER JOIN lock ON nodes.repos_id = lock.repos_id
AND nodes.repos_path = lock.repos_relpath
@@ -48,7 +51,8 @@ ORDER BY op_depth DESC
-- STMT_SELECT_BASE_NODE
SELECT repos_id, repos_path, presence, kind, revision, checksum,
translated_size, changed_revision, changed_date, changed_author, depth,
- symlink_target, last_mod_time, properties, file_external IS NOT NULL
+ symlink_target, last_mod_time, properties, file_external IS NOT NULL,
+ moved_to
FROM nodes
WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0
@@ -56,6 +60,10 @@ WHERE wc_id = ?1 AND local_relpath = ?2
SELECT nodes.repos_id, nodes.repos_path, presence, kind, revision,
checksum, translated_size, changed_revision, changed_date, changed_author,
depth, symlink_target, last_mod_time, properties, file_external IS NOT NULL,
+ moved_to,
+ /* All the columns until now must match those returned by
+ STMT_SELECT_BASE_NODE. The implementation of svn_wc__db_base_get_info()
+ assumes that these columns are followed by the lock information) */
lock_token, lock_owner, lock_comment, lock_date
FROM nodes
LEFT OUTER JOIN lock ON nodes.repos_id = lock.repos_id
@@ -119,7 +127,7 @@ WHERE wc_id = ?1 AND local_relpath = ?2
SELECT op_depth, nodes.repos_id, nodes.repos_path, presence, kind, revision,
checksum, translated_size, changed_revision, changed_date, changed_author,
depth, symlink_target, last_mod_time, properties, lock_token, lock_owner,
- lock_comment, lock_date, local_relpath
+ lock_comment, lock_date, local_relpath, moved_here, moved_to
FROM nodes
LEFT OUTER JOIN lock ON nodes.repos_id = lock.repos_id
AND nodes.repos_path = lock.repos_relpath
@@ -158,9 +166,9 @@ INSERT OR REPLACE INTO nodes (
wc_id, local_relpath, op_depth, parent_relpath, repos_id, repos_path,
revision, presence, depth, kind, changed_revision, changed_date,
changed_author, checksum, properties, translated_size, last_mod_time,
- dav_cache, symlink_target, file_external)
+ dav_cache, symlink_target, file_external, moved_to)
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14,
- ?15, ?16, ?17, ?18, ?19, ?20)
+ ?15, ?16, ?17, ?18, ?19, ?20, ?21)
-- STMT_SELECT_OP_DEPTH_CHILDREN
SELECT local_relpath FROM nodes
@@ -178,7 +186,7 @@ WHERE wc_id = ?1 AND parent_relpath = ?2
DELETE FROM nodes
WHERE wc_id = ?1
AND (local_relpath = ?2
- OR ((local_relpath > ?2 || '/') AND (local_relpath < ?2 || '0')))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
AND (op_depth < ?3
OR (op_depth = ?3 AND presence = 'base-deleted'))
@@ -186,7 +194,7 @@ WHERE wc_id = ?1
SELECT local_relpath FROM nodes
WHERE wc_id = ?1 AND op_depth = ?3
AND (parent_relpath = ?2
- OR ((parent_relpath > ?2 || '/') AND (parent_relpath < ?2 || '0')))
+ OR IS_STRICT_DESCENDANT_OF(parent_relpath, ?2))
AND presence == 'not-present'
-- STMT_COMMIT_DESCENDANT_TO_BASE
@@ -263,7 +271,7 @@ LEFT JOIN lock ON nodes.repos_id = lock.
WHERE wc_id = ?1 AND op_depth = 0
AND (?2 = ''
OR local_relpath = ?2
- OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
-- STMT_INSERT_WCROOT
INSERT INTO wcroot (local_abspath)
@@ -298,7 +306,7 @@ UPDATE nodes SET dav_cache = NULL
WHERE dav_cache IS NOT NULL AND wc_id = ?1 AND op_depth = 0
AND (?2 = ''
OR local_relpath = ?2
- OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
-- STMT_RECURSIVE_UPDATE_NODE_REPO
UPDATE nodes SET repos_id = ?4, dav_cache = NULL
@@ -306,7 +314,7 @@ WHERE wc_id = ?1
AND repos_id = ?3
AND (?2 = ''
OR local_relpath = ?2
- OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
-- STMT_UPDATE_LOCK_REPOS_ID
UPDATE lock SET repos_id = ?2
@@ -476,7 +484,7 @@ FROM nodes_current
WHERE wc_id = ?1
AND (?2 = ''
OR local_relpath = ?2
- OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
-- STMT_INSERT_TARGET_WITH_CHANGELIST
INSERT INTO targets_list(wc_id, local_relpath, parent_relpath, kind)
@@ -509,7 +517,7 @@ SELECT N.wc_id, N.local_relpath, N.paren
WHERE N.wc_id = ?1
AND (?2 = ''
OR N.local_relpath = ?2
- OR (N.local_relpath > ?2 || '/' AND N.local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(N.local_relpath, ?2))
AND A.changelist = ?3
-- STMT_SELECT_TARGETS
@@ -578,7 +586,7 @@ DELETE FROM nodes
WHERE wc_id = ?1
AND (?2 = ''
OR local_relpath = ?2
- OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
AND op_depth >= ?3
-- STMT_DELETE_ACTUAL_NODE
@@ -590,7 +598,7 @@ DELETE FROM actual_node
WHERE wc_id = ?1
AND (?2 = ''
OR local_relpath = ?2
- OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
-- STMT_DELETE_ACTUAL_NODE_WITHOUT_CONFLICT
DELETE FROM actual_node
@@ -611,7 +619,7 @@ DELETE FROM actual_node
WHERE wc_id = ?1
AND (?2 = ''
OR local_relpath = ?2
- OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
AND (changelist IS NULL
OR NOT EXISTS (SELECT 1 FROM nodes_current c
WHERE c.wc_id = ?1
@@ -647,7 +655,7 @@ SET properties = NULL,
WHERE wc_id = ?1
AND (?2 = ''
OR local_relpath = ?2
- OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
-- STMT_UPDATE_NODE_BASE_DEPTH
UPDATE nodes SET depth = ?3
@@ -779,7 +787,7 @@ DELETE FROM wc_lock
WHERE wc_id = ?1
AND (?2 = ''
OR local_dir_relpath = ?2
- OR (local_dir_relpath > ?2 || '/' AND local_dir_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_dir_relpath, ?2))
AND NOT EXISTS (SELECT 1 FROM nodes
WHERE nodes.wc_id = ?1
AND nodes.local_relpath = wc_lock.local_dir_relpath)
@@ -812,18 +820,8 @@ SELECT wc_id, local_relpath, ?4 /*op_dep
kind
FROM nodes
WHERE wc_id = ?1
- AND (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0')
- AND op_depth = ?3
- AND presence NOT IN ('base-deleted', 'not-present', 'excluded', 'absent')
-
--- STMT_INSERT_DELETE_NODE
-INSERT INTO nodes (
- wc_id, local_relpath, op_depth, parent_relpath, presence, kind)
-SELECT wc_id, local_relpath, ?4 /*op_depth*/, parent_relpath, 'base-deleted',
- kind
-FROM nodes
-WHERE wc_id = ?1
- AND local_relpath = ?2
+ AND (local_relpath = ?2
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
AND op_depth = ?3
AND presence NOT IN ('base-deleted', 'not-present', 'excluded', 'absent')
@@ -852,7 +850,7 @@ WHERE wc_id = ?1 AND local_relpath = ?2
UPDATE nodes SET op_depth = ?3 + 1
WHERE wc_id = ?1
AND (?2 = ''
- OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
AND op_depth = ?3
-- STMT_DOES_NODE_EXIST
@@ -864,7 +862,7 @@ SELECT local_relpath FROM nodes
WHERE wc_id = ?1
AND (?2 = ''
OR local_relpath = ?2
- OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
AND op_depth = 0 AND presence = 'absent'
LIMIT 1
@@ -874,7 +872,7 @@ SELECT local_relpath FROM nodes
WHERE wc_id = ?1
AND (?2 = ''
OR local_relpath = ?2
- OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
AND op_depth = 0
AND presence = 'absent'
@@ -965,7 +963,7 @@ FROM externals
WHERE wc_id = ?1
AND (?2 = ''
OR def_local_relpath = ?2
- OR (def_local_relpath > ?2 || '/' AND def_local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(def_local_relpath, ?2))
-- STMT_UPDATE_EXTERNAL_FILEINFO
UPDATE externals SET recorded_size = ?3, recorded_mod_time = ?4
@@ -984,7 +982,7 @@ FROM nodes n
WHERE wc_id = ?1
AND (?2 = ''
OR local_relpath = ?2
- OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
AND kind = 'dir' AND presence='normal'
AND op_depth=(SELECT MAX(op_depth) FROM nodes o
WHERE o.wc_id = ?1 AND o.local_relpath = n.local_relpath)
@@ -1112,14 +1110,18 @@ CREATE TEMPORARY TABLE revert_list (
conflict_working TEXT,
prop_reject TEXT,
notify INTEGER, /* 1 if an actual row had props or tree conflict */
+ op_depth INTEGER,
+ repos_id INTEGER,
+ kind TEXT,
PRIMARY KEY (local_relpath, actual)
);
DROP TRIGGER IF EXISTS trigger_revert_list_nodes;
CREATE TEMPORARY TRIGGER trigger_revert_list_nodes
BEFORE DELETE ON nodes
BEGIN
- INSERT OR REPLACE INTO revert_list(local_relpath, actual)
- SELECT OLD.local_relpath, 0;
+ INSERT OR REPLACE INTO revert_list(local_relpath, actual, op_depth,
+ repos_id, kind)
+ SELECT OLD.local_relpath, 0, OLD.op_depth, OLD.repos_id, OLD.kind;
END;
DROP TRIGGER IF EXISTS trigger_revert_list_actual_delete;
CREATE TEMPORARY TRIGGER trigger_revert_list_actual_delete
@@ -1156,11 +1158,20 @@ DROP TRIGGER IF EXISTS trigger_revert_li
DROP TRIGGER IF EXISTS trigger_revert_list_actual_update
-- STMT_SELECT_REVERT_LIST
-SELECT conflict_old, conflict_new, conflict_working, prop_reject, notify, actual
+SELECT conflict_old, conflict_new, conflict_working, prop_reject, notify,
+ actual, op_depth, repos_id, kind
FROM revert_list
WHERE local_relpath = ?1
ORDER BY actual DESC
+-- STMT_SELECT_REVERT_LIST_COPIED_CHILDREN
+SELECT local_relpath, kind
+FROM revert_list
+WHERE local_relpath LIKE ?1 ESCAPE '#'
+ AND op_depth >= ?2
+ AND repos_id IS NOT NULL
+ORDER BY local_relpath
+
-- STMT_DELETE_REVERT_LIST
DELETE FROM revert_list WHERE local_relpath = ?1
@@ -1192,7 +1203,7 @@ INSERT INTO delete_list(local_relpath)
SELECT local_relpath FROM nodes n
WHERE wc_id = ?1
AND (local_relpath = ?2
- OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
AND op_depth >= ?3
AND presence NOT IN ('base-deleted', 'not-present', 'excluded', 'absent')
AND op_depth = (SELECT MAX(op_depth) FROM nodes s
@@ -1217,7 +1228,7 @@ SELECT MIN(revision), MAX(revision),
WHERE wc_id = ?1
AND (?2 = ''
OR local_relpath = ?2
- OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
AND presence IN ('normal', 'incomplete')
AND file_external IS NULL
AND op_depth = 0
@@ -1227,7 +1238,7 @@ SELECT 1 FROM nodes
WHERE wc_id = ?1
AND (?2 = ''
OR local_relpath = ?2
- OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
AND op_depth = 0
AND (presence IN ('absent', 'excluded')
OR depth NOT IN ('infinity', 'unknown'))
@@ -1239,7 +1250,7 @@ SELECT 1 FROM nodes
WHERE wc_id = ?1
AND (?2 = ''
OR local_relpath = ?2
- OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
AND op_depth > 0
LIMIT 1
@@ -1248,7 +1259,7 @@ SELECT 1 FROM actual_node
WHERE wc_id = ?1
AND (?2 = ''
OR local_relpath = ?2
- OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
AND properties IS NOT NULL
LIMIT 1
@@ -1271,7 +1282,7 @@ SELECT o.repos_path || '/' || SUBSTR(s.l
FROM nodes AS o
LEFT JOIN nodes AS s
ON o.wc_id = s.wc_id
- AND s.local_relpath > ?2 || '/' AND s.local_relpath < ?2 || '0'
+ AND IS_STRICT_DESCENDANT_OF(s.local_relpath, ?2)
AND s.op_depth = 0
AND s.repos_id = o.repos_id
AND s.file_external IS NULL
@@ -1285,7 +1296,7 @@ SELECT SUBSTR(s.local_relpath, LENGTH(?2
FROM nodes AS o
LEFT JOIN nodes AS s
ON o.wc_id = s.wc_id
- AND s.local_relpath > ?2 || '/' AND s.local_relpath < ?2 || '0'
+ AND IS_STRICT_DESCENDANT_OF(s.local_relpath, ?2)
AND s.op_depth = 0
AND s.repos_id = o.repos_id
AND s.file_external IS NULL
@@ -1326,7 +1337,7 @@ SELECT local_relpath, translated_size, l
WHERE wc_id = ?1
AND (?2 = ''
OR local_relpath = ?2
- OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
AND op_depth = 0
AND kind='file'
AND presence='normal'
@@ -1349,13 +1360,16 @@ UPDATE nodes SET moved_to = NULL
WHERE wc_id = ?1
AND (?2 = ''
OR local_relpath = ?2
- OR (local_relpath > ?2 || '/' AND local_relpath < ?2 || '0'))
+ OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
AND op_depth = 0
+/* This statement returns pairs of move-roots below the path ?2 in WC_ID ?1.
+ * Each row returns a moved-here path (always a child of ?2) in the first
+ * column, and its matching moved-away (deleted) path in the second column. */
-- STMT_SELECT_MOVED_HERE_CHILDREN
SELECT moved_to, local_relpath FROM nodes
WHERE wc_id = ?1 AND op_depth = 0
- AND (moved_to > ?2 || '/' AND moved_to < ?2 || '0')
+ AND IS_STRICT_DESCENDANT_OF(moved_to, ?2)
/* ------------------------------------------------------------------------- */
Modified: subversion/branches/fs-py/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_wc/wc_db.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_wc/wc_db.c Mon Aug 22 15:21:13 2011
@@ -781,6 +781,8 @@ insert_base_node(void *baton,
svn_sqlite__stmt_t *stmt;
svn_filesize_t recorded_size = SVN_INVALID_FILESIZE;
apr_int64_t recorded_mod_time;
+ const char *moved_to_relpath = NULL;
+ svn_boolean_t have_row;
/* The directory at the WCROOT has a NULL parent_relpath. Otherwise,
bind the appropriate parent_relpath. */
@@ -798,24 +800,28 @@ insert_base_node(void *baton,
/* ### we can't handle this right now */
SVN_ERR_ASSERT(pibb->conflict == NULL);
- if (pibb->keep_recorded_info)
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_SELECT_BASE_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ if (have_row)
{
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_SELECT_BASE_NODE));
-
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
- SVN_ERR(svn_sqlite__step_row(stmt));
-
- recorded_size = get_recorded_size(stmt, 6);
- recorded_mod_time = svn_sqlite__column_int64(stmt, 12);
-
- SVN_ERR(svn_sqlite__reset(stmt));
+ /* A BASE node already exists. */
+ if (pibb->keep_recorded_info)
+ {
+ /* Preserve size and modification time if caller asked us to. */
+ recorded_size = get_recorded_size(stmt, 6);
+ recorded_mod_time = svn_sqlite__column_int64(stmt, 12);
+ }
+ /* Always preserve moved-to info. */
+ moved_to_relpath = svn_sqlite__column_text(stmt, 15, scratch_pool);
}
+ SVN_ERR(svn_sqlite__reset(stmt));
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_INSERT_NODE));
SVN_ERR(svn_sqlite__bindf(stmt, "isisisr"
"tstr" /* 8 - 11 */
- "isnnnnns", /* 12 - 19 */
+ "isnnnnnsss", /* 12 - 21 */
wcroot->wc_id, /* 1 */
local_relpath, /* 2 */
(apr_int64_t)0, /* op_depth is 0 for base */
@@ -831,8 +837,9 @@ insert_base_node(void *baton,
pibb->changed_date, /* 12 */
pibb->changed_author, /* 13 */
(pibb->kind == svn_wc__db_kind_symlink) ?
- pibb->target : NULL)); /* 19 */
-
+ pibb->target : NULL, /* 19 */
+ NULL /* 20 */,
+ moved_to_relpath /* 21 */));
if (pibb->kind == svn_wc__db_kind_file)
{
SVN_ERR(svn_sqlite__bind_checksum(stmt, 14, pibb->checksum,
@@ -2022,7 +2029,7 @@ base_get_info(svn_wc__db_status_t *statu
SVN_ERR_ASSERT(!repos_relpath || *repos_relpath);
if (lock)
{
- *lock = lock_from_columns(stmt, 15, 16, 17, 18, result_pool);
+ *lock = lock_from_columns(stmt, 16, 17, 18, 19, result_pool);
}
if (changed_rev)
{
@@ -5325,6 +5332,8 @@ op_revert_recursive_txn(void *baton,
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
apr_int64_t op_depth;
+ apr_int64_t select_op_depth;
+ svn_boolean_t moved_here;
int affected_rows;
apr_pool_t *iterpool;
@@ -5356,6 +5365,7 @@ op_revert_recursive_txn(void *baton,
}
op_depth = svn_sqlite__column_int64(stmt, 0);
+ moved_here = svn_sqlite__column_boolean(stmt, 15);
SVN_ERR(svn_sqlite__reset(stmt));
if (op_depth > 0 && op_depth != relpath_depth(local_relpath))
@@ -5366,13 +5376,13 @@ op_revert_recursive_txn(void *baton,
local_relpath,
scratch_pool));
- if (!op_depth)
- op_depth = 1; /* Don't delete BASE nodes */
+ /* Don't delete BASE nodes */
+ select_op_depth = op_depth ? op_depth : 1;
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_DELETE_NODES_RECURSIVE));
SVN_ERR(svn_sqlite__bindf(stmt, "isi", wcroot->wc_id,
- local_relpath, op_depth));
+ local_relpath, select_op_depth));
SVN_ERR(svn_sqlite__step_done(stmt));
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
@@ -5413,7 +5423,12 @@ op_revert_recursive_txn(void *baton,
}
svn_pool_destroy(iterpool);
- /* Clear any moved-to paths of the BASE nodes. */
+ /* Clear potential moved-to pointing at the target node itself. */
+ if (op_depth > 0 && op_depth == relpath_depth(local_relpath)
+ && moved_here)
+ SVN_ERR(clear_moved_to(local_relpath, wcroot, scratch_pool));
+
+ /* Clear any moved-to paths of potentially 'moved-away' nodes. */
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_CLEAR_MOVED_TO_RELPATH_RECURSIVE));
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
@@ -5471,6 +5486,8 @@ struct revert_list_read_baton {
const char **conflict_new;
const char **conflict_working;
const char **prop_reject;
+ svn_boolean_t *copied_here;
+ svn_wc__db_kind_t *kind;
apr_pool_t *result_pool;
};
@@ -5487,6 +5504,8 @@ revert_list_read(void *baton,
*(b->reverted) = FALSE;
*(b->conflict_new) = *(b->conflict_old) = *(b->conflict_working) = NULL;
*(b->prop_reject) = NULL;
+ *(b->copied_here) = FALSE;
+ *(b->kind) = svn_wc__db_kind_unknown;
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_SELECT_REVERT_LIST));
@@ -5494,9 +5513,10 @@ revert_list_read(void *baton,
SVN_ERR(svn_sqlite__step(&have_row, stmt));
if (have_row)
{
- svn_boolean_t another_row;
+ svn_boolean_t is_actual = (svn_sqlite__column_int64(stmt, 5) != 0);
+ svn_boolean_t another_row = FALSE;
- if (svn_sqlite__column_int64(stmt, 5))
+ if (is_actual)
{
if (!svn_sqlite__column_is_null(stmt, 4))
*(b->reverted) = TRUE;
@@ -5526,11 +5546,19 @@ revert_list_read(void *baton,
b->result_pool);
SVN_ERR(svn_sqlite__step(&another_row, stmt));
- if (another_row)
- *(b->reverted) = TRUE;
}
- else
- *(b->reverted) = TRUE;
+
+ if (!is_actual || another_row)
+ {
+ *(b->reverted) = TRUE;
+ if (!svn_sqlite__column_is_null(stmt, 7))
+ {
+ apr_int64_t op_depth = svn_sqlite__column_int64(stmt, 6);
+ *(b->copied_here) = (op_depth == relpath_depth(local_relpath));
+ }
+ *(b->kind) = svn_sqlite__column_token(stmt, 8, kind_map);
+ }
+
}
SVN_ERR(svn_sqlite__reset(stmt));
@@ -5551,6 +5579,8 @@ svn_wc__db_revert_list_read(svn_boolean_
const char **conflict_new,
const char **conflict_working,
const char **prop_reject,
+ svn_boolean_t *copied_here,
+ svn_wc__db_kind_t *kind,
svn_wc__db_t *db,
const char *local_abspath,
apr_pool_t *result_pool,
@@ -5560,7 +5590,7 @@ svn_wc__db_revert_list_read(svn_boolean_
const char *local_relpath;
struct revert_list_read_baton b = {reverted, conflict_old, conflict_new,
conflict_working, prop_reject,
- result_pool};
+ copied_here, kind, result_pool};
SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
db, local_abspath, scratch_pool, scratch_pool));
@@ -5571,6 +5601,80 @@ svn_wc__db_revert_list_read(svn_boolean_
return SVN_NO_ERROR;
}
+
+struct revert_list_read_copied_children_baton {
+ const apr_array_header_t **children;
+ apr_pool_t *result_pool;
+};
+
+static svn_error_t *
+revert_list_read_copied_children(void *baton,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *scratch_pool)
+{
+ struct revert_list_read_copied_children_baton *b = baton;
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+ apr_array_header_t *children;
+
+ children =
+ apr_array_make(b->result_pool, 0,
+ sizeof(svn_wc__db_revert_list_copied_child_info_t *));
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_SELECT_REVERT_LIST_COPIED_CHILDREN));
+ SVN_ERR(svn_sqlite__bindf(stmt, "si",
+ construct_like_arg(local_relpath, scratch_pool),
+ relpath_depth(local_relpath)));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ while (have_row)
+ {
+ svn_wc__db_revert_list_copied_child_info_t *child_info;
+ const char *child_relpath;
+
+ child_info = apr_palloc(b->result_pool, sizeof(*child_info));
+
+ child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+ child_info->abspath = svn_dirent_join(wcroot->abspath, child_relpath,
+ b->result_pool);
+ child_info->kind = svn_sqlite__column_token(stmt, 1, kind_map);
+ APR_ARRAY_PUSH(
+ children,
+ svn_wc__db_revert_list_copied_child_info_t *) = child_info;
+
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ }
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ *b->children = children;
+
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_wc__db_revert_list_read_copied_children(const apr_array_header_t **children,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_wcroot_t *wcroot;
+ const char *local_relpath;
+ struct revert_list_read_copied_children_baton b = {children, result_pool};
+
+ SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
+ db, local_abspath, scratch_pool, scratch_pool));
+ VERIFY_USABLE_WCROOT(wcroot);
+
+ SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath,
+ revert_list_read_copied_children, &b,
+ scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+
svn_error_t *
svn_wc__db_revert_list_notify(svn_wc_notify_func2_t notify_func,
void *notify_baton,
@@ -6324,13 +6428,6 @@ op_delete_txn(void *baton,
if (add_work)
{
/* Delete the node at LOCAL_RELPATH, and possibly mark it as moved. */
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_INSERT_DELETE_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "isii",
- wcroot->wc_id, local_relpath,
- select_depth, b->delete_depth));
- SVN_ERR(svn_sqlite__step_done(stmt));
-
if (b->moved_to_relpath)
{
/* Record moved-to relpath in BASE. */
@@ -6342,7 +6439,7 @@ op_delete_txn(void *baton,
SVN_ERR(svn_sqlite__step_done(stmt));
}
- /* Delete children, if any. */
+ /* Delete the node and possible descendants. */
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_INSERT_DELETE_FROM_NODE_RECURSIVE));
SVN_ERR(svn_sqlite__bindf(stmt, "isii",
@@ -6687,7 +6784,7 @@ read_info(svn_wc__db_status_t *status,
if (op_depth != 0)
*lock = NULL;
else
- *lock = lock_from_columns(stmt_info, 15, 16, 17, 18, result_pool);
+ *lock = lock_from_columns(stmt_info, 16, 17, 18, 19, result_pool);
}
if (have_work)
@@ -7038,18 +7135,27 @@ read_children_info(void *baton,
if (op_depth == 0)
{
+ const char *moved_to_relpath;
+
child_item->info.have_base = TRUE;
- /* Get the lock info. The query only reports lock info in the row at
- * op_depth 0. */
- if (op_depth == 0)
- child_item->info.lock = lock_from_columns(stmt, 15, 16, 17, 18,
- result_pool);
+ /* Get the lock info, available only at op_depth 0. */
+ child_item->info.lock = lock_from_columns(stmt, 15, 16, 17, 18,
+ result_pool);
+
+ /* Moved-to is only stored at op_depth 0. */
+ moved_to_relpath = svn_sqlite__column_text(stmt, 21, NULL);
+ if (moved_to_relpath)
+ child_item->info.moved_to_abspath =
+ svn_dirent_join(wcroot->abspath, moved_to_relpath, result_pool);
}
else
{
child_item->nr_layers++;
child_item->info.have_more_work = (child_item->nr_layers > 1);
+
+ /* Moved-here can only exist at op_depth > 0. */
+ child_item->info.moved_here = svn_sqlite__column_boolean(stmt, 20);
}
err = svn_sqlite__step(&have_row, stmt);
@@ -9669,6 +9775,7 @@ scan_deletion_txn(void *baton,
svn_wc__db_status_t child_presence;
svn_boolean_t child_has_base = FALSE;
apr_int64_t local_op_depth, op_depth;
+ svn_boolean_t found_moved_to = FALSE;
/* Initialize all the OUT parameters. */
if (sd_baton->base_del_relpath != NULL)
@@ -9795,9 +9902,12 @@ scan_deletion_txn(void *baton,
gimmick, not a real node that may have been deleted. */
}
- if ((sd_baton->moved_to_relpath != NULL
- || sd_baton->moved_to_op_root_relpath != NULL
- || sd_baton->base_del_relpath != NULL)
+ /* Evaluate moved-to information. Once moved-to info has been found, it
+ * must not be overwritten with ancestors' moved-to info. */
+ if ((! found_moved_to)
+ && (sd_baton->moved_to_relpath != NULL
+ || sd_baton->moved_to_op_root_relpath != NULL
+ || sd_baton->base_del_relpath != NULL)
&& !svn_sqlite__column_is_null(stmt, 2 /* moved_to */))
{
const char *moved_to_op_root_relpath;
@@ -9888,6 +9998,13 @@ scan_deletion_txn(void *baton,
*sd_baton->moved_to_op_root_relpath = moved_to_op_root_relpath ?
apr_pstrdup(sd_baton->result_pool, moved_to_op_root_relpath)
: NULL;
+
+ /* If all other out parameters are irrelevant, stop scanning.
+ * Happens to be only WORK_DEL_RELPATH. */
+ if (sd_baton->work_del_relpath == NULL)
+ break;
+
+ found_moved_to = TRUE;
}
op_depth = svn_sqlite__column_int64(stmt, 3);
Modified: subversion/branches/fs-py/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_wc/wc_db.h?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/fs-py/subversion/libsvn_wc/wc_db.h Mon Aug 22 15:21:13 2011
@@ -1506,6 +1506,10 @@ svn_wc__db_op_revert(svn_wc__db_t *db,
* path was reverted. Set *CONFLICT_OLD, *CONFLICT_NEW,
* *CONFLICT_WORKING and *PROP_REJECT to the names of the conflict
* files, or NULL if the names are not stored.
+ *
+ * Set *COPIED_HERE if the reverted node was copied here and is the
+ * operation root of the copy.
+ * Set *KIND to the node kind of the reverted node.
*
* Removes the row for LOCAL_ABSPATH from the revert list.
*/
@@ -1515,11 +1519,32 @@ svn_wc__db_revert_list_read(svn_boolean_
const char **conflict_new,
const char **conflict_working,
const char **prop_reject,
+ svn_boolean_t *copied_here,
+ svn_wc__db_kind_t *kind,
svn_wc__db_t *db,
const char *local_abspath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
+/* The type of elements in the array returned by
+ * svn_wc__db_revert_list_read_copied_children(). */
+typedef struct svn_wc__db_revert_list_copied_child_info_t {
+ const char *abspath;
+ svn_wc__db_kind_t kind;
+} svn_wc__db_revert_list_copied_child_info_t ;
+
+/* Return in *CHILDREN a list of reverted copied nodes at or within
+ * LOCAL_ABSPATH (which is a reverted file or a reverted directory).
+ * Allocate *COPIED_CHILDREN and its elements in RESULT_POOL.
+ * The elements are of type svn_wc__db_revert_list_copied_child_info_t. */
+svn_error_t *
+svn_wc__db_revert_list_read_copied_children(const apr_array_header_t **children,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+
/* Make revert notifications for all paths in the revert list that are
* equal to LOCAL_ABSPATH or below LOCAL_ABSPATH.
*
@@ -1842,6 +1867,9 @@ struct svn_wc__db_info_t {
svn_boolean_t locked; /* WC directory lock */
svn_wc__db_lock_t *lock; /* Repository file lock */
+
+ const char *moved_to_abspath; /* Only on op-roots. See svn_wc_status3_t. */
+ svn_boolean_t moved_here; /* On both op-roots and children. */
};
/* Return in *NODES a hash mapping name->struct svn_wc__db_info_t for
Modified: subversion/branches/fs-py/subversion/libsvn_wc/wc_db_wcroot.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_wc/wc_db_wcroot.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_wc/wc_db_wcroot.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_wc/wc_db_wcroot.c Mon Aug 22 15:21:13 2011
@@ -100,11 +100,13 @@ get_old_version(int *version,
of LOCAL_ABSPATH, using DB and SCRATCH_POOL as needed.
This function may do strange things, but at long as it comes up with the
- Right Answer, we should be happy. */
+ Right Answer, we should be happy.
+
+ Sets *KIND to svn_node_dir for symlinks. */
static svn_error_t *
-get_path_kind(svn_wc__db_t *db,
+get_path_kind(svn_node_kind_t *kind,
+ svn_wc__db_t *db,
const char *local_abspath,
- svn_node_kind_t *kind,
apr_pool_t *scratch_pool)
{
svn_boolean_t special;
@@ -132,7 +134,11 @@ get_path_kind(svn_wc__db_t *db,
}
SVN_ERR(svn_io_check_special_path(local_abspath, &db->parse_cache.kind,
- &special /* unused */, scratch_pool));
+ &special, scratch_pool));
+
+ /* The wcroot could be a symlink to a directory. (Issue #2557, #3987) */
+ if (special)
+ db->parse_cache.kind = svn_node_dir;
*kind = db->parse_cache.kind;
return SVN_NO_ERROR;
@@ -395,7 +401,7 @@ svn_wc__db_wcroot_parse_local_abspath(sv
### rid of this stat() call. it is going to happen for EVERY call
### into wc_db which references a file. calls for directories could
### get an early-exit in the hash lookup just above. */
- SVN_ERR(get_path_kind(db, local_abspath, &kind, scratch_pool));
+ SVN_ERR(get_path_kind(&kind, db, local_abspath, scratch_pool));
if (kind != svn_node_dir)
{
/* If the node specified by the path is NOT present, then it cannot
Modified: subversion/branches/fs-py/subversion/libsvn_wc/workqueue.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_wc/workqueue.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_wc/workqueue.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_wc/workqueue.c Mon Aug 22 15:21:13 2011
@@ -733,10 +733,7 @@ run_file_install(svn_wc__db_t *db,
cancel_func, cancel_baton,
scratch_pool));
- /* ### post-commit feature: avoid overwrite if same as working file. */
-
/* All done. Move the file into place. */
- /* ### fix this. we should delay the rename. */
{
svn_error_t *err;
@@ -750,7 +747,7 @@ run_file_install(svn_wc__db_t *db,
{
svn_error_t *err2;
- err2 = svn_io_make_dir_recursively(svn_dirent_dirname(dst_abspath,
+ err2 = svn_io_make_dir_recursively(svn_dirent_dirname(local_abspath,
scratch_pool),
scratch_pool);
Modified: subversion/branches/fs-py/subversion/mod_dav_svn/liveprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/mod_dav_svn/liveprops.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/mod_dav_svn/liveprops.c (original)
+++ subversion/branches/fs-py/subversion/mod_dav_svn/liveprops.c Mon Aug 22 15:21:13 2011
@@ -483,6 +483,8 @@ insert_prop_internal(const dav_resource
there's no point even checking. No matter what the
error is, we can't claim to have a mime type for
this resource. */
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, serr->apr_err,
+ resource->info->r, "%s", serr->message);
svn_error_clear(serr);
return DAV_PROP_INSERT_NOTDEF;
}
Modified: subversion/branches/fs-py/subversion/mod_dav_svn/mod_dav_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/mod_dav_svn/mod_dav_svn.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/mod_dav_svn/mod_dav_svn.c (original)
+++ subversion/branches/fs-py/subversion/mod_dav_svn/mod_dav_svn.c Mon Aug 22 15:21:13 2011
@@ -1000,7 +1000,7 @@ static const command_rec cmds[] =
/* per server */
AP_INIT_TAKE1("SVNInMemoryCacheSize", SVNInMemoryCacheSize_cmd, NULL,
RSRC_CONF,
- "specifies the maximum size im kB per process of Subversion's "
+ "specifies the maximum size in kB per process of Subversion's "
"in-memory object cache (default value is 16384; 0 deactivates "
"the cache)."),
/* per server */
Modified: subversion/branches/fs-py/subversion/svn/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/svn/main.c?rev=1160299&r1=1160298&r2=1160299&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/svn/main.c (original)
+++ subversion/branches/fs-py/subversion/svn/main.c Mon Aug 22 15:21:13 2011
@@ -1006,6 +1006,13 @@ const svn_opt_subcommand_desc2_t svn_cl_
" for deletion. If the patch creates a new file, that file is scheduled\n"
" for addition. Use 'svn revert' to undo deletions and additions you\n"
" do not agree with.\n"
+ "\n"
+ " Hint: If the patch file was created with Subversion, it will contain\n"
+ " the number of a revision N the patch will cleanly apply to\n"
+ " (look for lines like \"--- foo/bar.txt (revision N)\").\n"
+ " To avoid rejects, first update to the revision N using \n"
+ " 'svn update -r N', apply the patch, and then update back to the\n"
+ " HEAD revision. This way, conflicts can be resolved interactively.\n"
),
{'q', opt_dry_run, opt_strip, opt_reverse_diff,
opt_ignore_whitespace} },
@@ -1184,7 +1191,7 @@ const svn_opt_subcommand_desc2_t svn_cl_
"usage: revert PATH...\n"
"\n"
" Note: this subcommand does not require network access, and resolves\n"
- " any conflicted states. However, it does not restore removed directories.\n"),
+ " any conflicted states.\n"),
{opt_targets, 'R', opt_depth, 'q', opt_changelist} },
{ "status", svn_cl__status, {"stat", "st"}, N_
@@ -1936,12 +1943,6 @@ main(int argc, const char *argv[])
break;
case opt_changelist:
opt_state.changelist = apr_pstrdup(pool, opt_arg);
- if (opt_state.changelist[0] == '\0')
- {
- err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("Changelist names must not be empty"));
- return svn_cmdline_handle_exit_error(err, pool, "svn: ");
- }
apr_hash_set(changelists, opt_state.changelist,
APR_HASH_KEY_STRING, (void *)1);
break;