You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/02/04 21:48:13 UTC

svn commit: r1442344 [13/39] - in /subversion/branches/fsfs-format7: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/client-side/emacs/ contrib/server-side/fsfsfixer/fixer/ contrib/server-side/svncutter/ doc/...

Modified: subversion/branches/fsfs-format7/subversion/libsvn_repos/authz.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_repos/authz.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_repos/authz.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_repos/authz.c Mon Feb  4 20:48:05 2013
@@ -34,6 +34,7 @@
 #include "svn_config.h"
 #include "svn_ctype.h"
 #include "private/svn_fspath.h"
+#include "repos.h"
 
 
 /*** Structures. ***/
@@ -303,10 +304,8 @@ authz_parse_section(const char *section_
   svn_boolean_t conclusive;
 
   /* Does the section apply to us? */
-  if (is_applicable_section(b->qualified_repos_path,
-                            section_name) == FALSE
-      && is_applicable_section(b->repos_path,
-                               section_name) == FALSE)
+  if (!is_applicable_section(b->qualified_repos_path, section_name)
+      && !is_applicable_section(b->repos_path, section_name))
     return TRUE;
 
   /* Work out what this section grants. */
@@ -751,27 +750,293 @@ static svn_boolean_t authz_validate_sect
 }
 
 
-
-/*** Public functions. ***/
-
-svn_error_t *
-svn_repos_authz_read(svn_authz_t **authz_p, const char *file,
-                     svn_boolean_t must_exist, apr_pool_t *pool)
+/* Walk the configuration in AUTHZ looking for any errors. */
+static svn_error_t *
+authz_validate(svn_authz_t *authz, apr_pool_t *pool)
 {
-  svn_authz_t *authz = apr_palloc(pool, sizeof(*authz));
   struct authz_validate_baton baton = { 0 };
 
   baton.err = SVN_NO_ERROR;
-
-  /* Load the rule file. */
-  SVN_ERR(svn_config_read2(&authz->cfg, file, must_exist, TRUE, pool));
   baton.config = authz->cfg;
 
-  /* Step through the entire rule file, stopping on error. */
+  /* Step through the entire rule file stopping on error. */
   svn_config_enumerate_sections2(authz->cfg, authz_validate_section,
                                  &baton, pool);
   SVN_ERR(baton.err);
 
+  return SVN_NO_ERROR;
+}
+
+
+/* Retrieve the file at DIRENT (contained in a repo) then parse it as a config
+ * file placing the result into CFG_P allocated in POOL.
+ *
+ * If DIRENT cannot be parsed as a config file then an error is returned.  The
+ * contents of CFG_P is then undefined.  If MUST_EXIST is TRUE, a missing
+ * authz file is also an error.
+ *
+ * SCRATCH_POOL will be used for temporary allocations. */
+static svn_error_t *
+authz_retrieve_config_repo(svn_config_t **cfg_p, const char *dirent,
+                          svn_boolean_t must_exist,
+                          apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+  svn_error_t *err;
+  svn_repos_t *repos;
+  const char *repos_root_dirent;
+  const char *fs_path;
+  svn_fs_t *fs;
+  svn_fs_root_t *root;
+  svn_revnum_t youngest_rev;
+  svn_node_kind_t node_kind;
+  svn_stream_t *contents;
+
+  /* Search for a repository in the full path. */
+  repos_root_dirent = svn_repos_find_root_path(dirent, scratch_pool);
+  if (!repos_root_dirent)
+    return svn_error_createf(SVN_ERR_RA_LOCAL_REPOS_NOT_FOUND, NULL,
+                             "Unable to find repository at '%s'", dirent);
+
+  /* Attempt to open a repository at repos_root_dirent. */
+  SVN_ERR(svn_repos_open2(&repos, repos_root_dirent, NULL, scratch_pool));
+
+  fs_path = &dirent[strlen(repos_root_dirent)];
+
+  /* Root path is always a directory so no reason to go any further */
+  if (*fs_path == '\0')
+    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                             "'/' is not a file in repo '%s'",
+                             repos_root_dirent);
+
+  /* We skip some things that are non-important for how we're going to use
+   * this repo connection.  We do not set any capabilities since none of
+   * the current ones are important for what we're doing.  We also do not
+   * setup the environment that repos hooks would run under since we won't
+   * be triggering any. */
+
+  /* Get the filesystem. */
+  fs = svn_repos_fs(repos);
+
+  /* Find HEAD and the revision root */
+  SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, scratch_pool));
+  SVN_ERR(svn_fs_revision_root(&root, fs, youngest_rev, scratch_pool));
+
+  SVN_ERR(svn_fs_check_path(&node_kind, root, fs_path, scratch_pool));
+  if (node_kind == svn_node_none)
+    {
+      if (!must_exist)
+        {
+          SVN_ERR(svn_config_create(cfg_p, TRUE, scratch_pool));
+          return SVN_NO_ERROR;
+        }
+      else
+        {
+          return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                                   "'%s' path not found in repo '%s'", fs_path,
+                                   repos_root_dirent);
+        }
+    }
+  else if (node_kind != svn_node_file)
+    {
+      return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                               "'%s' is not a file in repo '%s'", fs_path,
+                               repos_root_dirent);
+    }
+
+  SVN_ERR(svn_fs_file_contents(&contents, root, fs_path, scratch_pool));
+  err = svn_config_parse(cfg_p, contents, TRUE, result_pool);
+
+  /* Add the URL to the error stack since the parser doesn't have it. */
+  if (err != SVN_NO_ERROR)
+    return svn_error_createf(err->apr_err, err, 
+                             "Error while parsing config file: '%s' in repo '%s':",
+                             fs_path, repos_root_dirent);
+
+  return SVN_NO_ERROR;
+}
+
+/* Given a PATH which might be a realative repo URL (^/), an absolute
+ * local repo URL (file://), an absolute path outside of the repo
+ * or a location in the Windows registry.
+ *
+ * Retrieve the configuration data that PATH points at and parse it into
+ * CFG_P allocated in POOL.
+ *
+ * If PATH cannot be parsed as a config file then an error is returned.  The
+ * contents of CFG_P is then undefined.  If MUST_EXIST is TRUE, a missing
+ * authz file is also an error.
+ *
+ * REPOS_ROOT points at the root of the repos you are
+ * going to apply the authz against, can be NULL if you are sure that you
+ * don't have a repos relative URL in PATH. */
+static svn_error_t *
+authz_retrieve_config(svn_config_t **cfg_p, const char *path,
+                      svn_boolean_t must_exist, const char *repos_root,
+                      apr_pool_t *pool)
+{
+  if (svn_path_is_repos_relative_url(path))
+    {
+      const char *dirent;
+      svn_error_t *err;
+      apr_pool_t *scratch_pool = svn_pool_create(pool);
+
+      err = svn_path_resolve_repos_relative_url(&dirent, path,
+                                                repos_root, scratch_pool);
+      dirent = svn_dirent_canonicalize(dirent, scratch_pool);
+
+      if (err == SVN_NO_ERROR) 
+        err = authz_retrieve_config_repo(cfg_p, dirent, must_exist, pool,
+                                         scratch_pool);
+
+      /* Close the repos and streams we opened. */
+      svn_pool_destroy(scratch_pool);
+
+      return err;
+    }
+  else if (svn_path_is_url(path))
+    {
+      const char *dirent;
+      svn_error_t *err;
+      apr_pool_t *scratch_pool = svn_pool_create(pool); 
+
+      err = svn_uri_get_dirent_from_file_url(&dirent, path, scratch_pool);
+
+      if (err == SVN_NO_ERROR)
+        err = authz_retrieve_config_repo(cfg_p, dirent, must_exist, pool,
+                                         scratch_pool);
+
+      /* Close the repos and streams we opened. */
+      svn_pool_destroy(scratch_pool);
+
+      return err;
+    }
+  else
+    {
+      /* Outside of repo file or Windows registry*/
+      SVN_ERR(svn_config_read2(cfg_p, path, must_exist, TRUE, pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+/* Callback to copy (name, value) group into the "groups" section
+   of another configuration. */
+static svn_boolean_t
+authz_copy_group(const char *name, const char *value,
+                 void *baton, apr_pool_t *pool)
+{
+  svn_config_t *authz_cfg = baton;
+
+  svn_config_set(authz_cfg, SVN_CONFIG_SECTION_GROUPS, name, value);
+
+  return TRUE;
+}
+
+/* Copy group definitions from GROUPS_CFG to the resulting AUTHZ.
+ * If AUTHZ already contains any group definition, report an error.
+ * Use POOL for temporary allocations. */
+static svn_error_t *
+authz_copy_groups(svn_authz_t *authz, svn_config_t *groups_cfg,
+                  apr_pool_t *pool)
+{
+  /* Easy out: we prohibit local groups in the authz file when global
+     groups are being used. */
+  if (svn_config_has_section(authz->cfg, SVN_CONFIG_SECTION_GROUPS))
+    {
+      return svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
+                              "Authz file cannot contain any groups "
+                              "when global groups are being used.");
+    }
+
+  svn_config_enumerate2(groups_cfg, SVN_CONFIG_SECTION_GROUPS,
+                        authz_copy_group, authz->cfg, pool);
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_repos__authz_read(svn_authz_t **authz_p, const char *path,
+                      const char *groups_path, svn_boolean_t must_exist,
+                      svn_boolean_t accept_urls, const char *repos_root,
+                      apr_pool_t *pool)
+{
+  svn_authz_t *authz = apr_palloc(pool, sizeof(*authz));
+
+  /* Load the authz file */
+  if (accept_urls)
+    SVN_ERR(authz_retrieve_config(&authz->cfg, path, must_exist, repos_root,
+                                  pool));
+  else
+    SVN_ERR(svn_config_read2(&authz->cfg, path, must_exist, TRUE, pool));
+
+  if (groups_path)
+    {
+      svn_config_t *groups_cfg;
+      svn_error_t *err;
+
+      /* Load the groups file */
+      if (accept_urls)
+        SVN_ERR(authz_retrieve_config(&groups_cfg, groups_path, must_exist,
+                                      repos_root, pool));
+      else
+        SVN_ERR(svn_config_read2(&groups_cfg, groups_path, must_exist,
+                                 TRUE, pool));
+
+      /* Copy the groups from groups_cfg into authz. */
+      err = authz_copy_groups(authz, groups_cfg, pool);
+
+      /* Add the paths to the error stack since the authz_copy_groups
+         routine knows nothing about them. */
+      if (err != SVN_NO_ERROR)
+        return svn_error_createf(err->apr_err, err,
+                                 "Error reading authz file '%s' with "
+                                 "groups file '%s':", path, groups_path);
+    }
+
+  /* Make sure there are no errors in the configuration. */
+  SVN_ERR(authz_validate(authz, pool));
+
+  *authz_p = authz;
+  return SVN_NO_ERROR;
+}
+
+
+
+/*** Public functions. ***/
+
+svn_error_t *
+svn_repos_authz_read2(svn_authz_t **authz_p, const char *path,
+                      const char *groups_path, svn_boolean_t must_exist,
+                      const char *repos_root, apr_pool_t *pool)
+{
+  return svn_repos__authz_read(authz_p, path, groups_path, must_exist,
+                               TRUE, repos_root, pool);
+}
+
+
+svn_error_t *
+svn_repos_authz_parse(svn_authz_t **authz_p, svn_stream_t *stream, 
+                      svn_stream_t *groups_stream, apr_pool_t *pool)
+{
+  svn_authz_t *authz = apr_palloc(pool, sizeof(*authz));
+
+  /* Parse the authz stream */
+  SVN_ERR(svn_config_parse(&authz->cfg, stream, TRUE, pool));
+
+  if (groups_stream)
+    {
+      svn_config_t *groups_cfg;
+
+      /* Parse the groups stream */
+      SVN_ERR(svn_config_parse(&groups_cfg, groups_stream, TRUE, pool));
+
+      SVN_ERR(authz_copy_groups(authz, groups_cfg, pool));
+    }
+
+  /* Make sure there are no errors in the configuration. */
+  SVN_ERR(authz_validate(authz, pool));
+
   *authz_p = authz;
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/fsfs-format7/subversion/libsvn_repos/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_repos/commit.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_repos/commit.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_repos/commit.c Mon Feb  4 20:48:05 2013
@@ -38,12 +38,13 @@
 #include "svn_props.h"
 #include "svn_mergeinfo.h"
 #include "svn_private_config.h"
-#include "svn_editor.h"
 
 #include "repos.h"
 
 #include "private/svn_fspath.h"
+#include "private/svn_fs_private.h"
 #include "private/svn_repos_private.h"
+#include "private/svn_editor.h"
 
 
 
@@ -1226,8 +1227,8 @@ complete_cb(void *baton,
   SVN_ERR(svn_repos__hooks_pre_commit(eb->repos, eb->txn_name, scratch_pool));
 
   /* Hook is done. Let's do the actual commit.  */
-  SVN_ERR(svn_fs_editor_commit(&revision, &post_commit_err, &conflict_path,
-                               eb->inner, scratch_pool, scratch_pool));
+  SVN_ERR(svn_fs__editor_commit(&revision, &post_commit_err, &conflict_path,
+                                eb->inner, scratch_pool, scratch_pool));
 
   /* Did a conflict occur during the commit process?  */
   if (conflict_path != NULL)
@@ -1345,10 +1346,10 @@ svn_repos__get_commit_ev2(svn_editor_t *
   eb->commit_cb = commit_cb;
   eb->commit_baton = commit_baton;
 
-  SVN_ERR(svn_fs_editor_create(&eb->inner, &eb->txn_name,
-                               repos->fs, SVN_FS_TXN_CHECK_LOCKS,
-                               cancel_func, cancel_baton,
-                               result_pool, scratch_pool));
+  SVN_ERR(svn_fs__editor_create(&eb->inner, &eb->txn_name,
+                                repos->fs, SVN_FS_TXN_CHECK_LOCKS,
+                                cancel_func, cancel_baton,
+                                result_pool, scratch_pool));
 
   /* The TXN has been created. Go ahead and apply all revision properties.  */
   SVN_ERR(apply_revprops(repos->fs, eb->txn_name, revprops, scratch_pool));

Modified: subversion/branches/fsfs-format7/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_repos/deprecated.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_repos/deprecated.c Mon Feb  4 20:48:05 2013
@@ -1006,3 +1006,13 @@ svn_repos_fs_begin_txn_for_update(svn_fs
 
   return SVN_NO_ERROR;
 }
+
+/*** From authz.c ***/
+
+svn_error_t *
+svn_repos_authz_read(svn_authz_t **authz_p, const char *file,
+                     svn_boolean_t must_exist, apr_pool_t *pool)
+{
+  return svn_repos__authz_read(authz_p, file, NULL, must_exist,
+                               FALSE, NULL, pool);
+}

Modified: subversion/branches/fsfs-format7/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_repos/dump.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_repos/dump.c Mon Feb  4 20:48:05 2013
@@ -1321,13 +1321,15 @@ verify_directory_entry(void *baton, cons
                        void *val, apr_pool_t *pool)
 {
   struct dir_baton *db = baton;
+  svn_fs_dirent_t *dirent = (svn_fs_dirent_t *)val;
   char *path = svn_relpath_join(db->path, (const char *)key, pool);
-  svn_node_kind_t kind;
   apr_hash_t *dirents;
   svn_filesize_t len;
 
-  SVN_ERR(svn_fs_check_path(&kind, db->edit_baton->fs_root, path, pool));
-  switch (kind) {
+  /* since we can't access the directory entries directly by their ID,
+     we need to navigate from the FS_ROOT to them (relatively expensive
+     because we may start at a never rev than the last change to node). */
+  switch (dirent->kind) {
   case svn_node_dir:
     /* Getting this directory's contents is enough to ensure that our
        link to it is correct. */
@@ -1340,7 +1342,8 @@ verify_directory_entry(void *baton, cons
     break;
   default:
     return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
-                             _("Unexpected node kind %d for '%s'"), kind, path);
+                             _("Unexpected node kind %d for '%s'"),
+                             dirent->kind, path);
   }
 
   return SVN_NO_ERROR;
@@ -1359,6 +1362,32 @@ verify_close_directory(void *dir_baton,
   return close_directory(dir_baton, pool);
 }
 
+/* Baton type used for forwarding notifications from FS API to REPOS API. */
+struct verify_fs2_notify_func_baton_t
+{
+   /* notification function to call (must not be NULL) */
+   svn_repos_notify_func_t notify_func;
+
+   /* baton to use for it */
+   void *notify_baton;
+
+   /* type of notification to send (we will simply plug in the revision) */
+   svn_repos_notify_t *notify;
+};
+
+/* Forward the notification to BATON. */
+static void
+verify_fs2_notify_func(svn_revnum_t revision,
+                       void *baton,
+                       apr_pool_t *pool)
+{
+  struct verify_fs2_notify_func_baton_t *notify_baton = baton;
+
+  notify_baton->notify->revision = revision;
+  notify_baton->notify_func(notify_baton->notify_baton,
+                            notify_baton->notify, pool);
+}
+
 svn_error_t *
 svn_repos_verify_fs2(svn_repos_t *repos,
                      svn_revnum_t start_rev,
@@ -1374,6 +1403,8 @@ svn_repos_verify_fs2(svn_repos_t *repos,
   svn_revnum_t rev;
   apr_pool_t *iterpool = svn_pool_create(pool);
   svn_repos_notify_t *notify;
+  svn_fs_progress_notify_func_t verify_notify = NULL;
+  struct verify_fs2_notify_func_baton_t *verify_notify_baton = NULL;
 
   /* Determine the current youngest revision of the filesystem. */
   SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool));
@@ -1396,14 +1427,25 @@ svn_repos_verify_fs2(svn_repos_t *repos,
                                "(youngest revision is %ld)"),
                              end_rev, youngest);
 
-  /* Verify global/auxiliary data and backend-specific data first. */
-  SVN_ERR(svn_fs_verify(svn_fs_path(fs, pool), cancel_func, cancel_baton,
-                        start_rev, end_rev, pool));
-
-  /* Create a notify object that we can reuse within the loop. */
+  /* Create a notify object that we can reuse within the loop and a
+     forwarding structure for notifications from inside svn_fs_verify(). */
   if (notify_func)
-    notify = svn_repos_notify_create(svn_repos_notify_verify_rev_end,
-                                     pool);
+    {
+      notify = svn_repos_notify_create(svn_repos_notify_verify_rev_end,
+                                       pool);
+
+      verify_notify = verify_fs2_notify_func;
+      verify_notify_baton = apr_palloc(pool, sizeof(*verify_notify_baton));
+      verify_notify_baton->notify_func = notify_func;
+      verify_notify_baton->notify_baton = notify_baton;
+      verify_notify_baton->notify
+        = svn_repos_notify_create(svn_repos_notify_verify_struc_rev, pool);
+    }
+
+  /* Verify global metadata and backend-specific data first. */
+  SVN_ERR(svn_fs_verify(svn_fs_path(fs, pool), start_rev, end_rev,
+                        verify_notify, verify_notify_baton,
+                        cancel_func, cancel_baton, pool));
 
   for (rev = start_rev; rev <= end_rev; rev++)
     {
@@ -1432,6 +1474,8 @@ svn_repos_verify_fs2(svn_repos_t *repos,
                                                 &cancel_edit_baton,
                                                 iterpool));
 
+      SVN_ERR(svn_fs_verify_rev(fs, rev, iterpool));
+
       SVN_ERR(svn_fs_revision_root(&to_root, fs, rev, iterpool));
       SVN_ERR(svn_repos_replay2(to_root, "", SVN_INVALID_REVNUM, FALSE,
                                 cancel_editor, cancel_edit_baton,

Modified: subversion/branches/fsfs-format7/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_repos/fs-wrap.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_repos/fs-wrap.c Mon Feb  4 20:48:05 2013
@@ -178,7 +178,7 @@ svn_repos__validate_prop(const char *nam
        * LF line endings. */
       if (svn_prop_needs_translation(name))
         {
-          if (svn_utf__is_valid(value->data, value->len) == FALSE)
+          if (!svn_utf__is_valid(value->data, value->len))
             {
               return svn_error_createf
                 (SVN_ERR_BAD_PROPERTY_VALUE, NULL,
@@ -743,6 +743,7 @@ svn_error_t *
 svn_repos_fs_get_inherited_props(apr_array_header_t **inherited_props_p,
                                  svn_fs_root_t *root,
                                  const char *path,
+                                 const char *propname,
                                  svn_repos_authz_func_t authz_read_func,
                                  void *authz_read_baton,
                                  apr_pool_t *result_pool,
@@ -757,7 +758,7 @@ svn_repos_fs_get_inherited_props(apr_arr
   while (!(parent_path[0] == '/' && parent_path[1] == '\0'))
     {
       svn_boolean_t allowed = TRUE;
-      apr_hash_t *parent_properties;
+      apr_hash_t *parent_properties = NULL;
 
       svn_pool_clear(iterpool);
       parent_path = svn_fspath__dirname(parent_path, scratch_pool);
@@ -767,8 +768,25 @@ svn_repos_fs_get_inherited_props(apr_arr
                                 authz_read_baton, iterpool));
       if (allowed)
         {
-          SVN_ERR(svn_fs_node_proplist(&parent_properties, root,
-                                       parent_path, result_pool));
+          if (propname)
+            {
+              svn_string_t *propval;
+
+              SVN_ERR(svn_fs_node_prop(&propval, root, parent_path, propname,
+                                       result_pool));
+              if (propval)
+                {
+                  parent_properties = apr_hash_make(result_pool);
+                  apr_hash_set(parent_properties, propname,
+                               APR_HASH_KEY_STRING, propval);
+                }
+            }
+          else
+            {
+              SVN_ERR(svn_fs_node_proplist(&parent_properties, root,
+                                           parent_path, result_pool));
+            }
+
           if (parent_properties && apr_hash_count(parent_properties))
             {
               svn_prop_inherited_item_t *i_props =

Modified: subversion/branches/fsfs-format7/subversion/libsvn_repos/reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_repos/reporter.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_repos/reporter.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_repos/reporter.c Mon Feb  4 20:48:05 2013
@@ -447,7 +447,8 @@ static svn_error_t *
 change_dir_prop(report_baton_t *b, void *dir_baton, const char *name,
                 const svn_string_t *value, apr_pool_t *pool)
 {
-  return b->editor->change_dir_prop(dir_baton, name, value, pool);
+  return svn_error_trace(b->editor->change_dir_prop(dir_baton, name, value,
+                                                    pool));
 }
 
 /* Call the file property-setting function of B->editor to set the
@@ -456,7 +457,8 @@ static svn_error_t *
 change_file_prop(report_baton_t *b, void *file_baton, const char *name,
                  const svn_string_t *value, apr_pool_t *pool)
 {
-  return b->editor->change_file_prop(file_baton, name, value, pool);
+  return svn_error_trace(b->editor->change_file_prop(file_baton, name, value,
+                                                     pool));
 }
 
 /* For the report B, return the relevant revprop data of revision REV in
@@ -752,8 +754,8 @@ check_auth(report_baton_t *b, svn_boolea
            apr_pool_t *pool)
 {
   if (b->authz_read_func)
-    return b->authz_read_func(allowed, b->t_root, path,
-                              b->authz_read_baton, pool);
+    return svn_error_trace(b->authz_read_func(allowed, b->t_root, path,
+                                              b->authz_read_baton, pool));
   *allowed = TRUE;
   return SVN_NO_ERROR;
 }
@@ -879,9 +881,9 @@ add_file_smartly(report_baton_t *b,
         }
     }
 
-  return b->editor->add_file(path, parent_baton,
-                             *copyfrom_path, *copyfrom_rev,
-                             pool, new_file_baton);
+  return svn_error_trace(b->editor->add_file(path, parent_baton,
+                                             *copyfrom_path, *copyfrom_rev,
+                                             pool, new_file_baton));
 }
 
 
@@ -1016,7 +1018,7 @@ update_entry(report_baton_t *b, svn_revn
 
   /* If there's no target, we have nothing more to do. */
   if (!t_entry)
-    return skip_path_info(b, e_path);
+    return svn_error_trace(skip_path_info(b, e_path));
 
   /* Check if the user is authorized to find out about the target. */
   SVN_ERR(check_auth(b, &allowed, t_path, pool));
@@ -1026,7 +1028,7 @@ update_entry(report_baton_t *b, svn_revn
         SVN_ERR(b->editor->absent_directory(e_path, dir_baton, pool));
       else
         SVN_ERR(b->editor->absent_file(e_path, dir_baton, pool));
-      return skip_path_info(b, e_path);
+      return svn_error_trace(skip_path_info(b, e_path));
     }
 
   if (t_entry->kind == svn_node_dir)
@@ -1042,7 +1044,7 @@ update_entry(report_baton_t *b, svn_revn
       SVN_ERR(delta_dirs(b, s_rev, s_path, t_path, new_baton, e_path,
                          info ? info->start_empty : FALSE,
                          wc_depth, requested_depth, pool));
-      return b->editor->close_directory(new_baton, pool);
+      return svn_error_trace(b->editor->close_directory(new_baton, pool));
     }
   else
     {
@@ -1074,7 +1076,8 @@ update_entry(report_baton_t *b, svn_revn
       SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5, b->t_root,
                                    t_path, TRUE, pool));
       hex_digest = svn_checksum_to_cstring(checksum, pool);
-      return b->editor->close_file(new_baton, hex_digest, pool);
+      return svn_error_trace(b->editor->close_file(new_baton, hex_digest,
+                                                   pool));
     }
 }
 
@@ -1353,8 +1356,6 @@ drive(report_baton_t *b, svn_revnum_t s_
 
   /* Collect information about the source and target nodes. */
   s_fullpath = svn_fspath__join(b->fs_base, b->s_operand, pool);
-  /* ### Weird: When I have a file external defined as "^/A/a X/xa",
-   * ### S_FULLPATH becomes "/A/a/xa" here, which is complete nonsense. */
   SVN_ERR(get_source_root(b, &s_root, s_rev));
   SVN_ERR(fake_dirent(&s_entry, s_root, s_fullpath, pool));
   SVN_ERR(fake_dirent(&t_entry, b->t_root, b->t_path, pool));
@@ -1392,7 +1393,7 @@ drive(report_baton_t *b, svn_revnum_t s_
                          t_entry, root_baton, b->s_operand, info,
                          info->depth, b->requested_depth, pool));
 
-  return b->editor->close_directory(root_baton, pool);
+  return svn_error_trace(b->editor->close_directory(root_baton, pool));
 }
 
 /* Initialize the baton fields for editor-driving, and drive the editor. */
@@ -1448,7 +1449,8 @@ finish_report(report_baton_t *b, apr_poo
     b->s_roots[i] = NULL;
 
   {
-    svn_error_t *err = drive(b, s_rev, info, pool);
+    svn_error_t *err = svn_error_trace(drive(b, s_rev, info, pool));
+
     if (err == SVN_NO_ERROR)
       return svn_error_trace(b->editor->close_edit(b->edit_baton, pool));
 
@@ -1500,7 +1502,8 @@ write_path_info(report_baton_t *b, const
   rep = apr_psprintf(pool, "+%" APR_SIZE_T_FMT ":%s%s%s%s%c%s",
                      strlen(path), path, lrep, rrep, drep,
                      start_empty ? '+' : '-', ltrep);
-  return svn_spillbuf__reader_write(b->reader, rep, strlen(rep), pool);
+  return svn_error_trace(
+            svn_spillbuf__reader_write(b->reader, rep, strlen(rep), pool));
 }
 
 svn_error_t *
@@ -1508,8 +1511,9 @@ svn_repos_set_path3(void *baton, const c
                     svn_depth_t depth, svn_boolean_t start_empty,
                     const char *lock_token, apr_pool_t *pool)
 {
-  return write_path_info(baton, path, NULL, rev, depth, start_empty,
-                         lock_token, pool);
+  return svn_error_trace(
+            write_path_info(baton, path, NULL, rev, depth, start_empty,
+                            lock_token, pool));
 }
 
 svn_error_t *
@@ -1522,8 +1526,9 @@ svn_repos_link_path3(void *baton, const 
     return svn_error_create(SVN_ERR_REPOS_BAD_ARGS, NULL,
                             _("Depth 'exclude' not supported for link"));
 
-  return write_path_info(baton, path, link_path, rev, depth,
-                         start_empty, lock_token, pool);
+  return svn_error_trace(
+            write_path_info(baton, path, link_path, rev, depth,
+                            start_empty, lock_token, pool));
 }
 
 svn_error_t *
@@ -1531,8 +1536,9 @@ svn_repos_delete_path(void *baton, const
 {
   /* We pass svn_depth_infinity because deletion of a path always
      deletes everything underneath it. */
-  return write_path_info(baton, path, NULL, SVN_INVALID_REVNUM,
-                         svn_depth_infinity, FALSE, NULL, pool);
+  return svn_error_trace(
+            write_path_info(baton, path, NULL, SVN_INVALID_REVNUM,
+                            svn_depth_infinity, FALSE, NULL, pool));
 }
 
 svn_error_t *

Modified: subversion/branches/fsfs-format7/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_repos/repos.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_repos/repos.c Mon Feb  4 20:48:05 2013
@@ -1019,10 +1019,18 @@ create_conf(svn_repos_t *repos, apr_pool
 "### The authz-db option controls the location of the authorization"         NL
 "### rules for path-based access control.  Unless you specify a path"        NL
 "### starting with a /, the file's location is relative to the"              NL
-"### directory containing this file.  If you don't specify an"               NL
-"### authz-db, no path-based access control is done."                        NL
+"### directory containing this file.  The specified path may be a"           NL
+"### repository relative URL (^/) or an absolute file:// URL to a text"      NL
+"### file in a Subversion repository.  If you don't specify an authz-db,"    NL
+"### no path-based access control is done."                                  NL
 "### Uncomment the line below to use the default authorization file."        NL
 "# authz-db = " SVN_REPOS__CONF_AUTHZ                                        NL
+"### The groups-db option controls the location of the groups file."         NL
+"### Unless you specify a path starting with a /, the file's location is"    NL
+"### relative to the directory containing this file.  The specified path"    NL
+"### may be a repository relative URL (^/) or an absolute file:// URL to a"  NL
+"### text file in a Subversion repository."                                  NL
+"# groups-db = " SVN_REPOS__CONF_GROUPS                                      NL
 "### This option specifies the authentication realm of the repository."      NL
 "### If two repositories have the same authentication realm, they should"    NL
 "### have the same password database, and vice versa.  The default realm"    NL
@@ -1537,6 +1545,23 @@ get_repos(svn_repos_t **repos_p,
   if (open_fs)
     SVN_ERR(svn_fs_open(&repos->fs, repos->db_path, fs_config, pool));
 
+#ifdef SVN_DEBUG_CRASH_AT_REPOS_OPEN
+  /* If $PATH/config/debug-abort exists, crash the server here.
+     This debugging feature can be used to test client recovery
+     when the server crashes.
+
+     See: Issue #4274 */
+  {
+    svn_node_kind_t kind;
+    svn_error_t *err = svn_io_check_path(
+        svn_dirent_join(repos->conf_path, "debug-abort", pool),
+        &kind, pool);
+    svn_error_clear(err);
+    if (!err && kind == svn_node_file)
+      SVN_ERR_MALFUNCTION_NO_RETURN();
+  }
+#endif /* SVN_DEBUG_CRASH_AT_REPOS_OPEN */
+
   *repos_p = repos;
   return SVN_NO_ERROR;
 }
@@ -2103,7 +2128,7 @@ svn_repos_stat(svn_dirent_t **dirent,
       return SVN_NO_ERROR;
     }
 
-  ent = apr_pcalloc(pool, sizeof(*ent));
+  ent = svn_dirent_create(pool);
   ent->kind = kind;
 
   if (kind == svn_node_file)

Modified: subversion/branches/fsfs-format7/subversion/libsvn_repos/repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_repos/repos.h?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_repos/repos.h (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_repos/repos.h Mon Feb  4 20:48:05 2013
@@ -95,10 +95,11 @@ extern "C" {
 #define SVN_REPOS__CONF_SVNSERVE_CONF "svnserve.conf"
 
 /* In the svnserve default configuration, these are the suggested
-   locations for the passwd and authz files (in the repository conf
-   directory), and we put example templates there. */
+   locations for the passwd, authz and groups files (in the repository
+   conf directory), and we put example templates there. */
 #define SVN_REPOS__CONF_PASSWD "passwd"
 #define SVN_REPOS__CONF_AUTHZ "authz"
+#define SVN_REPOS__CONF_GROUPS "groups"
 
 /* The Repository object, created by svn_repos_open2() and
    svn_repos_create(). */
@@ -304,6 +305,33 @@ svn_repos__hooks_post_unlock(svn_repos_t
                              apr_pool_t *pool);
 
 
+/*** Authz Functions ***/
+
+/* Read authz configuration data from PATH into *AUTHZ_P, allocated
+   in POOL.  If GROUPS_PATH is set, use the global groups parsed from it.
+
+   PATH and GROUPS_PATH may be a file or a registry path and iff ACCEPT_URLS
+   is set it may also be a repos relative url or an absolute file url.  When
+   ACCEPT_URLS is FALSE REPOS_ROOT can be NULL.
+
+   If PATH or GROUPS_PATH is not a valid authz rule file, then return 
+   SVN_AUTHZ_INVALID_CONFIG.  The contents of *AUTHZ_P is then
+   undefined.  If MUST_EXIST is TRUE, a missing authz or global groups file
+   is also an error.
+
+   If PATH is a repos relative URL then REPOS_ROOT must be set to
+   the root of the repository the authz configuration will be used with.
+   The same applies to GROUPS_PATH if it is being used. */
+svn_error_t *
+svn_repos__authz_read(svn_authz_t **authz_p,
+                      const char *path,
+                      const char *groups_path,
+                      svn_boolean_t must_exist,
+                      svn_boolean_t accept_urls,
+                      const char *repos_root,
+                      apr_pool_t *pool);
+
+
 /*** Utility Functions ***/
 
 /* Set *CHANGED_P to TRUE if ROOT1/PATH1 and ROOT2/PATH2 have

Modified: subversion/branches/fsfs-format7/subversion/libsvn_subr/auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_subr/auth.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_subr/auth.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_subr/auth.c Mon Feb  4 20:48:05 2013
@@ -422,9 +422,9 @@ svn_auth_get_platform_specific_provider(
       const char *library_label, *library_name;
       const char *provider_function_name, *version_function_name;
       library_name = apr_psprintf(pool,
-                                  "libsvn_auth_%s-%d.so.0",
+                                  "libsvn_auth_%s-%d.so.%d",
                                   provider_name,
-                                  SVN_VER_MAJOR);
+                                  SVN_VER_MAJOR, SVN_SOVERSION);
       library_label = apr_psprintf(pool, "svn_%s", provider_name);
       provider_function_name = apr_psprintf(pool,
                                             "svn_auth_get_%s_%s_provider",

Modified: subversion/branches/fsfs-format7/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_subr/cache-membuffer.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_subr/cache-membuffer.c Mon Feb  4 20:48:05 2013
@@ -1372,7 +1372,7 @@ membuffer_cache_set_internal(svn_membuff
 
   /* if there is an old version of that entry and the new data fits into
    * the old spot, just re-use that space. */
-  if (buffer && entry && entry->size >= size)
+  if (entry && ALIGN_VALUE(entry->size) >= size && buffer)
     {
       cache->data_used += size - entry->size;
       entry->size = size;
@@ -1430,7 +1430,10 @@ membuffer_cache_set_internal(svn_membuff
   else
     {
       /* if there is already an entry for this key, drop it.
+       * Since ensure_data_insertable may have removed entries from
+       * ENTRY's group, re-do the lookup.
        */
+      entry = find_entry(cache, group_index, to_find, FALSE);
       if (entry)
         drop_entry(cache, entry);
     }
@@ -2004,16 +2007,6 @@ svn_membuffer_cache_get(void **value_p,
                               DEBUG_CACHE_MEMBUFFER_TAG
                               result_pool));
 
-  /* We don't need more the key anymore.
-   * But since we allocate only small amounts of data per get() call and
-   * apr_pool_clear is somewhat expensive, we clear it only now and then.
-   */
-  if (++cache->alloc_counter > ALLOCATIONS_PER_POOL_CLEAR)
-    {
-      apr_pool_clear(cache->pool);
-      cache->alloc_counter = 0;
-    }
-
   /* return result */
   *found = *value_p != NULL;
 }
@@ -2072,7 +2065,7 @@ svn_membuffer_cache_set(void *cache_void
   cache->alloc_counter += 3;
   if (cache->alloc_counter > ALLOCATIONS_PER_POOL_CLEAR)
     {
-      apr_pool_clear(cache->pool);
+      svn_pool_clear(cache->pool);
       cache->alloc_counter = 0;
     }
 
@@ -2128,12 +2121,6 @@ svn_membuffer_cache_get_partial(void **v
       return SVN_NO_ERROR;
     }
 
-  if (++cache->alloc_counter > ALLOCATIONS_PER_POOL_CLEAR)
-    {
-      apr_pool_clear(cache->pool);
-      cache->alloc_counter = 0;
-    }
-
   combine_key(cache, key, cache->key_len);
   SVN_ERR(membuffer_cache_get_partial(cache->membuffer,
                                       cache->combined_key,

Modified: subversion/branches/fsfs-format7/subversion/libsvn_subr/cache_config.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_subr/cache_config.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_subr/cache_config.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_subr/cache_config.c Mon Feb  4 20:48:05 2013
@@ -131,7 +131,7 @@ svn_cache__get_global_membuffer_cache(vo
         {
           /* Memory and error cleanup */
           svn_error_clear(err);
-          apr_pool_destroy(pool);
+          svn_pool_destroy(pool);
 
           /* Prevent future attempts to create the cache. However, an
            * existing cache instance (see next comment) remains valid.
@@ -155,7 +155,7 @@ svn_cache__get_global_membuffer_cache(vo
        */
       old_cache = apr_atomic_casptr((volatile void **)&cache, new_cache, NULL);
       if (old_cache != NULL)
-        apr_pool_destroy(pool);
+        svn_pool_destroy(pool);
     }
 
   return cache;

Modified: subversion/branches/fsfs-format7/subversion/libsvn_subr/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_subr/cmdline.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_subr/cmdline.c Mon Feb  4 20:48:05 2013
@@ -33,14 +33,17 @@
 #include <unistd.h>
 #else
 #include <crtdbg.h>
+#include <io.h>
 #endif
 
+#include <apr.h>                /* for STDIN_FILENO */
 #include <apr_errno.h>          /* for apr_strerror */
 #include <apr_general.h>        /* for apr_initialize/apr_terminate */
 #include <apr_strings.h>        /* for apr_snprintf */
 #include <apr_pools.h>
 
 #include "svn_cmdline.h"
+#include "svn_ctype.h"
 #include "svn_dso.h"
 #include "svn_dirent_uri.h"
 #include "svn_path.h"
@@ -52,9 +55,13 @@
 #include "svn_xml.h"
 #include "svn_base64.h"
 #include "svn_config.h"
+#include "svn_sorts.h"
+#include "svn_props.h"
+#include "svn_subst.h"
 
 #include "private/svn_cmdline_private.h"
 #include "private/svn_utf_private.h"
+#include "private/svn_string_private.h"
 
 #include "svn_private_config.h"
 
@@ -478,7 +485,7 @@ svn_cmdline_create_auth_baton(svn_auth_b
       pb->config_dir = config_dir;
     }
 
-  if (non_interactive == FALSE)
+  if (!non_interactive)
     {
       /* This provider doesn't prompt the user in order to get creds;
          it prompts the user regarding the caching of creds. */
@@ -509,7 +516,7 @@ svn_cmdline_create_auth_baton(svn_auth_b
   svn_auth_get_ssl_client_cert_file_provider(&provider, pool);
   APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
 
-  if (non_interactive == FALSE)
+  if (!non_interactive)
     {
       /* This provider doesn't prompt the user in order to get creds;
          it prompts the user regarding the caching of creds. */
@@ -524,7 +531,7 @@ svn_cmdline_create_auth_baton(svn_auth_b
     }
   APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
 
-  if (non_interactive == FALSE)
+  if (!non_interactive)
     {
       svn_boolean_t ssl_client_cert_file_prompt;
 
@@ -758,3 +765,546 @@ svn_cmdline__apply_config_options(apr_ha
 
   return SVN_NO_ERROR;
 }
+
+/* Return a copy, allocated in POOL, of the next line of text from *STR
+ * up to and including a CR and/or an LF. Change *STR to point to the
+ * remainder of the string after the returned part. If there are no
+ * characters to be returned, return NULL; never return an empty string.
+ */
+static const char *
+next_line(const char **str, apr_pool_t *pool)
+{
+  const char *start = *str;
+  const char *p = *str;
+
+  /* n.b. Throughout this fn, we never read any character after a '\0'. */
+  /* Skip over all non-EOL characters, if any. */
+  while (*p != '\r' && *p != '\n' && *p != '\0')
+    p++;
+  /* Skip over \r\n or \n\r or \r or \n, if any. */
+  if (*p == '\r' || *p == '\n')
+    {
+      char c = *p++;
+
+      if ((c == '\r' && *p == '\n') || (c == '\n' && *p == '\r'))
+        p++;
+    }
+
+  /* Now p points after at most one '\n' and/or '\r'. */
+  *str = p;
+
+  if (p == start)
+    return NULL;
+
+  return svn_string_ncreate(start, p - start, pool)->data;
+}
+
+const char *
+svn_cmdline__indent_string(const char *str,
+                           const char *indent,
+                           apr_pool_t *pool)
+{
+  svn_stringbuf_t *out = svn_stringbuf_create_empty(pool);
+  const char *line;
+
+  while ((line = next_line(&str, pool)))
+    {
+      svn_stringbuf_appendcstr(out, indent);
+      svn_stringbuf_appendcstr(out, line);
+    }
+  return out->data;
+}
+
+svn_error_t *
+svn_cmdline__print_prop_hash(svn_stream_t *out,
+                             apr_hash_t *prop_hash,
+                             svn_boolean_t names_only,
+                             apr_pool_t *pool)
+{
+  apr_array_header_t *sorted_props;
+  int i;
+
+  sorted_props = svn_sort__hash(prop_hash, svn_sort_compare_items_lexically,
+                                pool);
+  for (i = 0; i < sorted_props->nelts; i++)
+    {
+      svn_sort__item_t item = APR_ARRAY_IDX(sorted_props, i, svn_sort__item_t);
+      const char *pname = item.key;
+      svn_string_t *propval = item.value;
+      const char *pname_stdout;
+
+      if (svn_prop_needs_translation(pname))
+        SVN_ERR(svn_subst_detranslate_string(&propval, propval,
+                                             TRUE, pool));
+
+      SVN_ERR(svn_cmdline_cstring_from_utf8(&pname_stdout, pname, pool));
+
+      if (out)
+        {
+          pname_stdout = apr_psprintf(pool, "  %s\n", pname_stdout);
+          SVN_ERR(svn_subst_translate_cstring2(pname_stdout, &pname_stdout,
+                                              APR_EOL_STR,  /* 'native' eol */
+                                              FALSE, /* no repair */
+                                              NULL,  /* no keywords */
+                                              FALSE, /* no expansion */
+                                              pool));
+
+          SVN_ERR(svn_stream_puts(out, pname_stdout));
+        }
+      else
+        {
+          /* ### We leave these printfs for now, since if propval wasn't
+             translated above, we don't know anything about its encoding.
+             In fact, it might be binary data... */
+          printf("  %s\n", pname_stdout);
+        }
+
+      if (!names_only)
+        {
+          /* Add an extra newline to the value before indenting, so that
+           * every line of output has the indentation whether the value
+           * already ended in a newline or not. */
+          const char *newval = apr_psprintf(pool, "%s\n", propval->data);
+          const char *indented_newval = svn_cmdline__indent_string(newval,
+                                                                   "    ",
+                                                                   pool);
+          if (out)
+            {
+              SVN_ERR(svn_stream_puts(out, indented_newval));
+            }
+          else
+            {
+              printf("%s", indented_newval);
+            }
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_cmdline__print_xml_prop_hash(svn_stringbuf_t **outstr,
+                                 apr_hash_t *prop_hash,
+                                 svn_boolean_t names_only,
+                                 svn_boolean_t inherited_props,
+                                 apr_pool_t *pool)
+{
+  apr_array_header_t *sorted_props;
+  int i;
+
+  if (*outstr == NULL)
+    *outstr = svn_stringbuf_create_empty(pool);
+
+  sorted_props = svn_sort__hash(prop_hash, svn_sort_compare_items_lexically,
+                                pool);
+  for (i = 0; i < sorted_props->nelts; i++)
+    {
+      svn_sort__item_t item = APR_ARRAY_IDX(sorted_props, i, svn_sort__item_t);
+      const char *pname = item.key;
+      svn_string_t *propval = item.value;
+
+      if (names_only)
+        {
+          svn_xml_make_open_tag(
+            outstr, pool, svn_xml_self_closing,
+            inherited_props ? "inherited_property" : "property",
+            "name", pname, NULL);
+        }
+      else
+        {
+          const char *pname_out;
+
+          if (svn_prop_needs_translation(pname))
+            SVN_ERR(svn_subst_detranslate_string(&propval, propval,
+                                                 TRUE, pool));
+
+          SVN_ERR(svn_cmdline_cstring_from_utf8(&pname_out, pname, pool));
+
+          svn_cmdline__print_xml_prop(outstr, pname_out, propval,
+                                      inherited_props, pool);
+        }
+    }
+
+    return SVN_NO_ERROR;
+}
+
+svn_boolean_t
+svn_cmdline__be_interactive(svn_boolean_t non_interactive,
+                            svn_boolean_t force_interactive)
+{
+  /* If neither --non-interactive nor --force-interactive was passed,
+   * be interactive if stdin is a terminal.
+   * If --force-interactive was passed, always be interactive. */
+  if (!force_interactive && !non_interactive)
+    {
+#ifdef WIN32
+      return (_isatty(STDIN_FILENO) != 0);
+#else
+      return (isatty(STDIN_FILENO) != 0);
+#endif
+    }
+  else if (force_interactive) 
+    return TRUE;
+
+  return !non_interactive;
+}
+
+
+/* Helper for the next two functions.  Set *EDITOR to some path to an
+   editor binary.  Sources to search include: the EDITOR_CMD argument
+   (if not NULL), $SVN_EDITOR, the runtime CONFIG variable (if CONFIG
+   is not NULL), $VISUAL, $EDITOR.  Return
+   SVN_ERR_CL_NO_EXTERNAL_EDITOR if no binary can be found. */
+static svn_error_t *
+find_editor_binary(const char **editor,
+                   const char *editor_cmd,
+                   apr_hash_t *config)
+{
+  const char *e;
+  struct svn_config_t *cfg;
+
+  /* Use the editor specified on the command line via --editor-cmd, if any. */
+  e = editor_cmd;
+
+  /* Otherwise look for the Subversion-specific environment variable. */
+  if (! e)
+    e = getenv("SVN_EDITOR");
+
+  /* If not found then fall back on the config file. */
+  if (! e)
+    {
+      cfg = config ? apr_hash_get(config, SVN_CONFIG_CATEGORY_CONFIG,
+                                  APR_HASH_KEY_STRING) : NULL;
+      svn_config_get(cfg, &e, SVN_CONFIG_SECTION_HELPERS,
+                     SVN_CONFIG_OPTION_EDITOR_CMD, NULL);
+    }
+
+  /* If not found yet then try general purpose environment variables. */
+  if (! e)
+    e = getenv("VISUAL");
+  if (! e)
+    e = getenv("EDITOR");
+
+#ifdef SVN_CLIENT_EDITOR
+  /* If still not found then fall back on the hard-coded default. */
+  if (! e)
+    e = SVN_CLIENT_EDITOR;
+#endif
+
+  /* Error if there is no editor specified */
+  if (e)
+    {
+      const char *c;
+
+      for (c = e; *c; c++)
+        if (!svn_ctype_isspace(*c))
+          break;
+
+      if (! *c)
+        return svn_error_create
+          (SVN_ERR_CL_NO_EXTERNAL_EDITOR, NULL,
+           _("The EDITOR, SVN_EDITOR or VISUAL environment variable or "
+             "'editor-cmd' run-time configuration option is empty or "
+             "consists solely of whitespace. Expected a shell command."));
+    }
+  else
+    return svn_error_create
+      (SVN_ERR_CL_NO_EXTERNAL_EDITOR, NULL,
+       _("None of the environment variables SVN_EDITOR, VISUAL or EDITOR are "
+         "set, and no 'editor-cmd' run-time configuration option was found"));
+
+  *editor = e;
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_cmdline__edit_file_externally(const char *path,
+                                  const char *editor_cmd,
+                                  apr_hash_t *config,
+                                  apr_pool_t *pool)
+{
+  const char *editor, *cmd, *base_dir, *file_name, *base_dir_apr;
+  char *old_cwd;
+  int sys_err;
+  apr_status_t apr_err;
+
+  svn_dirent_split(&base_dir, &file_name, path, pool);
+
+  SVN_ERR(find_editor_binary(&editor, editor_cmd, config));
+
+  apr_err = apr_filepath_get(&old_cwd, APR_FILEPATH_NATIVE, pool);
+  if (apr_err)
+    return svn_error_wrap_apr(apr_err, _("Can't get working directory"));
+
+  /* APR doesn't like "" directories */
+  if (base_dir[0] == '\0')
+    base_dir_apr = ".";
+  else
+    SVN_ERR(svn_path_cstring_from_utf8(&base_dir_apr, base_dir, pool));
+
+  apr_err = apr_filepath_set(base_dir_apr, pool);
+  if (apr_err)
+    return svn_error_wrap_apr
+      (apr_err, _("Can't change working directory to '%s'"), base_dir);
+
+  cmd = apr_psprintf(pool, "%s %s", editor, file_name);
+  sys_err = system(cmd);
+
+  apr_err = apr_filepath_set(old_cwd, pool);
+  if (apr_err)
+    svn_handle_error2(svn_error_wrap_apr
+                      (apr_err, _("Can't restore working directory")),
+                      stderr, TRUE /* fatal */, "svn: ");
+
+  if (sys_err)
+    /* Extracting any meaning from sys_err is platform specific, so just
+       use the raw value. */
+    return svn_error_createf(SVN_ERR_EXTERNAL_PROGRAM, NULL,
+                             _("system('%s') returned %d"), cmd, sys_err);
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_cmdline__edit_string_externally(svn_string_t **edited_contents /* UTF-8! */,
+                                    const char **tmpfile_left /* UTF-8! */,
+                                    const char *editor_cmd,
+                                    const char *base_dir /* UTF-8! */,
+                                    const svn_string_t *contents /* UTF-8! */,
+                                    const char *filename,
+                                    apr_hash_t *config,
+                                    svn_boolean_t as_text,
+                                    const char *encoding,
+                                    apr_pool_t *pool)
+{
+  const char *editor;
+  const char *cmd;
+  apr_file_t *tmp_file;
+  const char *tmpfile_name;
+  const char *tmpfile_native;
+  const char *tmpfile_apr, *base_dir_apr;
+  svn_string_t *translated_contents;
+  apr_status_t apr_err, apr_err2;
+  apr_size_t written;
+  apr_finfo_t finfo_before, finfo_after;
+  svn_error_t *err = SVN_NO_ERROR, *err2;
+  char *old_cwd;
+  int sys_err;
+  svn_boolean_t remove_file = TRUE;
+
+  SVN_ERR(find_editor_binary(&editor, editor_cmd, config));
+
+  /* Convert file contents from UTF-8/LF if desired. */
+  if (as_text)
+    {
+      const char *translated;
+      SVN_ERR(svn_subst_translate_cstring2(contents->data, &translated,
+                                           APR_EOL_STR, FALSE,
+                                           NULL, FALSE, pool));
+      translated_contents = svn_string_create_empty(pool);
+      if (encoding)
+        SVN_ERR(svn_utf_cstring_from_utf8_ex2(&translated_contents->data,
+                                              translated, encoding, pool));
+      else
+        SVN_ERR(svn_utf_cstring_from_utf8(&translated_contents->data,
+                                          translated, pool));
+      translated_contents->len = strlen(translated_contents->data);
+    }
+  else
+    translated_contents = svn_string_dup(contents, pool);
+
+  /* Move to BASE_DIR to avoid getting characters that need quoting
+     into tmpfile_name */
+  apr_err = apr_filepath_get(&old_cwd, APR_FILEPATH_NATIVE, pool);
+  if (apr_err)
+    return svn_error_wrap_apr(apr_err, _("Can't get working directory"));
+
+  /* APR doesn't like "" directories */
+  if (base_dir[0] == '\0')
+    base_dir_apr = ".";
+  else
+    SVN_ERR(svn_path_cstring_from_utf8(&base_dir_apr, base_dir, pool));
+  apr_err = apr_filepath_set(base_dir_apr, pool);
+  if (apr_err)
+    {
+      return svn_error_wrap_apr
+        (apr_err, _("Can't change working directory to '%s'"), base_dir);
+    }
+
+  /*** From here on, any problems that occur require us to cd back!! ***/
+
+  /* Ask the working copy for a temporary file named FILENAME-something. */
+  err = svn_io_open_uniquely_named(&tmp_file, &tmpfile_name,
+                                   "" /* dirpath */,
+                                   filename,
+                                   ".tmp",
+                                   svn_io_file_del_none, pool, pool);
+
+  if (err && (APR_STATUS_IS_EACCES(err->apr_err) || err->apr_err == EROFS))
+    {
+      const char *temp_dir_apr;
+
+      svn_error_clear(err);
+
+      SVN_ERR(svn_io_temp_dir(&base_dir, pool));
+
+      SVN_ERR(svn_path_cstring_from_utf8(&temp_dir_apr, base_dir, pool));
+      apr_err = apr_filepath_set(temp_dir_apr, pool);
+      if (apr_err)
+        {
+          return svn_error_wrap_apr
+            (apr_err, _("Can't change working directory to '%s'"), base_dir);
+        }
+
+      err = svn_io_open_uniquely_named(&tmp_file, &tmpfile_name,
+                                       "" /* dirpath */,
+                                       filename,
+                                       ".tmp",
+                                       svn_io_file_del_none, pool, pool);
+    }
+
+  if (err)
+    goto cleanup2;
+
+  /*** From here on, any problems that occur require us to cleanup
+       the file we just created!! ***/
+
+  /* Dump initial CONTENTS to TMP_FILE. */
+  apr_err = apr_file_write_full(tmp_file, translated_contents->data,
+                                translated_contents->len, &written);
+
+  apr_err2 = apr_file_close(tmp_file);
+  if (! apr_err)
+    apr_err = apr_err2;
+
+  /* Make sure the whole CONTENTS were written, else return an error. */
+  if (apr_err)
+    {
+      err = svn_error_wrap_apr(apr_err, _("Can't write to '%s'"),
+                               tmpfile_name);
+      goto cleanup;
+    }
+
+  err = svn_path_cstring_from_utf8(&tmpfile_apr, tmpfile_name, pool);
+  if (err)
+    goto cleanup;
+
+  /* Get information about the temporary file before the user has
+     been allowed to edit its contents. */
+  apr_err = apr_stat(&finfo_before, tmpfile_apr,
+                     APR_FINFO_MTIME, pool);
+  if (apr_err)
+    {
+      err = svn_error_wrap_apr(apr_err, _("Can't stat '%s'"), tmpfile_name);
+      goto cleanup;
+    }
+
+  /* Backdate the file a little bit in case the editor is very fast
+     and doesn't change the size.  (Use two seconds, since some
+     filesystems have coarse granularity.)  It's OK if this call
+     fails, so we don't check its return value.*/
+  apr_file_mtime_set(tmpfile_apr, finfo_before.mtime - 2000, pool);
+
+  /* Stat it again to get the mtime we actually set. */
+  apr_err = apr_stat(&finfo_before, tmpfile_apr,
+                     APR_FINFO_MTIME | APR_FINFO_SIZE, pool);
+  if (apr_err)
+    {
+      err = svn_error_wrap_apr(apr_err, _("Can't stat '%s'"), tmpfile_name);
+      goto cleanup;
+    }
+
+  /* Prepare the editor command line.  */
+  err = svn_utf_cstring_from_utf8(&tmpfile_native, tmpfile_name, pool);
+  if (err)
+    goto cleanup;
+  cmd = apr_psprintf(pool, "%s %s", editor, tmpfile_native);
+
+  /* If the caller wants us to leave the file around, return the path
+     of the file we'll use, and make a note not to destroy it.  */
+  if (tmpfile_left)
+    {
+      *tmpfile_left = svn_dirent_join(base_dir, tmpfile_name, pool);
+      remove_file = FALSE;
+    }
+
+  /* Now, run the editor command line.  */
+  sys_err = system(cmd);
+  if (sys_err != 0)
+    {
+      /* Extracting any meaning from sys_err is platform specific, so just
+         use the raw value. */
+      err =  svn_error_createf(SVN_ERR_EXTERNAL_PROGRAM, NULL,
+                               _("system('%s') returned %d"), cmd, sys_err);
+      goto cleanup;
+    }
+
+  /* Get information about the temporary file after the assumed editing. */
+  apr_err = apr_stat(&finfo_after, tmpfile_apr,
+                     APR_FINFO_MTIME | APR_FINFO_SIZE, pool);
+  if (apr_err)
+    {
+      err = svn_error_wrap_apr(apr_err, _("Can't stat '%s'"), tmpfile_name);
+      goto cleanup;
+    }
+
+  /* If the file looks changed... */
+  if ((finfo_before.mtime != finfo_after.mtime) ||
+      (finfo_before.size != finfo_after.size))
+    {
+      svn_stringbuf_t *edited_contents_s;
+      err = svn_stringbuf_from_file2(&edited_contents_s, tmpfile_name, pool);
+      if (err)
+        goto cleanup;
+
+      *edited_contents = svn_stringbuf__morph_into_string(edited_contents_s);
+
+      /* Translate back to UTF8/LF if desired. */
+      if (as_text)
+        {
+          err = svn_subst_translate_string2(edited_contents, FALSE, FALSE,
+                                            *edited_contents, encoding, FALSE,
+                                            pool, pool);
+          if (err)
+            {
+              err = svn_error_quick_wrap
+                (err,
+                 _("Error normalizing edited contents to internal format"));
+              goto cleanup;
+            }
+        }
+    }
+  else
+    {
+      /* No edits seem to have been made */
+      *edited_contents = NULL;
+    }
+
+ cleanup:
+  if (remove_file)
+    {
+      /* Remove the file from disk.  */
+      err2 = svn_io_remove_file2(tmpfile_name, FALSE, pool);
+
+      /* Only report remove error if there was no previous error. */
+      if (! err && err2)
+        err = err2;
+      else
+        svn_error_clear(err2);
+    }
+
+ cleanup2:
+  /* If we against all probability can't cd back, all further relative
+     file references would be screwed up, so we have to abort. */
+  apr_err = apr_filepath_set(old_cwd, pool);
+  if (apr_err)
+    {
+      svn_handle_error2(svn_error_wrap_apr
+                        (apr_err, _("Can't restore working directory")),
+                        stderr, TRUE /* fatal */, "svn: ");
+    }
+
+  return svn_error_trace(err);
+}

Modified: subversion/branches/fsfs-format7/subversion/libsvn_subr/config.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_subr/config.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_subr/config.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_subr/config.c Mon Feb  4 20:48:05 2013
@@ -129,7 +129,27 @@ svn_config_read2(svn_config_t **cfgp, co
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_config_parse(svn_config_t **cfgp, svn_stream_t *stream,
+                 svn_boolean_t section_names_case_sensitive,
+                 apr_pool_t *result_pool)
+{
+  svn_config_t *cfg;
+  svn_error_t *err;
+  apr_pool_t *scratch_pool = svn_pool_create(result_pool);
+
+  err = svn_config_create(&cfg, section_names_case_sensitive, result_pool);
 
+  if (err == SVN_NO_ERROR)
+    err = svn_config__parse_stream(cfg, stream, result_pool, scratch_pool);
+
+  if (err == SVN_NO_ERROR)
+    *cfgp = cfg;
+
+  svn_pool_destroy(scratch_pool);
+
+  return err;
+}
 
 /* Read various configuration sources into *CFGP, in this order, with
  * later reads overriding the results of earlier ones:
@@ -204,7 +224,7 @@ read_all(svn_config_t **cfgp,
     }
 
   if (! red_config)
-    *cfgp = NULL;
+    SVN_ERR(svn_config_create(cfgp, FALSE, pool));
 
   return SVN_NO_ERROR;
 }
@@ -776,6 +796,36 @@ svn_config_get_yes_no_ask(svn_config_t *
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_config_get_tristate(svn_config_t *cfg, svn_tristate_t *valuep,
+                        const char *section, const char *option,
+                        const char *unknown_value,
+                        svn_tristate_t default_value)
+{
+  const char *tmp_value;
+
+  svn_config_get(cfg, &tmp_value, section, option, NULL);
+
+  if (! tmp_value)
+    {
+      *valuep = default_value;
+    }
+  else if (0 == svn_cstring_casecmp(tmp_value, unknown_value))
+    {
+      *valuep = svn_tristate_unknown;
+    }
+  else
+    {
+      svn_boolean_t bool_val;
+      /* We already incorporated default_value into tmp_value if
+         necessary, so the FALSE below will be ignored unless the
+         caller is doing something it shouldn't be doing. */
+      SVN_ERR(get_bool(&bool_val, tmp_value, FALSE, section, option));
+      *valuep = bool_val ? svn_tristate_true : svn_tristate_false;
+    }
+
+  return SVN_NO_ERROR;
+}
 
 int
 svn_config_enumerate_sections(svn_config_t *cfg,

Modified: subversion/branches/fsfs-format7/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_subr/config_file.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_subr/config_file.c Mon Feb  4 20:48:05 2013
@@ -50,11 +50,10 @@
 /* File parsing context */
 typedef struct parse_context_t
 {
-  /* This config struct and file */
+  /* This config struct */
   svn_config_t *cfg;
-  const char *file;
 
-  /* The file descriptor */
+  /* The stream struct */
   svn_stream_t *stream;
 
   /* The current line in the file */
@@ -296,8 +295,7 @@ parse_option(int *pch, parse_context_t *
     {
       ch = EOF;
       err = svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
-                              "%s:%d: Option must end with ':' or '='",
-                              svn_dirent_local_style(ctx->file, scratch_pool),
+                              "line %d: Option must end with ':' or '='",
                               ctx->line);
     }
   else
@@ -340,8 +338,7 @@ parse_section_name(int *pch, parse_conte
     {
       ch = EOF;
       err = svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
-                              "%s:%d: Section header must end with ']'",
-                              svn_dirent_local_style(ctx->file, scratch_pool),
+                              "line %d: Section header must end with ']'",
                               ctx->line);
     }
   else
@@ -404,8 +401,6 @@ svn_config__parse_file(svn_config_t *cfg
                        svn_boolean_t must_exist, apr_pool_t *result_pool)
 {
   svn_error_t *err = SVN_NO_ERROR;
-  parse_context_t *ctx;
-  int ch, count;
   svn_stream_t *stream;
   apr_pool_t *scratch_pool = svn_pool_create(result_pool);
 
@@ -420,10 +415,32 @@ svn_config__parse_file(svn_config_t *cfg
   else
     SVN_ERR(err);
 
+  err = svn_config__parse_stream(cfg, stream, result_pool, scratch_pool);
+
+  if (err != SVN_NO_ERROR) 
+    {
+      /* Add the filename to the error stack. */
+      err = svn_error_createf(err->apr_err, err,
+                              "Error while parsing config file: %s:",
+                              svn_dirent_local_style(file, scratch_pool));
+    }
+
+  /* Close the streams (and other cleanup): */
+  svn_pool_destroy(scratch_pool);
+
+  return err;
+}
+
+svn_error_t *
+svn_config__parse_stream(svn_config_t *cfg, svn_stream_t *stream,
+                         apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+  parse_context_t *ctx;
+  int ch, count;
+
   ctx = apr_palloc(scratch_pool, sizeof(*ctx));
 
   ctx->cfg = cfg;
-  ctx->file = file;
   ctx->stream = stream;
   ctx->line = 1;
   ctx->ungotten_char = EOF;
@@ -444,10 +461,8 @@ svn_config__parse_file(svn_config_t *cfg
             SVN_ERR(parse_section_name(&ch, ctx, scratch_pool));
           else
             return svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
-                                     "%s:%d: Section header"
+                                     "line %d: Section header"
                                      " must start in the first column",
-                                     svn_dirent_local_style(file,
-                                                            scratch_pool),
                                      ctx->line);
           break;
 
@@ -459,10 +474,8 @@ svn_config__parse_file(svn_config_t *cfg
             }
           else
             return svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
-                                     "%s:%d: Comment"
+                                     "line %d: Comment"
                                      " must start in the first column",
-                                     svn_dirent_local_style(file,
-                                                            scratch_pool),
                                      ctx->line);
           break;
 
@@ -476,15 +489,11 @@ svn_config__parse_file(svn_config_t *cfg
         default:
           if (svn_stringbuf_isempty(ctx->section))
             return svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
-                                     "%s:%d: Section header expected",
-                                     svn_dirent_local_style(file,
-                                                            scratch_pool),
+                                     "line %d: Section header expected",
                                      ctx->line);
           else if (count != 0)
             return svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,
-                                     "%s:%d: Option expected",
-                                     svn_dirent_local_style(file,
-                                                            scratch_pool),
+                                     "line %d: Option expected",
                                      ctx->line);
           else
             SVN_ERR(parse_option(&ch, ctx, scratch_pool));
@@ -493,8 +502,6 @@ svn_config__parse_file(svn_config_t *cfg
     }
   while (ch != EOF);
 
-  /* Close the streams (and other cleanup): */
-  svn_pool_destroy(scratch_pool);
   return SVN_NO_ERROR;
 }
 
@@ -796,6 +803,9 @@ svn_config_ensure(const char *config_dir
         "###   http-timeout               Timeout for HTTP requests in seconds"
                                                                              NL
         "###   http-compression           Whether to compress HTTP requests" NL
+        "###   http-max-connections       Maximum number of parallel server" NL
+        "###                              connections to use for any given"  NL
+        "###                              HTTP operation."                   NL
         "###   neon-debug-mask            Debug mask for Neon HTTP library"  NL
         "###   ssl-authority-files        List of files, each of a trusted CA"
                                                                              NL
@@ -807,6 +817,9 @@ svn_config_ensure(const char *config_dir
         "###   http-library               Which library to use for http/https"
                                                                              NL
         "###                              connections."                      NL
+        "###   http-bulk-updates          Whether to request bulk update"    NL
+        "###                              responses or to fetch each file"   NL
+        "###                              in an individual request. "        NL
         "###   store-passwords            Specifies whether passwords used"  NL
         "###                              to authenticate against a"         NL
         "###                              Subversion server may be cached"   NL
@@ -826,8 +839,7 @@ svn_config_ensure(const char *config_dir
         "###                              unencrypted (i.e., as plaintext)." NL
 #endif
         "###   store-auth-creds           Specifies whether any auth info"   NL
-        "###                              (passwords as well as server certs)"
-                                                                             NL
+        "###                              (passwords, server certs, etc.)"   NL
         "###                              may be cached to disk."            NL
         "###   username                   Specifies the default username."   NL
         "###"                                                                NL

Modified: subversion/branches/fsfs-format7/subversion/libsvn_subr/config_impl.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_subr/config_impl.h?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_subr/config_impl.h (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_subr/config_impl.h Mon Feb  4 20:48:05 2013
@@ -32,6 +32,7 @@
 #include <apr_hash.h>
 #include "svn_types.h"
 #include "svn_string.h"
+#include "svn_io.h"
 #include "svn_config.h"
 #include "svn_private_config.h"
 
@@ -75,6 +76,12 @@ svn_error_t *svn_config__parse_file(svn_
                                     svn_boolean_t must_exist,
                                     apr_pool_t *pool);
 
+/* Read sections and options from a stream. */
+svn_error_t *svn_config__parse_stream(svn_config_t *cfg,
+                                      svn_stream_t *stream,
+                                      apr_pool_t *result_pool,
+                                      apr_pool_t *scratch_pool);
+
 /* The name of the magic [DEFAULT] section. */
 #define SVN_CONFIG__DEFAULT_SECTION "DEFAULT"
 

Modified: subversion/branches/fsfs-format7/subversion/libsvn_subr/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_subr/deprecated.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_subr/deprecated.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_subr/deprecated.c Mon Feb  4 20:48:05 2013
@@ -45,6 +45,7 @@
 
 #include "opt.h"
 #include "private/svn_opt_private.h"
+#include "private/svn_mergeinfo_private.h"
 
 #include "svn_private_config.h"
 
@@ -363,7 +364,7 @@ print_command_info(const svn_opt_subcomm
         {
           if (cmd->valid_options[i])
             {
-              if (have_options == FALSE)
+              if (!have_options)
                 {
                   SVN_ERR(svn_cmdline_fputs(_("\nValid options:\n"),
                                             stream, pool));
@@ -877,6 +878,22 @@ svn_io_dir_walk(const char *dirname,
                                           &baton, pool));
 }
 
+svn_error_t *
+svn_io_stat_dirent(const svn_io_dirent2_t **dirent_p,
+                   const char *path,
+                   svn_boolean_t ignore_enoent,
+                   apr_pool_t *result_pool,
+                   apr_pool_t *scratch_pool)
+{
+  return svn_error_trace(
+            svn_io_stat_dirent2(dirent_p,
+                                path,
+                                FALSE,
+                                ignore_enoent,
+                                result_pool,
+                                scratch_pool));
+}
+
 /*** From constructors.c ***/
 svn_log_changed_path_t *
 svn_log_changed_path_dup(const svn_log_changed_path_t *changed_path,
@@ -1122,8 +1139,11 @@ svn_rangelist_merge(svn_rangelist_t **ra
                     const svn_rangelist_t *changes,
                     apr_pool_t *pool)
 {
-  return svn_error_trace(svn_rangelist_merge2(*rangelist, changes,
-                                              pool, pool));
+  SVN_ERR(svn_rangelist_merge2(*rangelist, changes,
+                               pool, pool));
+
+  return svn_error_trace(
+            svn_rangelist__combine_adjacent_ranges(*rangelist, pool));
 }
 
 svn_error_t *

Modified: subversion/branches/fsfs-format7/subversion/libsvn_subr/error.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_subr/error.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_subr/error.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_subr/error.c Mon Feb  4 20:48:05 2013
@@ -221,6 +221,8 @@ svn_error_quick_wrap(svn_error_t *child,
                           new_msg);
 }
 
+/* Messages in tracing errors all point to this static string. */
+static const char error_tracing_link[] = "traced call";
 
 svn_error_t *
 svn_error__trace(const char *file, long line, svn_error_t *err)
@@ -235,8 +237,11 @@ svn_error__trace(const char *file, long 
   /* Only do the work when an error occurs.  */
   if (err)
     {
+      svn_error_t *trace;
       svn_error__locate(file, line);
-      return svn_error_quick_wrap(err, SVN_ERR__TRACED);
+      trace = make_error_internal(err->apr_err, err);
+      trace->message = error_tracing_link;
+      return trace;
     }
   return SVN_NO_ERROR;
 
@@ -383,7 +388,7 @@ svn_error__is_tracing_link(svn_error_t *
      ### we add a boolean field to svn_error_t that's set only for
      ### these "placeholder error chain" items.  Not such a bad idea,
      ### really...  */
-  return (err && err->message && !strcmp(err->message, SVN_ERR__TRACED));
+  return (err && err->message && !strcmp(err->message, error_tracing_link));
 #else
   return FALSE;
 #endif

Modified: subversion/branches/fsfs-format7/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_subr/io.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_subr/io.c Mon Feb  4 20:48:05 2013
@@ -834,7 +834,7 @@ svn_io_copy_file(const char *src,
     return SVN_NO_ERROR;
 #endif
 
-  SVN_ERR(svn_io_file_open(&from_file, src, APR_READ | APR_BINARY,
+  SVN_ERR(svn_io_file_open(&from_file, src, APR_READ,
                            APR_OS_DEFAULT, pool));
 
   /* For atomicity, we copy to a tmp file and then rename the tmp
@@ -1547,7 +1547,7 @@ io_set_file_perms(const char *path,
 
           /* Get the perms for the original file so we'll have any other bits
            * that were already set (like the execute bits, for example). */
-          SVN_ERR(svn_io_file_open(&fd, path, APR_READ | APR_BINARY,
+          SVN_ERR(svn_io_file_open(&fd, path, APR_READ,
                                    APR_OS_DEFAULT, pool));
           SVN_ERR(merge_default_file_perms(fd, &perms_to_set, pool));
           SVN_ERR(svn_io_file_close(fd, pool));
@@ -2273,7 +2273,9 @@ svn_io_remove_file2(const char *path,
 
   apr_err = apr_file_remove(path_apr, scratch_pool);
   if (!apr_err
-      || (ignore_enoent && APR_STATUS_IS_ENOENT(apr_err)))
+      || (ignore_enoent
+          && (APR_STATUS_IS_ENOENT(apr_err)
+              || SVN__APR_STATUS_IS_ENOTDIR(apr_err))))
     return SVN_NO_ERROR;
 
 #ifdef WIN32
@@ -2502,20 +2504,25 @@ svn_io_get_dirents3(apr_hash_t **dirents
 }
 
 svn_error_t *
-svn_io_stat_dirent(const svn_io_dirent2_t **dirent_p,
-                   const char *path,
-                   svn_boolean_t ignore_enoent,
-                   apr_pool_t *result_pool,
-                   apr_pool_t *scratch_pool)
+svn_io_stat_dirent2(const svn_io_dirent2_t **dirent_p,
+                    const char *path,
+                    svn_boolean_t verify_truename,
+                    svn_boolean_t ignore_enoent,
+                    apr_pool_t *result_pool,
+                    apr_pool_t *scratch_pool)
 {
   apr_finfo_t finfo;
   svn_io_dirent2_t *dirent;
   svn_error_t *err;
+  apr_int32_t wanted = APR_FINFO_TYPE | APR_FINFO_LINK
+                       | APR_FINFO_SIZE | APR_FINFO_MTIME;
+
+#if defined(WIN32) || defined(__OS2__)
+  if (verify_truename)
+    wanted |= APR_FINFO_NAME;
+#endif
 
-  err = svn_io_stat(&finfo, path,
-                    APR_FINFO_TYPE | APR_FINFO_LINK
-                    | APR_FINFO_SIZE | APR_FINFO_MTIME,
-                    scratch_pool);
+  err = svn_io_stat(&finfo, path, wanted, scratch_pool);
 
   if (err && ignore_enoent &&
       (APR_STATUS_IS_ENOENT(err->apr_err)
@@ -2530,6 +2537,78 @@ svn_io_stat_dirent(const svn_io_dirent2_
     }
   SVN_ERR(err);
 
+#if defined(WIN32) || defined(__OS2__) || defined(DARWIN)
+  if (verify_truename)
+    {
+      const char *requested_name = svn_dirent_basename(path, NULL);
+
+      if (requested_name[0] == '\0')
+        {
+          /* No parent directory. No need to stat/verify */
+        }
+#if defined(WIN32) || defined(__OS2__)
+      else if (finfo.name)
+        {
+          const char *name_on_disk;
+          SVN_ERR(entry_name_to_utf8(&name_on_disk, finfo.name, path,
+                                     scratch_pool));
+
+          if (strcmp(name_on_disk, requested_name) /* != 0 */)
+            {
+              if (ignore_enoent)
+                {
+                  *dirent_p = svn_io_dirent2_create(result_pool);
+                  return SVN_NO_ERROR;
+                }
+              else
+                return svn_error_createf(APR_ENOENT, NULL,
+                          _("Path '%s' not found, case obstructed by '%s'"),
+                          svn_dirent_local_style(path, scratch_pool),
+                          name_on_disk);
+            }
+        }
+#elif defined(DARWIN)
+      /* Currently apr doesn't set finfo.name on DARWIN, returning
+                   APR_INCOMPLETE.
+         ### Can we optimize this in another way? */
+      else
+        {
+          apr_hash_t *dirents;
+
+          err = svn_io_get_dirents3(&dirents,
+                                    svn_dirent_dirname(path, scratch_pool),
+                                    TRUE /* only_check_type */,
+                                    scratch_pool, scratch_pool);
+
+          if (err && ignore_enoent
+              && (APR_STATUS_IS_ENOENT(err->apr_err)
+                  || SVN__APR_STATUS_IS_ENOTDIR(err->apr_err)))
+            {
+              svn_error_clear(err);
+
+              *dirent_p = svn_io_dirent2_create(result_pool);
+              return SVN_NO_ERROR;
+            }
+          else
+            SVN_ERR(err);
+
+          if (! apr_hash_get(dirents, requested_name, APR_HASH_KEY_STRING))
+            {
+              if (ignore_enoent)
+                {
+                  *dirent_p = svn_io_dirent2_create(result_pool);
+                  return SVN_NO_ERROR;
+                }
+              else
+                return svn_error_createf(APR_ENOENT, NULL,
+                          _("Path '%s' not found"),
+                          svn_dirent_local_style(path, scratch_pool));
+            }
+        }
+#endif
+    }
+#endif
+
   dirent = svn_io_dirent2_create(result_pool);
   map_apr_finfo_to_node_kind(&(dirent->kind), &(dirent->special), &finfo);
 

Modified: subversion/branches/fsfs-format7/subversion/libsvn_subr/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_subr/mergeinfo.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_subr/mergeinfo.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_subr/mergeinfo.c Mon Feb  4 20:48:05 2013
@@ -611,6 +611,58 @@ svn_rangelist__parse(svn_rangelist_t **r
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_rangelist__combine_adjacent_ranges(svn_rangelist_t *rangelist,
+                                       apr_pool_t *scratch_pool)
+{
+  int i;
+  svn_merge_range_t *range, *lastrange;
+
+  lastrange = APR_ARRAY_IDX(rangelist, 0, svn_merge_range_t *);
+
+  for (i = 1; i < rangelist->nelts; i++)
+    {
+      range = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
+      if (lastrange->start <= range->end
+          && range->start <= lastrange->end)
+        {
+          /* The ranges are adjacent or intersect. */
+
+          /* svn_mergeinfo_parse promises to combine overlapping
+             ranges as long as their inheritability is the same. */
+          if (range->start < lastrange->end
+              && range->inheritable != lastrange->inheritable)
+            {
+              return svn_error_createf(SVN_ERR_MERGEINFO_PARSE_ERROR, NULL,
+                                       _("Unable to parse overlapping "
+                                         "revision ranges '%s' and '%s' "
+                                         "with different inheritance "
+                                         "types"),
+                                       range_to_string(lastrange,
+                                                       scratch_pool),
+                                       range_to_string(range,
+                                                       scratch_pool));
+            }
+
+          /* Combine overlapping or adjacent ranges with the
+             same inheritability. */
+          if (lastrange->inheritable == range->inheritable)
+            {
+              lastrange->end = MAX(range->end, lastrange->end);
+              if (i + 1 < rangelist->nelts)
+                memmove(rangelist->elts + (rangelist->elt_size * i),
+                        rangelist->elts + (rangelist->elt_size * (i + 1)),
+                        rangelist->elt_size * (rangelist->nelts - i));
+              rangelist->nelts--;
+              i--;
+            }
+        }
+      lastrange = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
+    }
+
+  return SVN_NO_ERROR;
+}
+
 /* revisionline -> PATHNAME COLON revisionlist */
 static svn_error_t *
 parse_revision_line(const char **input, const char *end, svn_mergeinfo_t hash,
@@ -648,52 +700,10 @@ parse_revision_line(const char **input, 
      and make sure there are no overlapping ranges. */
   if (rangelist->nelts > 1)
     {
-      int i;
-      svn_merge_range_t *range, *lastrange;
-
       qsort(rangelist->elts, rangelist->nelts, rangelist->elt_size,
             svn_sort_compare_ranges);
-      lastrange = APR_ARRAY_IDX(rangelist, 0, svn_merge_range_t *);
-
-      for (i = 1; i < rangelist->nelts; i++)
-        {
-          range = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
-          if (lastrange->start <= range->end
-              && range->start <= lastrange->end)
-            {
-              /* The ranges are adjacent or intersect. */
 
-              /* svn_mergeinfo_parse promises to combine overlapping
-                 ranges as long as their inheritability is the same. */
-              if (range->start < lastrange->end
-                  && range->inheritable != lastrange->inheritable)
-                {
-                  return svn_error_createf(SVN_ERR_MERGEINFO_PARSE_ERROR, NULL,
-                                           _("Unable to parse overlapping "
-                                             "revision ranges '%s' and '%s' "
-                                             "with different inheritance "
-                                             "types"),
-                                           range_to_string(lastrange,
-                                                           scratch_pool),
-                                           range_to_string(range,
-                                                           scratch_pool));
-                }
-
-              /* Combine overlapping or adjacent ranges with the
-                 same inheritability. */
-              if (lastrange->inheritable == range->inheritable)
-                {
-                  lastrange->end = MAX(range->end, lastrange->end);
-                  if (i + 1 < rangelist->nelts)
-                    memmove(rangelist->elts + (rangelist->elt_size * i),
-                            rangelist->elts + (rangelist->elt_size * (i + 1)),
-                            rangelist->elt_size * (rangelist->nelts - i));
-                  rangelist->nelts--;
-                  i--;
-                }
-            }
-          lastrange = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
-        }
+      SVN_ERR(svn_rangelist__combine_adjacent_ranges(rangelist, scratch_pool));
     }
 
   /* Handle any funky mergeinfo with relative merge source paths that
@@ -1753,7 +1763,7 @@ svn_mergeinfo_merge2(svn_mergeinfo_t mer
         {
           SVN_ERR(svn_rangelist_merge2(target, to_insert, result_pool,
                                        iterpool));
-          apr_pool_clear(iterpool);
+          svn_pool_clear(iterpool);
         }
       else
         apr_hash_set(mergeinfo, key, klen, to_insert);

Modified: subversion/branches/fsfs-format7/subversion/libsvn_subr/named_atomic.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_subr/named_atomic.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_subr/named_atomic.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_subr/named_atomic.c Mon Feb  4 20:48:05 2013
@@ -372,7 +372,7 @@ svn_named_atomic__is_supported(void)
         result = svn_tristate_false;
     }
 
-  return result == svn_tristate_true ? TRUE : FALSE;
+  return result == svn_tristate_true;
 #else
   return TRUE;
 #endif

Modified: subversion/branches/fsfs-format7/subversion/libsvn_subr/opt.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_subr/opt.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_subr/opt.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_subr/opt.c Mon Feb  4 20:48:05 2013
@@ -296,7 +296,7 @@ print_command_info2(const svn_opt_subcom
         {
           if (cmd->valid_options[i])
             {
-              if (have_options == FALSE)
+              if (!have_options)
                 {
                   SVN_ERR(svn_cmdline_fputs(_("\nValid options:\n"),
                                             stream, pool));