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(&current_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)