You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/08/10 22:56:05 UTC

svn commit: r984206 [12/35] - in /subversion/branches/ignore-mergeinfo: ./ build/ build/generator/ build/generator/templates/ build/hudson/ build/hudson/jobs/subversion-1.6.x-solaris/ build/hudson/jobs/subversion-1.6.x-ubuntu/ build/hudson/jobs/subvers...

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/error.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/error.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/error.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/error.c Tue Aug 10 20:55:56 2010
@@ -53,8 +53,8 @@ static const char SVN_FILE_LINE_UNDEFINE
    in locking and unlocking it. */
 
 /* XXX TODO: Define mutex here #if APR_HAS_THREADS */
-static const char *error_file = NULL;
-static long error_line = -1;
+static const char * volatile error_file = NULL;
+static long volatile error_line = -1;
 
 void
 svn_error__locate(const char *file, long line)

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/io.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/io.c Tue Aug 10 20:55:56 2010
@@ -224,6 +224,9 @@ io_check_path(const char *path,
     *kind = svn_node_none;
   else if (APR_STATUS_IS_ENOTDIR(apr_err)
 #ifdef WIN32
+           /* On Windows, APR_STATUS_IS_ENOTDIR includes several kinds of
+            * invalid-pathname error but not this one, so we include it. */
+           /* ### This fix should go into APR. */
            || (APR_TO_OS_ERROR(apr_err) == ERROR_INVALID_NAME)
 #endif
            )
@@ -625,7 +628,7 @@ static const char *temp_dir;
 
 /* Helper function to initialize temp dir. Passed to svn_atomic__init_once */
 static svn_error_t *
-init_temp_dir(apr_pool_t *scratch_pool)
+init_temp_dir(void *baton, apr_pool_t *scratch_pool)
 {
   /* Global pool for the temp path */
   apr_pool_t *global_pool = svn_pool_create(NULL);
@@ -650,7 +653,8 @@ svn_error_t *
 svn_io_temp_dir(const char **dir,
                 apr_pool_t *pool)
 {
-  SVN_ERR(svn_atomic__init_once(&temp_dir_init_state, init_temp_dir, pool));
+  SVN_ERR(svn_atomic__init_once(&temp_dir_init_state,
+                                init_temp_dir, NULL, pool));
 
   *dir = apr_pstrdup(pool, temp_dir);
 
@@ -782,6 +786,23 @@ svn_io_copy_file(const char *src,
   return svn_error_return(svn_io_file_rename(dst_tmp, dst, pool));
 }
 
+/* Wrapper for apr_file_perms_set(). */
+static svn_error_t *
+file_perms_set(const char *fname, apr_fileperms_t perms,
+               apr_pool_t *pool)
+{
+  const char *fname_apr;
+  apr_status_t status;
+
+  SVN_ERR(cstring_from_utf8(&fname_apr, fname, pool));
+
+  status = apr_file_perms_set(fname_apr, perms);
+  if (status)
+    return svn_error_wrap_apr(status, _("Can't set permissions on '%s'"),
+                              fname);
+  else
+    return SVN_NO_ERROR;
+}
 
 svn_error_t *
 svn_io_copy_perms(const char *src,
@@ -811,7 +832,7 @@ svn_io_copy_perms(const char *src,
     SVN_ERR(svn_io_file_open(&src_file, src, APR_READ, APR_OS_DEFAULT, pool));
     SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_PROT, src_file, pool));
     SVN_ERR(svn_io_file_close(src_file, pool));
-    err = svn_io_file_perms_set(dst, finfo.protection, pool);
+    err = file_perms_set(dst, finfo.protection, pool);
     if (err)
       {
         /* We shouldn't be able to get APR_INCOMPLETE or APR_ENOTIMPL
@@ -1125,7 +1146,7 @@ svn_io_sleep_for_timestamps(const char *
       now = apr_time_now(); /* Extract the time used for the path stat */
 
       if (now >= then)
-        return; /* Passing negative values may suspend indefinately (Windows) */
+        return; /* Passing negative values may suspend indefinitely (Windows) */
     }
 
   apr_sleep(then - now);
@@ -1808,27 +1829,6 @@ svn_stringbuf_from_file(svn_stringbuf_t 
   return svn_stringbuf_from_file2(result, filename, pool);
 }
 
-
-/* Get the name of FILE, or NULL if FILE is an unnamed stream. */
-static svn_error_t *
-file_name_get(const char **fname_utf8, apr_file_t *file, apr_pool_t *pool)
-{
-  apr_status_t apr_err;
-  const char *fname;
-
-  apr_err = apr_file_name_get(&fname, file);
-  if (apr_err)
-    return svn_error_wrap_apr(apr_err, _("Can't get file name"));
-
-  if (fname)
-    SVN_ERR(svn_path_cstring_to_utf8(fname_utf8, fname, pool));
-  else
-    *fname_utf8 = NULL;
-
-  return SVN_NO_ERROR;
-}
-
-
 svn_error_t *
 svn_stringbuf_from_aprfile(svn_stringbuf_t **result,
                            apr_file_t *file,
@@ -2553,8 +2553,10 @@ svn_io_parse_mimetypes_file(apr_hash_t *
           type = APR_ARRAY_IDX(tokens, 0, const char *);
           for (i = 1; i < tokens->nelts; i++)
             {
-              const char *ext = APR_ARRAY_IDX(tokens, i, const char *);
-              fileext_tolower((char *)ext);
+              /* We can safely address 'ext' as a non-const string because
+               * we know svn_cstring_split() allocated it in 'pool' for us. */
+              char *ext = APR_ARRAY_IDX(tokens, i, char *);
+              fileext_tolower(ext);
               apr_hash_set(types, ext, APR_HASH_KEY_STRING, type);
             }
         }
@@ -2711,7 +2713,7 @@ do_io_file_wrapper_cleanup(apr_file_t *f
   if (! status)
     return SVN_NO_ERROR;
 
-  err = file_name_get(&name, file, pool);
+  err = svn_io_file_name_get(&name, file, pool);
   if (err)
     name = NULL;
   svn_error_clear(err);
@@ -2898,7 +2900,7 @@ svn_io_read_length_line(apr_file_t *file
         }
     }
 
-  err = file_name_get(&name, file, pool);
+  err = svn_io_file_name_get(&name, file, pool);
   if (err)
     name = NULL;
   svn_error_clear(err);
@@ -3523,29 +3525,142 @@ svn_io_files_contents_same_p(svn_boolean
   return SVN_NO_ERROR;
 }
 
-/* Wrapper for apr_file_mktemp(). */
-svn_error_t *
-svn_io_file_mktemp(apr_file_t **new_file, const char *templ,
-                  apr_int32_t flags, apr_pool_t *pool)
+#ifdef WIN32
+/* Counter value of file_mktemp request (used in a threadsafe way), to make
+   sure that a single process normally never generates the same tempname
+   twice */
+static volatile apr_uint32_t tempname_counter = 0;
+#endif
+
+/* Creates a new temporary file in DIRECTORY with apr flags FLAGS.
+   Set *NEW_FILE to the file handle and *NEW_FILE_NAME to its name.
+   Perform temporary allocations in SCRATCH_POOL and the result in
+   RESULT_POOL. */
+static svn_error_t *
+temp_file_create(apr_file_t **new_file,
+                 const char **new_file_name,
+                 const char *directory,
+                 apr_int32_t flags,
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
 {
+#ifndef WIN32
+  const char *templ = svn_dirent_join(directory, "svn-XXXXXX", scratch_pool);
   const char *templ_apr;
   apr_status_t status;
 
-  SVN_ERR(svn_path_cstring_from_utf8(&templ_apr, templ, pool));
+  SVN_ERR(svn_path_cstring_from_utf8(&templ_apr, templ, scratch_pool));
 
   /* ### svn_path_cstring_from_utf8() guarantees to make a copy of the
          data available in POOL and we need a non-const pointer here,
-         as apr changes the template to return the new filename. 
-
-         But we can't provide the filename to our caller as that might need
-         more bytes then there are XXXXs after converting it back to utf-8. */
-  status = apr_file_mktemp(new_file, (char *)templ_apr, flags, pool);
+         as apr changes the template to return the new filename. */
+  status = apr_file_mktemp(new_file, (char *)templ_apr, flags, result_pool);
 
   if (status)
     return svn_error_wrap_apr(status, _("Can't create temporary file from "
                               "template '%s'"), templ);
-  else
-    return SVN_NO_ERROR;
+  
+  /* Translate the returned path back to utf-8 before returning it */
+  return svn_error_return(svn_path_cstring_to_utf8(new_file_name,
+                                                   templ_apr,
+                                                   result_pool));
+#else
+  /* The Windows implementation of apr_file_mktemp doesn't handle access
+     denied errors correctly. Therefore we implement our own temp file
+     creation function here. */
+
+  /* ### Most of this is borrowed from the svn_io_open_uniquely_named(),
+     ### the function we used before. But we try to guess a more unique
+     ### name before trying if it exists. */
+
+  /* Offset by some time value and a unique request nr to make the number
+     +- unique for both this process and on the computer */
+  int baseNr = (GetTickCount() << 11) + 7 * svn_atomic_inc(&tempname_counter) 
+               + GetCurrentProcessId();
+  int i;
+
+  /* ### Maybe use an iterpool? */
+  for (i = 0; i <= 99999; i++)
+    {
+      apr_uint32_t unique_nr;
+      const char *unique_name;
+      const char *unique_name_apr;
+      apr_file_t *try_file;
+      apr_status_t apr_err;
+
+      /* Generate a number that should be unique for this application and
+         usually for the entire computer to reduce the number of cycles
+         through this loop. (A bit of calculation is much cheaper then
+         disk io) */
+      unique_nr = baseNr + 3 * i;
+
+      unique_name = apr_psprintf(scratch_pool, "%s/svn-%X", directory,
+                                 unique_nr);
+
+      SVN_ERR(cstring_from_utf8(&unique_name_apr, unique_name, scratch_pool));
+
+      apr_err = file_open(&try_file, unique_name_apr, flags,
+                          APR_OS_DEFAULT, FALSE, scratch_pool);
+
+      if (APR_STATUS_IS_EEXIST(apr_err))
+          continue;
+      else if (apr_err)
+        {
+          /* On Win32, CreateFile fails with an "Access Denied" error
+             code, rather than "File Already Exists", if the colliding
+             name belongs to a directory. */
+
+          if (APR_STATUS_IS_EACCES(apr_err))
+            {
+              apr_finfo_t finfo;
+              apr_status_t apr_err_2 = apr_stat(&finfo, unique_name_apr,
+                                                APR_FINFO_TYPE, scratch_pool);
+
+              if (!apr_err_2 && finfo.filetype == APR_DIR)
+                continue;
+
+#ifdef WIN32
+              apr_err_2 = APR_TO_OS_ERROR(apr_err);
+
+              if (apr_err_2 == ERROR_ACCESS_DENIED ||
+                  apr_err_2 == ERROR_SHARING_VIOLATION)
+                {
+                  /* The file is in use by another process or is hidden;
+                     create a new name, but don't do this 99999 times in
+                     case the folder is not writable */
+                  i += 797;
+                  continue;
+                }
+#endif
+
+              /* Else fall through and return the original error. */
+            }
+
+          return svn_error_wrap_apr(apr_err, _("Can't open '%s'"),
+                                    svn_dirent_local_style(unique_name,
+                                                           scratch_pool));
+        }
+      else
+        {
+          /* Move file to the right pool */
+          apr_err = apr_file_setaside(new_file, try_file, result_pool);
+
+          if (apr_err)
+            return svn_error_wrap_apr(apr_err, _("Can't set aside '%s'"),
+                                      svn_dirent_local_style(unique_name,
+                                                             scratch_pool));
+
+          *new_file_name = apr_pstrdup(result_pool, unique_name);
+
+          return SVN_NO_ERROR;
+        }
+    }
+
+  return svn_error_createf(SVN_ERR_IO_UNIQUE_NAMES_EXHAUSTED,
+                           NULL,
+                           _("Unable to make name in '%s'"),
+                           svn_dirent_local_style(directory, scratch_pool));
+#endif
 }
 
 /* Wrapper for apr_file_name_get(). */
@@ -3561,27 +3676,15 @@ svn_io_file_name_get(const char **filena
   if (status)
     return svn_error_wrap_apr(status, _("Can't get file name"));
 
-  return svn_error_return(cstring_to_utf8(filename, fname_apr, pool));
-}
-
-/* Wrapper for apr_file_perms_set(). */
-svn_error_t *
-svn_io_file_perms_set(const char *fname, apr_fileperms_t perms,
-                      apr_pool_t *pool)
-{
-  const char *fname_apr;
-  apr_status_t status;
-
-  SVN_ERR(cstring_from_utf8(&fname_apr, fname, pool));
-
-  status = apr_file_perms_set(fname_apr, perms);
-  if (status)
-    return svn_error_wrap_apr(status, _("Can't set permissions on '%s'"),
-                              fname);
+  if (fname_apr)
+    SVN_ERR(svn_path_cstring_to_utf8(filename, fname_apr, pool));
   else
-    return SVN_NO_ERROR;
+    *filename = NULL;
+
+  return SVN_NO_ERROR;
 }
 
+
 svn_error_t *
 svn_io_open_unique_file3(apr_file_t **file,
                          const char **unique_path,
@@ -3592,7 +3695,6 @@ svn_io_open_unique_file3(apr_file_t **fi
 {
   apr_file_t *tempfile;
   const char *tempname;
-  char *path;
   struct temp_file_cleanup_s *baton = NULL;
   apr_int32_t flags = (APR_READ | APR_WRITE | APR_CREATE | APR_EXCL |
                        APR_BUFFERED | APR_BINARY);
@@ -3609,8 +3711,6 @@ svn_io_open_unique_file3(apr_file_t **fi
   if (dirpath == NULL)
     SVN_ERR(svn_io_temp_dir(&dirpath, scratch_pool));
 
-  path = svn_dirent_join(dirpath, "svn-XXXXXX", scratch_pool);
-
   switch (delete_when)
     {
       case svn_io_file_del_on_pool_cleanup:
@@ -3635,11 +3735,11 @@ svn_io_open_unique_file3(apr_file_t **fi
         break;
     }
 
-  SVN_ERR(svn_io_file_mktemp(&tempfile, path, flags, result_pool));
-  SVN_ERR(svn_io_file_name_get(&tempname, tempfile, scratch_pool));
+  SVN_ERR(temp_file_create(&tempfile, &tempname, dirpath, flags,
+                           result_pool, scratch_pool));
 
 #ifndef WIN32
-  /* ### svn_io_file_mktemp() creates files with mode 0600.
+  /* ### file_mktemp() creates files with mode 0600.
    * ### As of r40264, tempfiles created by svn_io_open_unique_file3()
    * ### often end up being copied or renamed into the working copy.
    * ### This will cause working files having mode 0600 while users might
@@ -3649,7 +3749,7 @@ svn_io_open_unique_file3(apr_file_t **fi
    * ### So we tweak perms of the tempfile here, but only if the umask
    * ### allows it. */
   SVN_ERR(merge_default_file_perms(tempfile, &perms, scratch_pool));
-  SVN_ERR(svn_io_file_perms_set(tempname, perms, scratch_pool));
+  SVN_ERR(file_perms_set(tempname, perms, scratch_pool));
 #endif
 
   if (file)
@@ -3658,14 +3758,14 @@ svn_io_open_unique_file3(apr_file_t **fi
     SVN_ERR(svn_io_file_close(tempfile, scratch_pool));
 
   if (unique_path)
-    *unique_path = apr_pstrdup(result_pool, tempname);
+    *unique_path = tempname; /* Was allocated in result_pool */
 
   if (baton)
     {
       if (unique_path)
         baton->name = *unique_path;
       else
-        baton->name = apr_pstrdup(result_pool, tempname);
+        baton->name = tempname; /* Was allocated in result_pool */
     }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/iter.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/iter.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/iter.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/iter.c Tue Aug 10 20:55:56 2010
@@ -153,7 +153,7 @@ svn_iter_apr_array(svn_boolean_t *comple
 
       svn_pool_clear(iterpool);
 
-      err = (*func)(baton, item, pool);
+      err = (*func)(baton, item, iterpool);
     }
 
   if (completed)
@@ -182,11 +182,12 @@ svn_iter__break(void)
   return &internal_break_error;
 }
 
-/* APR isn't fully constified, and apr_hash_this does not expect a const
- * hash index parameter. However, it does not modify the hash index,
- * and in Subversion we're trying to be const-correct.
- * So these functions all take const hash indices, and we cast the const
- * away when passing them down to APR to avoid compiler warnings. */
+/* Note about the type casts:  apr_hash_this() does not expect a const hash
+ * index pointer even though it does not modify the hash index.  In
+ * Subversion we're trying to be const-correct, so these functions all take
+ * a const hash index and we cast away the const when passing it down to
+ * APR.  (A compiler may warn about casting away 'const', but at least this
+ * cast is explicit and gathered in one place.) */
 
 const void *svn__apr_hash_index_key(const apr_hash_index_t *hi)
 {

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/lock.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/lock.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/lock.c Tue Aug 10 20:55:56 2010
@@ -43,8 +43,12 @@ svn_lock_create(apr_pool_t *pool)
 svn_lock_t *
 svn_lock_dup(const svn_lock_t *lock, apr_pool_t *pool)
 {
-  svn_lock_t *new_l = apr_palloc(pool, sizeof(*new_l));
+  svn_lock_t *new_l;
 
+  if (lock == NULL)
+    return NULL;
+  
+  new_l = apr_palloc(pool, sizeof(*new_l));
   *new_l = *lock;
 
   new_l->path = apr_pstrdup(pool, new_l->path);

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/mergeinfo.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/mergeinfo.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/mergeinfo.c Tue Aug 10 20:55:56 2010
@@ -1679,11 +1679,13 @@ svn_mergeinfo__remove_empty_rangelists(s
 svn_error_t *
 svn_mergeinfo__remove_prefix_from_catalog(svn_mergeinfo_catalog_t *out_catalog,
                                           svn_mergeinfo_catalog_t in_catalog,
-                                          const char *prefix,
+                                          const char *prefix_path,
                                           apr_pool_t *pool)
 {
   apr_hash_index_t *hi;
-  size_t prefix_len = strlen(prefix);
+  size_t prefix_len = strlen(prefix_path);
+
+  SVN_ERR_ASSERT(prefix_path[0] == '/');
 
   *out_catalog = apr_hash_make(pool);
 
@@ -1692,12 +1694,50 @@ svn_mergeinfo__remove_prefix_from_catalo
       const char *original_path = svn__apr_hash_index_key(hi);
       apr_ssize_t klen = svn__apr_hash_index_klen(hi);
       svn_mergeinfo_t value = svn__apr_hash_index_val(hi);
+      apr_ssize_t padding = 0;
 
       SVN_ERR_ASSERT(klen >= prefix_len);
-      SVN_ERR_ASSERT(strncmp(original_path, prefix, prefix_len) == 0);
+      SVN_ERR_ASSERT(svn_uri_is_ancestor(prefix_path, original_path));
+
+      /* If the ORIGINAL_PATH doesn't match the PREFIX_PATH exactly
+         and we're not simply removing a single leading slash (such as
+         when PREFIX_PATH is "/"), we advance our string offset by an
+         extra character (to get past the directory separator that
+         follows the prefix).  */
+      if ((strcmp(original_path, prefix_path) != 0) && (prefix_len != 1))
+        padding = 1;
+
+      apr_hash_set(*out_catalog, original_path + prefix_len + padding,
+                   klen - prefix_len - padding, value);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_mergeinfo__add_prefix_to_catalog(svn_mergeinfo_catalog_t *out_catalog,
+                                     svn_mergeinfo_catalog_t in_catalog,
+                                     const char *prefix_path,
+                                     apr_pool_t *result_pool,
+                                     apr_pool_t *scratch_pool)
+{
+  apr_hash_index_t *hi;
+
+  *out_catalog = apr_hash_make(result_pool);
+
+  for (hi = apr_hash_first(scratch_pool, in_catalog);
+       hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *original_path = svn__apr_hash_index_key(hi);
+      svn_mergeinfo_t value = svn__apr_hash_index_val(hi);
 
-      apr_hash_set(*out_catalog, original_path + prefix_len,
-                   klen-prefix_len, value);
+      if (original_path[0] == '/')
+        original_path++;
+
+      apr_hash_set(*out_catalog,
+                   svn_dirent_join(prefix_path, original_path, result_pool),
+                   APR_HASH_KEY_STRING, value);
     }
 
   return SVN_NO_ERROR;
@@ -1948,6 +1988,10 @@ svn_mergeinfo__filter_mergeinfo_by_range
                                           apr_pool_t *result_pool,
                                           apr_pool_t *scratch_pool)
 {
+  SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(youngest_rev));
+  SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(oldest_rev));
+  SVN_ERR_ASSERT(oldest_rev < youngest_rev);
+
   *filtered_mergeinfo = apr_hash_make(result_pool);
 
   if (mergeinfo)

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/opt.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/opt.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/opt.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/opt.c Tue Aug 10 20:55:56 2010
@@ -1065,6 +1065,23 @@ svn_opt_print_help3(apr_getopt_t *os,
   return SVN_NO_ERROR;
 }
 
+/* svn_opt__eat_peg_revisions was added to the 1.6 branch and, despite
+   its double underscore name, it is called from the application
+   layer.  So to remain ABI compatibilty with 1.6 the name must
+   continue to exist.  Adding this name is sufficient for the 1.6
+   client to link against the 1.7 libraries. */
+svn_error_t *
+svn_opt__eat_peg_revisions(apr_array_header_t **true_targets_p,
+                           const apr_array_header_t *targets,
+                           apr_pool_t *pool);
+svn_error_t *
+svn_opt__eat_peg_revisions(apr_array_header_t **true_targets_p,
+                           const apr_array_header_t *targets,
+                           apr_pool_t *pool)
+{
+  return svn_opt_eat_peg_revisions(true_targets_p, targets, pool);
+}
+
 svn_error_t *
 svn_opt_eat_peg_revisions(apr_array_header_t **true_targets_p,
                           const apr_array_header_t *targets,

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/path.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/path.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/path.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/path.c Tue Aug 10 20:55:56 2010
@@ -38,6 +38,8 @@
 #include "svn_io.h"                     /* for svn_io_stat() */
 #include "svn_ctype.h"
 
+#include "dirent_uri.h"
+
 
 /* The canonical empty path.  Can this be changed?  Well, change the empty
    test below and the path library will work, not so sure about the fs/wc
@@ -673,7 +675,7 @@ svn_path_is_url(const char *path)
 
       alphanum | mark | ":" | "@" | "&" | "=" | "+" | "$" | ","
 */
-static const char uri_char_validity[256] = {
+const char svn_uri__char_validity[256] = {
   0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
   0, 1, 0, 0, 1, 0, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
@@ -732,7 +734,7 @@ svn_path_is_uri_safe(const char *path)
             }
           return FALSE;
         }
-      else if (! uri_char_validity[((unsigned char)path[i])])
+      else if (! svn_uri__char_validity[((unsigned char)path[i])])
         {
           return FALSE;
         }
@@ -802,7 +804,7 @@ svn_path_uri_encode(const char *path, ap
 {
   const char *ret;
 
-  ret = uri_escape(path, uri_char_validity, pool);
+  ret = uri_escape(path, svn_uri__char_validity, pool);
 
   /* Our interface guarantees a copy. */
   if (ret == path)
@@ -921,7 +923,7 @@ svn_path_url_add_component2(const char *
                             apr_pool_t *pool)
 {
   /* = svn_path_uri_encode() but without always copying */
-  component = uri_escape(component, uri_char_validity, pool);
+  component = uri_escape(component, svn_uri__char_validity, pool);
 
   return svn_path_join(url, component, pool);
 }

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/skel.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/skel.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/skel.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/skel.c Tue Aug 10 20:55:56 2010
@@ -69,6 +69,8 @@ static const enum char_type skel_char_ty
 
 
 /* ### WTF? since when is number conversion LOCALE DEPENDENT? */
+/* stsp: In C99, various numerical string properties such as decimal point,
+ * thousands separator, and the plus/minus sign are locale dependent. */
 
 /* Converting text to numbers.  */
 
@@ -610,20 +612,20 @@ void svn_skel__prepend_str(const char *v
 }
 
 
-void svn_skel__append(svn_skel_t *list_skel, const svn_skel_t *skel)
+void svn_skel__append(svn_skel_t *list_skel, svn_skel_t *skel)
 {
   SVN_ERR_ASSERT_NO_RETURN(list_skel != NULL && !list_skel->is_atom);
 
   if (list_skel->children == NULL)
     {
-      list_skel->children = (svn_skel_t *)skel;
+      list_skel->children = skel;
     }
   else
     {
       list_skel = list_skel->children;
       while (list_skel->next != NULL)
         list_skel = list_skel->next;
-      list_skel->next = (svn_skel_t *)skel;
+      list_skel->next = skel;
     }
 }
 

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/sqlite.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/sqlite.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/sqlite.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/sqlite.c Tue Aug 10 20:55:56 2010
@@ -29,6 +29,8 @@
 #include "svn_dirent_uri.h"
 #include "svn_checksum.h"
 
+#include "internal_statements.h"
+
 #include "private/svn_sqlite.h"
 #include "svn_private_config.h"
 #include "private/svn_dep_compat.h"
@@ -48,6 +50,9 @@
   #include <sqlite3.h>
 #endif
 
+INTERNAL_STATEMENTS_SQL_DECLARE_STATEMENTS(internal_statements);
+
+
 #ifdef SQLITE3_DEBUG
 /* An sqlite query execution callback. */
 static void
@@ -65,7 +70,7 @@ struct svn_sqlite__db_t
   const char * const *statement_strings;
   int nbr_statements;
   svn_sqlite__stmt_t **prepared_stmts;
-  apr_pool_t *result_pool;
+  apr_pool_t *state_pool;
 };
 
 struct svn_sqlite__stmt_t
@@ -136,11 +141,11 @@ svn_sqlite__get_statement(svn_sqlite__st
   if (db->prepared_stmts[stmt_idx] == NULL)
     SVN_ERR(svn_sqlite__prepare(&db->prepared_stmts[stmt_idx], db,
                                 db->statement_strings[stmt_idx],
-                                db->result_pool));
+                                db->state_pool));
 
   *stmt = db->prepared_stmts[stmt_idx];
 
-  if ((*stmt)->needs_reset);
+  if ((*stmt)->needs_reset)
     return svn_error_return(svn_sqlite__reset(*stmt));
 
   return SVN_NO_ERROR;
@@ -668,7 +673,7 @@ static volatile svn_atomic_t sqlite_init
    manner. */
 /* Don't call this function directly!  Use svn_atomic__init_once(). */
 static svn_error_t *
-init_sqlite(apr_pool_t *pool)
+init_sqlite(void *baton, apr_pool_t *pool)
 {
   if (sqlite3_libversion_number() < SQLITE_VERSION_NUMBER)
     {
@@ -819,7 +824,8 @@ svn_sqlite__get_schema_version(int *vers
 {
   svn_sqlite__db_t db;
 
-  SVN_ERR(svn_atomic__init_once(&sqlite_init_state, init_sqlite, scratch_pool));
+  SVN_ERR(svn_atomic__init_once(&sqlite_init_state,
+                                init_sqlite, NULL, scratch_pool));
   SVN_ERR(internal_open(&db.db3, path, svn_sqlite__mode_readonly,
                         scratch_pool));
   SVN_ERR(svn_sqlite__read_schema_version(version, &db, scratch_pool));
@@ -874,7 +880,8 @@ svn_sqlite__open(svn_sqlite__db_t **db, 
                  int latest_schema, const char * const *upgrade_sql,
                  apr_pool_t *result_pool, apr_pool_t *scratch_pool)
 {
-  SVN_ERR(svn_atomic__init_once(&sqlite_init_state, init_sqlite, scratch_pool));
+  SVN_ERR(svn_atomic__init_once(&sqlite_init_state,
+                                init_sqlite, NULL, scratch_pool));
 
   *db = apr_pcalloc(result_pool, sizeof(**db));
 
@@ -927,7 +934,7 @@ svn_sqlite__open(svn_sqlite__db_t **db, 
   else
     (*db)->nbr_statements = 0;
 
-  (*db)->result_pool = result_pool;
+  (*db)->state_pool = result_pool;
   apr_pool_cleanup_register(result_pool, *db, close_apr, apr_pool_cleanup_null);
 
   return SVN_NO_ERROR;
@@ -936,7 +943,7 @@ svn_sqlite__open(svn_sqlite__db_t **db, 
 svn_error_t *
 svn_sqlite__close(svn_sqlite__db_t *db)
 {
-  apr_status_t result = apr_pool_cleanup_run(db->result_pool, db, close_apr);
+  apr_status_t result = apr_pool_cleanup_run(db->state_pool, db, close_apr);
 
   if (result == APR_SUCCESS)
     return SVN_NO_ERROR;
@@ -964,3 +971,68 @@ svn_sqlite__with_transaction(svn_sqlite_
 
   return svn_error_return(exec_sql(db, "COMMIT TRANSACTION;"));
 }
+
+svn_error_t *
+svn_sqlite__hotcopy(const char *src_path,
+                    const char *dst_path,
+                    apr_pool_t *scratch_pool)
+{
+  svn_sqlite__db_t *src_db;
+
+  SVN_ERR(svn_sqlite__open(&src_db, src_path, svn_sqlite__mode_readonly,
+                           internal_statements, 0, NULL,
+                           scratch_pool, scratch_pool));
+
+#if SQLITE_VERSION_AT_LEAST(3,6,11)
+  {
+    svn_sqlite__db_t *dst_db;
+    sqlite3_backup *backup;
+    int rc1, rc2;
+
+    SVN_ERR(svn_sqlite__open(&dst_db, dst_path, svn_sqlite__mode_rwcreate,
+                             NULL, 0, NULL, scratch_pool, scratch_pool));
+    backup = sqlite3_backup_init(dst_db->db3, "main", src_db->db3, "main");
+    if (!backup)
+      return svn_error_createf(SVN_ERR_SQLITE_ERROR, NULL,
+                               _("SQLite hotcopy failed for %s"), src_path);
+    do
+      {
+        /* Pages are usually 1024 byte (SQLite docs). On my laptop
+           copying gets faster as the number of pages is increased up
+           to about 64, beyond that speed levels off.  Lets put the
+           number of pages an order of magnitude higher, this is still
+           likely to be a fraction of large databases. */
+        rc1 = sqlite3_backup_step(backup, 1024);
+
+        /* Should we sleep on SQLITE_OK?  That would make copying a
+           large database take much longer.  When we do sleep how,
+           long should we sleep?  Should the sleep get longer if we
+           keep getting BUSY/LOCKED?  I have no real reason for
+           choosing 25. */
+        if (rc1 == SQLITE_BUSY || rc1 == SQLITE_LOCKED)
+          sqlite3_sleep(25);
+      }
+    while (rc1 == SQLITE_OK || rc1 == SQLITE_BUSY || rc1 == SQLITE_LOCKED);
+    rc2 = sqlite3_backup_finish(backup);
+    if (rc1 != SQLITE_DONE)
+      SQLITE_ERR(rc1, dst_db);
+    SQLITE_ERR(rc2, dst_db);
+    SVN_ERR(svn_sqlite__close(dst_db));
+  }
+#else
+  {
+    svn_sqlite__stmt_t *stmt;
+    /* The SELECT takes a shared lock in the source database which
+       blocks writers and so ensures that the database won't change
+       during the copy. */
+    SVN_ERR(svn_sqlite__get_statement(&stmt, src_db,
+                                      STMT_DUMMY_SELECT_FOR_BACKUP));
+    SVN_ERR(svn_sqlite__step_row(stmt));
+    SVN_ERR(svn_io_copy_file(src_path, dst_path, TRUE, scratch_pool));
+  }
+#endif
+
+  SVN_ERR(svn_sqlite__close(src_db));
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/stream.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/stream.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/stream.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/stream.c Tue Aug 10 20:55:56 2010
@@ -57,14 +57,6 @@ struct svn_stream_t {
   svn_io_line_transformer_cb_t line_transformer_cb;
 };
 
-/* A type which represents a mark on a stream. */
-struct svn_stream_mark_t {
-  union {
-    apr_off_t apr;
-    apr_size_t stringbuf;
-  } m;
-};
-
 
 /*** Generic streams. ***/
 
@@ -363,9 +355,9 @@ stream_readline(svn_stringbuf_t **string
 
       /* Read into STR up to and including the next EOL sequence. */
       match = eol_str;
+      numbytes = 1;
       while (*match)
         {
-          numbytes = 1;
           SVN_ERR(svn_stream_read(stream, &c, &numbytes));
           if (numbytes != 1)
             {
@@ -677,6 +669,10 @@ struct baton_apr {
   apr_off_t end;
 };
 
+/* svn_stream_mark_t for streams backed by APR files. */
+struct mark_apr {
+  apr_off_t off;
+};
 
 static svn_error_t *
 read_handler_apr(void *baton, char *buffer, apr_size_t *len)
@@ -727,9 +723,12 @@ static svn_error_t *
 mark_handler_apr(void *baton, svn_stream_mark_t **mark, apr_pool_t *pool)
 {
   struct baton_apr *btn = baton;
-  (*mark) = apr_palloc(pool, sizeof(**mark));
-  (*mark)->m.apr = 0;
-  SVN_ERR(svn_io_file_seek(btn->file, APR_CUR, &(*mark)->m.apr, btn->pool));
+  struct mark_apr *mark_apr;
+
+  mark_apr = apr_palloc(pool, sizeof(*mark_apr));
+  mark_apr->off = 0;
+  SVN_ERR(svn_io_file_seek(btn->file, APR_CUR, &mark_apr->off, btn->pool));
+  *mark = (svn_stream_mark_t *)mark_apr;
   return SVN_NO_ERROR;
 }
 
@@ -737,7 +736,10 @@ static svn_error_t *
 seek_handler_apr(void *baton, svn_stream_mark_t *mark)
 {
   struct baton_apr *btn = baton;
-  SVN_ERR(svn_io_file_seek(btn->file, APR_SET, &mark->m.apr, btn->pool));
+  struct mark_apr *mark_apr;
+
+  mark_apr = (struct mark_apr *)mark;
+  SVN_ERR(svn_io_file_seek(btn->file, APR_SET, &mark_apr->off, btn->pool));
   return SVN_NO_ERROR;
 }
 
@@ -1395,6 +1397,11 @@ struct stringbuf_stream_baton
   apr_size_t amt_read;
 };
 
+/* svn_stream_mark_t for streams backed by stringbufs. */
+struct stringbuf_stream_mark {
+    apr_size_t pos; 
+};
+
 static svn_error_t *
 read_handler_stringbuf(void *baton, char *buffer, apr_size_t *len)
 {
@@ -1427,17 +1434,25 @@ reset_handler_stringbuf(void *baton)
 static svn_error_t *
 mark_handler_stringbuf(void *baton, svn_stream_mark_t **mark, apr_pool_t *pool)
 {
-  struct stringbuf_stream_baton *btn = baton;
-  (*mark) = apr_palloc(pool, sizeof(**mark));
-  (*mark)->m.stringbuf = btn->amt_read;
+  struct stringbuf_stream_baton *btn;
+  struct stringbuf_stream_mark *stringbuf_stream_mark;
+
+  btn = baton;
+  stringbuf_stream_mark = apr_palloc(pool, sizeof(*stringbuf_stream_mark));
+  stringbuf_stream_mark->pos = btn->amt_read;
+  *mark = (svn_stream_mark_t *)stringbuf_stream_mark;
   return SVN_NO_ERROR;
 }
 
 static svn_error_t *
 seek_handler_stringbuf(void *baton, svn_stream_mark_t *mark)
 {
-  struct stringbuf_stream_baton *btn = baton;
-  btn->amt_read = mark->m.stringbuf;
+  struct stringbuf_stream_baton *btn;
+  struct stringbuf_stream_mark *stringbuf_stream_mark;
+
+  btn = baton;
+  stringbuf_stream_mark = (struct stringbuf_stream_mark *)mark;
+  btn->amt_read = stringbuf_stream_mark->pos;
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/subst.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/subst.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/subst.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/subst.c Tue Aug 10 20:55:56 2010
@@ -1029,9 +1029,7 @@ struct translated_stream_baton
   /* Buffer to hold read data
      between svn_stream_read() and translate_chunk(). */
   char *buf;
-
-  /* Pool in which (only!) this baton is allocated. */
-  apr_pool_t *pool;
+#define SVN__TRANSLATION_BUF_SIZE (SVN__STREAM_CHUNK_SIZE + 1)
 
   /* Pool for callback iterations */
   apr_pool_t *iterpool;
@@ -1048,7 +1046,6 @@ translated_stream_read(void *baton,
   apr_size_t readlen = SVN__STREAM_CHUNK_SIZE;
   apr_size_t unsatisfied = *len;
   apr_size_t off = 0;
-  apr_pool_t *iterpool;
 
   /* Optimization for a frequent special case. The configuration parser (and
      a few others) reads the stream one byte at a time. All the memcpy, pool
@@ -1069,13 +1066,12 @@ translated_stream_read(void *baton,
     }
 
   /* Standard code path. */
-  iterpool = b->iterpool;
   while (readlen == SVN__STREAM_CHUNK_SIZE && unsatisfied > 0)
     {
       apr_size_t to_copy;
       apr_size_t buffer_remainder;
 
-      svn_pool_clear(iterpool);
+      svn_pool_clear(b->iterpool);
       /* fill read buffer, if necessary */
       if (! (b->readbuf_off < b->readbuf->len))
         {
@@ -1084,14 +1080,14 @@ translated_stream_read(void *baton,
           svn_stringbuf_setempty(b->readbuf);
           b->readbuf_off = 0;
           SVN_ERR(svn_stream_read(b->stream, b->buf, &readlen));
-          buf_stream = svn_stream_from_stringbuf(b->readbuf, iterpool);
+          buf_stream = svn_stream_from_stringbuf(b->readbuf, b->iterpool);
 
           SVN_ERR(translate_chunk(buf_stream, b->in_baton, b->buf,
-                                  readlen, iterpool));
+                                  readlen, b->iterpool));
 
           if (readlen != SVN__STREAM_CHUNK_SIZE)
             SVN_ERR(translate_chunk(buf_stream, b->in_baton, NULL, 0,
-                                    iterpool));
+                                    b->iterpool));
 
           SVN_ERR(svn_stream_close(buf_stream));
         }
@@ -1135,7 +1131,8 @@ translated_stream_close(void *baton)
 
   SVN_ERR(svn_stream_close(b->stream));
 
-  svn_pool_destroy(b->pool);   /* Also destroys the baton itself */
+  svn_pool_destroy(b->iterpool);
+
   return SVN_NO_ERROR;
 }
 
@@ -1164,13 +1161,39 @@ translated_stream_reset(void *baton)
   return svn_error_return(err);
 }
 
+/* svn_stream_mark_t for translation streams. */
+typedef struct
+{
+  /* Saved translation state. */
+  struct translated_stream_baton saved_baton;
+
+  /* Mark set on the underlying stream. */
+  svn_stream_mark_t *mark;
+} mark_translated_t;
+
 /* Implements svn_io_mark_fn_t. */
 static svn_error_t *
 translated_stream_mark(void *baton, svn_stream_mark_t **mark, apr_pool_t *pool)
 {
+  mark_translated_t *mt;
   struct translated_stream_baton *b = baton;
+  
+  mt = apr_palloc(pool, sizeof(*mt));
+  SVN_ERR(svn_stream_mark(b->stream, &mt->mark, pool));
+
+  /* Save translation state. */
+  mt->saved_baton.in_baton = apr_pmemdup(pool, b->in_baton,
+                                         sizeof(*mt->saved_baton.in_baton));
+  mt->saved_baton.out_baton = apr_pmemdup(pool, b->out_baton,
+                                          sizeof(*mt->saved_baton.out_baton));
+  mt->saved_baton.written = b->written;
+  mt->saved_baton.readbuf = svn_stringbuf_dup(b->readbuf, pool);
+  mt->saved_baton.readbuf_off = b->readbuf_off;
+  mt->saved_baton.buf = apr_pmemdup(pool, b->buf, SVN__TRANSLATION_BUF_SIZE);
+
+  *mark = (svn_stream_mark_t *)mt;
 
-  return svn_error_return(svn_stream_mark(b->stream, mark, pool));
+  return SVN_NO_ERROR;
 }
 
 /* Implements svn_io_seek_fn_t. */
@@ -1178,30 +1201,25 @@ static svn_error_t *
 translated_stream_seek(void *baton, svn_stream_mark_t *mark)
 {
   struct translated_stream_baton *b = baton;
-  svn_error_t *err;
+  mark_translated_t *mt = (mark_translated_t *)mark;
 
   /* Flush output buffer if necessary. */
   if (b->written)
     SVN_ERR(translate_chunk(b->stream, b->out_baton, NULL, 0, b->iterpool));
 
-  err = svn_stream_seek(b->stream, mark);
-  if (err == NULL)
-    {
-      /* Force into boring state. */
-      b->in_baton->newline_off = 0;
-      b->in_baton->keyword_off = 0;
-      b->out_baton->newline_off = 0;
-      b->out_baton->keyword_off = 0;
-
-      /* Output buffer has been flushed. */
-      b->written = FALSE;
+  SVN_ERR(svn_stream_seek(b->stream, mt->mark));
 
-      /* Reset read buffer. */
-      svn_stringbuf_setempty(b->readbuf);
-      b->readbuf_off = 0;
-    }
+  /* Restore translation state, avoiding new allocations. */
+  *b->in_baton = *mt->saved_baton.in_baton;
+  *b->out_baton = *mt->saved_baton.out_baton;
+  b->written = mt->saved_baton.written;
+  svn_stringbuf_setempty(b->readbuf);
+  svn_stringbuf_appendbytes(b->readbuf, mt->saved_baton.readbuf->data, 
+                            mt->saved_baton.readbuf->len);
+  b->readbuf_off = mt->saved_baton.readbuf_off;
+  memcpy(b->buf, mt->saved_baton.buf, SVN__TRANSLATION_BUF_SIZE);
 
-  return svn_error_return(err);
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *
@@ -1248,37 +1266,40 @@ svn_subst_stream_translated(svn_stream_t
                             svn_boolean_t repair,
                             apr_hash_t *keywords,
                             svn_boolean_t expand,
-                            apr_pool_t *pool)
+                            apr_pool_t *result_pool)
 {
-  apr_pool_t *baton_pool = svn_pool_create(pool);
   struct translated_stream_baton *baton
-    = apr_palloc(baton_pool, sizeof(*baton));
-  svn_stream_t *s = svn_stream_create(baton, baton_pool);
+    = apr_palloc(result_pool, sizeof(*baton));
+  svn_stream_t *s = svn_stream_create(baton, result_pool);
 
-  /* Make sure EOL_STR and KEYWORDS are allocated in POOL, as
-     required by create_translation_baton() */
+  /* Make sure EOL_STR and KEYWORDS are allocated in RESULT_POOL
+     so they have the same lifetime as the stream. */
   if (eol_str)
-    eol_str = apr_pstrdup(baton_pool, eol_str);
+    eol_str = apr_pstrdup(result_pool, eol_str);
   if (keywords)
     {
       if (apr_hash_count(keywords) == 0)
         keywords = NULL;
       else
         {
-          /* deep copy the hash to make sure it's allocated in POOL */
-          apr_hash_t *copy = apr_hash_make(baton_pool);
+          /* deep copy the hash to make sure it's allocated in RESULT_POOL */
+          apr_hash_t *copy = apr_hash_make(result_pool);
           apr_hash_index_t *hi;
+          apr_pool_t *subpool;
 
-          for (hi = apr_hash_first(pool, keywords);
+          subpool = svn_pool_create(result_pool);
+          for (hi = apr_hash_first(subpool, keywords);
                hi; hi = apr_hash_next(hi))
             {
               const void *key;
               void *val;
+
               apr_hash_this(hi, &key, NULL, &val);
-              apr_hash_set(copy, apr_pstrdup(baton_pool, key),
+              apr_hash_set(copy, apr_pstrdup(result_pool, key),
                            APR_HASH_KEY_STRING,
-                           svn_string_dup(val, baton_pool));
+                           svn_string_dup(val, result_pool));
             }
+          svn_pool_destroy(subpool);
 
           keywords = copy;
         }
@@ -1287,15 +1308,14 @@ svn_subst_stream_translated(svn_stream_t
   /* Setup the baton fields */
   baton->stream = stream;
   baton->in_baton
-    = create_translation_baton(eol_str, repair, keywords, expand, baton_pool);
+    = create_translation_baton(eol_str, repair, keywords, expand, result_pool);
   baton->out_baton
-    = create_translation_baton(eol_str, repair, keywords, expand, baton_pool);
+    = create_translation_baton(eol_str, repair, keywords, expand, result_pool);
   baton->written = FALSE;
-  baton->readbuf = svn_stringbuf_create("", baton_pool);
+  baton->readbuf = svn_stringbuf_create("", result_pool);
   baton->readbuf_off = 0;
-  baton->iterpool = svn_pool_create(baton_pool);
-  baton->pool = baton_pool;
-  baton->buf = apr_palloc(baton->pool, SVN__STREAM_CHUNK_SIZE + 1);
+  baton->iterpool = svn_pool_create(result_pool);
+  baton->buf = apr_palloc(result_pool, SVN__TRANSLATION_BUF_SIZE);
 
   /* Setup the stream methods */
   svn_stream_set_read(s, translated_stream_read);
@@ -1352,6 +1372,7 @@ svn_subst_translate_cstring2(const char 
 /* ### this should be folded into svn_subst_copy_and_translate3 */
 static svn_error_t *
 detranslate_special_file(const char *src, const char *dst,
+                         svn_cancel_func_t cancel_func, void *cancel_baton,
                          apr_pool_t *scratch_pool)
 {
   const char *dst_tmp;
@@ -1366,10 +1387,11 @@ detranslate_special_file(const char *src
                                  scratch_pool, scratch_pool));
   SVN_ERR(svn_subst_read_specialfile(&src_stream, src,
                                      scratch_pool, scratch_pool));
-  SVN_ERR(svn_stream_copy3(src_stream, dst_stream, NULL, NULL, scratch_pool));
+  SVN_ERR(svn_stream_copy3(src_stream, dst_stream,
+                           cancel_func, cancel_baton, scratch_pool));
 
   /* Do the atomic rename from our temporary location. */
-  return svn_io_file_rename(dst_tmp, dst, scratch_pool);
+  return svn_error_return(svn_io_file_rename(dst_tmp, dst, scratch_pool));
 }
 
 /* Creates a special file DST from the "normal form" located in SOURCE.
@@ -1448,13 +1470,15 @@ create_special_file_from_stream(svn_stre
 
 
 svn_error_t *
-svn_subst_copy_and_translate3(const char *src,
+svn_subst_copy_and_translate4(const char *src,
                               const char *dst,
                               const char *eol_str,
                               svn_boolean_t repair,
                               apr_hash_t *keywords,
                               svn_boolean_t expand,
                               svn_boolean_t special,
+                              svn_cancel_func_t cancel_func,
+                              void *cancel_baton,
                               apr_pool_t *pool)
 {
   svn_stream_t *src_stream;
@@ -1494,7 +1518,10 @@ svn_subst_copy_and_translate3(const char
         }
       /* else !expand */
 
-      return svn_error_return(detranslate_special_file(src, dst, pool));
+      return svn_error_return(detranslate_special_file(src, dst,
+                                                       cancel_func,
+                                                       cancel_baton,
+                                                       pool));
     }
 
   /* The easy way out:  no translation needed, just copy. */
@@ -1514,7 +1541,8 @@ svn_subst_copy_and_translate3(const char
                                            keywords, expand, pool);
 
   /* ###: use cancel func/baton in place of NULL/NULL below. */
-  err = svn_stream_copy3(src_stream, dst_stream, NULL, NULL, pool);
+  err = svn_stream_copy3(src_stream, dst_stream, cancel_func, cancel_baton,
+                         pool);
   if (err)
     {
       /* On errors, we have a pathname available. */

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/utf.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/utf.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/utf.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/utf.c Tue Aug 10 20:55:56 2010
@@ -450,7 +450,6 @@ convert_to_stringbuf(xlate_handle_node_t
   apr_status_t apr_err;
   apr_size_t srclen = src_length;
   apr_size_t destlen = buflen;
-  char *destbuf;
 
   /* Initialize *DEST to an empty stringbuf.
      A 1:2 ratio of input bytes to output bytes (as assigned above)
@@ -458,7 +457,6 @@ convert_to_stringbuf(xlate_handle_node_t
      to be enough, we'll grow the buffer again, sizing it based on a
      1:3 ratio of the remainder of the string. */
   *dest = svn_stringbuf_create_ensure(buflen + 1, pool);
-  destbuf = (*dest)->data;
 
   /* Not only does it not make sense to convert an empty string, but
      apr-iconv is quite unreasonable about not allowing that. */

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/version.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/version.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/version.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/version.c Tue Aug 10 20:55:56 2010
@@ -38,6 +38,13 @@ svn_subr_version(void)
 svn_boolean_t svn_ver_compatible(const svn_version_t *my_version,
                                  const svn_version_t *lib_version)
 {
+  /* With normal development builds the matching rules are strict, to
+     avoid inadvertantly using the wrong libraries.  For backward
+     compatibility testing use --disable-full-version-match to
+     configure 1.7 and then the libraries that get built can be used
+     to replace those in 1.6 or earlier builds.  */
+
+#ifndef SVN_DISABLE_FULL_VERSION_MATCH
   if (lib_version->tag[0] != '\0')
     /* Development library; require exact match. */
     return svn_ver_equal(my_version, lib_version);
@@ -47,10 +54,11 @@ svn_boolean_t svn_ver_compatible(const s
     return (my_version->major == lib_version->major
             && my_version->minor == lib_version->minor
             && my_version->patch > lib_version->patch);
-  else
-    /* General compatibility rules for released versions. */
-    return (my_version->major == lib_version->major
-            && my_version->minor <= lib_version->minor);
+#endif
+
+  /* General compatibility rules for released versions. */
+  return (my_version->major == lib_version->major
+          && my_version->minor <= lib_version->minor);
 }
 
 

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/win32_xlate.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/win32_xlate.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/win32_xlate.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/win32_xlate.c Tue Aug 10 20:55:56 2010
@@ -52,7 +52,7 @@ static svn_atomic_t com_initialized = 0;
 /* Initializes COM and keeps COM available until process exit.
    Implements svn_atomic__init_once init_func */
 static svn_error_t *
-initialize_com(apr_pool_t* pool)
+initialize_com(void *baton, apr_pool_t* pool)
 {
   /* Try to initialize for apartment-threaded object concurrency. */
   HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
@@ -114,7 +114,7 @@ get_page_id_from_name(UINT *page_id_p, c
       return APR_SUCCESS;
     }
 
-  err = svn_atomic__init_once(&com_initialized, initialize_com, pool);
+  err = svn_atomic__init_once(&com_initialized, initialize_com, NULL, pool);
 
   if (err)
     {

Propchange: subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Tue Aug 10 20:55:56 2010
@@ -7,6 +7,5 @@ Release
 *~
 .*~
 libsvn_wc.def
-wc-metadata.h
 wc-checks.h
 wc-queries.h

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/README
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/README?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/README (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/README Tue Aug 10 20:55:56 2010
@@ -1,5 +1,13 @@
      Oh Most High and Fragrant Emacs, please be in -*- text -*- mode!
 
+##############################################################################
+### The vast majority of this file is completely out-of-date as a result   ###
+### of the ongoing work known as WC-NG.  Please consult that documentation ###
+### for a more relevant and complete reference.                            ###
+### (See the files in notes/wc-ng )                                        ###
+##############################################################################
+
+
 This is the library described in the section "The working copy
 management library" of svn-design.texi.  It performs local operations
 in the working copy, tweaking administrative files and versioned data.

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_crawler.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_crawler.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_crawler.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_crawler.c Tue Aug 10 20:55:56 2010
@@ -48,6 +48,7 @@
 #include "entries.h"
 #include "lock.h"
 #include "workqueue.h"
+#include "conflicts.h"
 
 #include "svn_private_config.h"
 
@@ -69,7 +70,7 @@ restore_file(svn_wc__db_t *db,
              svn_boolean_t use_commit_times,
              apr_pool_t *scratch_pool)
 {
-  const svn_skel_t *work_item;
+  svn_skel_t *work_item;
 
   SVN_ERR(svn_wc__wq_build_file_install(&work_item,
                                         db, local_abspath,
@@ -88,12 +89,8 @@ restore_file(svn_wc__db_t *db,
                          scratch_pool));
 
   /* Remove any text conflict */
-  SVN_ERR(svn_wc__internal_resolved_conflict(
-                    db, local_abspath, svn_depth_empty, TRUE, NULL, FALSE,
-                    svn_wc_conflict_choose_merged, NULL, NULL, NULL, NULL,
-                    scratch_pool));
-
-  return SVN_NO_ERROR;
+  return svn_error_return(svn_wc__resolve_text_conflict(db, local_abspath,
+                                                        scratch_pool));
 }
 
 /* Try to restore LOCAL_ABSPATH of node type KIND and if successfull,
@@ -137,8 +134,6 @@ restore_node(svn_boolean_t *restored,
           notify->kind = svn_node_file;
           (*notify_func)(notify_baton, notify, scratch_pool);
         }
-
-      /* Keep missing = FALSE */
     }
 
   return SVN_NO_ERROR;
@@ -148,7 +143,7 @@ restore_node(svn_boolean_t *restored,
    using DB.  In that case send the externals definition and DEPTH to
    EXTERNAL_FUNC.  Use SCRATCH_POOL for temporary allocations. */
 static svn_error_t *
-read_traversal_info(svn_wc__db_t *db,
+read_externals_info(svn_wc__db_t *db,
                     const char *local_abspath,
                     svn_wc_external_update_t external_func,
                     void *external_baton,
@@ -207,16 +202,8 @@ read_traversal_info(svn_wc__db_t *db,
    DEPTH_COMPATIBILITY_TRICK means the same thing here as it does
    in svn_wc_crawl_revisions3().
 
-   If TRAVERSAL_INFO is non-null, record this directory's
-   value of svn:externals in both TRAVERSAL_INFO->externals_old and
-   TRAVERSAL_INFO->externals_new, using wc_path + dir_path as the key,
-   and the raw (unparsed) value of the property as the value; store
-   this directory's depth in TRAVERSAL_INFO->depths, using the same
-   key and svn_depth_to_word(depth) as the value.  (Note: We set the
-   property value in both places, because its absence in just one or
-   the other place signals that the property was added or deleted;
-   thus, storing it in both places signals that it is present and, by
-   default, unchanged.)
+   If EXTERNAL_FUNC is non-NULL, then send externals information with
+   the help of EXTERNAL_BATON
 
    If RESTORE_FILES is set, then unexpectedly missing working files
    will be restored from text-base and NOTIFY_FUNC/NOTIFY_BATON
@@ -242,7 +229,7 @@ report_revisions_and_depths(svn_wc__db_t
                             apr_pool_t *scratch_pool)
 {
   const char *dir_abspath;
-  const apr_array_header_t *children;
+  const apr_array_header_t *base_children;
   apr_hash_t *dirents;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   int i;
@@ -254,7 +241,7 @@ report_revisions_and_depths(svn_wc__db_t
      notice that we're picking up hidden entries too (read_children never
      hides children). */
   dir_abspath = svn_dirent_join(anchor_abspath, dir_path, scratch_pool);
-  SVN_ERR(svn_wc__db_base_get_children(&children, db, dir_abspath,
+  SVN_ERR(svn_wc__db_base_get_children(&base_children, db, dir_abspath,
                                        scratch_pool, iterpool));
   SVN_ERR(svn_io_get_dir_filenames(&dirents, dir_abspath, scratch_pool));
 
@@ -275,18 +262,52 @@ report_revisions_and_depths(svn_wc__db_t
                                        NULL, db, dir_abspath,
                                        scratch_pool, iterpool));
 
-  /* If "this dir" has "svn:externals" property set on it, store its name
-     and depth in traversal_info. */
+  /* If "this dir" has "svn:externals" property set on it,
+   * call the external_func callback. */
   if (external_func)
     {
-      SVN_ERR(read_traversal_info(db, dir_abspath, external_func,
+      const apr_array_header_t *all_children;
+
+      SVN_ERR(read_externals_info(db, dir_abspath, external_func,
                                   external_baton, dir_depth, iterpool));
+
+      /* Also do this for added children. They aren't part of the base
+       * tree so we don't recurse into them. But our caller might still
+       * want to pull externals into them as part of the update operation. */
+      SVN_ERR(svn_wc__db_read_children(&all_children, db, dir_abspath,
+                                       scratch_pool, iterpool));
+      for (i = 0; i < all_children->nelts; ++i)
+        {
+          const char *child = APR_ARRAY_IDX(all_children, i, const char *);
+          const char *this_abspath;
+          svn_wc__db_status_t this_status;
+          svn_wc__db_kind_t this_kind;
+          svn_depth_t this_depth;
+
+          svn_pool_clear(iterpool);
+
+          this_abspath = svn_dirent_join(dir_abspath, child, iterpool);
+          SVN_ERR(svn_wc__db_read_info(&this_status, &this_kind, NULL, NULL,
+                                       NULL, NULL, NULL, NULL, NULL, NULL,
+                                       &this_depth, NULL, NULL, NULL, NULL,
+                                       NULL, NULL, NULL, NULL, NULL, NULL,
+                                       NULL, NULL, NULL,
+                                       db, this_abspath, iterpool, iterpool));
+          if (this_kind == svn_wc__db_kind_dir &&
+              this_status == svn_wc__db_status_added)
+            {
+              SVN_ERR(read_externals_info(db, this_abspath, external_func,
+                                          external_baton, this_depth,
+                                          iterpool));
+            }
+        }
     }
 
-  /* Looping over current directory's SVN entries: */
-  for (i = 0; i < children->nelts; ++i)
+
+  /* Looping over current directory's BASE children: */
+  for (i = 0; i < base_children->nelts; ++i)
     {
-      const char *child = APR_ARRAY_IDX(children, i, const char *);
+      const char *child = APR_ARRAY_IDX(base_children, i, const char *);
       const char *this_path, *this_abspath;
       const char *this_repos_root_url, *this_repos_relpath;
       svn_wc__db_status_t this_status;
@@ -310,31 +331,40 @@ report_revisions_and_depths(svn_wc__db_t
                                      NULL, NULL, NULL, NULL, NULL, &this_depth,
                                      NULL, NULL, NULL, &this_lock,
                                      db, this_abspath, iterpool, iterpool);
+      if (err)
+        {
+          if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
+            return svn_error_return(err);
 
-      if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
-        svn_error_clear(err);
-      else
-        SVN_ERR(err);
+          /* THIS_ABSPATH was listed as a BASE child of DIR_ABSPATH. Yet,
+             we just got an error trying to read it. What gives? :-P
 
-      /* ### While still using parent stubs: Fetch info from the stub.
-             Handles the error case above */
-      {
-        svn_boolean_t not_present;
+             This happens when THIS_ABSPATH is a subdirectory that is
+             marked in the parent stub as "not-present". The subdir is
+             then removed. Later, an addition is scheduled, putting the
+             subdirectory back, but ONLY containing WORKING nodes.
 
-        SVN_ERR(svn_wc__db_temp_is_dir_deleted(&not_present, &this_rev, db,
-                                               this_abspath, iterpool));
+             Thus, the BASE fetch comes out of the subdir, and fails.
 
-        if (not_present || err)
-          this_status = svn_wc__db_status_not_present;
+             For this case, we go ahead and treat this as a simple
+             not-present, and ignore whatever is in the subdirectory.  */
+          svn_error_clear(err);
 
-        if (!SVN_IS_VALID_REVNUM(this_rev))
-          this_rev = dir_rev; /* Obstructed node */
-      } /* /Stub handling */
+          this_status = svn_wc__db_status_not_present;
 
-      if (this_depth == svn_depth_unknown)
-        this_depth = svn_depth_infinity;
+          /* Note: the other THIS_* local variables pass to base_get_info
+             are NOT set at this point. But we don't need them...  */
+        }
 
-      SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(this_rev));
+      /* Note: some older code would attempt to check the parent stub
+         of subdirectories for the not-present state. That check was
+         redundant since a not-present directory has no BASE nodes
+         within it which may report another status.
+
+         There might be NO BASE node (per the condition above), but the
+         typical case is that base_get_info() reads the parent stub
+         because there is no subdir (with administrative data). Thus, we
+         already have all the information we need. No further testing.  */
 
       /* First check for exclusion */
       if (this_status == svn_wc__db_status_excluded)
@@ -360,8 +390,8 @@ report_revisions_and_depths(svn_wc__db_t
             }
           else
             {
-              /* We want to pull in the excluded target. So, report it as deleted,
-                 and server will respond properly. */
+              /* We want to pull in the excluded target. So, report it as
+                 deleted, and server will respond properly. */
               if (! report_everything)
                 SVN_ERR(reporter->delete_path(report_baton,
                                               this_path, iterpool));
@@ -370,20 +400,23 @@ report_revisions_and_depths(svn_wc__db_t
         }
 
       /*** The Big Tests: ***/
-      if (this_status == svn_wc__db_status_absent ||
-          this_status == svn_wc__db_status_excluded ||
-          this_status == svn_wc__db_status_not_present)
+      if (this_status == svn_wc__db_status_absent
+          || this_status == svn_wc__db_status_not_present)
         {
-          /* If the entry is 'deleted' or 'absent', make sure the server
+          /* If the entry is 'absent' or 'not-present', make sure the server
              knows it's gone...
              ...unless we're reporting everything, in which case we're
-             going to report it missing later anyway. */
+             going to report it missing later anyway.
+
+             This instructs the server to send it back to us, if it is
+             now available (an addition after a not-present state), or if
+             it is now authorized (change in authz for the absent item).  */
           if (! report_everything)
             SVN_ERR(reporter->delete_path(report_baton, this_path, iterpool));
           continue;
         }
 
-      /* Is the entry on disk? */
+      /* Is the entry NOT on the disk? We may be able to restore it.  */
       if (apr_hash_get(dirents, child, APR_HASH_KEY_STRING) == NULL)
         {
           svn_boolean_t missing = FALSE;
@@ -413,10 +446,10 @@ report_revisions_and_depths(svn_wc__db_t
               if (dirent_kind == svn_node_none)
                 {
                   svn_boolean_t restored;
+
                   SVN_ERR(restore_node(&restored, db, this_abspath, wrk_kind,
                                        use_commit_times, notify_func,
                                        notify_baton, iterpool));
-
                   if (!restored)
                     missing = TRUE;
                 }
@@ -424,10 +457,10 @@ report_revisions_and_depths(svn_wc__db_t
           else
             missing = TRUE;
 
-          /* If a node is still missing from disk here, we have no way to recreate
-             it locally, so report as missing and move along.  Again, don't bother
-             if we're reporting everything, because the dir is already missing on
-             the server. */
+          /* If a node is still missing from disk here, we have no way to
+             recreate it locally, so report as missing and move along.
+             Again, don't bother if we're reporting everything, because the
+             dir is already missing on the server. */
           if (missing && wrk_kind == svn_wc__db_kind_dir
                && (depth > svn_depth_files || depth == svn_depth_unknown))
             {
@@ -447,15 +480,28 @@ report_revisions_and_depths(svn_wc__db_t
         }
       else
         {
-          const char *childname = svn_uri_is_child(dir_repos_relpath,
-                                                   this_repos_relpath, NULL);
+          const char *childname = svn_relpath_is_child(dir_repos_relpath,
+                                                       this_repos_relpath,
+                                                       NULL);
 
-          if (!childname || strcmp(childname, child) != 0)
+          if (childname == NULL || strcmp(childname, child) != 0)
             this_switched = TRUE;
           else
             this_switched = FALSE;
         }
 
+      /* Tweak THIS_DEPTH to a useful value.  */
+      if (this_depth == svn_depth_unknown)
+        this_depth = svn_depth_infinity;
+
+      /* Obstructed nodes might report SVN_INVALID_REVNUM. Tweak it.
+
+         ### it seems that obstructed nodes should be handled quite a
+         ### bit differently. maybe reported as missing, like not-present
+         ### or absent nodes?  */
+      if (!SVN_IS_VALID_REVNUM(this_rev))
+        this_rev = dir_rev;
+
       /*** Files ***/
       if (this_kind == svn_wc__db_kind_file ||
           this_kind == svn_wc__db_kind_symlink)
@@ -515,8 +561,26 @@ report_revisions_and_depths(svn_wc__db_t
                && (depth > svn_depth_files
                    || depth == svn_depth_unknown))
         {
-          svn_boolean_t is_incomplete = (this_status == svn_wc__db_status_incomplete);
-          svn_boolean_t start_empty = is_incomplete;
+          svn_boolean_t is_incomplete;
+          svn_boolean_t start_empty;
+
+          /* If the subdir and its administrative area are not present,
+             then do NOT bother to report this node, much less recurse
+             into the thing.
+
+             Note: if the there is nothing on the disk, then we may have
+             reported it missing further above.
+
+             ### hmm. but what if we have a *file* obstructing the dir?
+             ### the code above will not report it, and we'll simply
+             ### skip it right here. I guess with an obstruction, we
+             ### can't really do anything with info the server might
+             ### send, so maybe this is just fine.  */
+          if (this_status == svn_wc__db_status_obstructed)
+            continue;
+
+          is_incomplete = (this_status == svn_wc__db_status_incomplete);
+          start_empty = is_incomplete;
 
           if (depth_compatibility_trick
               && this_depth <= svn_depth_files
@@ -831,6 +895,8 @@ svn_wc_crawl_revisions5(svn_wc_context_t
   SVN_ERR(reporter->set_path(report_baton, "", target_rev, target_depth,
                              start_empty, NULL, scratch_pool));
 
+  /* ### status can NEVER be deleted. should examine why this was
+     ### ever here. we may have remapped into wc-ng incorrectly.  */
   if (status != svn_wc__db_status_deleted)
     {
       apr_finfo_t info;
@@ -1043,7 +1109,8 @@ copying_stream(svn_stream_t *source,
 
 svn_error_t *
 svn_wc__internal_transmit_text_deltas(const char **tempfile,
-                                      unsigned char digest[],
+                                      const svn_checksum_t **new_text_base_md5_checksum,
+                                      const svn_checksum_t **new_text_base_sha1_checksum,
                                       svn_wc__db_t *db,
                                       const char *local_abspath,
                                       svn_boolean_t fulltext,
@@ -1054,13 +1121,14 @@ svn_wc__internal_transmit_text_deltas(co
 {
   svn_txdelta_window_handler_t handler;
   void *wh_baton;
-  const char *base_digest_hex;
-  const svn_checksum_t *expected_checksum = NULL;
-  svn_checksum_t *verify_checksum = NULL;
-  svn_checksum_t *local_checksum;
+  const svn_checksum_t *expected_md5_checksum;
+  svn_checksum_t *verify_checksum = NULL;  /* calc'd MD5 of BASE_STREAM */
+  svn_checksum_t *local_md5_checksum;  /* calc'd MD5 of LOCAL_STREAM */
+  svn_checksum_t *local_sha1_checksum;  /* calc'd SHA1 of LOCAL_STREAM */
+  const char *new_pristine_tmp_abspath;
   svn_error_t *err;
-  svn_stream_t *base_stream;
-  svn_stream_t *local_stream;
+  svn_stream_t *base_stream;  /* delta source */
+  svn_stream_t *local_stream;  /* delta target: LOCAL_ABSPATH transl. to NF */
 
   /* Translated input */
   SVN_ERR(svn_wc__internal_translated_stream(&local_stream, db,
@@ -1073,33 +1141,42 @@ svn_wc__internal_transmit_text_deltas(co
    * *TEMPFILE to the path to it. */
   if (tempfile)
     {
-      const char *tmp_base;
-      apr_file_t *tempbasefile;
-
-      SVN_ERR(svn_wc__text_base_path(&tmp_base, db, local_abspath, TRUE,
-                                     scratch_pool));
+      svn_stream_t *tempstream;
 
-      *tempfile = tmp_base;
+      SVN_ERR(svn_wc__text_base_deterministic_tmp_path(tempfile,
+                                                       db, local_abspath,
+                                                       result_pool));
 
       /* Make an untranslated copy of the working file in the
          administrative tmp area because a) we need to detranslate eol
          and keywords anyway, and b) after the commit, we're going to
          copy the tmp file to become the new text base anyway. */
-      SVN_ERR(svn_io_file_open(&tempbasefile, tmp_base,
-                               APR_WRITE | APR_CREATE, APR_OS_DEFAULT,
-                               result_pool));
+      SVN_ERR(svn_stream_open_writable(&tempstream, *tempfile,
+                                       scratch_pool, scratch_pool));
 
       /* Wrap the translated stream with a new stream that writes the
          translated contents into the new text base file as we read from it.
          Note that the new text base file will be closed when the new stream
          is closed. */
-      local_stream
-        = copying_stream(local_stream,
-                         svn_stream_from_aprfile2(tempbasefile, FALSE,
-                                                  scratch_pool),
-                         scratch_pool);
+      local_stream = copying_stream(local_stream, tempstream, scratch_pool);
+    }
+  if (new_text_base_sha1_checksum)
+    {
+      svn_stream_t *new_pristine_stream;
+
+      SVN_ERR(svn_wc__open_writable_base(&new_pristine_stream,
+                                         &new_pristine_tmp_abspath,
+                                         NULL, &local_sha1_checksum,
+                                         db, local_abspath,
+                                         scratch_pool, scratch_pool));
+      local_stream = copying_stream(local_stream, new_pristine_stream,
+                                    scratch_pool);
     }
 
+  /* Set BASE_STREAM to a stream providing the base (source) content for the
+   * delta, which may be an empty stream;
+   * set EXPECTED_CHECKSUM to its stored (or possibly calculated) MD5 checksum;
+   * and (usually) arrange for its VERIFY_CHECKSUM to be calculated later. */
   if (! fulltext)
     {
       /* Compute delta against the pristine contents */
@@ -1112,20 +1189,37 @@ svn_wc__internal_transmit_text_deltas(co
                                    NULL, NULL, NULL,
                                    NULL, NULL, NULL,
                                    NULL, NULL,
-                                   &expected_checksum, NULL,
+                                   &expected_md5_checksum, NULL,
                                    NULL, NULL, NULL, NULL, NULL,
                                    NULL, NULL, NULL,
                                    NULL, NULL, NULL,
                                    db, local_abspath,
                                    scratch_pool, scratch_pool));
+      /* SVN_EXPERIMENTAL_PRISTINE:
+         If we got a SHA-1, get the corresponding MD-5. */
+      if (expected_md5_checksum
+          && expected_md5_checksum->kind != svn_checksum_md5)
+        SVN_ERR(svn_wc__db_pristine_get_md5(&expected_md5_checksum,
+                                            db, local_abspath,
+                                            expected_md5_checksum,
+                                            scratch_pool, scratch_pool));
 
-      /* ### We want expected_checksum to ALWAYS be present, but on old
-         ### working copies maybe it won't be (unclear?). If it is there,
-         ### then we can use it as an expected value. If it is NOT there,
-         ### then we must compute it for the apply_textdelta() call. */
-      if (expected_checksum)
+      /* ### We want expected_md5_checksum to ALWAYS be present, but on old
+         working copies maybe it won't be (unclear?).  If it is there,
+         then we can pass it to apply_textdelta() as required, and later on
+         we can use it as an expected value to verify against.  Therefore
+         we prepare now to calculate (during the later reading of the base
+         stream) the actual checksum of the base stream as VERIFY_CHECKSUM.
+
+         If the base checksum was NOT recorded, then we must compute it NOW
+         for the apply_textdelta() call.  In this case, we won't bother to
+         calculate it a second time during the later reading of the stream
+         for the purpose of verification, and will leave VERIFY_CHECKSUM as
+         NULL. */
+      if (expected_md5_checksum)
         {
-          /* Compute a checksum for what is *actually* found */
+          /* Arrange to set VERIFY_CHECKSUM to the MD5 of what is *actually*
+             found when the base stream is read. */
           base_stream = svn_stream_checksummed2(base_stream, &verify_checksum,
                                                 NULL, svn_checksum_md5, TRUE,
                                                 scratch_pool);
@@ -1135,6 +1229,8 @@ svn_wc__internal_transmit_text_deltas(co
           svn_stream_t *p_stream;
           svn_checksum_t *p_checksum;
 
+          /* Set EXPECTED_CHECKSUM to the MD5 checksum of the existing
+           * pristine text, by reading the text and calculating it. */
           /* ### we should ALREADY have the checksum for pristine. */
           SVN_ERR(svn_wc__get_pristine_contents(&p_stream, db, local_abspath,
                                                 scratch_pool, scratch_pool));
@@ -1148,29 +1244,37 @@ svn_wc__internal_transmit_text_deltas(co
           /* Closing this will cause a full read/checksum. */
           SVN_ERR(svn_stream_close(p_stream));
 
-          expected_checksum = p_checksum;
+          expected_md5_checksum = p_checksum;
         }
-
-      /* apply_textdelta() is working against a base with this checksum */
-      base_digest_hex = svn_checksum_to_cstring_display(expected_checksum,
-                                                        scratch_pool);
     }
   else
     {
       /* Send a fulltext. */
       base_stream = svn_stream_empty(scratch_pool);
-      base_digest_hex = NULL;
+      expected_md5_checksum = NULL;
     }
 
   /* Tell the editor that we're about to apply a textdelta to the
      file baton; the editor returns to us a window consumer and baton.  */
-  SVN_ERR(editor->apply_textdelta(file_baton, base_digest_hex, scratch_pool,
-                                  &handler, &wh_baton));
+  {
+    /* apply_textdelta() is working against a base with this checksum */
+    const char *base_digest_hex = NULL;
+
+    if (expected_md5_checksum)
+      /* ### Why '..._display()'?  expected_md5_checksum should never be all-
+       * zero, but if it is, we would want to pass NULL not an all-zero
+       * digest to apply_textdelta(), wouldn't we? */
+      base_digest_hex = svn_checksum_to_cstring_display(expected_md5_checksum,
+                                                        scratch_pool);
+
+    SVN_ERR(editor->apply_textdelta(file_baton, base_digest_hex, scratch_pool,
+                                    &handler, &wh_baton));
+  }
 
   /* Run diff processing, throwing windows at the handler. */
   err = svn_txdelta_run(base_stream, local_stream,
                         handler, wh_baton,
-                        svn_checksum_md5, &local_checksum,
+                        svn_checksum_md5, &local_md5_checksum,
                         NULL, NULL,
                         scratch_pool, scratch_pool);
 
@@ -1189,8 +1293,8 @@ svn_wc__internal_transmit_text_deltas(co
 
   /* If we have an error, it may be caused by a corrupt text base.
      Check the checksum and discard `err' if they don't match. */
-  if (expected_checksum && verify_checksum
-      && !svn_checksum_match(expected_checksum, verify_checksum))
+  if (expected_md5_checksum && verify_checksum
+      && !svn_checksum_match(expected_md5_checksum, verify_checksum))
     {
       /* The entry checksum does not match the actual text
          base checksum.  Extreme badness. Of course,
@@ -1210,22 +1314,16 @@ svn_wc__internal_transmit_text_deltas(co
       if (tempfile)
         svn_error_clear(svn_io_remove_file2(*tempfile, TRUE, scratch_pool));
 
-      {
-        const char *text_base;
-
-        SVN_ERR(svn_wc__text_base_path(&text_base, db, local_abspath, FALSE,
-                                       scratch_pool));
-
-        return svn_error_createf(SVN_ERR_WC_CORRUPT_TEXT_BASE, NULL,
-                      _("Checksum mismatch for '%s':\n"
-                        "   expected:  %s\n"
-                        "     actual:  %s\n"),
-                      svn_dirent_local_style(text_base, scratch_pool),
-                      svn_checksum_to_cstring_display(expected_checksum,
+      return svn_error_createf(SVN_ERR_WC_CORRUPT_TEXT_BASE, NULL,
+                               _("Checksum mismatch for text base of '%s':\n"
+                                 "   expected:  %s\n"
+                                 "     actual:  %s\n"),
+                               svn_dirent_local_style(local_abspath,
                                                       scratch_pool),
-                      svn_checksum_to_cstring_display(verify_checksum,
-                                                      scratch_pool));
-      }
+                               svn_checksum_to_cstring_display(
+                                 expected_md5_checksum, scratch_pool),
+                               svn_checksum_to_cstring_display(
+                                 verify_checksum, scratch_pool));
     }
 
   /* Now, handle that delta transmission error if any, so we can stop
@@ -1235,19 +1333,32 @@ svn_wc__internal_transmit_text_deltas(co
                               svn_dirent_local_style(local_abspath,
                                                      scratch_pool)));
 
-  if (digest)
-    memcpy(digest, local_checksum->digest, svn_checksum_size(local_checksum));
+  if (new_text_base_md5_checksum)
+    *new_text_base_md5_checksum = svn_checksum_dup(local_md5_checksum,
+                                                   result_pool);
+  if (new_text_base_sha1_checksum)
+    {
+#ifdef SVN_EXPERIMENTAL_PRISTINE
+      SVN_ERR(svn_wc__db_pristine_install(db, new_pristine_tmp_abspath,
+                                          local_sha1_checksum,
+                                          local_md5_checksum,
+                                          scratch_pool));
+#endif
+      *new_text_base_sha1_checksum = svn_checksum_dup(local_sha1_checksum,
+                                                      result_pool);
+    }
 
   /* Close the file baton, and get outta here. */
   return editor->close_file(file_baton,
-                            svn_checksum_to_cstring(local_checksum,
+                            svn_checksum_to_cstring(local_md5_checksum,
                                                     scratch_pool),
                             scratch_pool);
 }
 
 svn_error_t *
 svn_wc_transmit_text_deltas3(const char **tempfile,
-                             unsigned char digest[],
+                             const svn_checksum_t **new_text_base_md5_checksum,
+                             const svn_checksum_t **new_text_base_sha1_checksum,
                              svn_wc_context_t *wc_ctx,
                              const char *local_abspath,
                              svn_boolean_t fulltext,
@@ -1256,8 +1367,11 @@ svn_wc_transmit_text_deltas3(const char 
                              apr_pool_t *result_pool,
                              apr_pool_t *scratch_pool)
 {
-  return svn_wc__internal_transmit_text_deltas(tempfile, digest, wc_ctx->db,
-                                               local_abspath, fulltext, editor,
+  return svn_wc__internal_transmit_text_deltas(tempfile,
+                                               new_text_base_md5_checksum,
+                                               new_text_base_sha1_checksum,
+                                               wc_ctx->db, local_abspath,
+                                               fulltext, editor,
                                                file_baton, result_pool,
                                                scratch_pool);
 }
@@ -1269,28 +1383,33 @@ svn_wc__internal_transmit_prop_deltas(sv
                                      void *baton,
                                      apr_pool_t *scratch_pool)
 {
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   int i;
   apr_array_header_t *propmods;
   svn_wc__db_kind_t kind;
 
-  SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath, FALSE, scratch_pool));
+  SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath, FALSE, iterpool));
 
   /* Get an array of local changes by comparing the hashes. */
   SVN_ERR(svn_wc__internal_propdiff(&propmods, NULL, db, local_abspath,
-                                    scratch_pool, scratch_pool));
+                                    scratch_pool, iterpool));
 
   /* Apply each local change to the baton */
   for (i = 0; i < propmods->nelts; i++)
     {
       const svn_prop_t *p = &APR_ARRAY_IDX(propmods, i, svn_prop_t);
+
+      svn_pool_clear(iterpool);
+
       if (kind == svn_wc__db_kind_file)
         SVN_ERR(editor->change_file_prop(baton, p->name, p->value,
-                                         scratch_pool));
+                                         iterpool));
       else
         SVN_ERR(editor->change_dir_prop(baton, p->name, p->value,
-                                        scratch_pool));
+                                        iterpool));
     }
 
+  svn_pool_destroy(iterpool);
   return SVN_NO_ERROR;
 }