You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2011/11/07 12:09:52 UTC
svn commit: r1198703 [2/2] - in /subversion/branches/showing-merge-info: ./
build/ build/ac-macros/ notes/ subversion/include/
subversion/include/private/ subversion/libsvn_client/
subversion/libsvn_delta/ subversion/libsvn_subr/ subversion/libsvn_wc/ ...
Modified: subversion/branches/showing-merge-info/subversion/libsvn_client/ra.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_client/ra.c?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_client/ra.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_client/ra.c Mon Nov 7 11:09:51 2011
@@ -429,7 +429,6 @@ resolve_rev_and_url(svn_revnum_t *rev_p,
{
svn_opt_revision_t peg_rev = *peg_revision;
svn_opt_revision_t start_rev = *revision;
- svn_opt_revision_t *good_rev;
const char *url;
svn_revnum_t rev;
@@ -440,15 +439,10 @@ resolve_rev_and_url(svn_revnum_t *rev_p,
/* Run the history function to get the object's (possibly
different) url in REVISION. */
- SVN_ERR(svn_client__repos_locations(&url, &good_rev, NULL, NULL,
+ SVN_ERR(svn_client__repos_locations(&url, &rev, NULL, NULL,
ra_session, path_or_url, &peg_rev,
&start_rev, NULL, ctx, pool));
- /* Resolve good_rev into a real revnum. */
- if (good_rev->kind == svn_opt_revision_unspecified)
- good_rev->kind = svn_opt_revision_head;
- SVN_ERR(svn_client__get_revision_number(&rev, NULL, ctx->wc_ctx, url,
- ra_session, good_rev, pool));
if (rev_p)
*rev_p = rev;
if (url_p)
@@ -601,9 +595,9 @@ svn_client__repos_location_segments(apr_
svn_error_t *
svn_client__repos_locations(const char **start_url,
- svn_opt_revision_t **start_revision,
+ svn_revnum_t *start_revision,
const char **end_url,
- svn_opt_revision_t **end_revision,
+ svn_revnum_t *end_revision,
svn_ra_session_t *ra_session,
const char *path,
const svn_opt_revision_t *revision,
@@ -723,14 +717,13 @@ svn_client__repos_locations(const char *
ra_session, end, pool));
/* Set the output revision variables. */
- *start_revision = apr_pcalloc(pool, sizeof(**start_revision));
- (*start_revision)->kind = svn_opt_revision_number;
- (*start_revision)->value.number = start_revnum;
- if (end->kind != svn_opt_revision_unspecified)
+ if (start_revision)
+ {
+ *start_revision = start_revnum;
+ }
+ if (end_revision && end->kind != svn_opt_revision_unspecified)
{
- *end_revision = apr_pcalloc(pool, sizeof(**end_revision));
- (*end_revision)->kind = svn_opt_revision_number;
- (*end_revision)->value.number = end_revnum;
+ *end_revision = end_revnum;
}
if (start_revnum == peg_revnum && end_revnum == peg_revnum)
Modified: subversion/branches/showing-merge-info/subversion/libsvn_delta/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_delta/compat.c?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_delta/compat.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_delta/compat.c Mon Nov 7 11:09:51 2011
@@ -27,6 +27,7 @@
#include "svn_sorts.h"
#include "svn_dirent_uri.h"
#include "svn_path.h"
+#include "svn_hash.h"
#include "svn_props.h"
#include "svn_pools.h"
@@ -105,6 +106,9 @@ struct ev2_edit_baton
svn_revnum_t target_revision;
apr_pool_t *edit_pool;
+ svn_boolean_t *found_abs_paths; /* Did we strip an incoming '/' from the
+ paths? */
+
void *root_baton;
start_edit_func_t start_edit;
@@ -126,16 +130,20 @@ struct ev2_file_baton
const char *path;
};
-enum action
+enum action_code_t
{
+ ACTION_MOVE,
+ ACTION_MKDIR,
+ ACTION_COPY,
+ ACTION_PROPSET,
+ ACTION_PUT,
ACTION_ADD,
- ACTION_DELETE,
- ACTION_SET_PROP
+ ACTION_DELETE
};
struct path_action
{
- enum action action;
+ enum action_code_t action;
void *args;
};
@@ -148,7 +156,7 @@ struct prop_args
static svn_error_t *
add_action(struct ev2_edit_baton *eb,
const char *path,
- enum action action,
+ enum action_code_t action,
void *args)
{
struct path_action *p_action;
@@ -180,10 +188,17 @@ process_actions(void *edit_baton,
{
struct ev2_edit_baton *eb = edit_baton;
apr_hash_t *props = NULL;
+ svn_boolean_t need_add = FALSE;
+ apr_array_header_t *children;
+ svn_stream_t *contents;
+ svn_kind_t kind;
int i;
if (*path == '/')
- path++;
+ {
+ path++;
+ *eb->found_abs_paths = TRUE;
+ }
/* Go through all of our actions, populating various datastructures
* dependent on them. */
@@ -194,7 +209,7 @@ process_actions(void *edit_baton,
switch (action->action)
{
- case ACTION_SET_PROP:
+ case ACTION_PROPSET:
{
const struct prop_args *p_args = action->args;
@@ -227,20 +242,18 @@ process_actions(void *edit_baton,
case ACTION_ADD:
{
- svn_kind_t *kind = action->args;
+ kind = *((svn_kind_t *) action->args);
+ need_add = TRUE;
- if (*kind == svn_kind_dir)
+ if (kind == svn_kind_dir)
{
- apr_array_header_t *children = apr_array_make(
- scratch_pool, 1, sizeof(const char *));
- SVN_ERR(svn_editor_add_directory(eb->editor, path, children,
- NULL, SVN_INVALID_REVNUM));
+ children = apr_array_make(scratch_pool, 1,
+ sizeof(const char *));
}
else
{
- svn_stream_t *contents = svn_stream_empty(scratch_pool);
- SVN_ERR(svn_editor_add_file(eb->editor, path, NULL, contents,
- NULL, SVN_INVALID_REVNUM));
+ /* ### Someday, we'll need the real contents here. */
+ contents = svn_stream_empty(scratch_pool);
}
break;
}
@@ -253,12 +266,28 @@ process_actions(void *edit_baton,
/* We've now got a wholistic view of what has happened to this node,
* so we can call our own editor APIs on it. */
- if (props)
+ if (need_add)
+ {
+ if (kind == svn_kind_dir)
+ {
+ SVN_ERR(svn_editor_add_directory(eb->editor, path, children,
+ props, SVN_INVALID_REVNUM));
+ }
+ else
+ {
+ SVN_ERR(svn_editor_add_file(eb->editor, path, NULL, contents,
+ props, SVN_INVALID_REVNUM));
+ }
+ }
+ else
{
- /* We fetched and modified the props in some way. Apply 'em now that
- we have the new set. */
- SVN_ERR(svn_editor_set_props(eb->editor, path, eb->target_revision,
- props, TRUE));
+ if (props)
+ {
+ /* We fetched and modified the props in some way. Apply 'em now that
+ we have the new set. */
+ SVN_ERR(svn_editor_set_props(eb->editor, path, eb->target_revision,
+ props, TRUE));
+ }
}
return SVN_NO_ERROR;
@@ -394,7 +423,7 @@ ev2_change_dir_prop(void *dir_baton,
p_args->name = apr_pstrdup(db->eb->edit_pool, name);
p_args->value = value ? svn_string_dup(value, db->eb->edit_pool) : NULL;
- SVN_ERR(add_action(db->eb, db->path, ACTION_SET_PROP, p_args));
+ SVN_ERR(add_action(db->eb, db->path, ACTION_PROPSET, p_args));
return SVN_NO_ERROR;
}
@@ -482,7 +511,7 @@ ev2_change_file_prop(void *file_baton,
p_args->name = apr_pstrdup(fb->eb->edit_pool, name);
p_args->value = value ? svn_string_dup(value, fb->eb->edit_pool) : NULL;
- SVN_ERR(add_action(fb->eb, fb->path, ACTION_SET_PROP, p_args));
+ SVN_ERR(add_action(fb->eb, fb->path, ACTION_PROPSET, p_args));
return SVN_NO_ERROR;
}
@@ -548,6 +577,7 @@ static svn_error_t *
delta_from_editor(const svn_delta_editor_t **deditor,
void **dedit_baton,
svn_editor_t *editor,
+ svn_boolean_t *found_abs_paths,
svn_delta_fetch_props_func_t fetch_props_func,
void *fetch_props_baton,
start_edit_func_t start_edit,
@@ -579,6 +609,8 @@ delta_from_editor(const svn_delta_editor
eb->paths = apr_hash_make(pool);
eb->target_revision = SVN_INVALID_REVNUM;
eb->edit_pool = pool;
+ eb->found_abs_paths = found_abs_paths;
+
eb->fetch_props_func = fetch_props_func;
eb->fetch_props_baton = fetch_props_baton;
@@ -595,15 +627,6 @@ delta_from_editor(const svn_delta_editor
-typedef enum action_code_t {
- ACTION_MV,
- ACTION_MKDIR,
- ACTION_CP,
- ACTION_PROPSET,
- ACTION_PUT,
- ACTION_RM
-} action_code_t;
-
struct operation {
enum {
OP_OPEN,
@@ -619,8 +642,9 @@ struct operation {
const char *copyfrom_url; /* to copy, valid for add and replace */
const char *src_file; /* for put, the source file for contents */
apr_hash_t *children; /* const char *path -> struct operation * */
- apr_hash_t *props; /* const char *prop_name ->
+ apr_hash_t *prop_mods; /* const char *prop_name ->
const svn_string_t *prop_value */
+ apr_array_header_t *prop_dels; /* const char *prop_name deletions */
void *baton; /* as returned by the commit editor */
};
@@ -632,13 +656,18 @@ struct editor_baton
svn_delta_fetch_kind_func_t fetch_kind_func;
void *fetch_kind_baton;
+ svn_delta_fetch_props_func_t fetch_props_func;
+ void *fetch_props_baton;
+
struct operation root;
svn_boolean_t root_opened;
+ svn_boolean_t *make_abs_paths;
apr_hash_t *paths;
apr_pool_t *edit_pool;
};
+
/* Find the operation associated with PATH, which is a single-path
component representing a child of the path represented by
OPERATION. If no such child operation exists, create a new one of
@@ -657,7 +686,8 @@ get_operation(const char *path,
child->operation = OP_OPEN;
child->copyfrom_revision = SVN_INVALID_REVNUM;
child->kind = svn_kind_dir;
- child->props = NULL;
+ child->prop_mods = apr_hash_make(result_pool);
+ child->prop_dels = apr_array_make(result_pool, 1, sizeof(const char *));
apr_hash_set(operation->children, apr_pstrdup(result_pool, path),
APR_HASH_KEY_STRING, child);
}
@@ -671,9 +701,9 @@ get_operation(const char *path,
ACTION URL REV SRC-FILE PROPNAME
------------ ----- ------- -------- --------
ACTION_MKDIR NULL invalid NULL NULL
- ACTION_CP valid valid NULL NULL
+ ACTION_COPY valid valid NULL NULL
ACTION_PUT NULL invalid valid NULL
- ACTION_RM NULL invalid NULL NULL
+ ACTION_DELETE NULL invalid NULL NULL
ACTION_PROPSET valid invalid NULL valid
Node type information is obtained for any copy source (to determine
@@ -682,7 +712,7 @@ get_operation(const char *path,
return an error on non-existent nodes). */
static svn_error_t *
build(struct editor_baton *eb,
- action_code_t action,
+ enum action_code_t action,
const char *relpath,
svn_kind_t kind,
const char *url,
@@ -715,8 +745,29 @@ build(struct editor_baton *eb,
/* Handle property changes. */
if (props)
{
+ apr_hash_t *current_props;
+ apr_array_header_t *propdiffs;
+
SVN_ERR(eb->fetch_kind_func(&operation->kind, eb->fetch_kind_baton,
relpath, scratch_pool));
+ SVN_ERR(eb->fetch_props_func(¤t_props, eb->fetch_props_baton,
+ relpath, scratch_pool, scratch_pool));
+
+ /* Use the edit pool, since most of the results will need to be
+ persisted. */
+ SVN_ERR(svn_prop_diffs(&propdiffs, props, current_props, eb->edit_pool));
+
+ for (i = 0; i < propdiffs->nelts; i++)
+ {
+ /* Note: the array returned by svn_prop_diffs() is an array of
+ actual structures, not pointers to them. */
+ svn_prop_t *prop = &APR_ARRAY_IDX(propdiffs, i, svn_prop_t);
+ if (!prop->value)
+ APR_ARRAY_PUSH(operation->prop_dels, const char *) = prop->name;
+ else
+ apr_hash_set(operation->prop_mods, prop->name, APR_HASH_KEY_STRING,
+ prop->value);
+ }
/* If we're not adding this thing ourselves, check for existence. */
if (! ((operation->operation == OP_ADD) ||
@@ -726,17 +777,16 @@ build(struct editor_baton *eb,
&& (operation->operation == OP_OPEN))
operation->operation = OP_PROPSET;
}
- operation->props = svn_prop_hash_dup(props, eb->edit_pool);
if (!operation->copyfrom_revision)
operation->copyfrom_revision = rev;
return SVN_NO_ERROR;
}
- if (action == ACTION_RM)
+ if (action == ACTION_DELETE)
operation->operation = OP_DELETE;
/* Handle copy operations (which can be adds or replacements). */
- else if (action == ACTION_CP)
+ else if (action == ACTION_COPY)
{
operation->operation =
operation->operation == OP_DELETE ? OP_REPLACE : OP_ADD;
@@ -954,6 +1004,10 @@ delete_cb(void *baton,
SVN_ERR(ensure_root_opened(eb));
+ SVN_ERR(build(eb, ACTION_DELETE, relpath, svn_kind_unknown,
+ NULL, SVN_INVALID_REVNUM, NULL, NULL, SVN_INVALID_REVNUM,
+ scratch_pool));
+
return SVN_NO_ERROR;
}
@@ -990,8 +1044,56 @@ move_cb(void *baton,
}
static svn_error_t *
+change_props(const svn_delta_editor_t *editor,
+ void *baton,
+ struct operation *child,
+ apr_pool_t *scratch_pool)
+{
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
+ if (child->prop_dels)
+ {
+ int i;
+ for (i = 0; i < child->prop_dels->nelts; i++)
+ {
+ const char *prop_name;
+
+ svn_pool_clear(iterpool);
+ prop_name = APR_ARRAY_IDX(child->prop_dels, i, const char *);
+ if (child->kind == svn_kind_dir)
+ SVN_ERR(editor->change_dir_prop(baton, prop_name,
+ NULL, iterpool));
+ else
+ SVN_ERR(editor->change_file_prop(baton, prop_name,
+ NULL, iterpool));
+ }
+ }
+
+ if (apr_hash_count(child->prop_mods))
+ {
+ apr_hash_index_t *hi;
+ for (hi = apr_hash_first(scratch_pool, child->prop_mods);
+ hi; hi = apr_hash_next(hi))
+ {
+ const char *name = svn__apr_hash_index_key(hi);
+ svn_string_t *val = svn__apr_hash_index_val(hi);
+
+ svn_pool_clear(iterpool);
+ if (child->kind == svn_kind_dir)
+ SVN_ERR(editor->change_dir_prop(baton, name, val, iterpool));
+ else
+ SVN_ERR(editor->change_file_prop(baton, name, val, iterpool));
+ }
+ }
+
+ svn_pool_destroy(iterpool);
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
drive(const struct operation *operation,
const svn_delta_editor_t *editor,
+ svn_boolean_t *make_abs_paths,
apr_pool_t *scratch_pool)
{
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
@@ -1008,6 +1110,28 @@ drive(const struct operation *operation,
child = svn__apr_hash_index_val(hi);
path = svn__apr_hash_index_key(hi);
+ if (path[0] != '/' && *make_abs_paths)
+ path = apr_pstrcat(iterpool, "/", path, NULL);
+
+ /* Deletes are simple -- just delete the thing. */
+ if (child->operation == OP_DELETE)
+ {
+ SVN_ERR(editor->delete_entry(path, SVN_INVALID_REVNUM,
+ operation->baton, iterpool));
+ }
+
+ if (child->operation == OP_OPEN || child->operation == OP_PROPSET)
+ {
+ if (child->kind == svn_kind_dir)
+ SVN_ERR(editor->open_directory(path, operation->baton,
+ SVN_INVALID_REVNUM,
+ iterpool, &child->baton));
+ else
+ SVN_ERR(editor->open_file(path, operation->baton,
+ SVN_INVALID_REVNUM,
+ iterpool, &file_baton));
+ }
+
if (child->operation == OP_ADD)
{
if (child->kind == svn_kind_dir)
@@ -1038,9 +1162,26 @@ drive(const struct operation *operation,
SVN_ERR(svn_stream_close(contents));
}
- /*SVN_DBG(("child: '%s'; operation: %d\n", path, child->operation));*/
- if (child->kind == svn_kind_dir)
- SVN_ERR(drive(child, editor, iterpool));
+ /* Only worry about properties and closing the file baton if we've
+ previously opened it. */
+ if (file_baton)
+ {
+ if (child->kind == svn_kind_file)
+ SVN_ERR(change_props(editor, file_baton, child, iterpool));
+ SVN_ERR(editor->close_file(file_baton, NULL, iterpool));
+ }
+
+ /* We *always* open the child directory, so drive the child, change any
+ props, and then close the directory. */
+ if (child->kind == svn_kind_dir
+ && (child->operation == OP_OPEN
+ || child->operation == OP_PROPSET
+ || child->operation == OP_ADD))
+ {
+ SVN_ERR(drive(child, editor, make_abs_paths, iterpool));
+ SVN_ERR(change_props(editor, child->baton, child, iterpool));
+ SVN_ERR(editor->close_directory(child->baton, iterpool));
+ }
}
return SVN_NO_ERROR;
@@ -1055,7 +1196,7 @@ complete_cb(void *baton,
svn_error_t *err;
/* Drive the tree we've created. */
- err = drive(&eb->root, eb->deditor, scratch_pool);
+ err = drive(&eb->root, eb->deditor, eb->make_abs_paths, scratch_pool);
if (!err)
err = eb->deditor->close_edit(eb->dedit_baton, scratch_pool);
if (err)
@@ -1077,7 +1218,7 @@ abort_cb(void *baton,
point. */
/* Drive the tree we've created. */
- err = drive(&eb->root, eb->deditor, scratch_pool);
+ err = drive(&eb->root, eb->deditor, eb->make_abs_paths, scratch_pool);
err2 = eb->deditor->abort_edit(eb->dedit_baton, scratch_pool);
@@ -1096,10 +1237,13 @@ static svn_error_t *
editor_from_delta(svn_editor_t **editor_p,
const svn_delta_editor_t *deditor,
void *dedit_baton,
+ svn_boolean_t *send_abs_paths,
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_delta_fetch_kind_func_t fetch_kind_func,
void *fetch_kind_baton,
+ svn_delta_fetch_props_func_t fetch_props_func,
+ void *fetch_props_baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -1127,14 +1271,18 @@ editor_from_delta(svn_editor_t **editor_
eb->fetch_kind_func = fetch_kind_func;
eb->fetch_kind_baton = fetch_kind_baton;
+ eb->fetch_props_func = fetch_props_func;
+ eb->fetch_props_baton = fetch_props_baton;
eb->root.children = apr_hash_make(result_pool);
eb->root.kind = svn_kind_dir;
eb->root.operation = OP_OPEN;
- eb->root.props = NULL;
+ eb->root.prop_mods = apr_hash_make(result_pool);
+ eb->root.prop_dels = apr_array_make(result_pool, 1, sizeof(const char *));
eb->root.copyfrom_revision = SVN_INVALID_REVNUM;
eb->root_opened = FALSE;
+ eb->make_abs_paths = send_abs_paths;
SVN_ERR(svn_editor_create(&editor, eb, cancel_func, cancel_baton,
result_pool, scratch_pool));
@@ -1177,14 +1325,24 @@ svn_editor__insert_shims(const svn_delta
svn_editor_t *editor;
struct start_edit_baton *seb = apr_palloc(result_pool, sizeof(*seb));
+ /* The reason this is a pointer is that we don't know the appropriate
+ value until we start receiving paths. So process_actions() sets the
+ flag, which drive() later consumes. */
+ svn_boolean_t *found_abs_paths = apr_palloc(result_pool,
+ sizeof(*found_abs_paths));
+
seb->deditor = deditor_in;
seb->dedit_baton = dedit_baton_in;
SVN_ERR(editor_from_delta(&editor, deditor_in, dedit_baton_in,
- NULL, NULL, shim_callbacks->fetch_kind_func,
+ found_abs_paths, NULL, NULL,
+ shim_callbacks->fetch_kind_func,
shim_callbacks->fetch_kind_baton,
+ shim_callbacks->fetch_props_func,
+ shim_callbacks->fetch_props_baton,
result_pool, scratch_pool));
SVN_ERR(delta_from_editor(deditor_out, dedit_baton_out, editor,
+ found_abs_paths,
shim_callbacks->fetch_props_func,
shim_callbacks->fetch_props_baton,
start_edit_func, seb,
Modified: subversion/branches/showing-merge-info/subversion/libsvn_subr/dirent_uri.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_subr/dirent_uri.c?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_subr/dirent_uri.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_subr/dirent_uri.c Mon Nov 7 11:09:51 2011
@@ -884,10 +884,10 @@ svn_dirent_local_style(const char *diren
}
const char *
-svn_relpath__internal_style(const char *dirent,
- apr_pool_t *pool)
+svn_relpath__internal_style(const char *relpath,
+ apr_pool_t *pool)
{
- return svn_relpath_canonicalize(internal_style(dirent, pool), pool);
+ return svn_relpath_canonicalize(internal_style(relpath, pool), pool);
}
@@ -1636,7 +1636,7 @@ svn_dirent_canonicalize(const char *dire
}
svn_boolean_t
-svn_dirent_is_canonical(const char *dirent, apr_pool_t *pool)
+svn_dirent_is_canonical(const char *dirent, apr_pool_t *scratch_pool)
{
const char *ptr = dirent;
if (*ptr == '/')
@@ -1649,7 +1649,8 @@ svn_dirent_is_canonical(const char *dire
/* TODO: Scan hostname and sharename and fall back to part code */
/* ### Fall back to old implementation */
- return (strcmp(dirent, svn_dirent_canonicalize(dirent, pool)) == 0);
+ return (strcmp(dirent, svn_dirent_canonicalize(dirent, scratch_pool))
+ == 0);
}
#endif /* SVN_USE_DOS_PATHS */
}
@@ -1723,7 +1724,7 @@ svn_relpath_is_canonical(const char *rel
}
svn_boolean_t
-svn_uri_is_canonical(const char *uri, apr_pool_t *pool)
+svn_uri_is_canonical(const char *uri, apr_pool_t *scratch_pool)
{
const char *ptr = uri, *seg = uri;
const char *schema_data = NULL;
Modified: subversion/branches/showing-merge-info/subversion/libsvn_wc/adm_ops.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_wc/adm_ops.c?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_wc/adm_ops.c Mon Nov 7 11:09:51 2011
@@ -595,6 +595,168 @@ erase_unversioned_from_wc(const char *pa
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_wc__delete_many(svn_wc_context_t *wc_ctx,
+ const apr_array_header_t *targets,
+ svn_boolean_t keep_local,
+ svn_boolean_t delete_unversioned_target,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ svn_wc_notify_func2_t notify_func,
+ void *notify_baton,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_t *db = wc_ctx->db;
+ svn_error_t *err;
+ svn_wc__db_status_t status;
+ svn_kind_t kind;
+ svn_boolean_t conflicted;
+ const apr_array_header_t *conflicts;
+ apr_array_header_t *versioned_targets;
+ const char *local_abspath;
+ int i;
+ apr_pool_t *iterpool;
+
+ iterpool = svn_pool_create(scratch_pool);
+ versioned_targets = apr_array_make(scratch_pool, targets->nelts,
+ sizeof(const char *));
+ for (i = 0; i < targets->nelts; i++)
+ {
+ svn_pool_clear(iterpool);
+
+ local_abspath = APR_ARRAY_IDX(targets, i, const char *);
+ err = svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, &conflicted,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ db, local_abspath, iterpool, iterpool);
+
+ if (err)
+ {
+ if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+ {
+ svn_error_clear(err);
+ if (delete_unversioned_target && !keep_local)
+ SVN_ERR(erase_unversioned_from_wc(local_abspath, FALSE,
+ cancel_func, cancel_baton,
+ iterpool));
+ continue;
+ }
+ else
+ return svn_error_trace(err);
+ }
+
+ APR_ARRAY_PUSH(versioned_targets, const char *) = local_abspath;
+
+ switch (status)
+ {
+ /* svn_wc__db_status_server_excluded handled by
+ * svn_wc__db_op_delete_many */
+ case svn_wc__db_status_excluded:
+ case svn_wc__db_status_not_present:
+ return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+ _("'%s' cannot be deleted"),
+ svn_dirent_local_style(local_abspath,
+ iterpool));
+
+ /* Explicitly ignore other statii */
+ default:
+ break;
+ }
+
+ if (status == svn_wc__db_status_normal
+ && kind == svn_kind_dir)
+ {
+ svn_boolean_t is_wcroot;
+ SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, local_abspath,
+ iterpool));
+
+ if (is_wcroot)
+ return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
+ _("'%s' is the root of a working copy and "
+ "cannot be deleted"),
+ svn_dirent_local_style(local_abspath,
+ iterpool));
+ }
+
+ /* Verify if we have a write lock on the parent of this node as we might
+ be changing the childlist of that directory. */
+ SVN_ERR(svn_wc__write_check(db, svn_dirent_dirname(local_abspath,
+ iterpool),
+ iterpool));
+
+ /* Read conflicts, to allow deleting the markers after updating the DB */
+ if (!keep_local && conflicted)
+ SVN_ERR(svn_wc__db_read_conflicts(&conflicts, db, local_abspath,
+ scratch_pool, iterpool));
+
+ }
+
+ if (versioned_targets->nelts == 0)
+ return SVN_NO_ERROR;
+
+ SVN_ERR(svn_wc__db_op_delete_many(db, versioned_targets,
+ cancel_func, cancel_baton,
+ notify_func, notify_baton, scratch_pool));
+
+ if (!keep_local && conflicted && conflicts != NULL)
+ {
+ svn_pool_clear(iterpool);
+
+ /* Do we have conflict markers that should be removed? */
+ for (i = 0; i < conflicts->nelts; i++)
+ {
+ const svn_wc_conflict_description2_t *desc;
+
+ desc = APR_ARRAY_IDX(conflicts, i,
+ const svn_wc_conflict_description2_t*);
+
+ if (desc->kind == svn_wc_conflict_kind_text)
+ {
+ if (desc->base_abspath != NULL)
+ {
+ SVN_ERR(svn_io_remove_file2(desc->base_abspath, TRUE,
+ iterpool));
+ }
+ if (desc->their_abspath != NULL)
+ {
+ SVN_ERR(svn_io_remove_file2(desc->their_abspath, TRUE,
+ iterpool));
+ }
+ if (desc->my_abspath != NULL)
+ {
+ SVN_ERR(svn_io_remove_file2(desc->my_abspath, TRUE,
+ iterpool));
+ }
+ }
+ else if (desc->kind == svn_wc_conflict_kind_property
+ && desc->their_abspath != NULL)
+ {
+ SVN_ERR(svn_io_remove_file2(desc->their_abspath, TRUE,
+ iterpool));
+ }
+ }
+ }
+
+ /* By the time we get here, the db knows that all targets are now
+ * unversioned. */
+ if (!keep_local)
+ {
+ for (i = 0; i < versioned_targets->nelts; i++)
+ {
+ svn_pool_clear(iterpool);
+
+ local_abspath = APR_ARRAY_IDX(versioned_targets, i, const char *);
+ SVN_ERR(erase_unversioned_from_wc(local_abspath, TRUE,
+ cancel_func, cancel_baton,
+ iterpool));
+ }
+ }
+
+ svn_pool_destroy(iterpool);
+
+ return SVN_NO_ERROR;
+}
svn_error_t *
svn_wc__delete_internal(svn_wc_context_t *wc_ctx,
Modified: subversion/branches/showing-merge-info/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_wc/update_editor.c?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_wc/update_editor.c Mon Nov 7 11:09:51 2011
@@ -4614,17 +4614,6 @@ close_edit(void *edit_baton,
struct edit_baton *eb = edit_baton;
apr_pool_t *scratch_pool = eb->pool;
- /* The editor didn't even open the root; we have to take care of
- some cleanup stuffs. */
- if (! eb->root_opened
- && *eb->target_basename == '\0')
- {
- /* We need to "un-incomplete" the root directory. */
- SVN_ERR(svn_wc__db_temp_op_end_directory_update(eb->db,
- eb->anchor_abspath,
- scratch_pool));
- }
-
/* By definition, anybody "driving" this editor for update or switch
purposes at a *minimum* must have called set_target_revision() at
the outset, and close_edit() at the end -- even if it turned out
Modified: subversion/branches/showing-merge-info/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_wc/wc-queries.sql?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_wc/wc-queries.sql Mon Nov 7 11:09:51 2011
@@ -1193,21 +1193,18 @@ DROP TABLE IF EXISTS delete_list;
CREATE TEMPORARY TABLE delete_list (
/* ### we should put the wc_id in here in case a delete spans multiple
### working copies. queries, etc will need to be adjusted. */
- local_relpath TEXT PRIMARY KEY NOT NULL
+ local_relpath TEXT PRIMARY KEY NOT NULL UNIQUE
)
/* This matches the selection in STMT_INSERT_DELETE_FROM_NODE_RECURSIVE */
-- STMT_INSERT_DELETE_LIST
INSERT INTO delete_list(local_relpath)
-SELECT local_relpath FROM nodes n
+SELECT local_relpath FROM nodes_current
WHERE wc_id = ?1
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')
- AND op_depth = (SELECT MAX(op_depth) FROM nodes s
- WHERE s.wc_id = n.wc_id
- AND s.local_relpath = n.local_relpath)
-- STMT_SELECT_DELETE_LIST
SELECT local_relpath FROM delete_list
Modified: subversion/branches/showing-merge-info/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_wc/wc_db.c?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_wc/wc_db.c Mon Nov 7 11:09:51 2011
@@ -6226,10 +6226,10 @@ struct op_delete_baton_t {
};
static svn_error_t *
-op_delete_txn(void *baton,
- svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- apr_pool_t *scratch_pool)
+delete_node(void *baton,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *scratch_pool)
{
struct op_delete_baton_t *b = baton;
svn_wc__db_status_t status;
@@ -6240,8 +6240,6 @@ op_delete_txn(void *baton,
svn_boolean_t refetch_depth = FALSE;
svn_kind_t kind;
- SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb, STMT_CREATE_DELETE_LIST));
-
SVN_ERR(read_info(&status,
&kind, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -6503,6 +6501,51 @@ op_delete_txn(void *baton,
return SVN_NO_ERROR;
}
+static svn_error_t *
+op_delete_txn(void *baton,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *scratch_pool)
+{
+
+ SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb, STMT_CREATE_DELETE_LIST));
+ SVN_ERR(delete_node(baton, wcroot, local_relpath, scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+
+struct op_delete_many_baton_t {
+ apr_array_header_t *rel_targets;
+} op_delete_many_baton_t;
+
+static svn_error_t *
+op_delete_many_txn(void *baton,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *scratch_pool)
+{
+ struct op_delete_many_baton_t *odmb = baton;
+ int i;
+ apr_pool_t *iterpool;
+
+ SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb, STMT_CREATE_DELETE_LIST));
+ iterpool = svn_pool_create(scratch_pool);
+ for (i = 0; i < odmb->rel_targets->nelts; i++)
+ {
+ const char *target_relpath = APR_ARRAY_IDX(odmb->rel_targets, i,
+ const char *);
+ struct op_delete_baton_t odb;
+
+ svn_pool_clear(iterpool);
+ odb.delete_depth = relpath_depth(target_relpath);
+ odb.moved_to_relpath = NULL;
+ SVN_ERR(delete_node(&odb, wcroot, target_relpath, iterpool));
+ }
+ svn_pool_destroy(iterpool);
+
+ return SVN_NO_ERROR;
+}
+
static svn_error_t *
do_delete_notify(void *baton,
@@ -6529,9 +6572,6 @@ do_delete_notify(void *baton,
svn_pool_clear(iterpool);
- if (cancel_func)
- SVN_ERR(cancel_func(cancel_baton));
-
notify_relpath = svn_sqlite__column_text(stmt, 0, NULL);
notify_abspath = svn_dirent_join(wcroot->abspath,
notify_relpath,
@@ -6547,7 +6587,15 @@ do_delete_notify(void *baton,
}
svn_pool_destroy(iterpool);
- return svn_error_trace(svn_sqlite__reset(stmt));
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ /* We only allow cancellation after notification for all deleted nodes
+ * has happened. The nodes are already deleted so we should notify for
+ * all of them. */
+ if (cancel_func)
+ SVN_ERR(cancel_func(cancel_baton));
+
+ return SVN_NO_ERROR;
}
@@ -6613,6 +6661,67 @@ svn_wc__db_op_delete(svn_wc__db_t *db,
}
+svn_error_t *
+svn_wc__db_op_delete_many(svn_wc__db_t *db,
+ apr_array_header_t *targets,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ svn_wc_notify_func2_t notify_func,
+ void *notify_baton,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_wcroot_t *wcroot;
+ const char *local_relpath;
+ struct op_delete_many_baton_t odmb;
+ int i;
+ apr_pool_t *iterpool;
+
+ odmb.rel_targets = apr_array_make(scratch_pool, targets->nelts,
+ sizeof(const char *));
+ iterpool = svn_pool_create(scratch_pool);
+ SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
+ db,
+ APR_ARRAY_IDX(targets, 0,
+ const char *),
+ scratch_pool, iterpool));
+ VERIFY_USABLE_WCROOT(wcroot);
+ for (i = 0; i < targets->nelts; i++)
+ {
+ const char *local_abspath = APR_ARRAY_IDX(targets, i, const char*);
+ svn_wc__db_wcroot_t *target_wcroot;
+
+ svn_pool_clear(iterpool);
+
+ SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&target_wcroot,
+ &local_relpath, db,
+ APR_ARRAY_IDX(targets, i,
+ const char *),
+ scratch_pool, iterpool));
+ VERIFY_USABLE_WCROOT(target_wcroot);
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+ /* Assert that all targets are within the same working copy. */
+ SVN_ERR_ASSERT(wcroot->wc_id == target_wcroot->wc_id);
+
+ APR_ARRAY_PUSH(odmb.rel_targets, const char *) = local_relpath;
+ SVN_ERR(flush_entries(target_wcroot, local_abspath, svn_depth_infinity,
+ iterpool));
+
+ }
+ svn_pool_destroy(iterpool);
+
+ /* Perform the deletion operation (transactionally), perform any
+ notifications necessary, and then clean out our temporary tables. */
+ return svn_error_trace(with_finalization(wcroot, wcroot->abspath,
+ op_delete_many_txn, &odmb,
+ do_delete_notify, NULL,
+ cancel_func, cancel_baton,
+ notify_func, notify_baton,
+ STMT_FINALIZE_DELETE,
+ scratch_pool));
+}
+
+
/* Like svn_wc__db_read_info(), but taking WCROOT+LOCAL_RELPATH instead of
DB+LOCAL_ABSPATH, and outputting repos ids instead of URL+UUID. */
static svn_error_t *
@@ -7215,9 +7324,7 @@ read_children_info(void *baton,
child_item->info.moved_here = svn_sqlite__column_boolean(stmt, 20);
}
- err = svn_sqlite__step(&have_row, stmt);
- if (err)
- SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
}
SVN_ERR(svn_sqlite__reset(stmt));
@@ -7271,9 +7378,7 @@ read_children_info(void *baton,
apr_hash_set(conflicts, apr_pstrdup(result_pool, name),
APR_HASH_KEY_STRING, "");
- err = svn_sqlite__step(&have_row, stmt);
- if (err)
- SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
}
SVN_ERR(svn_sqlite__reset(stmt));
@@ -7508,9 +7613,7 @@ svn_wc__db_read_children_walker_info(apr
apr_hash_set(*nodes, apr_pstrdup(result_pool, name),
APR_HASH_KEY_STRING, child);
- err = svn_sqlite__step(&have_row, stmt);
- if (err)
- SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
}
SVN_ERR(svn_sqlite__reset(stmt));
@@ -9033,6 +9136,17 @@ bump_node_revision(svn_wc__db_wcroot_t *
new_repos_id,
scratch_pool));
+ if (db_kind == svn_kind_dir && status == svn_wc__db_status_incomplete)
+ {
+ svn_sqlite__stmt_t *stmt;
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_UPDATE_NODE_BASE_PRESENCE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "ist", wcroot->wc_id, local_relpath,
+ presence_map, svn_wc__db_status_normal));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+ }
+
/* Early out */
if (depth <= svn_depth_empty
|| db_kind != svn_kind_dir
@@ -11613,55 +11727,6 @@ svn_wc__db_wclock_owns_lock(svn_boolean_
return SVN_NO_ERROR;
}
-/* Lock helper for svn_wc__db_temp_op_end_directory_update */
-static svn_error_t *
-end_directory_update(void *baton,
- svn_wc__db_wcroot_t *wcroot,
- const char *local_relpath,
- apr_pool_t *scratch_pool)
-{
- svn_sqlite__stmt_t *stmt;
- svn_wc__db_status_t base_status;
-
- SVN_ERR(base_get_info(&base_status, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
- wcroot, local_relpath, scratch_pool, scratch_pool));
-
- SVN_ERR_ASSERT(base_status == svn_wc__db_status_incomplete);
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_UPDATE_NODE_BASE_PRESENCE));
- SVN_ERR(svn_sqlite__bindf(stmt, "ist", wcroot->wc_id, local_relpath,
- presence_map, svn_wc__db_status_normal));
- SVN_ERR(svn_sqlite__step_done(stmt));
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_wc__db_temp_op_end_directory_update(svn_wc__db_t *db,
- const char *local_dir_abspath,
- apr_pool_t *scratch_pool)
-{
- svn_wc__db_wcroot_t *wcroot;
- const char *local_relpath;
-
- SVN_ERR_ASSERT(svn_dirent_is_absolute(local_dir_abspath));
-
- SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
- local_dir_abspath, scratch_pool, scratch_pool));
- VERIFY_USABLE_WCROOT(wcroot);
-
- SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, end_directory_update,
- NULL, scratch_pool));
-
- SVN_ERR(flush_entries(wcroot, local_dir_abspath, svn_depth_empty,
- scratch_pool));
-
- return SVN_NO_ERROR;
-}
-
-
struct start_directory_update_baton_t
{
svn_revnum_t new_rev;
Modified: subversion/branches/showing-merge-info/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/libsvn_wc/wc_db.h?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/showing-merge-info/subversion/libsvn_wc/wc_db.h Mon Nov 7 11:09:51 2011
@@ -1407,6 +1407,32 @@ svn_wc__db_op_delete(svn_wc__db_t *db,
apr_pool_t *scratch_pool);
+/* Mark all LOCAL_ABSPATH in the TARGETS array, and all of their children,
+ * for deletion.
+ *
+ * This function is more efficient than svn_wc__db_op_delete() because
+ * only one sqlite transaction is used for all targets.
+ * It currently lacks support for moves (though this could be changed,
+ * at which point svn_wc__db_op_delete() becomes redundant).
+ *
+ * If NOTIFY_FUNC is not NULL, then it will be called (with NOTIFY_BATON)
+ * for each node deleted. While this processing occurs, if CANCEL_FUNC is
+ * not NULL, then it will be called (with CANCEL_BATON) to detect cancellation
+ * during the processing.
+ *
+ * Note: the notification (and cancellation) occur outside of a SQLite
+ * transaction.
+ */
+svn_error_t *
+svn_wc__db_op_delete_many(svn_wc__db_t *db,
+ apr_array_header_t *targets,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ svn_wc_notify_func2_t notify_func,
+ void *notify_baton,
+ apr_pool_t *scratch_pool);
+
+
/* ### mark PATH as (possibly) modified. "svn edit" ... right API here? */
svn_error_t *
svn_wc__db_op_modified(svn_wc__db_t *db,
@@ -2286,6 +2312,11 @@ svn_wc__db_global_update(svn_wc__db_t *d
The modifications are mutually exclusive. If NEW_REPOS_ROOT is non-NULL,
set the repository root of the entry to NEW_REPOS_ROOT.
+ If LOCAL_ABSPATH is an incomplete directory then mark it complete
+ by setting the status to normal. (Removing incomplete is usually
+ done by the editor during close_directory, but if the editor driver
+ simply called close_edit it gets done here.)
+
If LOCAL_ABSPATH is a directory, then, walk entries below LOCAL_ABSPATH
according to DEPTH thusly:
@@ -2844,15 +2875,6 @@ svn_wc__db_temp_op_start_directory_updat
svn_revnum_t new_rev,
apr_pool_t *scratch_pool);
-/* Marks a directory update started with
- svn_wc__db_temp_op_start_directory_update as completed, by removing
- the incomplete status */
-svn_error_t *
-svn_wc__db_temp_op_end_directory_update(svn_wc__db_t *db,
- const char *local_dir_abspath,
- apr_pool_t *scratch_pool);
-
-
/* Copy the base tree at LOCAL_ABSPATH into the working tree as copy,
leaving any subtree additions and copies as-is. This allows the
base node tree to be removed. */
Modified: subversion/branches/showing-merge-info/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/svn/cl.h?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/svn/cl.h (original)
+++ subversion/branches/showing-merge-info/subversion/svn/cl.h Mon Nov 7 11:09:51 2011
@@ -766,42 +766,19 @@ svn_cl__node_description(const svn_wc_co
const char *wc_repos_root_URL,
apr_pool_t *pool);
-/* Return, in @a *true_targets_p, a copy of @a targets with peg revision
- * specifiers snipped off the end of each element.
- *
- * ### JAF TODO: This function is not good because it does not allow the
- * ### caller to detect if an invalid peg revision was specified.
- * ###
- * ### Callers should never have a need to silently *discard* all peg
- * ### revisions, even if they are doing this *after* saving any peg
- * ### revisions that might be of interest on certain arguments: I don't
- * ### think it can ever be correct to silently ignore a peg revision that
- * ### is specified, whether it makes semantic sense or not.
- * ###
- * ### Instead, callers should parse all the arguments and silently
- * ### ignore an *empty* peg revision part (just an "@", which can be
- * ### used to escape an earlier "@" in the argument) on any argument,
- * ### even an argument on which a peg revision does not make sense,
- * ### but should not silently ignore a non-empty peg when it does not
- * ### make sense.
- * ###
- * ### Something like:
- * ### For each (URL-like?) argument that doesn't accept a peg rev:
- * ### Parse into peg-rev and true-path parts;
- * ### If (peg rev != unspecified)
- * ### Error("This arg doesn't accept a peg rev.").
- * ### Use the true-path part.
+/* Return, in @a *true_targets_p, a shallow copy of @a targets with any
+ * empty peg revision specifier snipped off the end of each element. If any
+ * target has a non-empty peg revision specifier, throw an error. The user
+ * may have specified a peg revision where it doesn't make sense to do so,
+ * or may have forgotten to escape an '@' character in a filename.
*
* This function is useful for subcommands for which peg revisions
- * do not make any sense. Such subcommands still need to allow peg
- * revisions to be specified on the command line so that users of
+ * do not make any sense. Such subcommands still need to allow an empty
+ * peg revision to be specified on the command line so that users of
* the command line client can consistently escape '@' characters
* in filenames by appending an '@' character, regardless of the
* subcommand being used.
*
- * If a peg revision is present but cannot be parsed, an error is thrown.
- * The user has likely forgotten to escape an '@' character in a filename.
- *
* It is safe to pass the address of @a targets as @a true_targets_p.
*
* Do all allocations in @a pool. */
Modified: subversion/branches/showing-merge-info/subversion/svn/copy-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/svn/copy-cmd.c?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/svn/copy-cmd.c (original)
+++ subversion/branches/showing-merge-info/subversion/svn/copy-cmd.c Mon Nov 7 11:09:51 2011
@@ -76,7 +76,18 @@ svn_cl__copy(apr_getopt_t *os,
APR_ARRAY_PUSH(sources, svn_client_copy_source_t *) = source;
}
- SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, pool));
+ /* Get DST_PATH (the target path or URL) and check that no peg revision is
+ * specified for it. */
+ {
+ const char *tgt = APR_ARRAY_IDX(targets, targets->nelts - 1, const char *);
+ svn_opt_revision_t peg;
+
+ SVN_ERR(svn_opt_parse_path(&peg, &dst_path, tgt, pool));
+ if (peg.kind != svn_opt_revision_unspecified)
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("'%s': a peg revision is not allowed here"),
+ tgt);
+ }
/* Figure out which type of notification to use.
(There is no need to check that the src paths are homogeneous;
@@ -84,8 +95,6 @@ svn_cl__copy(apr_getopt_t *os,
error if they are not.) */
src_path = APR_ARRAY_IDX(targets, 0, const char *);
srcs_are_urls = svn_path_is_url(src_path);
- dst_path = APR_ARRAY_IDX(targets, targets->nelts - 1, const char *);
- apr_array_pop(targets);
dst_is_url = svn_path_is_url(dst_path);
if ((! srcs_are_urls) && (! dst_is_url))
Modified: subversion/branches/showing-merge-info/subversion/svn/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/svn/main.c?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/svn/main.c (original)
+++ subversion/branches/showing-merge-info/subversion/svn/main.c Mon Nov 7 11:09:51 2011
@@ -145,7 +145,11 @@ const apr_getopt_option_t svn_cl__option
{"change", 'c', 1,
N_("the change made by revision ARG (like -r ARG-1:ARG)\n"
" "
- "If ARG is negative this is like -r ARG:ARG-1")},
+ "If ARG is negative this is like -r ARG:ARG-1\n"
+ " "
+ "If ARG is of the form ARG1-ARG2 then this is like\n"
+ " "
+ "ARG1:ARG2, where ARG1 is inclusive")},
{"revision", 'r', 1,
N_("ARG (some commands also take ARG1:ARG2 range)\n"
" "
Modified: subversion/branches/showing-merge-info/subversion/svn/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/svn/util.c?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/svn/util.c (original)
+++ subversion/branches/showing-merge-info/subversion/svn/util.c Mon Nov 7 11:09:51 2011
@@ -1358,10 +1358,14 @@ svn_cl__eat_peg_revisions(apr_array_head
for (i = 0; i < targets->nelts; i++)
{
const char *target = APR_ARRAY_IDX(targets, i, const char *);
- const char *true_target;
+ const char *true_target, *peg;
- SVN_ERR(svn_opt__split_arg_at_peg_revision(&true_target, NULL,
+ SVN_ERR(svn_opt__split_arg_at_peg_revision(&true_target, &peg,
target, pool));
+ if (peg[0] && peg[1])
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("'%s': a peg revision is not allowed here"),
+ target);
APR_ARRAY_PUSH(true_targets, const char *) = true_target;
}
Modified: subversion/branches/showing-merge-info/subversion/tests/cmdline/copy_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/tests/cmdline/copy_tests.py?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/tests/cmdline/copy_tests.py (original)
+++ subversion/branches/showing-merge-info/subversion/tests/cmdline/copy_tests.py Mon Nov 7 11:09:51 2011
@@ -3444,11 +3444,12 @@ def copy_peg_rev_url(sbox):
wc_dir)
# Copy using a peg rev
- # Add peg rev '@HEAD' to sigma_url when copying which tests for issue #3651.
+ # Add an empty peg specifier ('@') to sigma_url when copying, to test for
+ # issue #3651 "svn copy does not eat peg revision within copy target path".
svntest.actions.run_and_verify_svn(None, None, [],
'cp',
iota_url + '@HEAD', '-r', '1',
- sigma_url + '@HEAD', '-m', 'rev 3')
+ sigma_url + '@', '-m', 'rev 3')
# Validate the copy destination's mergeinfo (we expect none).
svntest.actions.run_and_verify_svn(None, [], [],
Modified: subversion/branches/showing-merge-info/subversion/tests/cmdline/dav-mirror-autocheck.sh
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/tests/cmdline/dav-mirror-autocheck.sh?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/tests/cmdline/dav-mirror-autocheck.sh (original)
+++ subversion/branches/showing-merge-info/subversion/tests/cmdline/dav-mirror-autocheck.sh Mon Nov 7 11:09:51 2011
@@ -323,7 +323,7 @@ fi
[ -r "$MOD_AUTHZ_SVN" ] \
|| fail "authz_svn_module not found, please use '--enable-shared --enable-dso --with-apxs' with your 'configure' script"
-export LD_LIBRARY_PATH="$ABS_BUILDDIR/subversion/libsvn_ra_neon/.libs:$ABS_BUILDDIR/subversion/libsvn_ra_local/.libs:$ABS_BUILDDIR/subversion/libsvn_ra_svn/.libs"
+export LD_LIBRARY_PATH="$ABS_BUILDDIR/subversion/libsvn_ra_neon/.libs:$ABS_BUILDDIR/subversion/libsvn_ra_local/.libs:$ABS_BUILDDIR/subversion/libsvn_ra_svn/.libs:$LD_LIBRARY_PATH"
MASTER_REPOS="${MASTER_REPOS:-"$HTTPD_ROOT/master_repos"}"
SLAVE_REPOS="${SLAVE_REPOS:-"$HTTPD_ROOT/slave_repos"}"
Modified: subversion/branches/showing-merge-info/subversion/tests/cmdline/davautocheck.sh
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/tests/cmdline/davautocheck.sh?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/tests/cmdline/davautocheck.sh (original)
+++ subversion/branches/showing-merge-info/subversion/tests/cmdline/davautocheck.sh Mon Nov 7 11:09:51 2011
@@ -195,7 +195,7 @@ fi
[ -r "$MOD_AUTHZ_SVN" ] \
|| fail "authz_svn_module not found, please use '--enable-shared --enable-dso --with-apxs' with your 'configure' script"
-export LD_LIBRARY_PATH="$ABS_BUILDDIR/subversion/libsvn_ra_neon/.libs:$ABS_BUILDDIR/subversion/libsvn_ra_local/.libs:$ABS_BUILDDIR/subversion/libsvn_ra_svn/.libs"
+export LD_LIBRARY_PATH="$ABS_BUILDDIR/subversion/libsvn_ra_neon/.libs:$ABS_BUILDDIR/subversion/libsvn_ra_local/.libs:$ABS_BUILDDIR/subversion/libsvn_ra_svn/.libs:$LD_LIBRARY_PATH"
case "`uname`" in
Darwin*) LDD='otool -L'
Modified: subversion/branches/showing-merge-info/subversion/tests/cmdline/patch_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/tests/cmdline/patch_tests.py?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/tests/cmdline/patch_tests.py (original)
+++ subversion/branches/showing-merge-info/subversion/tests/cmdline/patch_tests.py Mon Nov 7 11:09:51 2011
@@ -3858,6 +3858,61 @@ def patch_reversed_add_with_props2(sbox)
1, # dry-run
'--reverse-diff')
+def patch_dev_null(sbox):
+ "patch with /dev/null filenames"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ patch_file_path = make_patch_path(sbox)
+
+ # Git (and maybe other tools) use '/dev/null' as the old path for
+ # newly added files, and as the new path for deleted files.
+ # The path selection algorithm in 'svn patch' must detect this and
+ # avoid using '/dev/null' as a patch target.
+ unidiff_patch = [
+ "Index: new\n",
+ "===================================================================\n",
+ "--- /dev/null\n",
+ "+++ new (revision 0)\n",
+ "@@ -0,0 +1 @@\n",
+ "+new\n",
+ "\n",
+ "Index: A/B/E/beta\n",
+ "===================================================================\n",
+ "--- A/B/E/beta (revision 1)\n",
+ "+++ /dev/null\n",
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'beta'.\n",
+ ]
+
+ svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
+
+ new_contents = "new\n"
+ expected_output = [
+ 'A %s\n' % os.path.join(wc_dir, 'new'),
+ 'D %s\n' % os.path.join(wc_dir, 'A', 'B', 'E', 'beta'),
+ ]
+
+ expected_disk = svntest.main.greek_state.copy()
+ expected_disk.add({'new' : Item(contents=new_contents)})
+ expected_disk.remove('A/B/E/beta')
+
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.add({'new' : Item(status='A ', wc_rev=0)})
+ expected_status.tweak('A/B/E/beta', status='D ')
+
+ expected_skip = wc.State('', { })
+
+ svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+ expected_output,
+ expected_disk,
+ expected_status,
+ expected_skip,
+ None, # expected err
+ 1, # check-props
+ 1) # dry-run
+
########################################################################
#Run the tests
@@ -3898,6 +3953,7 @@ test_list = [ None,
patch_deletes_prop,
patch_reversed_add_with_props,
patch_reversed_add_with_props2,
+ patch_dev_null,
]
if __name__ == '__main__':
Modified: subversion/branches/showing-merge-info/subversion/tests/libsvn_delta/editor-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/tests/libsvn_delta/editor-test.c?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/tests/libsvn_delta/editor-test.c (original)
+++ subversion/branches/showing-merge-info/subversion/tests/libsvn_delta/editor-test.c Mon Nov 7 11:09:51 2011
@@ -267,6 +267,7 @@ editor_from_delta_editor_test(const svn_
void *dedit_baton;
const svn_delta_editor_t *deditor;
svn_editor_t *editor;
+ svn_boolean_t make_abs_paths = TRUE;
svn_pool_clear(iterpool);
@@ -275,6 +276,7 @@ editor_from_delta_editor_test(const svn_
/* Construct our editor, and from it a delta editor. */
SVN_ERR(get_noop_editor(&editor, NULL, NULL, NULL, iterpool, iterpool));
SVN_ERR(delta_from_editor(&deditor, &dedit_baton, editor,
+ &make_abs_paths,
NULL, NULL, NULL, NULL, iterpool));
SVN_ERR(svn_repos_replay2(revision_root, "", SVN_INVALID_REVNUM, TRUE,
Modified: subversion/branches/showing-merge-info/subversion/tests/libsvn_repos/repos-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/subversion/tests/libsvn_repos/repos-test.c?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/subversion/tests/libsvn_repos/repos-test.c (original)
+++ subversion/branches/showing-merge-info/subversion/tests/libsvn_repos/repos-test.c Mon Nov 7 11:09:51 2011
@@ -1348,6 +1348,149 @@ commit_authz_cb(svn_repos_authz_access_t
+enum action_t {
+ A_DELETE,
+ A_ADD_FILE,
+ A_ADD_DIR,
+ A_CHANGE_FILE_PROP
+};
+struct authz_path_action_t
+{
+ enum action_t action;
+ const char *path;
+ svn_boolean_t authz_error_expected;
+ const char *copyfrom_path;
+};
+
+/* Return the appropriate dir baton for the parent of PATH in *DIR_BATON,
+ allocated in POOL. */
+static svn_error_t *
+get_dir_baton(void **dir_baton,
+ const char *path,
+ const svn_delta_editor_t *editor,
+ void *root_baton,
+ apr_pool_t *pool)
+{
+ int i;
+ apr_array_header_t *path_bits = svn_path_decompose(path, pool);
+ const char *path_so_far = "";
+
+ *dir_baton = root_baton;
+ for (i = 0; i < (path_bits->nelts - 1); i++)
+ {
+ const char *path_bit = APR_ARRAY_IDX(path_bits, i, const char *);
+ path_so_far = svn_path_join(path_so_far, path_bit, pool);
+ SVN_ERR(editor->open_directory(path_so_far, *dir_baton,
+ SVN_INVALID_REVNUM, pool, dir_baton));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* Return the appropriate file baton for PATH in *FILE_BATON, allocated in
+ POOL. */
+static svn_error_t *
+get_file_baton(void **file_baton,
+ const char *path,
+ const svn_delta_editor_t *editor,
+ void *root_baton,
+ apr_pool_t *pool)
+{
+ void *dir_baton;
+
+ SVN_ERR(get_dir_baton(&dir_baton, path, editor, root_baton, pool));
+
+ SVN_ERR(editor->open_file(path, dir_baton, SVN_INVALID_REVNUM, pool,
+ file_baton));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_path_authz(svn_repos_t *repos,
+ struct authz_path_action_t *path_action,
+ svn_authz_t *authz_file,
+ svn_revnum_t youngest_rev,
+ apr_pool_t *scratch_pool)
+{
+ void *edit_baton;
+ void *root_baton;
+ void *dir_baton;
+ void *file_baton;
+ void *out_baton;
+ const svn_delta_editor_t *editor;
+ svn_error_t *err;
+ svn_error_t *err2;
+
+ /* Create a new commit editor in which we're going to play with
+ authz */
+ SVN_ERR(svn_repos_get_commit_editor4(&editor, &edit_baton, repos,
+ NULL, "file://test", "/",
+ "plato", "test commit", NULL,
+ NULL, commit_authz_cb, authz_file,
+ scratch_pool));
+
+ /* Start fiddling. First get the root, which is readonly. */
+ SVN_ERR(editor->open_root(edit_baton, 1, scratch_pool, &root_baton));
+
+ /* Fetch the appropriate baton for our action. This may involve opening
+ intermediate batons, but we only care about the final one for the
+ cooresponding action. */
+ if (path_action->action == A_CHANGE_FILE_PROP)
+ SVN_ERR(get_file_baton(&file_baton, path_action->path, editor, root_baton,
+ scratch_pool));
+ else
+ SVN_ERR(get_dir_baton(&dir_baton, path_action->path, editor, root_baton,
+ scratch_pool));
+
+ /* Test the appropriate action. */
+ switch (path_action->action)
+ {
+ case A_DELETE:
+ err = editor->delete_entry(path_action->path, SVN_INVALID_REVNUM,
+ dir_baton, scratch_pool);
+ break;
+
+ case A_CHANGE_FILE_PROP:
+ err = editor->change_file_prop(file_baton, "svn:test",
+ svn_string_create("test", scratch_pool),
+ scratch_pool);
+ break;
+
+ case A_ADD_FILE:
+ err = editor->add_file(path_action->path, dir_baton,
+ path_action->copyfrom_path, youngest_rev,
+ scratch_pool, &out_baton);
+ break;
+
+ case A_ADD_DIR:
+ err = editor->add_directory(path_action->path, dir_baton,
+ path_action->copyfrom_path, youngest_rev,
+ scratch_pool, &out_baton);
+ break;
+ }
+
+ /* Don't worry about closing batons, just abort the edit. Since errors
+ may be delayed, we need to capture results of the abort as well. */
+ err2 = editor->abort_edit(edit_baton, scratch_pool);
+ if (!err)
+ err = err2;
+ else
+ svn_error_clear(err2);
+
+ /* Check for potential errors. */
+ if (path_action->authz_error_expected)
+ {
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_AUTHZ_UNWRITABLE);
+ svn_error_clear(err);
+ }
+ else
+ SVN_ERR(err);
+
+ return SVN_NO_ERROR;
+}
+
+
/* Test that the commit editor is taking authz into account
properly */
static svn_error_t *
@@ -1359,13 +1502,26 @@ commit_editor_authz(const svn_test_opts_
svn_fs_txn_t *txn;
svn_fs_root_t *txn_root;
svn_revnum_t youngest_rev;
- void *edit_baton;
- void *root_baton, *dir_baton, *dir2_baton, *file_baton;
- svn_error_t *err;
- const svn_delta_editor_t *editor;
svn_authz_t *authz_file;
- apr_pool_t *subpool = svn_pool_create(pool);
+ apr_pool_t *iterpool;
const char *authz_contents;
+ int i;
+ struct authz_path_action_t path_actions[] = {
+ { A_DELETE, "/iota", TRUE },
+ { A_CHANGE_FILE_PROP, "/iota", TRUE },
+ { A_ADD_FILE, "/alpha", TRUE },
+ { A_ADD_FILE, "/alpha", TRUE, "file://test/A/B/lambda" },
+ { A_ADD_DIR, "/I", TRUE },
+ { A_ADD_DIR, "/J", TRUE, "file://test/A/D" },
+ { A_ADD_FILE, "/A/alpha", TRUE },
+ { A_ADD_FILE, "/A/B/theta", FALSE },
+ { A_DELETE, "/A/mu", FALSE },
+ { A_ADD_DIR, "/A/E", FALSE },
+ { A_ADD_DIR, "/A/J", FALSE, "file://test/A/D" },
+ { A_DELETE, "A/D/G", TRUE },
+ { A_DELETE, "A/D/H", FALSE },
+ { A_CHANGE_FILE_PROP, "A/D/gamma", FALSE }
+ };
/* The Test Plan
*
@@ -1375,25 +1531,24 @@ commit_editor_authz(const svn_test_opts_
* authorized/denied when necessary. We don't try to be exhaustive
* in the kinds of authz lookups. We just make sure that the editor
* replies to the calls in a way that proves it is doing authz
- * lookups.
+ * lookups. Some actions are tested implicitly (such as open_file being
+ * required for change_file_props).
*
- * Note that this use of the commit editor is not kosher according
- * to the generic editor API (we aren't allowed to continue editing
- * after an error, nor are we allowed to assume that errors are
- * returned by the operations which caused them). But it should
- * work fine with this particular editor implementation.
+ * Note that because of the error handling requirements of the generic
+ * editor API, each operation needs its own editor, which is handled by
+ * a helper function above.
*/
/* Create a filesystem and repository. */
SVN_ERR(svn_test__create_repos(&repos, "test-repo-commit-authz",
- opts, subpool));
+ opts, pool));
fs = svn_repos_fs(repos);
/* Prepare a txn to receive the greek tree. */
- SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, subpool));
- SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
- SVN_ERR(svn_test__create_greek_tree(txn_root, subpool));
- SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, subpool));
+ SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, pool));
+ SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+ SVN_ERR(svn_test__create_greek_tree(txn_root, pool));
+ SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(youngest_rev));
/* Load the authz rules for the greek tree. */
@@ -1419,147 +1574,18 @@ commit_editor_authz(const svn_test_opts_
"[/A/D/G]" NL
"plato = r"; /* No newline at end of file. */
- SVN_ERR(authz_get_handle(&authz_file, authz_contents, subpool));
-
- /* Create a new commit editor in which we're going to play with
- authz */
- SVN_ERR(svn_repos_get_commit_editor4(&editor, &edit_baton, repos,
- NULL, "file://test", "/",
- "plato", "test commit", NULL,
- NULL, commit_authz_cb, authz_file,
- subpool));
-
- /* Start fiddling. First get the root, which is readonly. All
- write operations fail because of the root's permissions. */
- SVN_ERR(editor->open_root(edit_baton, 1, subpool, &root_baton));
-
- /* Test denied file deletion. */
- err = editor->delete_entry("/iota", SVN_INVALID_REVNUM, root_baton, subpool);
- if (err == SVN_NO_ERROR || err->apr_err != SVN_ERR_AUTHZ_UNWRITABLE)
- return svn_error_createf(SVN_ERR_TEST_FAILED, err,
- "Got %s error instead of expected "
- "SVN_ERR_AUTHZ_UNWRITABLE",
- err ? "unexpected" : "no");
- svn_error_clear(err);
-
- /* Test authorized file open. */
- SVN_ERR(editor->open_file("/iota", root_baton, SVN_INVALID_REVNUM,
- subpool, &file_baton));
-
- /* Test unauthorized file prop set. */
- err = editor->change_file_prop(file_baton, "svn:test",
- svn_string_create("test", subpool),
- subpool);
- if (err == SVN_NO_ERROR || err->apr_err != SVN_ERR_AUTHZ_UNWRITABLE)
- return svn_error_createf(SVN_ERR_TEST_FAILED, err,
- "Got %s error instead of expected "
- "SVN_ERR_AUTHZ_UNWRITABLE",
- err ? "unexpected" : "no");
- svn_error_clear(err);
-
- /* Test denied file addition. */
- err = editor->add_file("/alpha", root_baton, NULL, SVN_INVALID_REVNUM,
- subpool, &file_baton);
- if (err == SVN_NO_ERROR || err->apr_err != SVN_ERR_AUTHZ_UNWRITABLE)
- return svn_error_createf(SVN_ERR_TEST_FAILED, err,
- "Got %s error instead of expected "
- "SVN_ERR_AUTHZ_UNWRITABLE",
- err ? "unexpected" : "no");
- svn_error_clear(err);
-
- /* Test denied file copy. */
- err = editor->add_file("/alpha", root_baton, "file://test/A/B/lambda",
- youngest_rev, subpool, &file_baton);
- if (err == SVN_NO_ERROR || err->apr_err != SVN_ERR_AUTHZ_UNWRITABLE)
- return svn_error_createf(SVN_ERR_TEST_FAILED, err,
- "Got %s error instead of expected "
- "SVN_ERR_AUTHZ_UNWRITABLE",
- err ? "unexpected" : "no");
- svn_error_clear(err);
-
- /* Test denied directory addition. */
- err = editor->add_directory("/I", root_baton, NULL,
- SVN_INVALID_REVNUM, subpool, &dir_baton);
- if (err == SVN_NO_ERROR || err->apr_err != SVN_ERR_AUTHZ_UNWRITABLE)
- return svn_error_createf(SVN_ERR_TEST_FAILED, err,
- "Got %s error instead of expected "
- "SVN_ERR_AUTHZ_UNWRITABLE",
- err ? "unexpected" : "no");
- svn_error_clear(err);
-
- /* Test denied directory copy. */
- err = editor->add_directory("/J", root_baton, "file://test/A/D",
- youngest_rev, subpool, &dir_baton);
- if (err == SVN_NO_ERROR || err->apr_err != SVN_ERR_AUTHZ_UNWRITABLE)
- return svn_error_createf(SVN_ERR_TEST_FAILED, err,
- "Got %s error instead of expected "
- "SVN_ERR_AUTHZ_UNWRITABLE",
- err ? "unexpected" : "no");
- svn_error_clear(err);
-
- /* Open directory /A, to which we have read/write access. */
- SVN_ERR(editor->open_directory("/A", root_baton,
- SVN_INVALID_REVNUM,
- subpool, &dir_baton));
-
- /* Test denied file addition. Denied because of a conflicting rule
- on the file path itself. */
- err = editor->add_file("/A/alpha", dir_baton, NULL,
- SVN_INVALID_REVNUM, subpool, &file_baton);
- if (err == SVN_NO_ERROR || err->apr_err != SVN_ERR_AUTHZ_UNWRITABLE)
- return svn_error_createf(SVN_ERR_TEST_FAILED, err,
- "Got %s error instead of expected "
- "SVN_ERR_AUTHZ_UNWRITABLE",
- err ? "unexpected" : "no");
- svn_error_clear(err);
-
- /* Test authorized file addition. */
- SVN_ERR(editor->add_file("/A/B/theta", dir_baton, NULL,
- SVN_INVALID_REVNUM, subpool,
- &file_baton));
-
- /* Test authorized file deletion. */
- SVN_ERR(editor->delete_entry("/A/mu", SVN_INVALID_REVNUM, dir_baton,
- subpool));
-
- /* Test authorized directory creation. */
- SVN_ERR(editor->add_directory("/A/E", dir_baton, NULL,
- SVN_INVALID_REVNUM, subpool,
- &dir2_baton));
-
- /* Test authorized copy of a tree. */
- SVN_ERR(editor->add_directory("/A/J", dir_baton, "file://test/A/D",
- youngest_rev, subpool,
- &dir2_baton));
-
- /* Open /A/D. This should be granted. */
- SVN_ERR(editor->open_directory("/A/D", dir_baton, SVN_INVALID_REVNUM,
- subpool, &dir_baton));
-
- /* Test denied recursive deletion. */
- err = editor->delete_entry("/A/D/G", SVN_INVALID_REVNUM, dir_baton,
- subpool);
- if (err == SVN_NO_ERROR || err->apr_err != SVN_ERR_AUTHZ_UNWRITABLE)
- return svn_error_createf(SVN_ERR_TEST_FAILED, err,
- "Got %s error instead of expected "
- "SVN_ERR_AUTHZ_UNWRITABLE",
- err ? "unexpected" : "no");
- svn_error_clear(err);
+ SVN_ERR(authz_get_handle(&authz_file, authz_contents, pool));
- /* Test authorized recursive deletion. */
- SVN_ERR(editor->delete_entry("/A/D/H", SVN_INVALID_REVNUM,
- dir_baton, subpool));
-
- /* Test authorized propset (open the file first). */
- SVN_ERR(editor->open_file("/A/D/gamma", dir_baton, SVN_INVALID_REVNUM,
- subpool, &file_baton));
- SVN_ERR(editor->change_file_prop(file_baton, "svn:test",
- svn_string_create("test", subpool),
- subpool));
+ iterpool = svn_pool_create(pool);
+ for (i = 0; i < (sizeof(path_actions) / sizeof(struct authz_path_action_t));
+ i++)
+ {
+ svn_pool_clear(iterpool);
+ SVN_ERR(test_path_authz(repos, &path_actions[i], authz_file,
+ youngest_rev, iterpool));
+ }
- /* Done. */
- SVN_ERR(editor->abort_edit(edit_baton, subpool));
- svn_pool_destroy(subpool);
+ svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
Propchange: subversion/branches/showing-merge-info/subversion/tests/libsvn_wc/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Mon Nov 7 11:09:51 2011
@@ -8,3 +8,4 @@ svn-test-work
entries-compat-test
op-depth-test
wc-lock-tester
+wc-incomplete-tester
Modified: subversion/branches/showing-merge-info/tools/dev/benchmarks/suite1/cronjob
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/tools/dev/benchmarks/suite1/cronjob?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/tools/dev/benchmarks/suite1/cronjob (original)
+++ subversion/branches/showing-merge-info/tools/dev/benchmarks/suite1/cronjob Mon Nov 7 11:09:51 2011
@@ -58,7 +58,7 @@ if [ "$?" -ne "0" ]; then
echo "$subject"
else
- rev="$(svn info /home/neels/pat/trunk/src | grep Revision)"
+ rev="$(/home/neels/pat/stable/prefix/bin/svn info /home/neels/pat/trunk/src | grep Revision)"
if [ -z "$rev" ]; then
subject="Working copy problem."
echo "$subject" > "$results"
Modified: subversion/branches/showing-merge-info/tools/dev/benchmarks/suite1/run
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/tools/dev/benchmarks/suite1/run?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/tools/dev/benchmarks/suite1/run (original)
+++ subversion/branches/showing-merge-info/tools/dev/benchmarks/suite1/run Mon Nov 7 11:09:51 2011
@@ -18,17 +18,10 @@
# under the License.
# Where are the svn binaries you want to benchmark?
-if [ "$USER" = "neels" ]; then
- SVN_A_NAME="1.7.x"
- SVN_A="$HOME/pat/bench/prefix/bin/svn"
- SVN_B_NAME="trunk"
- SVN_B="$HOME/pat/trunk/prefix/bin/svn"
-else
- SVN_A_NAME="1.6"
- SVN_A="$HOME/src/svn-1.6.x/subversion/svn/svn"
- SVN_B_NAME="trunk"
- SVN_B="$HOME/src/svn/subversion/svn/svn"
-fi
+SVN_A_NAME="1.7.x"
+SVN_A="$HOME/pat/bench/prefix/bin/svn"
+SVN_B_NAME="trunk"
+SVN_B="$HOME/pat/trunk/prefix/bin/svn"
benchmark="$PWD/benchmark.py"
@@ -71,6 +64,11 @@ cs=100
started="$(date)"
echo "Started at $started"
+echo "
+*Disclaimer:* this tests only file://-URL access on a GNU/Linux VM.
+This is intended to measure changes in performance of the local working
+copy layer, *only*. These results are *not* generally true for everyone."
+
batch $al $as $N
batch $bl $bs $N
batch $cl $cs $N
Modified: subversion/branches/showing-merge-info/tools/server-side/svnauthz-validate.c
URL: http://svn.apache.org/viewvc/subversion/branches/showing-merge-info/tools/server-side/svnauthz-validate.c?rev=1198703&r1=1198702&r2=1198703&view=diff
==============================================================================
--- subversion/branches/showing-merge-info/tools/server-side/svnauthz-validate.c (original)
+++ subversion/branches/showing-merge-info/tools/server-side/svnauthz-validate.c Mon Nov 7 11:09:51 2011
@@ -40,10 +40,12 @@ main(int argc, const char **argv)
svn_authz_t *authz;
const char *authz_file;
- if (argc <= 1)
+ if (argc != 2 && argc != 4 && argc != 5)
{
- printf("Usage: %s PATH \n\n", argv[0]);
- printf("Loads the authz file at PATH and validates its syntax. \n"
+ printf("Usage: %s FILE [USER PATH [REPOS_NAME]]\n\n", argv[0]);
+ printf("Loads the authz file at FILE and validates its syntax.\n"
+ "Optionally reports the access available to USER for PATH in\n"
+ "repository REPOS_NAME.\n"
"Returns:\n"
" 0 when syntax is OK.\n"
" 1 when syntax is invalid.\n"
@@ -62,6 +64,31 @@ main(int argc, const char **argv)
/* Read the access file and validate it. */
err = svn_repos_authz_read(&authz, authz_file, TRUE, pool);
+ if (!err && (argc == 4 || argc == 5))
+ {
+ const char *user = argv[2], *path = argv[3];
+ const char *repos = argc == 5 ? argv[4] : "";
+ svn_boolean_t read_access, write_access;
+
+ if (path[0] != '/')
+ path = apr_pstrcat(pool, "/", path, NULL);
+
+ err = svn_repos_authz_check_access(authz, repos, path, user,
+ svn_authz_write, &write_access,
+ pool);
+ if (!write_access && !err)
+ err = svn_repos_authz_check_access(authz, repos, path, user,
+ svn_authz_read, &read_access,
+ pool);
+ if (!err)
+ printf("user '%s' has %s access to '%s'%s%s\n",
+ user,
+ write_access ? "rw" : read_access ? "r" : "no",
+ path,
+ repos[0] ? "in repository " : "",
+ repos);
+ }
+
svn_pool_destroy(pool);
if (err)