You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by da...@apache.org on 2010/12/12 17:43:45 UTC

svn commit: r1044847 [3/4] - in /subversion/branches/diff-optimizations-bytes: ./ build/ build/ac-macros/ build/generator/templates/ notes/ notes/api-errata/ notes/api-errata/1.7/ subversion/include/ subversion/include/private/ subversion/libsvn_client...

Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc-queries.sql?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc-queries.sql Sun Dec 12 16:43:42 2010
@@ -191,7 +191,8 @@ SELECT dav_cache FROM nodes
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0;
 
 -- STMT_SELECT_DELETION_INFO
-SELECT nodes_base.presence, nodes_work.presence, nodes_work.moved_to
+SELECT nodes_base.presence, nodes_work.presence, nodes_work.moved_to,
+       nodes_work.op_depth
 FROM nodes nodes_work
 LEFT OUTER JOIN nodes nodes_base ON nodes_base.wc_id = nodes_work.wc_id
   AND nodes_base.local_relpath = nodes_work.local_relpath
@@ -319,20 +320,15 @@ WHERE wc_id = ?1 AND local_relpath = ?2;
 DELETE FROM actual_node
 WHERE wc_id = ?1 AND local_relpath = ?2;
 
--- STMT_DELETE_ACTUAL_NODE_WITHOUT_CHANGELIST
-DELETE FROM actual_node
-WHERE wc_id = ?1 AND local_relpath = ?2
-      AND changelist IS NULL;
-
 -- STMT_DELETE_ACTUAL_NODE_WITHOUT_CONFLICT
 DELETE FROM actual_node
 WHERE wc_id = ?1 AND local_relpath = ?2
       AND tree_conflict_data IS NULL;
 
--- STMT_DELETE_NOT_PRESENT_NODES_RECURSIVE
+-- STMT_DELETE_CHILD_NODES_RECURSIVE
 DELETE FROM nodes
 WHERE wc_id = ?1 AND local_relpath LIKE ?2 ESCAPE '#' AND op_depth = ?3
-  AND presence = 'not-present';
+  AND presence = ?4
 
 -- STMT_CLEAR_ACTUAL_NODE_LEAVING_CHANGELIST
 UPDATE actual_node
@@ -386,10 +382,6 @@ WHERE wc_id = ?1 AND local_relpath = ?2 
 UPDATE nodes SET presence = ?3
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0;
 
--- STMT_UPDATE_NODE_BASE_PRESENCE_KIND
-UPDATE nodes SET presence = ?3, kind = ?4
-WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0;
-
 -- STMT_UPDATE_NODE_WORKING_PRESENCE
 UPDATE nodes SET presence = ?3
 WHERE wc_id = ?1 AND local_relpath = ?2
@@ -525,6 +517,19 @@ SELECT wc_id, local_relpath, ?3 AS op_de
 FROM nodes
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0;
 
+-- STMT_INSERT_WORKING_NODE_FROM_NODE
+INSERT OR REPLACE INTO nodes (
+    wc_id, local_relpath, op_depth, parent_relpath, presence, kind, checksum,
+    changed_revision, changed_date, changed_author, depth, symlink_target,
+    translated_size, last_mod_time, properties)
+SELECT wc_id, local_relpath, ?3 AS op_depth, parent_relpath, ?4 AS presence,
+       kind, checksum, changed_revision, changed_date, changed_author, depth,
+       symlink_target, translated_size, last_mod_time, properties
+FROM nodes
+WHERE wc_id = ?1 AND local_relpath = ?2
+ORDER BY op_depth DESC
+LIMIT 1;
+
 -- STMT_INSERT_WORKING_NODE_FROM_BASE_COPY
 INSERT INTO nodes (
     wc_id, local_relpath, op_depth, parent_relpath, repos_id, repos_path,
@@ -584,75 +589,6 @@ SELECT 1 FROM nodes WHERE wc_id = ?1 AND
   AND op_depth = (SELECT MAX(op_depth) FROM nodes
                   WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth > 0);
 
-
--- STMT_COPY_NODES_ROW
-INSERT OR REPLACE INTO nodes (
-    wc_id, local_relpath, op_depth, parent_relpath,
-    repos_id, repos_path, revision, presence, /* moved_here, moved_to, */
-    kind, properties, depth, checksum, symlink_target,
-    changed_revision, changed_date, changed_author,
-    translated_size, last_mod_time /* dav_cache, file_external */ )
-SELECT wc_id,
-    ?4 /*dst_relpath*/,
-    ?6 /*dst_op_depth*/,
-    ?5 /*dst_parent_*/,
-    repos_id, repos_path, revision, presence, /* moved_here, moved_to, */
-    kind, properties, depth, checksum, symlink_target,
-    changed_revision, changed_date, changed_author,
-    translated_size, last_mod_time /* dav_cache, file_external */
-FROM nodes
-WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3;
-
--- STMT_COPY_NODES_AT_SAME_OP_DEPTH
-INSERT OR REPLACE INTO nodes (
-    wc_id, local_relpath, op_depth, parent_relpath,
-    repos_id, repos_path, revision, presence, /* moved_here, moved_to, */
-    kind, properties, depth, checksum, symlink_target,
-    changed_revision, changed_date, changed_author,
-    translated_size, last_mod_time /* dav_cache, file_external */ )
-SELECT wc_id,
-    ?4 /*dst_relpath*/ || SUBSTR(local_relpath, ?6 /*LEN(src_relpath)+1*/),
-    ?5 /*dst_depth*/,
-    ?4 /*dst_relpath*/ || SUBSTR(parent_relpath, ?6 /*LEN(src_relpath)+1*/),
-    repos_id, repos_path, revision, presence, /* moved_here, moved_to, */
-    kind, properties, depth, checksum, symlink_target,
-    changed_revision, changed_date, changed_author,
-    translated_size, last_mod_time /* dav_cache, file_external */
-FROM nodes
-WHERE wc_id = ?1 AND local_relpath LIKE ?2 ESCAPE '#' AND op_depth = ?3;
-
--- STMT_COPY_NODES_AT_GREATER_OP_DEPTH
-INSERT OR REPLACE INTO nodes (
-    wc_id, local_relpath, op_depth, parent_relpath,
-    repos_id, repos_path, revision, presence, /* moved_here, moved_to, */
-    kind, properties, depth, checksum, symlink_target,
-    changed_revision, changed_date, changed_author,
-    translated_size, last_mod_time /* dav_cache, file_external */ )
-SELECT wc_id,
-    ?4 /*dst_relpath*/ || SUBSTR(local_relpath, ?6 /*LEN(src_relpath)+1*/),
-    op_depth + ?5 /*dst_depth*/ - ?3 /*src_depth*/,
-    ?4 /*dst_relpath*/ || SUBSTR(parent_relpath, ?6 /*LEN(src_relpath)+1*/),
-    repos_id, repos_path, revision, presence, /* moved_here, moved_to, */
-    kind, properties, depth, checksum, symlink_target,
-    changed_revision, changed_date, changed_author,
-    translated_size, last_mod_time /* dav_cache, file_external */
-FROM nodes
-WHERE wc_id = ?1 AND local_relpath LIKE ?2 ESCAPE '#' AND op_depth > ?3;
-
--- STMT_COPY_ACTUAL_NODE_ROWS
-INSERT OR REPLACE INTO actual_node (
-     wc_id, local_relpath, parent_relpath, properties,
-     conflict_old, conflict_new, conflict_working,
-     prop_reject, changelist, text_mod, tree_conflict_data )
-SELECT wc_id,
-     ?4 /*dst_relpath*/ || SUBSTR(local_relpath,  ?6 /*LEN(src_relpath)+1*/),
-     ?5 /*dst_parent_*/ || SUBSTR(parent_relpath, ?7 /*LEN(src_parent_)+1*/),
-     properties,
-     conflict_old, conflict_new, conflict_working,
-     prop_reject, changelist, text_mod, tree_conflict_data
-FROM actual_node
-WHERE wc_id = ?1 AND (local_relpath = ?2 OR local_relpath LIKE ?3 ESCAPE '#');
-
 -- STMT_SELECT_ABSENT_NODES
 SELECT local_relpath FROM nodes
 WHERE wc_id = ?1 AND (local_relpath = ?2 OR local_relpath LIKE ?3 ESCAPE '#')
@@ -789,6 +725,13 @@ WHERE nodes_work.local_relpath = ?1
   AND nodes_work.op_depth = (SELECT MAX(op_depth) FROM nodes
                              WHERE local_relpath = ?1 AND op_depth > 0);
 
+-- STMT_HAS_WORKING_NODES
+SELECT 1 FROM nodes WHERE op_depth > 0;
+
+-- STMT_UPDATE_CHECKSUM
+UPDATE nodes SET checksum = ?4
+WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3;
+
 
 /* ------------------------------------------------------------------------- */
 

Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc.h?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc.h (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc.h Sun Dec 12 16:43:42 2010
@@ -124,12 +124,25 @@ extern "C" {
  * The change from 19 to 20 introduces NODES and drops BASE_NODE and
  * WORKING_NODE, op_depth is always 0 or 2. 
  *
+ * The change from 20 to 21 moved tree conflict storage from the
+ * parent to the conflicted node.
+ *
+ * The change from 21 to 22 moved tree conflict storage from
+ * conflict_data column to the tree_conflict_data column.
+ *
+ * The change from 22 to 23 introduced multi-layer op_depth processing for
+ * NODES.
+ *
  * == 1.7.x shipped with format ???
  *
  * Please document any further format changes here.
  */
 
-#define SVN_WC__VERSION 22
+#define SVN_WC__VERSION 23
+
+#if SVN_WC__VERSION >= 23
+#define SVN_WC__OP_DEPTH
+#endif
 
 /* Formats <= this have no concept of "revert text-base/props".  */
 #define SVN_WC__NO_REVERT_FILES 4

Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc_db.c?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc_db.c Sun Dec 12 16:43:42 2010
@@ -299,7 +299,6 @@ scan_addition(svn_wc__db_status_t *statu
 
 static svn_error_t *
 scan_deletion(const char **base_del_relpath,
-              svn_boolean_t *base_replaced,
               const char **moved_to_relpath,
               const char **work_del_relpath,
               svn_wc__db_pdh_t *pdh,
@@ -2942,7 +2941,7 @@ get_info_for_copy(apr_int64_t *copyfrom_
     {
       const char *base_del_relpath, *work_del_relpath;
 
-      SVN_ERR(scan_deletion(&base_del_relpath, NULL, NULL, &work_del_relpath,
+      SVN_ERR(scan_deletion(&base_del_relpath, NULL, &work_del_relpath,
                             pdh, local_relpath, scratch_pool, scratch_pool));
       if (work_del_relpath)
         {
@@ -4436,31 +4435,42 @@ svn_wc__db_temp_op_set_dir_depth(svn_wc_
 
    ### Do we need to handle incomplete here? */
 static svn_error_t *
-delete_not_present_children(svn_wc__db_pdh_t *pdh,
-                            const char *local_relpath,
-                            apr_pool_t *scratch_pool)
+remove_children(svn_wc__db_pdh_t *pdh,
+                const char *local_relpath,
+                svn_wc__db_status_t status,
+                apr_int64_t op_depth,
+                apr_pool_t *scratch_pool)
 {
   svn_sqlite__stmt_t *stmt;
-#ifdef SVN_WC__OP_DEPTH
-  apr_int64_t op_depth = relpath_depth(local_relpath);
-#else
-  apr_int64_t op_depth = 2;  /* ### temporary op_depth */
-#endif
 
   SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
-                                    STMT_DELETE_NOT_PRESENT_NODES_RECURSIVE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "isi", pdh->wcroot->wc_id,
+                                    STMT_DELETE_CHILD_NODES_RECURSIVE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "isit", pdh->wcroot->wc_id,
                             construct_like_arg(local_relpath,
                                                scratch_pool),
-                            op_depth));
+                            op_depth, presence_map, status));
   SVN_ERR(svn_sqlite__step_done(stmt));
 
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+db_working_actual_remove(svn_wc__db_pdh_t *pdh,
+                         const char *local_relpath,
+                         apr_pool_t *scratch_pool);
+
+static svn_error_t *
+info_below_working(svn_boolean_t *have_base,
+                   svn_boolean_t *have_work,
+                   svn_wc__db_status_t *status,
+                   svn_wc__db_pdh_t *pdh,
+                   const char *local_relpath,
+                   apr_pool_t *scratch_pool);
+
 /* Update the working node for LOCAL_ABSPATH setting presence=STATUS */
 static svn_error_t *
-db_working_update_presence(svn_wc__db_status_t status,
+db_working_update_presence(apr_int64_t op_depth,
+                           svn_wc__db_status_t status,
                            svn_wc__db_pdh_t *pdh,
                            const char *local_relpath,
                            apr_pool_t *scratch_pool)
@@ -4475,11 +4485,55 @@ db_working_update_presence(svn_wc__db_st
 
   if (status == svn_wc__db_status_base_deleted)
     {
-      /* Switching to base-deleted is undoing an add/copy.  If this
-         was a copy then any children of the copy will now be
-         not-present and should be removed.  By this stage an add will
-         have no children. */
-      SVN_ERR(delete_not_present_children(pdh, local_relpath, scratch_pool));
+      /* Switching to base-deleted is undoing an add/copy.  By this
+         stage an add will have no children. */
+#ifdef SVN_WC__OP_DEPTH
+      const apr_array_header_t *children;
+      apr_pool_t *iterpool;
+      int i;
+
+      /* Children of the copy will be marked deleted in the layer
+         above. */
+      SVN_ERR(remove_children(pdh, local_relpath,
+                              svn_wc__db_status_base_deleted, op_depth + 1,
+                              scratch_pool));
+
+      /* Children of the copy that overlay a lower level become
+         base_deleted, otherwise they get removed. */
+      SVN_ERR(gather_repo_children(&children, pdh, local_relpath, op_depth,
+                                   scratch_pool, scratch_pool));
+      iterpool = svn_pool_create(scratch_pool);
+      for (i = 0; i < children->nelts; ++i)
+        {
+          const char *name = APR_ARRAY_IDX(children, i, const char *);
+          const char *child_relpath;
+          svn_boolean_t below_base, below_work;
+          svn_wc__db_status_t below_status;
+
+          svn_pool_clear(iterpool);
+
+          child_relpath = svn_relpath_join(local_relpath, name, iterpool);
+          SVN_ERR(info_below_working(&below_base, &below_work, &below_status,
+                                     pdh, child_relpath, iterpool));
+          if ((below_base || below_work)
+              && (below_status == svn_wc__db_status_normal
+                  || below_status == svn_wc__db_status_added
+                  || below_status == svn_wc__db_status_incomplete))
+            SVN_ERR(db_working_update_presence(op_depth,
+                                               svn_wc__db_status_base_deleted,
+                                               pdh, child_relpath, iterpool));
+          else
+            SVN_ERR(db_working_actual_remove(pdh, child_relpath, iterpool));
+        }
+      svn_pool_destroy(iterpool);
+#else
+      /* If this was a copy then any children of the copy will now be
+         not-present and should be removed. */
+      SVN_ERR(remove_children(pdh, local_relpath,
+                              svn_wc__db_status_not_present,
+                              2 /* ### temporary op_depth */,
+                              scratch_pool));
+#endif
 
       /* Reset the copyfrom in case this was a copy.
          ### What else should be reset? Properties? Or copy the node again? */
@@ -4535,7 +4589,19 @@ db_working_actual_remove(svn_wc__db_pdh_
   SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
   SVN_ERR(svn_sqlite__step_done(stmt));
 
-  SVN_ERR(delete_not_present_children(pdh, local_relpath, scratch_pool));
+#ifndef SVN_WC__OP_DEPTH
+  SVN_ERR(remove_children(pdh, local_relpath, svn_wc__db_status_not_present,
+                          2 /* ### temporary op_depth */, scratch_pool));
+#else
+  SVN_ERR(remove_children(pdh, local_relpath, svn_wc__db_status_base_deleted,
+                          op_depth + 1, scratch_pool));
+  SVN_ERR(remove_children(pdh, local_relpath, svn_wc__db_status_normal,
+                          op_depth, scratch_pool));
+  SVN_ERR(remove_children(pdh, local_relpath, svn_wc__db_status_not_present,
+                          op_depth, scratch_pool));
+  SVN_ERR(remove_children(pdh, local_relpath, svn_wc__db_status_incomplete,
+                          op_depth, scratch_pool));
+#endif
 
   /* Postcondition: There are no NODES rows in this subtree, at same or
    * greater op_depth. */
@@ -4586,8 +4652,13 @@ db_working_insert(svn_wc__db_status_t st
   apr_int64_t op_depth = 2; /* ### temporary op_depth */
 #endif
 
+#ifdef SVN_WC__OP_DEPTH
+  SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+                                    STMT_INSERT_WORKING_NODE_FROM_NODE));
+#else
   SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
                                     STMT_INSERT_WORKING_NODE_FROM_BASE));
+#endif
   SVN_ERR(svn_sqlite__bindf(stmt, "isit", pdh->wcroot->wc_id,
                             local_relpath, op_depth, presence_map, status));
   SVN_ERR(svn_sqlite__insert(NULL, stmt));
@@ -4795,7 +4866,10 @@ temp_op_delete_txn(void *baton, svn_sqli
 {
   struct temp_op_delete_baton *b = baton;
   svn_wc__db_status_t status, new_working_status;
-  svn_boolean_t have_work, new_have_work;
+  svn_boolean_t have_work, add_work = FALSE, del_work = FALSE, mod_work = FALSE;
+#ifndef SVN_WC__OP_DEPTH
+  svn_boolean_t new_have_work;
+#endif
 
   SVN_ERR(read_info(&status,
                     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -4805,8 +4879,10 @@ temp_op_delete_txn(void *baton, svn_sqli
                     b->pdh, b->local_relpath,
                     scratch_pool, scratch_pool));
 
+#ifndef SVN_WC__OP_DEPTH
   new_have_work = have_work;
   new_working_status = status;
+#endif
 
   if (!have_work)
     {
@@ -4814,13 +4890,17 @@ temp_op_delete_txn(void *baton, svn_sqli
       if (status == svn_wc__db_status_normal
           || status == svn_wc__db_status_incomplete)
         {
+#ifdef SVN_WC__OP_DEPTH
+          add_work = TRUE;
+#else
           new_have_work = TRUE;
           new_working_status = svn_wc__db_status_base_deleted;
+#endif
         }
     }
   else if (status == svn_wc__db_status_added)
     {
-      /* ADD/COPY-HERE/MOVE-HERE */
+      /* ADD/COPY-HERE/MOVE-HERE that could be a replace */
       svn_boolean_t add_or_root_of_copy;
 
       SVN_ERR(is_add_or_root_of_copy(&add_or_root_of_copy,
@@ -4833,24 +4913,51 @@ temp_op_delete_txn(void *baton, svn_sqli
           SVN_ERR(info_below_working(&below_base, &below_work, &below_status,
                                      b->pdh, b->local_relpath, scratch_pool));
 
+#ifdef SVN_WC__OP_DEPTH
+          if ((below_base || below_work)
+              && below_status != svn_wc__db_status_not_present)
+            mod_work = TRUE;
+          else
+            del_work = TRUE;
+#else
           if (below_base && below_status != svn_wc__db_status_not_present)
             new_working_status = svn_wc__db_status_base_deleted;
           else
             new_have_work = FALSE;
+#endif
         }
       else
-        new_working_status = svn_wc__db_status_not_present;
+        {
+#ifdef SVN_WC__OP_DEPTH
+          add_work = TRUE;
+#else
+          new_working_status = svn_wc__db_status_not_present;
+#endif
+        }
     }
   else if (status == svn_wc__db_status_incomplete)
     {
       svn_boolean_t add_or_root_of_copy;
       SVN_ERR(is_add_or_root_of_copy(&add_or_root_of_copy,
                                      b->pdh, b->local_relpath, scratch_pool));
+#ifdef SVN_WC__OP_DEPTH
+      if (add_or_root_of_copy)
+        del_work = TRUE;
+      else
+        add_work = TRUE;
+#else
       if (add_or_root_of_copy)
         new_have_work = FALSE;
+#endif
     }
 
-  if (!new_have_work && have_work)
+#ifndef SVN_WC__OP_DEPTH
+  del_work = !new_have_work && have_work;
+  add_work = new_have_work && !have_work;
+  mod_work = new_have_work && have_work && new_working_status != status;
+#endif
+
+  if (del_work)
     {
       SVN_ERR(db_working_actual_remove(b->pdh, b->local_relpath, scratch_pool));
 
@@ -4858,15 +4965,21 @@ temp_op_delete_txn(void *baton, svn_sqli
       SVN_ERR(svn_wc__db_temp_forget_directory(b->db, b->local_abspath,
                                                scratch_pool));
     }
-  else if (new_have_work && !have_work)
+  else if (add_work)
     {
+#ifdef SVN_WC__OP_DEPTH
+      new_working_status = svn_wc__db_status_base_deleted;
+#endif
       SVN_ERR(db_working_insert(new_working_status, b->pdh, b->local_relpath,
                                 scratch_pool));
     }
-  else if (new_have_work && have_work
-           && new_working_status != status)
+  else if (mod_work)
     {
-      SVN_ERR(db_working_update_presence(new_working_status, b->pdh,
+#ifdef SVN_WC__OP_DEPTH
+      new_working_status = svn_wc__db_status_base_deleted;
+#endif
+      SVN_ERR(db_working_update_presence(relpath_depth(b->local_relpath),
+                                         new_working_status, b->pdh,
                                          b->local_relpath, scratch_pool));
     }
   else
@@ -5803,7 +5916,7 @@ svn_wc__db_global_relocate(svn_wc__db_t 
       if (status == svn_wc__db_status_deleted)
         {
           const char *work_del_relpath;
-          SVN_ERR(scan_deletion(NULL, NULL, NULL, &work_del_relpath,
+          SVN_ERR(scan_deletion(NULL, NULL, &work_del_relpath,
                                 pdh, local_dir_relpath,
                                 scratch_pool, scratch_pool));
           if (work_del_relpath)
@@ -6866,7 +6979,8 @@ svn_wc__db_scan_addition(svn_wc__db_stat
   svn_wc__db_pdh_t *pdh;
   const char *local_relpath;
   const char *op_root_relpath;
-  apr_int64_t repos_id, original_repos_id;
+  apr_int64_t repos_id = INVALID_REPOS_ID;
+  apr_int64_t original_repos_id = INVALID_REPOS_ID;
   apr_int64_t *repos_id_p
     = (repos_root_url || repos_uuid) ? &repos_id : NULL;
   apr_int64_t *original_repos_id_p
@@ -6889,6 +7003,7 @@ svn_wc__db_scan_addition(svn_wc__db_stat
                                        result_pool);
   /* REPOS_ID must be valid if requested; ORIGINAL_REPOS_ID need not be. */
   SVN_ERR_ASSERT(repos_id_p == NULL || repos_id != INVALID_REPOS_ID);
+
   SVN_ERR(fetch_repos_info(repos_root_url, repos_uuid, pdh->wcroot->sdb,
                            repos_id, result_pool));
   SVN_ERR(fetch_repos_info(original_root_url, original_uuid,
@@ -6903,7 +7018,6 @@ svn_wc__db_scan_addition(svn_wc__db_stat
  * DB+LOCAL_ABSPATH, and outputting relpaths instead of abspaths. */
 static svn_error_t *
 scan_deletion(const char **base_del_relpath,
-              svn_boolean_t *base_replaced,
               const char **moved_to_relpath,
               const char **work_del_relpath,
               svn_wc__db_pdh_t *pdh,
@@ -6917,12 +7031,13 @@ scan_deletion(const char **base_del_relp
   svn_boolean_t child_has_base = FALSE;
   svn_boolean_t found_moved_to = FALSE;
   svn_wc__db_wcroot_t *wcroot = pdh->wcroot;
+#ifdef SVN_WC__OP_DEPTH
+  apr_int64_t local_op_depth, op_depth;
+#endif
 
   /* Initialize all the OUT parameters.  */
   if (base_del_relpath != NULL)
     *base_del_relpath = NULL;
-  if (base_replaced != NULL)
-    *base_replaced = FALSE;  /* becomes TRUE when we know for sure.  */
   if (moved_to_relpath != NULL)
     *moved_to_relpath = NULL;
   if (work_del_relpath != NULL)
@@ -6993,7 +7108,7 @@ scan_deletion(const char **base_del_relp
         }
 
       /* We need the presence of the WORKING node. Note that legal values
-         are: normal, not-present, base-deleted.  */
+         are: normal, not-present, base-deleted, incomplete.  */
       work_presence = svn_sqlite__column_token(stmt, 1, presence_map);
 
       /* The starting node should be deleted.  */
@@ -7006,6 +7121,8 @@ scan_deletion(const char **base_del_relp
                                  path_for_error_message(wcroot,
                                                         local_relpath,
                                                         scratch_pool));
+
+      /* ### incomplete not handled */
       SVN_ERR_ASSERT(work_presence == svn_wc__db_status_normal
                      || work_presence == svn_wc__db_status_not_present
                      || work_presence == svn_wc__db_status_base_deleted);
@@ -7043,16 +7160,6 @@ scan_deletion(const char **base_del_relp
           /* If a BASE node is marked as not-present, then we'll ignore
              it within this function. That status is simply a bookkeeping
              gimmick, not a real node that may have been deleted.  */
-
-          /* If we're looking at a present BASE node, *and* there is a
-             WORKING node (present or deleted), then a replacement has
-             occurred here or in an ancestor.  */
-          if (base_replaced != NULL
-              && base_presence == svn_wc__db_status_normal
-              && work_presence != svn_wc__db_status_base_deleted)
-            {
-              *base_replaced = TRUE;
-            }
         }
 
       /* Only grab the nearest ancestor.  */
@@ -7074,12 +7181,22 @@ scan_deletion(const char **base_del_relp
                                     svn_sqlite__column_text(stmt, 2, NULL));
         }
 
+#ifdef SVN_WC__OP_DEPTH
+      op_depth = svn_sqlite__column_int64(stmt, 3);
+      if (current_relpath == local_relpath)
+        local_op_depth = op_depth;
+
+      if (work_del_relpath && !work_del_relpath[0]
+          && ((op_depth < local_op_depth && op_depth > 0)
+              || child_presence == svn_wc__db_status_not_present))
+#else
       if (work_del_relpath != NULL
           && work_presence == svn_wc__db_status_normal
           && child_presence == svn_wc__db_status_not_present)
-        {
           /* Parent is normal, but child was deleted. Therefore, the child
              is the root of a WORKING subtree deletion.  */
+#endif
+        {
           *work_del_relpath = apr_pstrdup(result_pool, child_relpath);
         }
 
@@ -7105,7 +7222,6 @@ scan_deletion(const char **base_del_relp
 
 svn_error_t *
 svn_wc__db_scan_deletion(const char **base_del_abspath,
-                         svn_boolean_t *base_replaced,
                          const char **moved_to_abspath,
                          const char **work_del_abspath,
                          svn_wc__db_t *db,
@@ -7124,7 +7240,7 @@ svn_wc__db_scan_deletion(const char **ba
                               scratch_pool, scratch_pool));
   VERIFY_USABLE_PDH(pdh);
 
-  SVN_ERR(scan_deletion(&base_del_relpath, base_replaced, &moved_to_relpath,
+  SVN_ERR(scan_deletion(&base_del_relpath, &moved_to_relpath,
                         &work_del_relpath,
                         pdh, local_relpath, result_pool, scratch_pool));
 

Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc_db.h?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc_db.h Sun Dec 12 16:43:42 2010
@@ -1943,8 +1943,7 @@ svn_wc__db_scan_addition(svn_wc__db_stat
    the deleted node.
 
    In this example, BASE_DEL_ABSPATH will bet set to B/W. That is the root of
-   the BASE tree (implicitly) deleted by the replacement. BASE_REPLACED will
-   be set to TRUE since B/W replaces the BASE node at B/W. WORK_DEL_ABSPATH
+   the BASE tree (implicitly) deleted by the replacement. WORK_DEL_ABSPATH
    will be set to the subtree deleted within the replacement; in this case,
    B/W/D. No move-away took place, so MOVED_TO_ABSPATH is set to NULL.
 
@@ -1954,14 +1953,12 @@ svn_wc__db_scan_addition(svn_wc__db_stat
    post-move, but that is not known or reported by this function.
 
    If BASE does not have a B/W, then the WORKING B/W is not a replacement,
-   but a simple add/copy/move-here. BASE_DEL_ABSPATH will be set to NULL,
-   and BASE_REPLACED will be set to FALSE.
+   but a simple add/copy/move-here. BASE_DEL_ABSPATH will be set to NULL.
 
    If B/W/D does not exist in the WORKING tree (we're only talking about a
    deletion of nodes of the BASE tree), then deleting B/W/D would have marked
    the subtree for deletion. BASE_DEL_ABSPATH will refer to B/W/D,
-   BASE_REPLACED will be FALSE, MOVED_TO_ABSPATH will be NULL, and
-   WORK_DEL_ABSPATH will be NULL.
+   MOVED_TO_ABSPATH will be NULL, and WORK_DEL_ABSPATH will be NULL.
 
    If the BASE node B/W/D was moved instead of deleted, then MOVED_TO_ABSPATH
    would indicate the target location (and other OUT values as above).
@@ -2009,11 +2006,6 @@ svn_wc__db_scan_addition(svn_wc__db_stat
    BASE_DEL_ABSPATH will specify the nearest ancestor of the explicit or
    implicit deletion (if any) that applies to the BASE tree.
 
-   BASE_REPLACED will specify whether the node at BASE_DEL_ABSPATH has
-   been replaced (shadowed) by nodes in the WORKING tree. If no BASE
-   deletion has occurred (BASE_DEL_ABSPATH is NULL, meaning the deletion
-   is confined to the WORKING TREE), then BASE_REPLACED will be FALSE.
-
    MOVED_TO_ABSPATH will specify the nearest ancestor that has moved-away,
    if any. If no ancestors have been moved-away, then this is set to NULL.
 
@@ -2033,7 +2025,6 @@ svn_wc__db_scan_addition(svn_wc__db_stat
 */
 svn_error_t *
 svn_wc__db_scan_deletion(const char **base_del_abspath,
-                         svn_boolean_t *base_replaced,
                          const char **moved_to_abspath,
                          const char **work_del_abspath,
                          svn_wc__db_t *db,

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/blame-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/blame-cmd.c?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/blame-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/blame-cmd.c Sun Dec 12 16:43:42 2010
@@ -203,11 +203,11 @@ blame_receiver(void *baton,
          we may need to adjust this. */
       if (merged_revision < revision)
         {
-          svn_stream_printf(out, pool, "G ");
+          SVN_ERR(svn_stream_printf(out, pool, "G "));
           use_merged = TRUE;
         }
       else
-        svn_stream_printf(out, pool, "  ");
+        SVN_ERR(svn_stream_printf(out, pool, "  "));
     }
 
   if (use_merged)

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/cl.h?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/cl.h (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/cl.h Sun Dec 12 16:43:42 2010
@@ -817,6 +817,11 @@ svn_cl__opt_parse_path(svn_opt_revision_
                        const char *path,
                        apr_pool_t *pool);
 
+/* Return an error if TARGETS contains a mixture of URLs and paths; otherwise
+ * return SVN_NO_ERROR. */
+svn_error_t *
+svn_cl__assert_homogeneous_target_type(const apr_array_header_t *targets);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/copy-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/copy-cmd.c?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/copy-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/copy-cmd.c Sun Dec 12 16:43:42 2010
@@ -78,8 +78,10 @@ svn_cl__copy(apr_getopt_t *os,
 
   SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, pool));
 
-  /* Figure out which type of trace editor to use.
-     If the src_paths are not homogeneous, setup_copy will return an error. */
+  /* Figure out which type of notification to use.
+     (There is no need to check that the src paths are homogeneous;
+     svn_client_copy6() through its subroutine try_copy() will return an
+     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 *);

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/delete-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/delete-cmd.c?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/delete-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/delete-cmd.c Sun Dec 12 16:43:42 2010
@@ -48,7 +48,6 @@ svn_cl__delete(apr_getopt_t *os,
   apr_array_header_t *targets;
   svn_error_t *err;
   svn_boolean_t is_url;
-  int i;
 
   SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                       opt_state->targets,
@@ -57,17 +56,8 @@ svn_cl__delete(apr_getopt_t *os,
   if (! targets->nelts)
     return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
 
-  /* Check that all targets are of the same type. */
+  SVN_ERR(svn_cl__assert_homogeneous_target_type(targets));
   is_url = svn_path_is_url(APR_ARRAY_IDX(targets, 0, const char *));
-  for (i = 1; i < targets->nelts; i++)
-    {
-      const char *target = APR_ARRAY_IDX(targets, i, const char *);
-      if (is_url != svn_path_is_url(target))
-        return svn_error_return(
-                 svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-                                  _("Cannot mix repository and working copy "
-                                    "targets")));
-    }
 
   if (! is_url)
     {

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/diff-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/diff-cmd.c?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/diff-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/diff-cmd.c Sun Dec 12 16:43:42 2010
@@ -260,7 +260,7 @@ svn_cl__diff(apr_getopt_t *os,
     }
   else
     {
-      svn_boolean_t working_copy_present = FALSE, url_present = FALSE;
+      svn_boolean_t working_copy_present;
 
       /* The 'svn diff [-r N[:M]] [TARGET[@REV]...]' case matches. */
 
@@ -272,25 +272,14 @@ svn_cl__diff(apr_getopt_t *os,
       old_target = "";
       new_target = "";
 
-      /* Check to see if at least one of our paths is a working copy
-         path. */
-      for (i = 0; i < targets->nelts; ++i)
-        {
-          const char *path = APR_ARRAY_IDX(targets, i, const char *);
-          if (! svn_path_is_url(path))
-            working_copy_present = TRUE;
-          else
-            url_present = TRUE;
-        }
+      SVN_ERR(svn_cl__assert_homogeneous_target_type(targets));
 
-      if (url_present && working_copy_present)
-        return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-                                  _("Cannot mix repository and working copy "
-                                    "targets"));
+      working_copy_present = ! svn_path_is_url(APR_ARRAY_IDX(targets, 0,
+                                                             const char *));
 
       if (opt_state->start_revision.kind == svn_opt_revision_unspecified
           && working_copy_present)
-          opt_state->start_revision.kind = svn_opt_revision_base;
+        opt_state->start_revision.kind = svn_opt_revision_base;
       if (opt_state->end_revision.kind == svn_opt_revision_unspecified)
         opt_state->end_revision.kind = working_copy_present
           ? svn_opt_revision_working : svn_opt_revision_head;

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/info-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/info-cmd.c?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/info-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/info-cmd.c Sun Dec 12 16:43:42 2010
@@ -462,25 +462,19 @@ print_info(void *baton,
         svn_cl__node_description(info->tree_conflict->src_right_version,
                                  info->repos_root_URL, pool);
 
-      svn_cmdline_printf(pool,
-                         "%s: %s\n",
-                         _("Tree conflict"),
-                         desc);
+      SVN_ERR(svn_cmdline_printf(pool, "%s: %s\n", _("Tree conflict"), desc));
 
       if (src_left_version)
-        svn_cmdline_printf(pool,
-                           "  %s: %s\n",
-                           _("Source  left"), /* (1) */
-                           src_left_version);
+        SVN_ERR(svn_cmdline_printf(pool, "  %s: %s\n",
+                                   _("Source  left"), /* (1) */
+                                   src_left_version));
         /* (1): Sneaking in a space in "Source  left" so that it is the
          * same length as "Source right" while it still starts in the same
          * column. That's just a tiny tweak in the English `svn'. */
 
       if (src_right_version)
-        svn_cmdline_printf(pool,
-                           "  %s: %s\n",
-                           _("Source right"),
-                           src_right_version);
+        SVN_ERR(svn_cmdline_printf(pool, "  %s: %s\n", _("Source right"),
+                                   src_right_version));
     }
 
   /* Print extra newline separator. */

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/lock-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/lock-cmd.c?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/lock-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/lock-cmd.c Sun Dec 12 16:43:42 2010
@@ -89,8 +89,6 @@ svn_cl__lock(apr_getopt_t *os,
   svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
   apr_array_header_t *targets;
   const char *comment;
-  svn_boolean_t wc_present = FALSE, url_present = FALSE;
-  int i;
 
   SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                       opt_state->targets,
@@ -100,21 +98,7 @@ svn_cl__lock(apr_getopt_t *os,
   if (! targets->nelts)
     return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
 
-  /* Check to see if at least one of our paths is a working copy
-   * path or a repository url. */
-  for (i = 0; i < targets->nelts; ++i)
-    {
-      const char *target = APR_ARRAY_IDX(targets, i, const char *);
-      if (! svn_path_is_url(target))
-       wc_present = TRUE;
-      else
-       url_present = TRUE;
-    }
-
-  if (url_present && wc_present)
-    return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-                        _("Cannot mix repository and working copy "
-                          "targets"));
+  SVN_ERR(svn_cl__assert_homogeneous_target_type(targets));
 
   /* Get comment. */
   SVN_ERR(get_comment(&comment, ctx, opt_state, pool));

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/mergeinfo-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/mergeinfo-cmd.c?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/mergeinfo-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/mergeinfo-cmd.c Sun Dec 12 16:43:42 2010
@@ -48,9 +48,9 @@ print_log_rev(void *baton,
               apr_pool_t *pool)
 {
   if (log_entry->non_inheritable)
-    svn_cmdline_printf(pool, "r%ld*\n", log_entry->revision);
+    SVN_ERR(svn_cmdline_printf(pool, "r%ld*\n", log_entry->revision));
   else
-    svn_cmdline_printf(pool, "r%ld\n", log_entry->revision);
+    SVN_ERR(svn_cmdline_printf(pool, "r%ld\n", log_entry->revision));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/mkdir-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/mkdir-cmd.c?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/mkdir-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/mkdir-cmd.c Sun Dec 12 16:43:42 2010
@@ -56,6 +56,8 @@ svn_cl__mkdir(apr_getopt_t *os,
   if (! targets->nelts)
     return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
 
+  SVN_ERR(svn_cl__assert_homogeneous_target_type(targets));
+
   if (! svn_path_is_url(APR_ARRAY_IDX(targets, 0, const char *)))
     {
       ctx->log_msg_func3 = NULL;

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/propget-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/propget-cmd.c?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/propget-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/propget-cmd.c Sun Dec 12 16:43:42 2010
@@ -155,7 +155,7 @@ print_properties(svn_stream_t *out,
           apr_hash_t *hash = apr_hash_make(iterpool);
 
           apr_hash_set(hash, pname_utf8, APR_HASH_KEY_STRING, propval);
-          svn_cl__print_prop_hash(out, hash, FALSE, iterpool);
+          SVN_ERR(svn_cl__print_prop_hash(out, hash, FALSE, iterpool));
         }
       else
         {

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/status.c?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/status.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/status.c Sun Dec 12 16:43:42 2010
@@ -167,8 +167,10 @@ print_status(const char *path,
           old_tree_conflict = svn_wc__cd2_to_cd(tree_conflict, pool);
 
           tree_status_code = 'C';
-          svn_cl__get_human_readable_tree_conflict_description(
-            &desc, old_tree_conflict, pool);
+          SVN_ERR(svn_cl__get_human_readable_tree_conflict_description(
+                            &desc,
+                            old_tree_conflict,
+                            pool));
           tree_desc_line = apr_psprintf(pool, "\n      >   %s", desc);
           (*tree_conflicts)++;
         }

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/unlock-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/unlock-cmd.c?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/unlock-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/unlock-cmd.c Sun Dec 12 16:43:42 2010
@@ -49,8 +49,6 @@ svn_cl__unlock(apr_getopt_t *os,
   svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
   svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
   apr_array_header_t *targets;
-  svn_boolean_t wc_present = FALSE, url_present = FALSE;
-  int i;
 
   SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                       opt_state->targets,
@@ -62,22 +60,7 @@ svn_cl__unlock(apr_getopt_t *os,
 
   SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, scratch_pool));
 
-  /* Check to see if at least one of our paths is a working copy
-   * path or a repository url. */
-  for (i = 0; i < targets->nelts; ++i)
-    {
-      const char *target = APR_ARRAY_IDX(targets, i, const char *);
-
-      if (! svn_path_is_url(target))
-        wc_present = TRUE;
-      else
-        url_present = TRUE;
-    }
-
-  if (url_present && wc_present)
-    return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-                             _("Cannot mix repository and working copy "
-                               "targets"));
+  SVN_ERR(svn_cl__assert_homogeneous_target_type(targets));
 
   return svn_error_return(
     svn_client_unlock(targets, opt_state->force, ctx, scratch_pool));

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/update-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/update-cmd.c?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/update-cmd.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/update-cmd.c Sun Dec 12 16:43:42 2010
@@ -110,6 +110,7 @@ svn_cl__update(apr_getopt_t *os,
   svn_boolean_t depth_is_sticky;
   struct svn_cl__check_externals_failed_notify_baton nwb;
   apr_array_header_t *result_revs;
+  int i;
 
   SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                       opt_state->targets,
@@ -120,29 +121,15 @@ svn_cl__update(apr_getopt_t *os,
 
   SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, scratch_pool));
 
-  /* If any targets are URLs, notify that we're skipping them and remove
-     them from TARGETS.  Although svn_client_update4() would skip them
-     anyway, we don't want to pass invalid targets to it, and especially
-     not to print_update_summary(). */
-  {
-    apr_array_header_t *new_targets
-      = apr_array_make(scratch_pool, targets->nelts, sizeof(const char *));
-    int i;
-
-    for (i = 0; i < targets->nelts; i++)
-      {
-        const char *target = APR_ARRAY_IDX(targets, i, const char *);
-
-        if (svn_path_is_url(target))
-          ctx->notify_func2(ctx->notify_baton2,
-                            svn_wc_create_notify_url(
-                              target, svn_wc_notify_skip, scratch_pool),
-                            scratch_pool);
-        else
-          APR_ARRAY_PUSH(new_targets, const char *) = target;
-      }
-    targets = new_targets;
-  }
+  /* If any targets are URLs, display error message and exit. */
+  for (i = 0; i < targets->nelts; i++)
+    {
+      const char *target = APR_ARRAY_IDX(targets, i, const char *);
+
+      if (svn_path_is_url(target))
+        return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                 _("'%s' is not a local path"), target);
+    }
 
   /* If using changelists, convert targets into a set of paths that
      match the specified changelist(s). */

Modified: subversion/branches/diff-optimizations-bytes/subversion/svn/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svn/util.c?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svn/util.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svn/util.c Sun Dec 12 16:43:42 2010
@@ -61,6 +61,7 @@
 
 #include "private/svn_token.h"
 #include "private/svn_opt_private.h"
+#include "private/svn_client_private.h"
 
 
 
@@ -1345,3 +1346,16 @@ svn_cl__opt_parse_path(svn_opt_revision_
 
   return SVN_NO_ERROR;
 }
+
+svn_error_t *
+svn_cl__assert_homogeneous_target_type(const apr_array_header_t *targets)
+{
+  svn_error_t *err;
+
+  err = svn_client__assert_homogeneous_target_type(targets);
+  if (err && err->apr_err == SVN_ERR_ILLEGAL_TARGET)
+    return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, err,
+                             _("Cannot mix repository and working copy "
+                               "targets"));
+  return err;
+}

Modified: subversion/branches/diff-optimizations-bytes/subversion/svnadmin/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svnadmin/main.c?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svnadmin/main.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svnadmin/main.c Sun Dec 12 16:43:42 2010
@@ -1594,7 +1594,7 @@ main(int argc, const char *argv[])
 
   if (argc <= 1)
     {
-      subcommand_help(NULL, NULL, pool);
+      SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
       svn_pool_destroy(pool);
       return EXIT_FAILURE;
     }
@@ -1621,7 +1621,7 @@ main(int argc, const char *argv[])
         break;
       else if (apr_err)
         {
-          subcommand_help(NULL, NULL, pool);
+          SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
           svn_pool_destroy(pool);
           return EXIT_FAILURE;
         }
@@ -1734,7 +1734,7 @@ main(int argc, const char *argv[])
         break;
       default:
         {
-          subcommand_help(NULL, NULL, pool);
+          SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
           svn_pool_destroy(pool);
           return EXIT_FAILURE;
         }
@@ -1768,7 +1768,7 @@ main(int argc, const char *argv[])
             {
               svn_error_clear(svn_cmdline_fprintf(stderr, pool,
                                         _("subcommand argument required\n")));
-              subcommand_help(NULL, NULL, pool);
+              SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
               svn_pool_destroy(pool);
               return EXIT_FAILURE;
             }
@@ -1786,7 +1786,7 @@ main(int argc, const char *argv[])
               svn_error_clear(svn_cmdline_fprintf(stderr, pool,
                                                   _("Unknown command: '%s'\n"),
                                                   first_arg_utf8));
-              subcommand_help(NULL, NULL, pool);
+              SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
               svn_pool_destroy(pool);
               return EXIT_FAILURE;
             }
@@ -1837,7 +1837,7 @@ main(int argc, const char *argv[])
                                           pool);
           svn_opt_format_option(&optstr, badopt, FALSE, pool);
           if (subcommand->name[0] == '-')
-            subcommand_help(NULL, NULL, pool);
+            SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
           else
             svn_error_clear(svn_cmdline_fprintf(stderr, pool
                             , _("Subcommand '%s' doesn't accept option '%s'\n"

Modified: subversion/branches/diff-optimizations-bytes/subversion/svndumpfilter/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svndumpfilter/main.c?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svndumpfilter/main.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svndumpfilter/main.c Sun Dec 12 16:43:42 2010
@@ -1294,7 +1294,7 @@ main(int argc, const char *argv[])
 
   if (argc <= 1)
     {
-      subcommand_help(NULL, NULL, pool);
+      SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
       svn_pool_destroy(pool);
       return EXIT_FAILURE;
     }
@@ -1320,7 +1320,7 @@ main(int argc, const char *argv[])
         break;
       else if (apr_err)
         {
-          subcommand_help(NULL, NULL, pool);
+          SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
           svn_pool_destroy(pool);
           return EXIT_FAILURE;
         }
@@ -1359,7 +1359,7 @@ main(int argc, const char *argv[])
           break;
         default:
           {
-            subcommand_help(NULL, NULL, pool);
+            SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
             svn_pool_destroy(pool);
             return EXIT_FAILURE;
           }
@@ -1394,7 +1394,7 @@ main(int argc, const char *argv[])
               svn_error_clear(svn_cmdline_fprintf
                               (stderr, pool,
                                _("Subcommand argument required\n")));
-              subcommand_help(NULL, NULL, pool);
+              SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
               svn_pool_destroy(pool);
               return EXIT_FAILURE;
             }
@@ -1414,7 +1414,7 @@ main(int argc, const char *argv[])
               svn_error_clear(svn_cmdline_fprintf(stderr, pool,
                                                   _("Unknown command: '%s'\n"),
                                                   first_arg_utf8));
-              subcommand_help(NULL, NULL, pool);
+              SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
               svn_pool_destroy(pool);
               return EXIT_FAILURE;
             }
@@ -1496,7 +1496,7 @@ main(int argc, const char *argv[])
                                           pool);
           svn_opt_format_option(&optstr, badopt, FALSE, pool);
           if (subcommand->name[0] == '-')
-            subcommand_help(NULL, NULL, pool);
+            SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
           else
             svn_error_clear(svn_cmdline_fprintf
                             (stderr, pool,

Modified: subversion/branches/diff-optimizations-bytes/subversion/svnlook/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svnlook/main.c?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svnlook/main.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svnlook/main.c Sun Dec 12 16:43:42 2010
@@ -1841,6 +1841,24 @@ warning_func(void *baton,
 }
 
 
+/* Return an error if the number of arguments (excluding the repository
+ * argument) is not NUM_ARGS.  NUM_ARGS must be 0 or 1.  The arguments
+ * are assumed to be found in OPT_STATE->arg1 and OPT_STATE->arg2. */
+static svn_error_t *
+check_number_of_args(struct svnlook_opt_state *opt_state,
+                     int num_args)
+{
+  if ((num_args == 0 && opt_state->arg1 != NULL)
+      || (num_args == 1 && opt_state->arg2 != NULL))
+    return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                            _("Too many arguments given"));
+  if ((num_args == 1 && opt_state->arg1 == NULL))
+    return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, NULL,
+                            _("Missing repository path argument"));
+  return SVN_NO_ERROR;
+}
+
+
 /* Factory function for the context baton. */
 static svn_error_t *
 get_ctxt_baton(svnlook_ctxt_t **baton_p,
@@ -1887,6 +1905,8 @@ subcommand_author(apr_getopt_t *os, void
   struct svnlook_opt_state *opt_state = baton;
   svnlook_ctxt_t *c;
 
+  SVN_ERR(check_number_of_args(opt_state, 0));
+
   SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
   SVN_ERR(do_author(c, pool));
   return SVN_NO_ERROR;
@@ -1899,10 +1919,7 @@ subcommand_cat(apr_getopt_t *os, void *b
   struct svnlook_opt_state *opt_state = baton;
   svnlook_ctxt_t *c;
 
-  if (opt_state->arg1 == NULL)
-    return svn_error_createf
-      (SVN_ERR_CL_INSUFFICIENT_ARGS, NULL,
-       _("Missing repository path argument"));
+  SVN_ERR(check_number_of_args(opt_state, 1));
 
   SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
   SVN_ERR(do_cat(c, opt_state->arg1, pool));
@@ -1916,6 +1933,8 @@ subcommand_changed(apr_getopt_t *os, voi
   struct svnlook_opt_state *opt_state = baton;
   svnlook_ctxt_t *c;
 
+  SVN_ERR(check_number_of_args(opt_state, 0));
+
   SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
   SVN_ERR(do_changed(c, pool));
   return SVN_NO_ERROR;
@@ -1928,6 +1947,8 @@ subcommand_date(apr_getopt_t *os, void *
   struct svnlook_opt_state *opt_state = baton;
   svnlook_ctxt_t *c;
 
+  SVN_ERR(check_number_of_args(opt_state, 0));
+
   SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
   SVN_ERR(do_date(c, pool));
   return SVN_NO_ERROR;
@@ -1940,6 +1961,8 @@ subcommand_diff(apr_getopt_t *os, void *
   struct svnlook_opt_state *opt_state = baton;
   svnlook_ctxt_t *c;
 
+  SVN_ERR(check_number_of_args(opt_state, 0));
+
   SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
   SVN_ERR(do_diff(c, pool));
   return SVN_NO_ERROR;
@@ -1952,6 +1975,8 @@ subcommand_dirschanged(apr_getopt_t *os,
   struct svnlook_opt_state *opt_state = baton;
   svnlook_ctxt_t *c;
 
+  SVN_ERR(check_number_of_args(opt_state, 0));
+
   SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
   SVN_ERR(do_dirs_changed(c, pool));
   return SVN_NO_ERROR;
@@ -1964,10 +1989,7 @@ subcommand_filesize(apr_getopt_t *os, vo
   struct svnlook_opt_state *opt_state = baton;
   svnlook_ctxt_t *c;
 
-  if (opt_state->arg1 == NULL)
-    return svn_error_createf
-      (SVN_ERR_CL_INSUFFICIENT_ARGS, NULL,
-       _("Missing repository path argument"));
+  SVN_ERR(check_number_of_args(opt_state, 1));
 
   SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
   SVN_ERR(do_filesize(c, opt_state->arg1, pool));
@@ -2012,10 +2034,11 @@ subcommand_history(apr_getopt_t *os, voi
 {
   struct svnlook_opt_state *opt_state = baton;
   svnlook_ctxt_t *c;
-  const char *path = "/";
+  const char *path = (opt_state->arg1 ? opt_state->arg1 : "/");
 
-  if (opt_state->arg1)
-    path = opt_state->arg1;
+  if (opt_state->arg2 != NULL)
+    return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                            _("Too many arguments given"));
 
   SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
   SVN_ERR(do_history(c, path, pool));
@@ -2029,18 +2052,13 @@ subcommand_lock(apr_getopt_t *os, void *
 {
   struct svnlook_opt_state *opt_state = baton;
   svnlook_ctxt_t *c;
-  const char *path;
   svn_lock_t *lock;
 
-  if (opt_state->arg1)
-    path = opt_state->arg1;
-  else
-    return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, NULL,
-                            _("Missing path argument"));
+  SVN_ERR(check_number_of_args(opt_state, 1));
 
   SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
 
-  SVN_ERR(svn_fs_get_lock(&lock, c->fs, path, pool));
+  SVN_ERR(svn_fs_get_lock(&lock, c->fs, opt_state->arg1, pool));
 
   if (lock)
     {
@@ -2078,6 +2096,8 @@ subcommand_info(apr_getopt_t *os, void *
   struct svnlook_opt_state *opt_state = baton;
   svnlook_ctxt_t *c;
 
+  SVN_ERR(check_number_of_args(opt_state, 0));
+
   SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
   SVN_ERR(do_author(c, pool));
   SVN_ERR(do_date(c, pool));
@@ -2092,6 +2112,8 @@ subcommand_log(apr_getopt_t *os, void *b
   struct svnlook_opt_state *opt_state = baton;
   svnlook_ctxt_t *c;
 
+  SVN_ERR(check_number_of_args(opt_state, 0));
+
   SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
   SVN_ERR(do_log(c, FALSE, pool));
   return SVN_NO_ERROR;
@@ -2117,6 +2139,10 @@ subcommand_pget(apr_getopt_t *os, void *
         (SVN_ERR_CL_INSUFFICIENT_ARGS, NULL,
          _("Missing propname or repository path argument"));
     }
+  if ((opt_state->revprop && opt_state->arg2 != NULL)
+      || os->ind < os->argc)
+    return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                            _("Too many arguments given"));
 
   SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
   SVN_ERR(do_pget(c, opt_state->arg1,
@@ -2131,10 +2157,7 @@ subcommand_plist(apr_getopt_t *os, void 
   struct svnlook_opt_state *opt_state = baton;
   svnlook_ctxt_t *c;
 
-  if (!opt_state->revprop && opt_state->arg1 == NULL)
-    return svn_error_create
-      (SVN_ERR_CL_INSUFFICIENT_ARGS, NULL,
-       _("Missing repository path argument"));
+  SVN_ERR(check_number_of_args(opt_state, opt_state->revprop ? 0 : 1));
 
   SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
   SVN_ERR(do_plist(c, opt_state->revprop ? NULL : opt_state->arg1,
@@ -2149,6 +2172,10 @@ subcommand_tree(apr_getopt_t *os, void *
   struct svnlook_opt_state *opt_state = baton;
   svnlook_ctxt_t *c;
 
+  if (opt_state->arg2 != NULL)
+    return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                            _("Too many arguments given"));
+
   SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
   SVN_ERR(do_tree(c, opt_state->arg1 ? opt_state->arg1 : "",
                   opt_state->show_ids, opt_state->full_paths,
@@ -2163,6 +2190,8 @@ subcommand_youngest(apr_getopt_t *os, vo
   struct svnlook_opt_state *opt_state = baton;
   svnlook_ctxt_t *c;
 
+  SVN_ERR(check_number_of_args(opt_state, 0));
+
   SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
   SVN_ERR(svn_cmdline_printf(pool, "%ld\n", c->rev_id));
   return SVN_NO_ERROR;
@@ -2176,6 +2205,8 @@ subcommand_uuid(apr_getopt_t *os, void *
   svnlook_ctxt_t *c;
   const char *uuid;
 
+  SVN_ERR(check_number_of_args(opt_state, 0));
+
   SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
   SVN_ERR(svn_fs_get_uuid(c->fs, &uuid, pool));
   SVN_ERR(svn_cmdline_printf(pool, "%s\n", uuid));
@@ -2230,7 +2261,7 @@ main(int argc, const char *argv[])
 
   if (argc <= 1)
     {
-      subcommand_help(NULL, NULL, pool);
+      SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
       svn_pool_destroy(pool);
       return EXIT_FAILURE;
     }
@@ -2255,7 +2286,7 @@ main(int argc, const char *argv[])
         break;
       else if (apr_err)
         {
-          subcommand_help(NULL, NULL, pool);
+          SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
           svn_pool_destroy(pool);
           return EXIT_FAILURE;
         }
@@ -2355,7 +2386,7 @@ main(int argc, const char *argv[])
           break;
 
         default:
-          subcommand_help(NULL, NULL, pool);
+          SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
           svn_pool_destroy(pool);
           return EXIT_FAILURE;
 
@@ -2397,7 +2428,7 @@ main(int argc, const char *argv[])
               svn_error_clear
                 (svn_cmdline_fprintf(stderr, pool,
                                      _("Subcommand argument required\n")));
-              subcommand_help(NULL, NULL, pool);
+              SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
               svn_pool_destroy(pool);
               return EXIT_FAILURE;
             }
@@ -2417,7 +2448,7 @@ main(int argc, const char *argv[])
                 (svn_cmdline_fprintf(stderr, pool,
                                      _("Unknown command: '%s'\n"),
                                      first_arg_utf8));
-              subcommand_help(NULL, NULL, pool);
+              SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
               svn_pool_destroy(pool);
               return EXIT_FAILURE;
             }
@@ -2449,7 +2480,7 @@ main(int argc, const char *argv[])
           svn_error_clear
             (svn_cmdline_fprintf(stderr, pool,
                                  _("Repository argument required\n")));
-          subcommand_help(NULL, NULL, pool);
+          SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
           svn_pool_destroy(pool);
           return EXIT_FAILURE;
         }
@@ -2504,7 +2535,7 @@ main(int argc, const char *argv[])
                                           pool);
           svn_opt_format_option(&optstr, badopt, FALSE, pool);
           if (subcommand->name[0] == '-')
-            subcommand_help(NULL, NULL, pool);
+            SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
           else
             svn_error_clear
               (svn_cmdline_fprintf

Modified: subversion/branches/diff-optimizations-bytes/subversion/svnrdump/dump_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svnrdump/dump_editor.c?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svnrdump/dump_editor.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svnrdump/dump_editor.c Sun Dec 12 16:43:42 2010
@@ -207,8 +207,8 @@ dump_props(struct dump_edit_baton *eb,
       SVN_ERR(svn_stream_printf(eb->stream, pool, "\n\n"));
 
       /* Cleanup so that data is never dumped twice. */
-      svn_hash__clear(eb->props, eb->pool);
-      svn_hash__clear(eb->deleted_props, eb->pool);
+      SVN_ERR(svn_hash__clear(eb->props, eb->pool));
+      SVN_ERR(svn_hash__clear(eb->deleted_props, eb->pool));
       if (trigger_var)
         *trigger_var = FALSE;
     }
@@ -525,7 +525,7 @@ close_directory(void *dir_baton,
                         FALSE, NULL, SVN_INVALID_REVNUM, pool));
     }
 
-  svn_hash__clear(db->deleted_entries, pool);
+  SVN_ERR(svn_hash__clear(db->deleted_entries, pool));
   return SVN_NO_ERROR;
 }
 
@@ -725,7 +725,7 @@ apply_textdelta(void *file_baton, const 
 
   eb->dump_text = TRUE;
   eb->base_checksum = apr_pstrdup(eb->pool, base_checksum);
-  svn_stream_close(delta_filestream);
+  SVN_ERR(svn_stream_close(delta_filestream));
 
   /* The actual writing takes place when this function has
      finished. Set handler and handler_baton now so for
@@ -806,8 +806,8 @@ close_file(void *file_baton,
 
       /* Cleanup */
       eb->dump_props = FALSE;
-      svn_hash__clear(eb->props, eb->pool);
-      svn_hash__clear(eb->deleted_props, eb->pool);
+      SVN_ERR(svn_hash__clear(eb->props, eb->pool));
+      SVN_ERR(svn_hash__clear(eb->deleted_props, eb->pool));
     }
 
   /* Dump the text */

Modified: subversion/branches/diff-optimizations-bytes/subversion/svnrdump/svnrdump.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/svnrdump/svnrdump.c?rev=1044847&r1=1044846&r2=1044847&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/svnrdump/svnrdump.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/svnrdump/svnrdump.c Sun Dec 12 16:43:42 2010
@@ -74,33 +74,40 @@ static svn_opt_subcommand_t dump_cmd, lo
 enum svn_svnrdump__longopt_t
   {
     opt_config_dir = SVN_OPT_FIRST_LONGOPT_ID,
+    opt_config_option,
     opt_auth_username,
     opt_auth_password,
-    opt_non_interactive,
     opt_auth_nocache,
+    opt_non_interactive,
+    opt_incremental,
     opt_version,
-    opt_config_option,
   };
 
+#define SVN_SVNRDUMP__BASE_OPTIONS opt_config_dir, \
+                                   opt_config_option, \
+                                   opt_auth_username, \
+                                   opt_auth_password, \
+                                   opt_auth_nocache, \
+                                   opt_non_interactive
+
 static const svn_opt_subcommand_desc2_t svnrdump__cmd_table[] =
-  {
-    { "dump", dump_cmd, { 0 },
-      N_("usage: svnrdump dump URL [-r LOWER[:UPPER]]\n\n"
-         "Dump revisions LOWER to UPPER of repository at remote URL "
-         "to stdout in a 'dumpfile' portable format.\n"
-         "If only LOWER is given, dump that one revision.\n"),
-      { 0 } },
-    { "load", load_cmd, { 0 },
-      N_("usage: svnrdump load URL\n\n"
-         "Load a 'dumpfile' given on stdin to a repository "
-         "at remote URL.\n"),
-      { 0 } },
-    { "help", 0, { "?", "h" },
-      N_("usage: svnrdump help [SUBCOMMAND...]\n\n"
-         "Describe the usage of this program or its subcommands.\n"),
-      { 0 } },
-    { NULL, NULL, { 0 }, NULL, { 0 } }
-  };
+{
+  { "dump", dump_cmd, { 0 },
+    N_("usage: svnrdump dump URL [-r LOWER[:UPPER]]\n\n"
+       "Dump revisions LOWER to UPPER of repository at remote URL to stdout\n"
+       "in a 'dumpfile' portable format.  If only LOWER is given, dump that\n"
+       "one revision.\n"),
+    { 'r', 'q', opt_incremental, SVN_SVNRDUMP__BASE_OPTIONS } },
+  { "load", load_cmd, { 0 },
+    N_("usage: svnrdump load URL\n\n"
+       "Load a 'dumpfile' given on stdin to a repository at remote URL.\n"),
+    { 'q', SVN_SVNRDUMP__BASE_OPTIONS } },
+  { "help", 0, { "?", "h" },
+    N_("usage: svnrdump help [SUBCOMMAND...]\n\n"
+       "Describe the usage of this program or its subcommands.\n"),
+    { 0 } },
+  { NULL, NULL, { 0 }, NULL, { 0 } }
+};
 
 static const apr_getopt_option_t svnrdump__options[] =
   {
@@ -108,6 +115,8 @@ static const apr_getopt_option_t svnrdum
                       N_("specify revision number ARG (or X:Y range)")},
     {"quiet",         'q', 0,
                       N_("no progress (only errors) to stderr")},
+    {"incremental",   opt_incremental, 0,
+                      N_("dump incrementally")},
     {"config-dir",    opt_config_dir, 1,
                       N_("read user configuration files from directory ARG")},
     {"username",      opt_auth_username, 1,
@@ -149,9 +158,10 @@ struct replay_baton {
 typedef struct opt_baton_t {
   svn_ra_session_t *session;
   const char *url;
-  svn_revnum_t start_revision;
-  svn_revnum_t end_revision;
+  svn_opt_revision_t start_revision;
+  svn_opt_revision_t end_revision;
   svn_boolean_t quiet;
+  svn_boolean_t incremental;
 } opt_baton_t;
 
 /* Print dumpstream-formatted information about REVISION.
@@ -170,7 +180,7 @@ replay_revstart(svn_revnum_t revision,
   svn_stream_t *stdout_stream;
   svn_stream_t *revprop_stream;
 
-  svn_stream_for_stdout(&stdout_stream, pool);
+  SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));
 
   /* Revision-number: 19 */
   SVN_ERR(svn_stream_printf(stdout_stream, pool,
@@ -220,7 +230,8 @@ replay_revend(svn_revnum_t revision,
   /* No resources left to free. */
   struct replay_baton *rb = replay_baton;
   if (! rb->quiet)
-    svn_cmdline_fprintf(stderr, pool, "* Dumped revision %lu.\n", revision);
+    SVN_ERR(svn_cmdline_fprintf(stderr, pool, "* Dumped revision %lu.\n",
+                                revision));
   return SVN_NO_ERROR;
 }
 
@@ -271,6 +282,49 @@ open_connection(svn_ra_session_t **sessi
   return SVN_NO_ERROR;
 }
 
+/* Print a revision record header for REVISION to STDOUT_STREAM.  Use
+ * SESSION to contact the repository for revision properties and
+ * such.
+ */
+static svn_error_t *
+dump_revision_header(svn_ra_session_t *session,
+                     svn_stream_t *stdout_stream, 
+                     svn_revnum_t revision,
+                     apr_pool_t *pool)
+{
+  apr_hash_t *prophash;
+  svn_stringbuf_t *propstring;
+  svn_stream_t *propstream;
+
+  SVN_ERR(svn_stream_printf(stdout_stream, pool,
+                            SVN_REPOS_DUMPFILE_REVISION_NUMBER
+                            ": %ld\n", revision));
+
+  prophash = apr_hash_make(pool);
+  propstring = svn_stringbuf_create("", pool);
+  SVN_ERR(svn_ra_rev_proplist(session, revision, &prophash, pool));
+
+  propstream = svn_stream_from_stringbuf(propstring, pool);
+  SVN_ERR(svn_hash_write2(prophash, propstream, "PROPS-END", pool));
+  SVN_ERR(svn_stream_close(propstream));
+
+  /* Property-content-length: 14; Content-length: 14 */
+  SVN_ERR(svn_stream_printf(stdout_stream, pool,
+                            SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
+                            ": %" APR_SIZE_T_FMT "\n",
+                            propstring->len));
+  SVN_ERR(svn_stream_printf(stdout_stream, pool,
+                            SVN_REPOS_DUMPFILE_CONTENT_LENGTH
+                            ": %" APR_SIZE_T_FMT "\n\n",
+                            propstring->len));
+  /* The properties */
+  SVN_ERR(svn_stream_write(stdout_stream, propstring->data,
+                           &(propstring->len)));
+  SVN_ERR(svn_stream_printf(stdout_stream, pool, "\n"));
+
+  return SVN_NO_ERROR;
+}
+
 /* Replay revisions START_REVISION thru END_REVISION (inclusive) of
  * the repository located at URL, using callbacks which generate
  * Subversion repository dumpstreams describing the changes made in
@@ -283,6 +337,7 @@ replay_revisions(svn_ra_session_t *sessi
                  svn_revnum_t start_revision,
                  svn_revnum_t end_revision,
                  svn_boolean_t quiet,
+                 svn_boolean_t incremental,
                  apr_pool_t *pool)
 {
   const svn_delta_editor_t *dump_editor;
@@ -312,46 +367,62 @@ replay_revisions(svn_ra_session_t *sessi
   /* Fake revision 0 if necessary */
   if (start_revision == 0)
     {
-      apr_hash_t *prophash;
-      svn_stringbuf_t *propstring;
-      svn_stream_t *propstream;
-      SVN_ERR(svn_stream_printf(stdout_stream, pool,
-                                SVN_REPOS_DUMPFILE_REVISION_NUMBER
-                                ": %ld\n", start_revision));
-
-      prophash = apr_hash_make(pool);
-      propstring = svn_stringbuf_create("", pool);
-
-      SVN_ERR(svn_ra_rev_proplist(session, start_revision,
-                                  &prophash, pool));
-
-      propstream = svn_stream_from_stringbuf(propstring, pool);
-      SVN_ERR(svn_hash_write2(prophash, propstream, "PROPS-END", pool));
-      SVN_ERR(svn_stream_close(propstream));
-
-      /* Property-content-length: 14; Content-length: 14 */
-      SVN_ERR(svn_stream_printf(stdout_stream, pool,
-                                SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
-                                ": %" APR_SIZE_T_FMT "\n",
-                                propstring->len));
-      SVN_ERR(svn_stream_printf(stdout_stream, pool,
-                                SVN_REPOS_DUMPFILE_CONTENT_LENGTH
-                                ": %" APR_SIZE_T_FMT "\n\n",
-                                propstring->len));
-      /* The properties */
-      SVN_ERR(svn_stream_write(stdout_stream, propstring->data,
-                               &(propstring->len)));
-      SVN_ERR(svn_stream_printf(stdout_stream, pool, "\n"));
+      SVN_ERR(dump_revision_header(session, stdout_stream,
+                                   start_revision, pool));
+
+      /* Revision 0 has no tree changes, so we're done. */
       if (! quiet)
-        svn_cmdline_fprintf(stderr, pool, "* Dumped revision %lu.\n",
-                            start_revision);
+        SVN_ERR(svn_cmdline_fprintf(stderr, pool, "* Dumped revision %lu.\n",
+                                    start_revision));
+      start_revision++;
+
+      /* If our first revision is 0, we can treat this as an
+         incremental dump. */
+      incremental = TRUE;
+    }
+
+  if (incremental)
+    {
+      SVN_ERR(svn_ra_replay_range(session, start_revision, end_revision,
+                                  0, TRUE, replay_revstart, replay_revend,
+                                  replay_baton, pool));
+    }
+  else
+    {
+      const svn_ra_reporter3_t *reporter;
+      void *report_baton;
 
+      /* First, we need to dump the start_revision in full.  We'll
+         start with a revision record header. */
+      SVN_ERR(dump_revision_header(session, stdout_stream,
+                                   start_revision, pool));
+
+      /* Then, we'll drive the dump editor with what would look like a
+         full checkout of the repository as it looked in
+         START_REVISION.  We do this by manufacturing a basic 'report'
+         to the update reporter, telling it that we have nothing to
+         start with.  The delta between nothing and everything-at-REV
+         is, effectively, a full dump of REV. */
+      SVN_ERR(svn_ra_do_update2(session, &reporter, &report_baton,
+                                start_revision, "", svn_depth_infinity,
+                                FALSE, dump_editor, dump_baton, pool));
+      SVN_ERR(reporter->set_path(report_baton, "", start_revision,
+                                 svn_depth_infinity, TRUE, NULL, pool));
+      SVN_ERR(reporter->finish_report(report_baton, pool));
+      
+      /* All finished with START_REVISION! */
+      if (! quiet)
+        SVN_ERR(svn_cmdline_fprintf(stderr, pool, "* Dumped revision %lu.\n",
+                                    start_revision));
       start_revision++;
+
+      /* Now go pick up additional revisions in the range, if any. */
+      if (start_revision <= end_revision)
+        SVN_ERR(svn_ra_replay_range(session, start_revision, end_revision,
+                                    0, TRUE, replay_revstart, replay_revend,
+                                    replay_baton, pool));
     }
 
-  SVN_ERR(svn_ra_replay_range(session, start_revision, end_revision,
-                              0, TRUE, replay_revstart, replay_revend,
-                              replay_baton, pool));
   SVN_ERR(svn_stream_close(stdout_stream));
   return SVN_NO_ERROR;
 }
@@ -378,7 +449,7 @@ load_revisions(svn_ra_session_t *session
   SVN_ERR(drive_dumpstream_loader(stdin_stream, parser, parse_baton,
                                   session, check_cancel, NULL, pool));
 
-  svn_stream_close(stdin_stream);
+  SVN_ERR(svn_stream_close(stdin_stream));
 
   return SVN_NO_ERROR;
 }
@@ -450,8 +521,9 @@ dump_cmd(apr_getopt_t *os,
 {
   opt_baton_t *opt_baton = baton;
   return replay_revisions(opt_baton->session, opt_baton->url,
-                          opt_baton->start_revision, opt_baton->end_revision,
-                          opt_baton->quiet, pool);
+                          opt_baton->start_revision.value.number,
+                          opt_baton->end_revision.value.number,
+                          opt_baton->quiet, opt_baton->incremental, pool);
 }
 
 /* Handle the "load" subcommand.  Implements `svn_opt_subcommand_t'.  */
@@ -482,13 +554,95 @@ help_cmd(apr_getopt_t *os,
                              NULL, pool);
 }
 
+/* Examine the OPT_BATON's 'start_revision' and 'end_revision'
+ * members, making sure that they make sense (in general, and as
+ * applied to a repository whose current youngest revision is
+ * LATEST_REVISION).
+ */
+static svn_error_t *
+validate_and_resolve_revisions(opt_baton_t *opt_baton,
+                               svn_revnum_t latest_revision,
+                               apr_pool_t *pool)
+{
+  svn_revnum_t provided_start_rev = SVN_INVALID_REVNUM;
+
+  /* Ensure that the start revision is something we can handle.  We
+     want a number >= 0.  If unspecified, make it a number (r0) --
+     anything else is bogus.  */
+  if (opt_baton->start_revision.kind == svn_opt_revision_number)
+    {
+      provided_start_rev = opt_baton->start_revision.value.number;
+    }
+  else if (opt_baton->start_revision.kind == svn_opt_revision_unspecified)
+    {
+      opt_baton->start_revision.kind = svn_opt_revision_number;
+      opt_baton->start_revision.value.number = 0;
+    }
+
+  if (opt_baton->start_revision.kind != svn_opt_revision_number)
+    {
+      return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                              _("Unsupported revision specifier used; use "
+                                "only integer values or 'HEAD'"));
+    }
+
+  if ((opt_baton->start_revision.value.number < 0) ||
+      (opt_baton->start_revision.value.number > latest_revision))
+    {
+      return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                               _("Revision '%ld' does not exist"),
+                               opt_baton->start_revision.value.number);
+    }
+
+  /* Ensure that the end revision is something we can handle.  We want
+     a number <= the youngest, and > the start revision.  If
+     unspecified, make it a number (start_revision + 1 if that was
+     specified, the youngest revision in the repository otherwise) --
+     anything else is bogus.  */
+  if (opt_baton->end_revision.kind == svn_opt_revision_unspecified)
+    {
+      opt_baton->end_revision.kind = svn_opt_revision_number;
+      if (SVN_IS_VALID_REVNUM(provided_start_rev))
+        opt_baton->end_revision.value.number = provided_start_rev;
+      else
+        opt_baton->end_revision.value.number = latest_revision;
+    }
+
+  if (opt_baton->end_revision.kind != svn_opt_revision_number)
+    {
+      return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                              _("Unsupported revision specifier used; use "
+                                "only integer values or 'HEAD'"));
+    }
+
+  if ((opt_baton->end_revision.value.number < 0) ||
+      (opt_baton->end_revision.value.number > latest_revision))
+    {
+      return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                               _("Revision '%ld' does not exist"),
+                               opt_baton->end_revision.value.number);
+    }
+
+  /* Finally, make sure that the end revision is younger than the
+     start revision.  We don't do "backwards" 'round here.  */
+  if (opt_baton->end_revision.value.number < 
+      opt_baton->start_revision.value.number)
+    {
+      return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                              _("LOWER revision cannot be greater than "
+                                "UPPER revision; consider reversing your "
+                                "revision range"));
+    }
+  return SVN_NO_ERROR;
+}
+
 int
 main(int argc, const char **argv)
 {
+  svn_error_t *err = SVN_NO_ERROR;
   const svn_opt_subcommand_desc2_t *subcommand = NULL;
   opt_baton_t *opt_baton;
-  char *revision_cut = NULL;
-  svn_revnum_t latest_revision = svn_opt_revision_unspecified;
+  svn_revnum_t latest_revision = SVN_INVALID_REVNUM;
   apr_pool_t *pool = NULL;
   const char *config_dir = NULL;
   const char *username = NULL;
@@ -498,14 +652,16 @@ main(int argc, const char **argv)
   apr_array_header_t *config_options = NULL;
   apr_getopt_t *os;
   const char *first_arg;
+  apr_array_header_t *received_opts;
+  int i;
 
   if (svn_cmdline_init ("svnrdump", stderr) != EXIT_SUCCESS)
     return EXIT_FAILURE;
 
   pool = svn_pool_create(NULL);
   opt_baton = apr_pcalloc(pool, sizeof(*opt_baton));
-  opt_baton->start_revision = svn_opt_revision_unspecified;
-  opt_baton->end_revision = svn_opt_revision_unspecified;
+  opt_baton->start_revision.kind = svn_opt_revision_unspecified;
+  opt_baton->end_revision.kind = svn_opt_revision_unspecified;
   opt_baton->url = NULL;
 
   SVNRDUMP_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));
@@ -535,6 +691,8 @@ main(int argc, const char **argv)
   apr_signal(SIGXFSZ, SIG_IGN);
 #endif
 
+  received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int));
+
   while (1)
     {
       int opt;
@@ -550,23 +708,34 @@ main(int argc, const char **argv)
           exit(EXIT_FAILURE);
         }
 
+      /* Stash the option code in an array before parsing it. */
+      APR_ARRAY_PUSH(received_opts, int) = opt;
+
       switch(opt)
         {
         case 'r':
           {
-            revision_cut = strchr(opt_arg, ':');
-            if (revision_cut)
+            /* Make sure we've not seen -r already. */
+            if (opt_baton->start_revision.kind != svn_opt_revision_unspecified)
               {
-                opt_baton->start_revision =
-                  (svn_revnum_t)strtoul(opt_arg, &revision_cut, 10);
-                opt_baton->end_revision =
-                  (svn_revnum_t)strtoul(revision_cut + 1, NULL, 10);
+                err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                       _("Multiple revision arguments "
+                                         "encountered; try '-r N:M' instead "
+                                         "of '-r N -r M'"));
+                return svn_cmdline_handle_exit_error(err, pool, "svnrdump: ");
               }
-            else
+            /* Parse the -r argument. */
+            if (svn_opt_parse_revision(&(opt_baton->start_revision),
+                                       &(opt_baton->end_revision),
+                                       opt_arg, pool) != 0)
               {
-                opt_baton->start_revision =
-                  (svn_revnum_t)strtoul(opt_arg, NULL, 10);
-                opt_baton->end_revision = opt_baton->start_revision;
+                const char *utf8_opt_arg;
+                err = svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool);
+                if (! err)
+                  err = svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                          _("Syntax error in revision "
+                                            "argument '%s'"), utf8_opt_arg);
+                return svn_cmdline_handle_exit_error(err, pool, "svnrdump: ");
               }
           }
           break;
@@ -596,6 +765,9 @@ main(int argc, const char **argv)
         case opt_non_interactive:
           non_interactive = TRUE;
           break;
+        case opt_incremental:
+          opt_baton->incremental = TRUE;
+          break;
         case opt_config_option:
           if (!config_options)
               config_options =
@@ -625,8 +797,7 @@ main(int argc, const char **argv)
   if (subcommand == NULL)
     {
       const char *first_arg_utf8;
-      svn_error_t *err = svn_utf_cstring_to_utf8(&first_arg_utf8,
-                                                 first_arg, pool);
+      err = svn_utf_cstring_to_utf8(&first_arg_utf8, first_arg, pool);
       if (err)
         return svn_cmdline_handle_exit_error(err, pool, "svnrdump: ");
       svn_error_clear(svn_cmdline_fprintf(stderr, pool,
@@ -637,6 +808,39 @@ main(int argc, const char **argv)
       exit(EXIT_FAILURE);
     }
 
+  /* Check that the subcommand wasn't passed any inappropriate options. */
+  for (i = 0; i < received_opts->nelts; i++)
+    {
+      int opt_id = APR_ARRAY_IDX(received_opts, i, int);
+
+      /* All commands implicitly accept --help, so just skip over this
+         when we see it. Note that we don't want to include this option
+         in their "accepted options" list because it would be awfully
+         redundant to display it in every commands' help text. */
+      if (opt_id == 'h' || opt_id == '?')
+        continue;
+
+      if (! svn_opt_subcommand_takes_option3(subcommand, opt_id, NULL))
+        {
+          const char *optstr;
+          const apr_getopt_option_t *badopt =
+            svn_opt_get_option_from_code2(opt_id, svnrdump__options,
+                                          subcommand, pool);
+          svn_opt_format_option(&optstr, badopt, FALSE, pool);
+          if (subcommand->name[0] == '-')
+            SVN_INT_ERR(help_cmd(NULL, NULL, pool));
+          else
+            svn_error_clear
+              (svn_cmdline_fprintf
+               (stderr, pool,
+                _("Subcommand '%s' doesn't accept option '%s'\n"
+                  "Type 'svnrdump help %s' for usage.\n"),
+                subcommand->name, optstr, subcommand->name));
+          svn_pool_destroy(pool);
+          return EXIT_FAILURE;
+        }
+    }
+
   if (subcommand && strcmp(subcommand->name, "help") == 0)
     {
       SVNRDUMP_ERR(help_cmd(os, opt_baton, pool));
@@ -670,24 +874,10 @@ main(int argc, const char **argv)
      unspecified.  */
   SVNRDUMP_ERR(svn_ra_get_latest_revnum(opt_baton->session,
                                         &latest_revision, pool));
-  if (opt_baton->start_revision == svn_opt_revision_unspecified)
-    opt_baton->start_revision = 0;
-  if (opt_baton->end_revision == svn_opt_revision_unspecified)
-    opt_baton->end_revision = latest_revision;
-  if (opt_baton->end_revision > latest_revision)
-    {
-      SVN_INT_ERR(svn_cmdline_fprintf(stderr, pool,
-                                      _("Revision %ld does not exist.\n"),
-                                      opt_baton->end_revision));
-      exit(EXIT_FAILURE);
-    }
-  if (opt_baton->end_revision < opt_baton->start_revision)
-    {
-      SVN_INT_ERR(svn_cmdline_fprintf(stderr, pool,
-                                      _("LOWER cannot be greater "
-                                        "than UPPER.\n")));
-      exit(EXIT_FAILURE);
-    }
+
+  /* Make sure any provided revisions make sense. */
+  SVNRDUMP_ERR(validate_and_resolve_revisions(opt_baton, 
+                                              latest_revision, pool));
 
   /* Dispatch the subcommand */
   SVNRDUMP_ERR((*subcommand->cmd_func)(os, opt_baton, pool));