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));