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 2012/02/08 03:15:44 UTC

svn commit: r1241739 [2/2] - in /subversion/branches/ev2-export: ./ build/ subversion/bindings/swig/ subversion/bindings/swig/include/ subversion/bindings/swig/perl/libsvn_swig_perl/ subversion/bindings/swig/perl/native/t/ subversion/bindings/swig/pyth...

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/commit.c?rev=1241739&r1=1241738&r2=1241739&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/commit.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/commit.c Wed Feb  8 02:15:42 2012
@@ -794,9 +794,19 @@ prop_fetch_func(apr_hash_t **props,
   svn_fs_root_t *fs_root;
   svn_error_t *err;
 
-  if (path[0] != '/')
-    /* Get an absolute path for use in the FS. */
-    path = svn_fspath__join(eb->base_path, path, scratch_pool);
+  if (svn_path_is_url(path))
+    {
+      /* This is a copyfrom URL. */
+      path = svn_uri_skip_ancestor(eb->repos_url, path, scratch_pool);
+      path = svn_fspath__canonicalize(path, scratch_pool);
+    }
+  else
+    {
+      /* This is a base-relative path. */
+      if (path[0] != '/')
+        /* Get an absolute path for use in the FS. */
+        path = svn_fspath__join(eb->base_path, path, scratch_pool);
+    }
 
   SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs,
                                svn_fs_txn_base_revision(eb->txn),

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/fs-wrap.c?rev=1241739&r1=1241738&r2=1241739&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/fs-wrap.c Wed Feb  8 02:15:42 2012
@@ -61,7 +61,7 @@ svn_repos_fs_commit_txn(const char **con
     return err;
 
   /* Run post-commit hooks. */
-  if ((err2 = svn_repos__hooks_post_commit(repos, *new_rev, pool)))
+  if ((err2 = svn_repos__hooks_post_commit(repos, *new_rev, txn_name, pool)))
     {
       err2 = svn_error_create
                (SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED, err2,

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/hooks.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/hooks.c?rev=1241739&r1=1241738&r2=1241739&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/hooks.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/hooks.c Wed Feb  8 02:15:42 2012
@@ -159,6 +159,37 @@ check_hook_result(const char *name, cons
                           failure_message->data);
 }
 
+/* Copy the environment given as key/value pairs of ENV_HASH into
+ * an array of C strings allocated in RESULT_POOL.
+ * If the hook environment is empty, return NULL.
+ * Use SCRATCH_POOL for temporary allocations. */
+static const char **
+env_from_env_hash(apr_hash_t *env_hash,
+                  apr_pool_t *result_pool,
+                  apr_pool_t *scratch_pool)
+{
+  apr_hash_index_t *hi;
+  const char **env;
+  const char **envp;
+  
+  if (!env_hash)
+    return NULL;
+
+  env = apr_palloc(result_pool,
+                   sizeof(const char *) * (apr_hash_count(env_hash) + 1));
+  envp = env;
+  for (hi = apr_hash_first(scratch_pool, env_hash); hi; hi = apr_hash_next(hi))
+    {
+      *envp = apr_psprintf(result_pool, "%s=%s",
+                           (const char *)svn__apr_hash_index_key(hi),
+                           (const char *)svn__apr_hash_index_val(hi));
+      envp++;
+    }
+  *envp = NULL;
+
+  return env;
+}
+
 /* NAME, CMD and ARGS are the name, path to and arguments for the hook
    program that is to be run.  The hook's exit status will be checked,
    and if an error occurred the hook's stderr output will be added to
@@ -174,7 +205,7 @@ run_hook_cmd(svn_string_t **result,
              const char *name,
              const char *cmd,
              const char **args,
-             const char *const *hooks_env,
+             apr_hash_t *hooks_env,
              apr_file_t *stdin_handle,
              apr_pool_t *pool)
 {
@@ -197,9 +228,10 @@ run_hook_cmd(svn_string_t **result,
             (apr_err, _("Can't create null stdout for hook '%s'"), cmd);
     }
 
-  err = svn_io_start_cmd3(&cmd_proc, ".", cmd, args, hooks_env, FALSE,
-                          FALSE, stdin_handle, result != NULL, null_handle,
-                          TRUE, NULL, pool);
+  err = svn_io_start_cmd3(&cmd_proc, ".", cmd, args,
+                          env_from_env_hash(hooks_env, pool, pool),
+                          FALSE, FALSE, stdin_handle, result != NULL,
+                          null_handle, TRUE, NULL, pool);
 
   if (err)
     {
@@ -449,6 +481,7 @@ svn_repos__hooks_pre_commit(svn_repos_t 
 svn_error_t  *
 svn_repos__hooks_post_commit(svn_repos_t *repos,
                              svn_revnum_t rev,
+                             const char *txn_name,
                              apr_pool_t *pool)
 {
   const char *hook = svn_repos_post_commit_hook(repos, pool);
@@ -460,12 +493,13 @@ svn_repos__hooks_post_commit(svn_repos_t
     }
   else if (hook)
     {
-      const char *args[4];
+      const char *args[5];
 
       args[0] = hook;
       args[1] = svn_dirent_local_style(svn_repos_path(repos, pool), pool);
       args[2] = apr_psprintf(pool, "%ld", rev);
-      args[3] = NULL;
+      args[3] = txn_name;
+      args[4] = NULL;
 
       SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_POST_COMMIT, hook, args,
                            repos->hooks_env, NULL, pool));

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/load-fs-vtable.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/load-fs-vtable.c?rev=1241739&r1=1241738&r2=1241739&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/load-fs-vtable.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/load-fs-vtable.c Wed Feb  8 02:15:42 2012
@@ -900,19 +900,28 @@ close_revision(void *baton)
   const char *conflict_msg = NULL;
   svn_revnum_t committed_rev;
   svn_error_t *err;
+  const char *txn_name;
 
   /* If we're skipping this revision or it has an invalid revision
      number, we're done here. */
   if (rb->skipped || (rb->rev <= 0))
     return SVN_NO_ERROR;
 
+  /* Get the txn name, if it will be needed. */
+  if (pb->use_pre_commit_hook || pb->use_post_commit_hook)
+    {
+      err = svn_fs_txn_name(&txn_name, rb->txn, rb->pool);
+      if (err)
+        {
+          svn_error_clear(svn_fs_abort_txn(rb->txn, rb->pool));
+          return svn_error_trace(err);
+        }
+    }
+
   /* Run the pre-commit hook, if so commanded. */
   if (pb->use_pre_commit_hook)
     {
-      const char *txn_name;
-      err = svn_fs_txn_name(&txn_name, rb->txn, rb->pool);
-      if (! err)
-        err = svn_repos__hooks_pre_commit(pb->repos, txn_name, rb->pool);
+      err = svn_repos__hooks_pre_commit(pb->repos, txn_name, rb->pool);
       if (err)
         {
           svn_error_clear(svn_fs_abort_txn(rb->txn, rb->pool));
@@ -945,7 +954,7 @@ close_revision(void *baton)
   if (pb->use_post_commit_hook)
     {
       if ((err = svn_repos__hooks_post_commit(pb->repos, committed_rev,
-                                              rb->pool)))
+                                              txn_name, rb->pool)))
         return svn_error_create
           (SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED, err,
            _("Commit succeeded, but post-commit hook failed"));

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/reporter.c?rev=1241739&r1=1241738&r2=1241739&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/reporter.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/reporter.c Wed Feb  8 02:15:42 2012
@@ -898,6 +898,21 @@ update_entry(report_baton_t *b, svn_revn
       SVN_ERR(svn_repos_deleted_rev(svn_fs_root_fs(b->t_root), t_path,
                                     s_rev, b->t_rev, &deleted_rev,
                                     pool));
+
+      if (!SVN_IS_VALID_REVNUM(deleted_rev))
+        {
+          /* Two possibilities: either the thing doesn't exist in S_REV; or
+             it wasn't deleted between S_REV and B->T_REV.  In the first case,
+             I think we should leave DELETED_REV as SVN_INVALID_REVNUM, but
+             in the second, it should be set to B->T_REV-1 for the call to
+             delete_entry() below. */
+          svn_node_kind_t kind;
+
+          SVN_ERR(svn_fs_check_path(&kind, b->t_root, t_path, pool));
+          if (kind != svn_node_none)
+            deleted_rev = b->t_rev - 1;
+        }
+
       SVN_ERR(b->editor->delete_entry(e_path, deleted_rev, dir_baton,
                                       pool));
       s_path = NULL;

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/repos.c?rev=1241739&r1=1241738&r2=1241739&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/repos.c Wed Feb  8 02:15:42 2012
@@ -167,7 +167,7 @@ svn_repos_post_revprop_change_hook(svn_r
 
 void
 svn_repos_hooks_setenv(svn_repos_t *repos,
-                       const char *const *hooks_env)
+                       apr_hash_t *hooks_env)
 {
   repos->hooks_env = hooks_env;
 }
@@ -742,6 +742,7 @@ PREWRITTEN_HOOKS_TEXT
 "#"                                                                          NL
 "#   [1] REPOS-PATH   (the path to this repository)"                         NL
 "#   [2] REV          (the number of the revision just committed)"           NL
+"#   [3] TXN-NAME     (the name of the transaction that has become REV)"     NL
 "#"                                                                          NL
 "# The default working directory for the invocation is undefined, so"        NL
 "# the program should set one explicitly if it cares."                       NL
@@ -771,6 +772,7 @@ PREWRITTEN_HOOKS_TEXT
 ""                                                                           NL
 "REPOS=\"$1\""                                                               NL
 "REV=\"$2\""                                                                 NL
+"TXN_NAME=\"$3\""                                                            NL
                                                                              NL
 "mailer.py commit \"$REPOS\" \"$REV\" /path/to/mailer.conf"                  NL;
 
@@ -1046,7 +1048,17 @@ create_conf(svn_repos_t *repos, apr_pool
 "### to the effective key length for encryption (e.g. 128 means 128-bit"     NL
 "### encryption). The values below are the defaults."                        NL
 "# min-encryption = 0"                                                       NL
-"# max-encryption = 256"                                                     NL;
+"# max-encryption = 256"                                                     NL
+""                                                                           NL
+"[hooks-env]"                                                                NL
+"### Options in this section define environment variables for use by"        NL
+"### hook scripts run by svnserve."                                          NL
+#ifdef WIN32
+"# PATH = C:\\Program Files\\Subversion\\bin"                                NL
+#else
+"# PATH = /bin:/sbin:/usr/bin:/usr/sbin"                                     NL
+#endif
+"# LC_CTYPE = en_US.UTF-8"                                                   NL;
 
     SVN_ERR_W(svn_io_file_create(svn_repos_svnserve_conf(repos, pool),
                                  svnserve_conf_contents, pool),

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/repos.h?rev=1241739&r1=1241738&r2=1241739&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/repos.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/repos.h Wed Feb  8 02:15:42 2012
@@ -143,7 +143,7 @@ struct svn_repos_t
 
   /* The environment inherited to hook scripts. If NULL, hooks run
    * in an empty environment. */
-  const char *const *hooks_env;
+  apr_hash_t *hooks_env;
 };
 
 
@@ -179,6 +179,7 @@ svn_repos__hooks_pre_commit(svn_repos_t 
 svn_error_t *
 svn_repos__hooks_post_commit(svn_repos_t *repos,
                              svn_revnum_t rev,
+                             const char *txn_name,
                              apr_pool_t *pool);
 
 /* Run the pre-revprop-change hook for REPOS.  Use POOL for any

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c?rev=1241739&r1=1241738&r2=1241739&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c Wed Feb  8 02:15:42 2012
@@ -1999,8 +1999,10 @@ deserialize_svn_stringbuf(void **item,
                           apr_size_t buffer_size,
                           apr_pool_t *result_pool)
 {
-  svn_string_t *value_str = apr_palloc(result_pool, sizeof(svn_string_t));
+  svn_stringbuf_t *value_str = apr_palloc(result_pool, sizeof(svn_stringbuf_t));
 
+  value_str->pool = result_pool;
+  value_str->blocksize = buffer_size;
   value_str->data = buffer;
   value_str->len = buffer_size-1;
   *item = value_str;

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/checksum.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/checksum.c?rev=1241739&r1=1241738&r2=1241739&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/checksum.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/checksum.c Wed Feb  8 02:15:42 2012
@@ -423,3 +423,27 @@ svn_checksum_mismatch_err(const svn_chec
                 svn_checksum_to_cstring_display(expected, scratch_pool),
                 svn_checksum_to_cstring_display(actual, scratch_pool));
 }
+
+svn_boolean_t
+svn_checksum_is_empty_checksum(svn_checksum_t *checksum)
+{
+  /* By definition, the NULL checksum matches all others, including the
+     empty one. */
+  if (!checksum)
+    return TRUE;
+
+  switch (checksum->kind)
+    {
+      case svn_checksum_md5:
+        return svn_md5__digests_match(checksum->digest,
+                                      svn_md5__empty_string_digest());
+
+      case svn_checksum_sha1:
+        return svn_sha1__digests_match(checksum->digest,
+                                       svn_sha1__empty_string_digest());
+
+      default:
+        /* We really shouldn't get here, but if we do... */
+        return FALSE;
+    }
+}

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/io.c?rev=1241739&r1=1241738&r2=1241739&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/io.c Wed Feb  8 02:15:42 2012
@@ -3280,6 +3280,15 @@ svn_io_write_unique(const char **tmp_pat
 svn_error_t *
 svn_io_file_trunc(apr_file_t *file, apr_off_t offset, apr_pool_t *pool)
 {
+  /* This is a work-around. APR would flush the write buffer
+     _after_ truncating the file causing now invalid buffered
+     data to be written behind OFFSET. */
+  SVN_ERR(do_io_file_wrapper_cleanup
+    (file, apr_file_flush(file),
+     N_("Can't flush file '%s'"),
+     N_("Can't flush stream"),
+     pool));
+
   return do_io_file_wrapper_cleanup
     (file, apr_file_trunc(file, offset),
      N_("Can't truncate file '%s'"),

Modified: subversion/branches/ev2-export/subversion/mod_dav_svn/mod_dav_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/mod_dav_svn/mod_dav_svn.c?rev=1241739&r1=1241738&r2=1241739&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/mod_dav_svn/mod_dav_svn.c (original)
+++ subversion/branches/ev2-export/subversion/mod_dav_svn/mod_dav_svn.c Wed Feb  8 02:15:42 2012
@@ -225,9 +225,7 @@ merge_dir_config(apr_pool_t *p, void *ba
   newconf->txdelta_cache = INHERIT_VALUE(parent, child, txdelta_cache);
   newconf->fulltext_cache = INHERIT_VALUE(parent, child, fulltext_cache);
   newconf->root_dir = INHERIT_VALUE(parent, child, root_dir);
-  newconf->hooks_env = apr_hash_merge(p, child->hooks_env, parent->hooks_env,
-                                      NULL /* child overrides parent */,
-                                      NULL /* unused data baton */);
+  newconf->hooks_env = INHERIT_VALUE(parent, child, hooks_env);
 
   if (parent->fs_path)
     ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
@@ -540,14 +538,36 @@ SVNHooksEnv_cmd(cmd_parms *cmd, void *co
   apr_array_header_t *var;
 
   var = svn_cstring_split(arg1, "=", TRUE, cmd->pool);
-  if (var && var->nelts == 2)
+  if (var && var->nelts >= 2)
     {
       dir_conf_t *conf = config;
+      const char *name;
+      const char *val;
 
-      apr_hash_set(conf->hooks_env,
-                   APR_ARRAY_IDX(var, 0, const char *),
-                   APR_HASH_KEY_STRING,
-                   APR_ARRAY_IDX(var, 1, const char *));
+      name = apr_pstrdup(apr_hash_pool_get(conf->hooks_env),
+                         APR_ARRAY_IDX(var, 0, const char *));
+
+      /* Special case for values which contain '='. */
+      if (var->nelts > 2)
+        {
+          svn_stringbuf_t *buf;
+          int i;
+
+          buf = svn_stringbuf_create(APR_ARRAY_IDX(var, 1, const char *),
+                                     cmd->pool);
+          for (i = 2; i < var->nelts; i++)
+            {
+              svn_stringbuf_appendbyte(buf, '=');
+              svn_stringbuf_appendcstr(buf, APR_ARRAY_IDX(var, i, const char *));
+            } 
+
+          val = apr_pstrdup(apr_hash_pool_get(conf->hooks_env), buf->data);
+        }
+      else
+        val = apr_pstrdup(apr_hash_pool_get(conf->hooks_env),
+                          APR_ARRAY_IDX(var, 1, const char *));
+
+      apr_hash_set(conf->hooks_env, name, APR_HASH_KEY_STRING, val);
     }
 
   return NULL;

Modified: subversion/branches/ev2-export/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/mod_dav_svn/repos.c?rev=1241739&r1=1241738&r2=1241739&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/mod_dav_svn/repos.c (original)
+++ subversion/branches/ev2-export/subversion/mod_dav_svn/repos.c Wed Feb  8 02:15:42 2012
@@ -1917,33 +1917,6 @@ parse_querystring(request_rec *r, const 
   return NULL;
 }
 
-/* Copy the environment given as key/value pairs of ENV_HASH into
- * an array of C strings allocated in RESULT_POOL.
- * Use SCRATCH_POOL for temporary allocations. */
-static const char **
-env_from_env_hash(apr_hash_t *env_hash,
-                  apr_pool_t *result_pool,
-                  apr_pool_t *scratch_pool)
-{
-  apr_hash_index_t *hi;
-  const char **env;
-  const char **envp;
-  
-  env = apr_palloc(result_pool,
-                   sizeof(const char *) * (apr_hash_count(env_hash) + 1));
-  envp = env;
-  for (hi = apr_hash_first(scratch_pool, env_hash); hi; hi = apr_hash_next(hi))
-    {
-      *envp = apr_psprintf(result_pool, "%s=%s",
-                           (const char *)svn__apr_hash_index_key(hi),
-                           (const char *)svn__apr_hash_index_val(hi));
-      envp++;
-    }
-  *envp = NULL;
-
-  return env;
-}
-
 static dav_error *
 get_resource(request_rec *r,
              const char *root_path,
@@ -2171,8 +2144,6 @@ get_resource(request_rec *r,
   repos->repos = userdata;
   if (repos->repos == NULL)
     {
-      apr_hash_t *hooks_env;
-
       /* construct FS configuration parameters */
       fs_config = apr_hash_make(r->connection->pool);
       apr_hash_set(fs_config,
@@ -2217,14 +2188,7 @@ get_resource(request_rec *r,
         }
 
       /* Configure the hooks environment, if not empty. */
-      hooks_env = dav_svn__get_hooks_env(r);
-      if (hooks_env && apr_hash_count(hooks_env) > 0)
-        {
-          const char **env;
-          
-          env = env_from_env_hash(hooks_env, r->connection->pool, r->pool);
-          svn_repos_hooks_setenv(repos->repos, env);
-        }
+      svn_repos_hooks_setenv(repos->repos, dav_svn__get_hooks_env(r));
     }
 
   /* cache the filesystem object */

Modified: subversion/branches/ev2-export/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/svnserve/serve.c?rev=1241739&r1=1241738&r2=1241739&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/svnserve/serve.c (original)
+++ subversion/branches/ev2-export/subversion/svnserve/serve.c Wed Feb  8 02:15:42 2012
@@ -2949,6 +2949,24 @@ repos_path_valid(const char *path)
   return TRUE;
 }
 
+/* Callback which receives hook environment variables from the hook
+ * environment configuration section,
+ * An implementation of svn_config_enumerator2_t. */
+static svn_boolean_t
+hooks_env_conf_cb(const char *name,
+                  const char *value,
+                  void *baton,
+                  apr_pool_t *pool)
+{
+  apr_hash_t *hooks_env = baton;
+  apr_pool_t *hash_pool = apr_hash_pool_get(hooks_env);
+
+  apr_hash_set(hooks_env, apr_pstrdup(hash_pool, name),
+               APR_HASH_KEY_STRING, apr_pstrdup(hash_pool, value));
+
+  return TRUE;
+}
+
 /* Look for the repository given by URL, using ROOT as the virtual
  * repository root.  If we find one, fill in the repos, fs, cfg,
  * repos_url, and fs_path fields of B.  Set B->repos's client
@@ -3039,6 +3057,17 @@ static svn_error_t *find_repos(const cha
                                  "No access allowed to this repository",
                                  b, conn, pool);
 
+  /* If a hook environment has been configured, set it up. */
+  if (svn_config_has_section(b->cfg, SVN_CONFIG_SECTION_HOOKS_ENV))
+    {
+      apr_hash_t *hooks_env = apr_hash_make(pool);
+
+      svn_config_enumerate2(b->cfg, SVN_CONFIG_SECTION_HOOKS_ENV,
+                            hooks_env_conf_cb, hooks_env, pool);
+
+      svn_repos_hooks_setenv(b->repos, hooks_env);
+    }
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/ev2-export/subversion/tests/cmdline/svnrdump_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/svnrdump_tests.py?rev=1241739&r1=1241738&r2=1241739&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/svnrdump_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/svnrdump_tests.py Wed Feb  8 02:15:42 2012
@@ -93,7 +93,8 @@ def compare_repos_dumps(svnrdump_sbox, s
     "Dump files", "DUMP", svnadmin_contents, svnrdump_contents)
 
 def run_dump_test(sbox, dumpfile_name, expected_dumpfile_name = None,
-                  subdir = None, bypass_prop_validation = False):
+                  subdir = None, bypass_prop_validation = False,
+                  ignore_base_checksums = False):
   """Load a dumpfile using 'svnadmin load', dump it with 'svnrdump
   dump' and check that the same dumpfile is produced or that
   expected_dumpfile_name is produced if provided. Additionally, the
@@ -129,8 +130,15 @@ def run_dump_test(sbox, dumpfile_name, e
     svnadmin_dumpfile = open(os.path.join(svnrdump_tests_dir,
                                           expected_dumpfile_name),
                              'rb').readlines()
-    svnadmin_dumpfile = svntest.verify.UnorderedOutput(svnadmin_dumpfile)
     # Compare the output from stdout
+    if ignore_base_checksums:
+      svnadmin_dumpfile = [l for l in svnadmin_dumpfile
+                                    if not l.startswith('Text-delta-base-md5')]
+      svnrdump_dumpfile = [l for l in svnrdump_dumpfile
+                                    if not l.startswith('Text-delta-base-md5')]
+
+    svnadmin_dumpfile = svntest.verify.UnorderedOutput(svnadmin_dumpfile)
+
     svntest.verify.compare_and_display_lines(
       "Dump files", "DUMP", svnadmin_dumpfile, svnrdump_dumpfile,
       None, mismatched_headers_re)
@@ -354,7 +362,7 @@ def copy_bad_line_endings2_dump(sbox):
   "dump: non-LF line endings in svn:* props"
   run_dump_test(sbox, "copy-bad-line-endings2.dump",
                 expected_dumpfile_name="copy-bad-line-endings2.expected.dump",
-                bypass_prop_validation=True)
+                bypass_prop_validation=True, ignore_base_checksums=True)
 
 def commit_a_copy_of_root_dump(sbox):
   "dump: commit a copy of root"

Modified: subversion/branches/ev2-export/subversion/tests/cmdline/switch_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/switch_tests.py?rev=1241739&r1=1241738&r2=1241739&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/switch_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/switch_tests.py Wed Feb  8 02:15:42 2012
@@ -1532,33 +1532,29 @@ def mergeinfo_switch_elision(sbox):
   beta_path     = os.path.join(wc_dir, "A", "B", "E", "beta")
 
   # Make branches A/B_COPY_1 and A/B_COPY_2
-  svntest.actions.run_and_verify_svn(
-    None,
-    ["A    " + os.path.join(wc_dir, "A", "B_COPY_1", "lambda") + "\n",
+  expected_stdout = verify.UnorderedOutput([
+     "A    " + os.path.join(wc_dir, "A", "B_COPY_1", "lambda") + "\n",
      "A    " + os.path.join(wc_dir, "A", "B_COPY_1", "E") + "\n",
      "A    " + os.path.join(wc_dir, "A", "B_COPY_1", "E", "alpha") + "\n",
      "A    " + os.path.join(wc_dir, "A", "B_COPY_1", "E", "beta") + "\n",
      "A    " + os.path.join(wc_dir, "A", "B_COPY_1", "F") + "\n",
      "Checked out revision 1.\n",
-     "A         " + B_COPY_1_path + "\n"],
-    [],
-    'copy',
-    sbox.repo_url + "/A/B",
-    B_COPY_1_path)
-
-  svntest.actions.run_and_verify_svn(
-    None,
-    ["A    " + os.path.join(wc_dir, "A", "B_COPY_2", "lambda") + "\n",
+     "A         " + B_COPY_1_path + "\n",
+    ])
+  svntest.actions.run_and_verify_svn(None, expected_stdout, [], 'copy',
+                                     sbox.repo_url + "/A/B", B_COPY_1_path)
+
+  expected_stdout = verify.UnorderedOutput([
+     "A    " + os.path.join(wc_dir, "A", "B_COPY_2", "lambda") + "\n",
      "A    " + os.path.join(wc_dir, "A", "B_COPY_2", "E") + "\n",
      "A    " + os.path.join(wc_dir, "A", "B_COPY_2", "E", "alpha") + "\n",
      "A    " + os.path.join(wc_dir, "A", "B_COPY_2", "E", "beta") + "\n",
      "A    " + os.path.join(wc_dir, "A", "B_COPY_2", "F") + "\n",
      "Checked out revision 1.\n",
-     "A         " + B_COPY_2_path + "\n"],
-    [],
-    'copy',
-    sbox.repo_url + "/A/B",
-    B_COPY_2_path)
+     "A         " + B_COPY_2_path + "\n",
+    ])
+  svntest.actions.run_and_verify_svn(None, expected_stdout, [], 'copy',
+                                     sbox.repo_url + "/A/B", B_COPY_2_path)
 
   expected_output = svntest.wc.State(wc_dir, {
     'A/B_COPY_1' : Item(verb='Adding'),

Modified: subversion/branches/ev2-export/subversion/tests/cmdline/update_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/update_tests.py?rev=1241739&r1=1241738&r2=1241739&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/update_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/update_tests.py Wed Feb  8 02:15:42 2012
@@ -3142,19 +3142,17 @@ def mergeinfo_update_elision(sbox):
   lambda_path = os.path.join(wc_dir, "A", "B", "lambda")
 
   # Make a branch A/B_COPY
-  svntest.actions.run_and_verify_svn(
-    None,
-    ["A    " + os.path.join(wc_dir, "A", "B_COPY", "lambda") + "\n",
+  expected_stdout =  verify.UnorderedOutput([
+     "A    " + os.path.join(wc_dir, "A", "B_COPY", "lambda") + "\n",
      "A    " + os.path.join(wc_dir, "A", "B_COPY", "E") + "\n",
      "A    " + os.path.join(wc_dir, "A", "B_COPY", "E", "alpha") + "\n",
      "A    " + os.path.join(wc_dir, "A", "B_COPY", "E", "beta") + "\n",
      "A    " + os.path.join(wc_dir, "A", "B_COPY", "F") + "\n",
      "Checked out revision 1.\n",
-     "A         " + B_COPY_path + "\n"],
-    [],
-    'copy',
-    sbox.repo_url + "/A/B",
-    B_COPY_path)
+     "A         " + B_COPY_path + "\n",
+    ])
+  svntest.actions.run_and_verify_svn(None, expected_stdout, [], 'copy',
+                                     sbox.repo_url + "/A/B", B_COPY_path)
 
   expected_output = wc.State(wc_dir, {'A/B_COPY' : Item(verb='Adding')})
 

Modified: subversion/branches/ev2-export/subversion/tests/libsvn_subr/checksum-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/libsvn_subr/checksum-test.c?rev=1241739&r1=1241738&r2=1241739&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/libsvn_subr/checksum-test.c (original)
+++ subversion/branches/ev2-export/subversion/tests/libsvn_subr/checksum-test.c Wed Feb  8 02:15:42 2012
@@ -59,11 +59,34 @@ test_checksum_parse(apr_pool_t *pool)
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test_checksum_empty(apr_pool_t *pool)
+{
+  svn_checksum_t *checksum;
+  char data = '\0';
+
+  checksum = svn_checksum_empty_checksum(svn_checksum_md5, pool);
+  SVN_TEST_ASSERT(svn_checksum_is_empty_checksum(checksum));
+
+  checksum = svn_checksum_empty_checksum(svn_checksum_sha1, pool);
+  SVN_TEST_ASSERT(svn_checksum_is_empty_checksum(checksum));
+
+  SVN_ERR(svn_checksum(&checksum, svn_checksum_md5, &data, 0, pool));
+  SVN_TEST_ASSERT(svn_checksum_is_empty_checksum(checksum));
+
+  SVN_ERR(svn_checksum(&checksum, svn_checksum_sha1, &data, 0, pool));
+  SVN_TEST_ASSERT(svn_checksum_is_empty_checksum(checksum));
+
+  return SVN_NO_ERROR;
+}
+
 /* An array of all test functions */
 struct svn_test_descriptor_t test_funcs[] =
   {
     SVN_TEST_NULL,
     SVN_TEST_PASS2(test_checksum_parse,
                    "checksum parse"),
+    SVN_TEST_PASS2(test_checksum_empty,
+                   "checksum emptiness"),
     SVN_TEST_NULL
   };

Modified: subversion/branches/ev2-export/tools/dev/merge-graph.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/tools/dev/merge-graph.py?rev=1241739&r1=1241738&r2=1241739&view=diff
==============================================================================
--- subversion/branches/ev2-export/tools/dev/merge-graph.py (original)
+++ subversion/branches/ev2-export/tools/dev/merge-graph.py Wed Feb  8 02:15:42 2012
@@ -23,260 +23,8 @@ args_message = 'GRAPH_CONFIG_FILE...'
 help_message = """Produce pretty graphs representing branches and merging.
 For each config file specified, construct a graph and write it as a PNG file."""
 
-# Config file format:
-example = """
-  [graph]
-  filename = merge-sync-1.png
-  title = Sync Merge: CC vs SVN
-  # Branches: (branch name, branched from node, first rev, last rev).
-  branches = [
-    ('A', 'O0', 1, 4),
-    ('O', None, 0, 0),
-    ('B', 'O0', 1, 5)
-    ]
-  # Changes: nodes in which a change was committed; merge targets need not
-  # be listed here.
-  changes = [
-    'A1', 'A2', 'A3', 'A4',
-    'B1', 'B2', 'B3', 'B4', 'B5'
-    ]
-  # Merges: (base node, source-right node, target node, label).
-  # Base is also known as source-left.
-  merges = [
-    ('O0', 'A:1', 'B3', 'sync'),
-    ('A2', 'A:3', 'B5', 'sync'),
-    ]
-  # Annotations for nodes: (node, annotation text).
-  annotations = [
-    ('A2', 'cc:YCA')
-    ]
-"""
-
-# Notes about different kinds of merge.
-#
-# A basic 3-way merge is ...
-#
-# The ClearCase style of merge is a 3-way merge.
-#
-# The Subversion style of merge (that is, one phase of a Subversion merge)
-# is a three-way merge with its base (typically the YCA) on the source branch.
-
-
 import sys
-import pydot
-from pydot import Node, Edge
-
-
-def mergeinfo_to_node_list(mi):
-  """Convert a mergeinfo string such as '/foo:1,3-5*' into a list of
-     node names such as ['foo1', 'foo3', 'foo4', 'foo5']."""
-  ### Doesn't yet strip the leading slash.
-  l = []
-  if mi:
-    for mi_str in mi.split(' '):
-      path, ranges = mi_str.split(':')
-      for r in ranges.split(','):
-        if r.endswith('*'):
-          # TODO: store & use this 'non-inheritable' flag
-          # Remove the flag
-          r = r[:-1]
-        rlist = r.split('-')
-        r1 = int(rlist[0])
-        if len(rlist) == 2:
-          r2 = int(rlist[1])
-        else:
-          r2 = r1
-        for rev in range(r1, r2 + 1):
-          l.append(path + str(rev))
-  return l
-
-
-class MergeGraph(pydot.Graph):
-  """Base class, not intended for direct use.  Use MergeDot for the main
-     graph and MergeSubgraph for a subgraph."""
-
-  def mk_origin_node(graph, name, label):
-    """Add a node to the graph"""
-    graph.add_node(Node(name, label=label, shape='plaintext'))
-
-  def mk_invis_node(graph, name):
-    """Add a node to the graph"""
-    graph.add_node(Node(name, style='invis'))
-
-  def mk_node(graph, name, label=None):
-    """Add a node to the graph, if not already present"""
-    if not graph.get_node(name):
-      if not label:
-        label = name
-      if name in graph.changes:
-        graph.add_node(Node(name, label=label))
-      else:
-        graph.add_node(Node(name, color='grey', label=''))
-
-  def mk_merge_target(graph, target_node, important):
-    """Add a merge target node to the graph."""
-    if important:
-      color = 'red'
-    else:
-      color = 'black'
-    graph.add_node(Node(target_node, color=color, fontcolor=color, style='bold'))
-
-  def mk_edge(graph, name1, name2, **attrs):
-    """Add an ordinary edge to the graph"""
-    graph.add_edge(Edge(name1, name2, dir='none', style='dotted', color='grey', **attrs))
-
-  def mk_br_edge(graph, name1, name2):
-    """Add a branch-creation edge to the graph"""
-    # Constraint=false to avoid the Y-shape skewing the nice parallel branch lines
-    graph.mk_edge(name1, name2, constraint='false')
-
-  def mk_merge_edge(graph, src_node, tgt_node, kind, label, important):
-    """Add a merge edge to the graph"""
-    if important:
-      color = 'red'
-    else:
-      color = 'grey'
-    e = Edge(src_node, tgt_node, constraint='false',
-             label='"' + label + '"',
-             color=color, fontcolor=color,
-             style='bold')
-    if kind == 'cherry':
-      e.set_style('dashed')
-    graph.add_edge(e)
-
-  def mk_mergeinfo_edge(graph, base_node, src_node, important):
-    """"""
-    if important:
-      color = 'red'
-    else:
-      color = 'grey'
-    graph.add_edge(Edge(base_node, src_node,
-                        dir='both', arrowtail='odot', arrowhead='tee',
-                        color=color, constraint='false'))
-
-  def mk_invis_edge(graph, name1, name2):
-    """Add an invisible edge to the graph"""
-    graph.add_edge(Edge(name1, name2, style='invis'))
-
-  def add_merge(graph, merge, important):
-    """Add a merge"""
-    base_node, src_node, tgt_node, kind = merge
-
-    if base_node and src_node:  # and kind != 'cherry':
-      graph.mk_mergeinfo_edge(base_node, src_node, important)
-
-    # Merge target node
-    graph.mk_merge_target(tgt_node, important)
-
-    # Merge edge
-    graph.mk_merge_edge(src_node, tgt_node, kind, kind, important)
-
-  def add_annotation(graph, node, label, color='red'):
-    """Add a graph node that serves as an annotation to a normal node.
-       More than one annotation can be added to the same normal node."""
-    subg_name = node + '_annotations'
-
-    def get_subgraph(graph, name):
-      """Equivalent to pydot.Graph.get_subgraph() when there is no more than
-         one subgraph of the given name, but working aroung a bug in
-         pydot.Graph.get_subgraph()."""
-      for subg in graph.get_subgraph_list():
-        if subg.get_name() == name:
-          return subg
-      return None
-
-    g = get_subgraph(graph, subg_name)
-    if not g:
-      g = pydot.Subgraph(subg_name, rank='same')
-      graph.add_subgraph(g)
-
-    ann_node = node + '_'
-    while g.get_node(ann_node):
-      ann_node = ann_node + '_'
-    g.add_node(Node(ann_node, shape='box', color=color, label='"' + label + '"'))
-    g.add_edge(Edge(ann_node, node, style='dotted', color=color, dir='none', constraint='false'))
-
-class MergeSubgraph(MergeGraph, pydot.Subgraph):
-  """"""
-  def __init__(graph, **attrs):
-    """"""
-    MergeGraph.__init__(graph)
-    pydot.Subgraph.__init__(graph, **attrs)
-
-class MergeDot(MergeGraph, pydot.Dot):
-  """
-  # TODO: In the 'merges' input, find the predecessor automatically.
-  """
-  def __init__(graph, config_filename, **attrs):
-    """Return a new MergeDot graph generated from a config file."""
-    MergeGraph.__init__(graph)
-    pydot.Dot.__init__(graph, **attrs)
-
-    graph.read_config(config_filename)
-
-    graph.construct()
-
-  def read_config(graph, config_filename):
-    """Initialize a MergeDot graph's input data from a config file."""
-    import ConfigParser
-    config = ConfigParser.SafeConfigParser()
-    files_read = config.read(config_filename)
-    if len(files_read) == 0:
-      print >> sys.stderr, 'graph: unable to read graph config from "' + config_filename + '"'
-      sys.exit(1)
-    graph.filename = config.get('graph', 'filename')
-    graph.title = config.get('graph', 'title')
-    graph.branches = eval(config.get('graph', 'branches'))
-    graph.changes = eval(config.get('graph', 'changes'))
-    graph.merges = eval(config.get('graph', 'merges'))
-    graph.annotations = eval(config.get('graph', 'annotations'))
-
-  def construct(graph):
-    """"""
-    # Origin nodes (done first, in an attempt to set the order)
-    for br, orig, r1, head in graph.branches:
-      name = br + '0'
-      if r1 > 0:
-        graph.mk_origin_node(name, br)
-      else:
-        graph.mk_node(name, label=br)
-
-    # Edges and target nodes for merges
-    for merge in graph.merges:
-      # Emphasize the last merge, as it's the important one
-      important = (merge == graph.merges[-1])
-      graph.add_merge(merge, important)
-
-    # Parallel edges for basic lines of descent
-    for br, orig, r1, head in graph.branches:
-      sub_g = MergeSubgraph(ordering='out')
-      for i in range(1, head + 1):
-        prev_n = br + str(i - 1)
-        this_n = br + str(i)
-
-        # Normal edges and nodes
-        if i < r1:
-          graph.mk_invis_node(this_n)
-        else:
-          graph.mk_node(this_n)
-        if i <= r1:
-          graph.mk_invis_edge(prev_n, this_n)
-        else:
-          graph.mk_edge(prev_n, this_n)
-
-      # Branch creation edges
-      if orig:
-        sub_g.mk_br_edge(orig, br + str(r1))
-
-      graph.add_subgraph(sub_g)
-
-    # Annotations
-    for node, label in graph.annotations:
-      graph.add_annotation(node, label)
-
-    # A title for the graph (added last so it goes at the top)
-    #if graph.title:
-    #  graph.add_node(Node('title', shape='plaintext', label='"' + graph.title + '"'))
+from mergegraph import MergeDot
 
 
 # If run as a program, process each input filename as a graph config file.

Propchange: subversion/branches/ev2-export/tools/dev/merge-graph.py
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/branches/ev2-export/tools/examples/get-location-segments.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/tools/examples/get-location-segments.py?rev=1241739&r1=1241738&r2=1241739&view=diff
==============================================================================
--- subversion/branches/ev2-export/tools/examples/get-location-segments.py (original)
+++ subversion/branches/ev2-export/tools/examples/get-location-segments.py Wed Feb  8 02:15:42 2012
@@ -105,6 +105,9 @@ def prompt_func_simple_prompt(realm, use
   simple_cred.may_save = False
   return simple_cred
 
+def prompt_func_gnome_keyring_prompt(keyring, pool):
+  return getpass.getpass(prompt="Password for '%s' GNOME keyring: " % keyring)
+
 def main():
   try:
     url, peg_revision, start_revision, end_revision = parse_args(sys.argv[1:])
@@ -125,7 +128,12 @@ ERROR: %s
 
   core.svn_config_ensure(None)
   ctx = client.svn_client_create_context()
-  providers = [
+  ctx.config = core.svn_config_get_config(None)
+
+  # Make sure that these are at the start of the list, so passwords from
+  # gnome-keyring / kwallet are checked before asking for new passwords.
+  providers = core.svn_auth_get_platform_specific_client_providers(ctx.config['config'], None)
+  providers.extend([
     client.get_simple_provider(),
     core.svn_auth_get_ssl_server_trust_file_provider(),
     core.svn_auth_get_simple_prompt_provider(prompt_func_simple_prompt, 2),
@@ -134,9 +142,12 @@ ERROR: %s
     client.get_ssl_server_trust_file_provider(),
     client.get_ssl_client_cert_file_provider(),
     client.get_ssl_client_cert_pw_file_provider(),
-    ]
+  ])
+
   ctx.auth_baton = core.svn_auth_open(providers)
-  ctx.config = core.svn_config_get_config(None)
+
+  if hasattr(core, 'svn_auth_set_gnome_keyring_unlock_prompt_func'):
+    core.svn_auth_set_gnome_keyring_unlock_prompt_func(ctx.auth_baton, prompt_func_gnome_keyring_prompt)
 
   ra_callbacks = ra.callbacks_t()
   ra_callbacks.auth_baton = ctx.auth_baton