You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by jc...@apache.org on 2010/12/29 01:10:29 UTC
svn commit: r1053489 [2/7] - in
/subversion/branches/diff-optimizations-bytes: ./ build/ build/ac-macros/
build/generator/ build/generator/swig/ contrib/client-side/svn_load_dirs/
notes/ subversion/bindings/javahl/native/ subversion/bindings/swig/ subv...
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra/util.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra/util.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra/util.c Wed Dec 29 00:10:25 2010
@@ -25,8 +25,10 @@
/*** Includes. ***/
#include <apr_pools.h>
+#include <apr_network_io.h>
#include "svn_types.h"
+#include "svn_pools.h"
#include "svn_error.h"
#include "svn_error_codes.h"
#include "svn_dirent_uri.h"
@@ -70,3 +72,171 @@ svn_ra__assert_mergeinfo_capable_server(
}
return SVN_NO_ERROR;
}
+
+/* Does ERR mean "the current value of the revprop isn't equal to
+ the *OLD_VALUE_P you gave me"?
+ */
+static svn_boolean_t is_atomicity_error(svn_error_t *err)
+{
+ return svn_error_find_cause(err, SVN_ERR_FS_PROP_BASEVALUE_MISMATCH) != NULL;
+}
+
+svn_error_t *
+svn_ra__release_operational_lock(svn_ra_session_t *session,
+ const char *lock_revprop_name,
+ const svn_string_t *mylocktoken,
+ apr_pool_t *scratch_pool)
+{
+ svn_string_t *reposlocktoken;
+ svn_boolean_t be_atomic;
+
+ SVN_ERR(svn_ra_has_capability(session, &be_atomic,
+ SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+ scratch_pool));
+ SVN_ERR(svn_ra_rev_prop(session, 0, lock_revprop_name,
+ &reposlocktoken, scratch_pool));
+ if (reposlocktoken && svn_string_compare(reposlocktoken, mylocktoken))
+ {
+ svn_error_t *err;
+
+ err = svn_ra_change_rev_prop2(session, 0, lock_revprop_name,
+ be_atomic ? &mylocktoken : NULL, NULL,
+ scratch_pool);
+ if (is_atomicity_error(err))
+ return svn_error_createf(err->apr_err, err,
+ _("Lock was stolen by '%s'; unable to "
+ "remove it"), reposlocktoken->data);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_ra__get_operational_lock(const svn_string_t **lock_string_p,
+ const svn_string_t **stolen_lock_p,
+ svn_ra_session_t *session,
+ const char *lock_revprop_name,
+ svn_boolean_t steal_lock,
+ int num_retries,
+ svn_ra__lock_retry_func_t retry_func,
+ void *retry_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *pool)
+{
+ char hostname_str[APRMAXHOSTLEN + 1] = { 0 };
+ svn_string_t *mylocktoken, *reposlocktoken;
+ apr_status_t apr_err;
+ svn_boolean_t be_atomic;
+ apr_pool_t *subpool;
+ int i;
+
+ *lock_string_p = NULL;
+ if (stolen_lock_p)
+ *stolen_lock_p = NULL;
+
+ SVN_ERR(svn_ra_has_capability(session, &be_atomic,
+ SVN_RA_CAPABILITY_ATOMIC_REVPROPS, pool));
+
+ /* We build a lock token from the local hostname and a UUID. */
+ apr_err = apr_gethostname(hostname_str, sizeof(hostname_str), pool);
+ if (apr_err)
+ return svn_error_wrap_apr(apr_err,
+ _("Unable to determine local hostname"));
+ mylocktoken = svn_string_createf(pool, "%s:%s", hostname_str,
+ svn_uuid_generate(pool));
+
+ /* Ye Olde Retry Loope */
+ subpool = svn_pool_create(pool);
+
+ for (i = 0; i < num_retries; ++i)
+ {
+ svn_error_t *err;
+ const svn_string_t *unset = NULL;
+
+ svn_pool_clear(subpool);
+
+ /* Check for cancellation. If we're cancelled, don't leave a
+ stray lock behind! */
+ if (cancel_func)
+ {
+ err = cancel_func(cancel_baton);
+ if (err && err->apr_err == SVN_ERR_CANCELLED)
+ return svn_error_compose_create(
+ svn_ra__release_operational_lock(session,
+ lock_revprop_name,
+ mylocktoken,
+ subpool),
+ err);
+ SVN_ERR(err);
+ }
+
+ /* Ask the repository for the value of the LOCK_REVPROP_NAME. */
+ SVN_ERR(svn_ra_rev_prop(session, 0, lock_revprop_name,
+ &reposlocktoken, subpool));
+
+ /* Did we get a value from the repository? We'll check to see
+ if it matches our token. If so, we call it success. If not
+ and we're told to steal locks, we remember the existing lock
+ token and fall through to the locking code; othewise, we
+ sleep and retry. */
+ if (reposlocktoken)
+ {
+ if (svn_string_compare(reposlocktoken, mylocktoken))
+ {
+ *lock_string_p = mylocktoken;
+ return SVN_NO_ERROR;
+ }
+ else if (! steal_lock)
+ {
+ if (retry_func)
+ SVN_ERR(retry_func(retry_baton, reposlocktoken, subpool));
+ apr_sleep(apr_time_from_sec(1));
+ continue;
+ }
+ else
+ {
+ if (stolen_lock_p)
+ *stolen_lock_p = svn_string_dup(reposlocktoken, pool);
+ unset = reposlocktoken;
+ }
+ }
+
+ /* No lock value in the repository, or we plan to steal it?
+ Well, if we've got a spare iteration, we'll try to set the
+ lock. (We use the spare iteration to verify that we still
+ have the lock after setting it.) */
+ if (i < num_retries - 1)
+ {
+ /* Except in the very last iteration, try to set the lock. */
+ err = svn_ra_change_rev_prop2(session, 0, lock_revprop_name,
+ be_atomic ? &unset : NULL,
+ mylocktoken, subpool);
+
+ if (be_atomic && err && is_atomicity_error(err))
+ {
+ /* Someone else has the lock. No problem, we'll loop again. */
+ svn_error_clear(err);
+ }
+ else if (be_atomic && err == SVN_NO_ERROR)
+ {
+ /* Yay! We have the lock! However, for compatibility
+ with concurrent processes that don't support
+ atomicity, loop anyway to double-check that they
+ haven't overwritten our lock.
+ */
+ continue;
+ }
+ else
+ {
+ /* We have a genuine error, or aren't atomic and need
+ to loop. */
+ SVN_ERR(err);
+ }
+ }
+ }
+
+ return svn_error_createf(APR_EINVAL, NULL,
+ _("Couldn't get lock on destination repos "
+ "after %d attempts"), i);
+}
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra_local/ra_plugin.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra_local/ra_plugin.c Wed Dec 29 00:10:25 2010
@@ -416,7 +416,7 @@ svn_ra_local__get_schemes(apr_pool_t *po
/* Do nothing.
*
- * Why is this acceptable? As of now, FS warnings are used for only
+ * Why is this acceptable? FS warnings used to be used for only
* two things: failures to close BDB repositories and failures to
* interact with memcached in FSFS (new in 1.6). In 1.5 and earlier,
* we did not call svn_fs_set_warning_func in ra_local, which means
@@ -433,6 +433,9 @@ static void
ignore_warnings(void *baton,
svn_error_t *err)
{
+#ifdef SVN_DEBUG
+ SVN_DBG(("Ignoring FS warning %d\n", err ? err->apr_err : 0));
+#endif
return;
}
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra_serf/ra_serf.h?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra_serf/ra_serf.h Wed Dec 29 00:10:25 2010
@@ -883,10 +883,12 @@ svn_ra_serf__define_ns(svn_ra_serf__ns_t
* Look up @a name in the @a ns_list list for previously declared namespace
* definitions.
*
- * @return @a svn_ra_serf__dav_props_t tuple representing the expanded name.
+ * Return (in @a *returned_prop_name) @a svn_ra_serf__dav_props_t tuple
+ * representing the expanded name.
*/
-svn_ra_serf__dav_props_t
-svn_ra_serf__expand_ns(svn_ra_serf__ns_t *ns_list,
+void
+svn_ra_serf__expand_ns(svn_ra_serf__dav_props_t *returned_prop_name,
+ svn_ra_serf__ns_t *ns_list,
const char *name);
/*
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra_serf/util.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra_serf/util.c Wed Dec 29 00:10:25 2010
@@ -1171,7 +1171,7 @@ start_xml(void *userData, const char *ra
svn_ra_serf__define_ns(&parser->state->ns_list, attrs, parser->state->pool);
- name = svn_ra_serf__expand_ns(parser->state->ns_list, raw_name);
+ svn_ra_serf__expand_ns(&name, parser->state->ns_list, raw_name);
parser->error = parser->start(parser, parser->user_data, name, attrs);
}
@@ -1185,7 +1185,7 @@ end_xml(void *userData, const char *raw_
if (parser->error)
return;
- name = svn_ra_serf__expand_ns(parser->state->ns_list, raw_name);
+ svn_ra_serf__expand_ns(&name, parser->state->ns_list, raw_name);
parser->error = parser->end(parser, parser->user_data, name);
}
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra_serf/xml.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra_serf/xml.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra_serf/xml.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_ra_serf/xml.c Wed Dec 29 00:10:25 2010
@@ -86,8 +86,9 @@ svn_ra_serf__define_ns(svn_ra_serf__ns_t
* Look up NAME in the NS_LIST list for previously declared namespace
* definitions and return a DAV_PROPS_T-tuple that has values.
*/
-svn_ra_serf__dav_props_t
-svn_ra_serf__expand_ns(svn_ra_serf__ns_t *ns_list,
+void
+svn_ra_serf__expand_ns(svn_ra_serf__dav_props_t *returned_prop_name,
+ svn_ra_serf__ns_t *ns_list,
const char *name)
{
const char *colon;
@@ -120,7 +121,8 @@ svn_ra_serf__expand_ns(svn_ra_serf__ns_t
prop_name.name = name;
}
- return prop_name;
+ *returned_prop_name = prop_name;
+ return;
}
void
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/commit.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/commit.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/commit.c Wed Dec 29 00:10:25 2010
@@ -38,6 +38,7 @@
#include "svn_props.h"
#include "repos.h"
#include "svn_private_config.h"
+#include "private/svn_repos_private.h"
@@ -644,7 +645,68 @@ change_dir_prop(void *dir_baton,
name, value, pool);
}
+const char *
+svn_repos__post_commit_error_str(svn_error_t *err,
+ apr_pool_t *pool)
+{
+ svn_error_t *hook_err1, *hook_err2;
+ const char *msg;
+
+ if (! err)
+ return _("(no error)");
+
+ err = svn_error_purge_tracing(err);
+
+ /* hook_err1 is the SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED wrapped
+ error from the post-commit script, if any, and hook_err2 should
+ be the original error, but be defensive and handle a case where
+ SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED doesn't wrap an error. */
+ hook_err1 = svn_error_find_cause(err, SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED);
+ if (hook_err1 && hook_err1->child)
+ hook_err2 = hook_err1->child;
+ else
+ hook_err2 = hook_err1;
+
+ /* This implementation counts on svn_repos_fs_commit_txn() returning
+ svn_fs_commit_txn() as the parent error with a child
+ SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED error. If the parent error
+ is SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED then there was no error
+ in svn_fs_commit_txn().
+
+ The post-commit hook error message is already self describing, so
+ it can be dropped into an error message without any additional
+ text. */
+ if (hook_err1)
+ {
+ if (err == hook_err1)
+ {
+ if (hook_err2->message)
+ msg = apr_pstrdup(pool, hook_err2->message);
+ else
+ msg = _("post-commit hook failed with no error message");
+ }
+ else
+ {
+ msg = hook_err2->message
+ ? hook_err2->message
+ : _("post-commit hook failed with no error message.");
+ msg = apr_psprintf(
+ pool,
+ _("post commit FS processing had error '%s' and %s"),
+ err->message ? err->message : _("(no error message)"),
+ msg);
+ }
+ }
+ else
+ {
+ msg = apr_psprintf(pool,
+ _("post-commit FS processing had error '%s'."),
+ hook_err2->message ? hook_err2->message
+ : _("(no error message)"));
+ }
+ return msg;
+}
static svn_error_t *
close_edit(void *edit_baton,
@@ -654,7 +716,7 @@ close_edit(void *edit_baton,
svn_revnum_t new_revision = SVN_INVALID_REVNUM;
svn_error_t *err;
const char *conflict;
- char *post_commit_err = NULL;
+ const char *post_commit_err = NULL;
/* If no transaction has been created (ie. if open_root wasn't
called before close_edit), abort the operation here with an
@@ -667,51 +729,40 @@ close_edit(void *edit_baton,
err = svn_repos_fs_commit_txn(&conflict, eb->repos,
&new_revision, eb->txn, pool);
- if (err)
+ if (SVN_IS_VALID_REVNUM(new_revision))
{
- if (err->apr_err == SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED)
+ if (err)
{
/* If the error was in post-commit, then the commit itself
succeeded. In which case, save the post-commit warning
(to be reported back to the client, who will probably
display it as a warning) and clear the error. */
- if (err->child && err->child->message)
- {
- svn_error_t *warning_err = err->child;
-#ifdef SVN_ERR__TRACING
- /* Skip over any trace records. */
- while (warning_err->message != NULL
- && strcmp(warning_err->message, SVN_ERR__TRACED) == 0)
- warning_err = warning_err->child;
-#endif
- post_commit_err = apr_pstrdup(pool, warning_err->message);
- }
-
+ post_commit_err = svn_repos__post_commit_error_str(err, pool);
svn_error_clear(err);
err = SVN_NO_ERROR;
}
- else /* Got a real error -- one that stopped the commit */
- {
- /* ### todo: we should check whether it really was a conflict,
- and return the conflict info if so? */
+ }
+ else
+ {
+ /* ### todo: we should check whether it really was a conflict,
+ and return the conflict info if so? */
- /* If the commit failed, it's *probably* due to a conflict --
- that is, the txn being out-of-date. The filesystem gives us
- the ability to continue diddling the transaction and try
- again; but let's face it: that's not how the cvs or svn works
- from a user interface standpoint. Thus we don't make use of
- this fs feature (for now, at least.)
-
- So, in a nutshell: svn commits are an all-or-nothing deal.
- Each commit creates a new fs txn which either succeeds or is
- aborted completely. No second chances; the user simply
- needs to update and commit again :)
-
- We ignore the possible error result from svn_fs_abort_txn();
- it's more important to return the original error. */
- svn_error_clear(svn_fs_abort_txn(eb->txn, pool));
- return svn_error_return(err);
- }
+ /* If the commit failed, it's *probably* due to a conflict --
+ that is, the txn being out-of-date. The filesystem gives us
+ the ability to continue diddling the transaction and try
+ again; but let's face it: that's not how the cvs or svn works
+ from a user interface standpoint. Thus we don't make use of
+ this fs feature (for now, at least.)
+
+ So, in a nutshell: svn commits are an all-or-nothing deal.
+ Each commit creates a new fs txn which either succeeds or is
+ aborted completely. No second chances; the user simply
+ needs to update and commit again :)
+
+ We ignore the possible error result from svn_fs_abort_txn();
+ it's more important to return the original error. */
+ svn_error_clear(svn_fs_abort_txn(eb->txn, pool));
+ return svn_error_return(err);
}
/* Pass new revision information to the caller's callback. */
@@ -743,8 +794,8 @@ close_edit(void *edit_baton,
commit_info->author = author ? author->data : NULL;
commit_info->post_commit_err = post_commit_err;
err = (*eb->commit_callback)(commit_info,
- eb->commit_callback_baton,
- pool);
+ eb->commit_callback_baton,
+ pool);
}
}
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/deprecated.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/deprecated.c Wed Dec 29 00:10:25 2010
@@ -718,7 +718,7 @@ svn_repos_load_fs2(svn_repos_t *repos,
apr_pool_t *pool)
{
return svn_repos_load_fs3(repos, dumpstream, uuid_action, parent_dir,
- use_pre_commit_hook, use_post_commit_hook,
+ use_pre_commit_hook, use_post_commit_hook, FALSE,
feedback_stream ? repos_notify_handler : NULL,
feedback_stream, cancel_func, cancel_baton, pool);
}
@@ -804,7 +804,7 @@ svn_repos_get_fs_build_parser2(const svn
apr_pool_t *pool)
{
return svn_repos_get_fs_build_parser3(parser, parse_baton, repos, use_history,
- uuid_action, parent_dir,
+ FALSE, uuid_action, parent_dir,
outstream ? repos_notify_handler : NULL,
outstream, pool);
}
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/fs-wrap.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/fs-wrap.c Wed Dec 29 00:10:25 2010
@@ -33,6 +33,7 @@
#include "svn_time.h"
#include "repos.h"
#include "svn_private_config.h"
+#include "private/svn_repos_private.h"
#include "private/svn_utf_private.h"
@@ -45,25 +46,29 @@ svn_repos_fs_commit_txn(const char **con
svn_fs_txn_t *txn,
apr_pool_t *pool)
{
- svn_error_t *err;
+ svn_error_t *err, *err2;
const char *txn_name;
+ *new_rev = SVN_INVALID_REVNUM;
+
/* Run pre-commit hooks. */
SVN_ERR(svn_fs_txn_name(&txn_name, txn, pool));
SVN_ERR(svn_repos__hooks_pre_commit(repos, txn_name, pool));
/* Commit. */
- SVN_ERR(svn_fs_commit_txn(conflict_p, new_rev, txn, pool));
+ err = svn_fs_commit_txn(conflict_p, new_rev, txn, pool);
+ if (! SVN_IS_VALID_REVNUM(*new_rev))
+ return err;
- /* Run post-commit hooks. Notice that we're wrapping the error
- with a -specific- errorcode, so that our caller knows not to try
- and abort the transaction. */
- if ((err = svn_repos__hooks_post_commit(repos, *new_rev, pool)))
- return svn_error_create
- (SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED, err,
- _("Commit succeeded, but post-commit hook failed"));
+ /* Run post-commit hooks. */
+ if ((err2 = svn_repos__hooks_post_commit(repos, *new_rev, pool)))
+ {
+ err2 = svn_error_create
+ (SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED, err2,
+ _("Commit succeeded, but post-commit hook failed"));
+ }
- return SVN_NO_ERROR;
+ return svn_error_compose_create(err, err2);
}
@@ -152,15 +157,10 @@ svn_repos_fs_begin_txn_for_update(svn_fs
/*** Property wrappers ***/
-/* Validate that property NAME is valid for use in a Subversion
- repository; return SVN_ERR_REPOS_BAD_ARGS if it isn't. For some "svn:"
- properties, also validate the value, and return SVN_ERR_BAD_PROPERTY_VALUE
- if it is not valid.
-
- Use POOL for temporary allocations.
- */
-static svn_error_t *
-validate_prop(const char *name, const svn_string_t *value, apr_pool_t *pool)
+svn_error_t *
+svn_repos__validate_prop(const char *name,
+ const svn_string_t *value,
+ apr_pool_t *pool)
{
svn_prop_kind_t kind = svn_property_kind(NULL, name);
@@ -223,7 +223,7 @@ svn_repos_fs_change_node_prop(svn_fs_roo
apr_pool_t *pool)
{
/* Validate the property, then call the wrapped function. */
- SVN_ERR(validate_prop(name, value, pool));
+ SVN_ERR(svn_repos__validate_prop(name, value, pool));
return svn_fs_change_node_prop(root, path, name, value, pool);
}
@@ -238,7 +238,7 @@ svn_repos_fs_change_txn_props(svn_fs_txn
for (i = 0; i < txnprops->nelts; i++)
{
svn_prop_t *prop = &APR_ARRAY_IDX(txnprops, i, svn_prop_t);
- SVN_ERR(validate_prop(prop->name, prop->value, pool));
+ SVN_ERR(svn_repos__validate_prop(prop->name, prop->value, pool));
}
return svn_fs_change_txn_props(txn, txnprops, pool);
@@ -286,7 +286,7 @@ svn_repos_fs_change_rev_prop4(svn_repos_
const svn_string_t *old_value;
char action;
- SVN_ERR(validate_prop(name, new_value, pool));
+ SVN_ERR(svn_repos__validate_prop(name, new_value, pool));
/* Fetch OLD_VALUE for svn_fs_change_rev_prop2(). */
if (old_value_p)
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/hooks.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/hooks.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/hooks.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/hooks.c Wed Dec 29 00:10:25 2010
@@ -177,56 +177,14 @@ run_hook_cmd(svn_string_t **result,
apr_file_t *stdin_handle,
apr_pool_t *pool)
{
- apr_file_t *read_errhandle, *write_errhandle, *null_handle;
- apr_file_t *read_outhandle, *write_outhandle;
+ apr_file_t *null_handle;
apr_status_t apr_err;
svn_error_t *err;
apr_proc_t cmd_proc;
- /* Create a pipe to access stderr of the child. */
- apr_err = apr_file_pipe_create(&read_errhandle, &write_errhandle, pool);
- if (apr_err)
- return svn_error_wrap_apr
- (apr_err, _("Can't create pipe for hook '%s'"), cmd);
-
- /* Pipes are inherited by default, but we don't want that, since
- APR will duplicate the write end of the pipe for the child process.
- Not closing the read end is harmless, but if the write end is inherited,
- it will be inherited by grandchildren as well. This causes problems
- if a hook script puts long-running jobs in the background. Even if
- they redirect stderr to something else, the write end of our pipe will
- still be open, causing us to block. */
- apr_err = apr_file_inherit_unset(read_errhandle);
- if (apr_err)
- return svn_error_wrap_apr
- (apr_err, _("Can't make pipe read handle non-inherited for hook '%s'"),
- cmd);
-
- apr_err = apr_file_inherit_unset(write_errhandle);
- if (apr_err)
- return svn_error_wrap_apr
- (apr_err, _("Can't make pipe write handle non-inherited for hook '%s'"),
- cmd);
-
if (result)
{
- /* Create a pipe to access stdout of the child. */
- apr_err = apr_file_pipe_create(&read_outhandle, &write_outhandle, pool);
- if (apr_err)
- return svn_error_wrap_apr
- (apr_err, _("Can't create pipe for hook '%s'"), cmd);
-
- apr_err = apr_file_inherit_unset(read_outhandle);
- if (apr_err)
- return svn_error_wrap_apr
- (apr_err,
- _("Can't make pipe read handle non-inherited for hook '%s'"), cmd);
-
- apr_err = apr_file_inherit_unset(write_outhandle);
- if (apr_err)
- return svn_error_wrap_apr
- (apr_err,
- _("Can't make pipe write handle non-inherited for hook '%s'"), cmd);
+ null_handle = NULL;
}
else
{
@@ -238,26 +196,9 @@ run_hook_cmd(svn_string_t **result,
(apr_err, _("Can't create null stdout for hook '%s'"), cmd);
}
- err = svn_io_start_cmd(&cmd_proc, ".", cmd, args, FALSE,
- stdin_handle, result ? write_outhandle : null_handle,
- write_errhandle, pool);
-
- /* This seems to be done automatically if we pass the third parameter of
- apr_procattr_child_in/out_set(), but svn_io_run_cmd()'s interface does
- not support those parameters. We need to close the write end of the
- pipe so we don't hang on the read end later, if we need to read it. */
- apr_err = apr_file_close(write_errhandle);
- if (!err && apr_err)
- return svn_error_wrap_apr
- (apr_err, _("Error closing write end of stderr pipe"));
-
- if (result)
- {
- apr_err = apr_file_close(write_outhandle);
- if (!err && apr_err)
- return svn_error_wrap_apr
- (apr_err, _("Error closing write end of stderr pipe"));
- }
+ err = svn_io_start_cmd2(&cmd_proc, ".", cmd, args, FALSE,
+ FALSE, stdin_handle, result != NULL, null_handle,
+ TRUE, NULL, pool);
if (err)
{
@@ -266,13 +207,13 @@ run_hook_cmd(svn_string_t **result,
}
else
{
- err = check_hook_result(name, cmd, &cmd_proc, read_errhandle, pool);
+ err = check_hook_result(name, cmd, &cmd_proc, cmd_proc.err, pool);
}
/* Hooks are fallible, and so hook failure is "expected" to occur at
times. When such a failure happens we still want to close the pipe
and null file */
- apr_err = apr_file_close(read_errhandle);
+ apr_err = apr_file_close(cmd_proc.err);
if (!err && apr_err)
return svn_error_wrap_apr
(apr_err, _("Error closing read end of stderr pipe"));
@@ -280,8 +221,8 @@ run_hook_cmd(svn_string_t **result,
if (result)
{
svn_stringbuf_t *native_stdout;
- SVN_ERR(svn_stringbuf_from_aprfile(&native_stdout, read_outhandle, pool));
- apr_err = apr_file_close(read_outhandle);
+ SVN_ERR(svn_stringbuf_from_aprfile(&native_stdout, cmd_proc.out, pool));
+ apr_err = apr_file_close(cmd_proc.out);
if (!err && apr_err)
return svn_error_wrap_apr
(apr_err, _("Error closing read end of stderr pipe"));
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/load-fs-vtable.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/load-fs-vtable.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/load-fs-vtable.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_repos/load-fs-vtable.c Wed Dec 29 00:10:25 2010
@@ -52,6 +52,7 @@ struct parse_baton
svn_fs_t *fs;
svn_boolean_t use_history;
+ svn_boolean_t validate_props;
svn_boolean_t use_pre_commit_hook;
svn_boolean_t use_post_commit_hook;
enum svn_repos_load_uuid uuid_action;
@@ -111,6 +112,44 @@ struct node_baton
/*----------------------------------------------------------------------*/
+
+/* Change revision property NAME to VALUE for REVISION in REPOS. If
+ VALIDATE_PROPS is set, use functions which perform validation of
+ the property value. Otherwise, bypass those checks. */
+static svn_error_t *
+change_rev_prop(svn_repos_t *repos,
+ svn_revnum_t revision,
+ const char *name,
+ const svn_string_t *value,
+ svn_boolean_t validate_props,
+ apr_pool_t *pool)
+{
+ if (validate_props)
+ return svn_fs_change_rev_prop2(svn_repos_fs(repos), revision, name,
+ NULL, value, pool);
+ else
+ return svn_repos_fs_change_rev_prop4(repos, revision, NULL, name,
+ NULL, value, FALSE, FALSE,
+ NULL, NULL, pool);
+}
+
+/* Change property NAME to VALUE for PATH in TXN_ROOT. If
+ VALIDATE_PROPS is set, use functions which perform validation of
+ the property value. Otherwise, bypass those checks. */
+static svn_error_t *
+change_node_prop(svn_fs_root_t *txn_root,
+ const char *path,
+ const char *name,
+ const svn_string_t *value,
+ svn_boolean_t validate_props,
+ apr_pool_t *pool)
+{
+ if (validate_props)
+ return svn_repos_fs_change_node_prop(txn_root, path, name, value, pool);
+ else
+ return svn_fs_change_node_prop(txn_root, path, name, value, pool);
+}
+
/* Prepend the mergeinfo source paths in MERGEINFO_ORIG with PARENT_DIR, and
return it in *MERGEINFO_VAL. */
static svn_error_t *
@@ -582,8 +621,7 @@ new_node_record(void **node_baton,
*node_baton = nb;
return SVN_NO_ERROR;
}
-
-
+
static svn_error_t *
set_revision_property(void *baton,
const char *name,
@@ -593,7 +631,10 @@ set_revision_property(void *baton,
if (rb->rev > 0)
{
- SVN_ERR(svn_fs_change_txn_prop(rb->txn, name, value, rb->pool));
+ if (rb->pb->validate_props)
+ SVN_ERR(svn_repos_fs_change_txn_prop(rb->txn, name, value, rb->pool));
+ else
+ SVN_ERR(svn_fs_change_txn_prop(rb->txn, name, value, rb->pool));
/* Remember any datestamp that passes through! (See comment in
close_revision() below.) */
@@ -610,8 +651,8 @@ set_revision_property(void *baton,
SVN_ERR(svn_fs_youngest_rev(&youngest_rev, pb->fs, rb->pool));
if (youngest_rev == 0)
- SVN_ERR(svn_fs_change_rev_prop2(pb->fs, 0, name, NULL, value,
- rb->pool));
+ SVN_ERR(change_rev_prop(pb->repos, 0, name, value,
+ pb->validate_props, rb->pool));
}
return SVN_NO_ERROR;
@@ -676,8 +717,8 @@ set_node_property(void *baton,
}
}
- return svn_fs_change_node_prop(rb->txn_root, nb->path,
- name, value, nb->pool);
+ return change_node_prop(rb->txn_root, nb->path, name, value,
+ pb->validate_props, nb->pool);
}
@@ -688,8 +729,8 @@ delete_node_property(void *baton,
struct node_baton *nb = baton;
struct revision_baton *rb = nb->rb;
- return svn_fs_change_node_prop(rb->txn_root, nb->path,
- name, NULL, nb->pool);
+ return change_node_prop(rb->txn_root, nb->path, name, NULL,
+ rb->pb->validate_props, nb->pool);
}
@@ -709,10 +750,8 @@ remove_node_props(void *baton)
const void *key;
apr_hash_this(hi, &key, NULL, NULL);
-
- SVN_ERR(svn_fs_change_node_prop(rb->txn_root, nb->path,
- (const char *) key, NULL,
- nb->pool));
+ SVN_ERR(change_node_prop(rb->txn_root, nb->path, key, NULL,
+ rb->pb->validate_props, nb->pool));
}
return SVN_NO_ERROR;
@@ -801,7 +840,18 @@ close_revision(void *baton)
}
/* Commit. */
- if ((err = svn_fs_commit_txn(&conflict_msg, new_rev, rb->txn, rb->pool)))
+ err = svn_fs_commit_txn(&conflict_msg, new_rev, rb->txn, rb->pool);
+ if (SVN_IS_VALID_REVNUM(*new_rev))
+ {
+ if (err)
+ {
+ /* ### Log any error, but better yet is to rev
+ ### close_revision()'s API to allow both new_rev and err
+ ### to be returned, see #3768. */
+ svn_error_clear(err);
+ }
+ }
+ else
{
svn_error_clear(svn_fs_abort_txn(rb->txn, rb->pool));
if (conflict_msg)
@@ -858,9 +908,8 @@ close_revision(void *baton)
Note that if rb->datestamp is NULL, that's fine -- if the dump
data doesn't carry a datestamp, we want to preserve that fact in
the load. */
- SVN_ERR(svn_fs_change_rev_prop(pb->fs, *new_rev,
- SVN_PROP_REVISION_DATE, rb->datestamp,
- rb->pool));
+ SVN_ERR(change_rev_prop(pb->repos, *new_rev, SVN_PROP_REVISION_DATE,
+ rb->datestamp, pb->validate_props, rb->pool));
if (pb->notify_func)
{
@@ -886,6 +935,7 @@ svn_repos_get_fs_build_parser3(const svn
void **parse_baton,
svn_repos_t *repos,
svn_boolean_t use_history,
+ svn_boolean_t validate_props,
enum svn_repos_load_uuid uuid_action,
const char *parent_dir,
svn_repos_notify_func_t notify_func,
@@ -910,6 +960,7 @@ svn_repos_get_fs_build_parser3(const svn
pb->repos = repos;
pb->fs = svn_repos_fs(repos);
pb->use_history = use_history;
+ pb->validate_props = validate_props;
pb->notify_func = notify_func;
pb->notify_baton = notify_baton;
pb->notify = svn_repos_notify_create(svn_repos_notify_load_txn_start, pool);
@@ -934,6 +985,7 @@ svn_repos_load_fs3(svn_repos_t *repos,
const char *parent_dir,
svn_boolean_t use_pre_commit_hook,
svn_boolean_t use_post_commit_hook,
+ svn_boolean_t validate_props,
svn_repos_notify_func_t notify_func,
void *notify_baton,
svn_cancel_func_t cancel_func,
@@ -949,6 +1001,7 @@ svn_repos_load_fs3(svn_repos_t *repos,
SVN_ERR(svn_repos_get_fs_build_parser3(&parser, &parse_baton,
repos,
TRUE, /* look for copyfrom revs */
+ validate_props,
uuid_action,
parent_dir,
notify_func,
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/deprecated.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/deprecated.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/deprecated.c Wed Dec 29 00:10:25 2010
@@ -250,6 +250,16 @@ svn_subst_stream_translated_to_normal_fo
}
svn_error_t *
+svn_subst_translate_string(svn_string_t **new_value,
+ const svn_string_t *value,
+ const char *encoding,
+ apr_pool_t *pool)
+{
+ return svn_subst_translate_string2(new_value, NULL, NULL, value,
+ encoding, pool, pool);
+}
+
+svn_error_t *
svn_subst_stream_detranslated(svn_stream_t **stream_p,
const char *src,
svn_subst_eol_style_t eol_style,
@@ -754,6 +764,22 @@ svn_io_get_dirents(apr_hash_t **dirents,
return svn_io_get_dirents2(dirents, path, pool);
}
+svn_error_t *
+svn_io_start_cmd(apr_proc_t *cmd_proc,
+ const char *path,
+ const char *cmd,
+ const char *const *args,
+ svn_boolean_t inherit,
+ apr_file_t *infile,
+ apr_file_t *outfile,
+ apr_file_t *errfile,
+ apr_pool_t *pool)
+{
+ return svn_io_start_cmd2(cmd_proc, path, cmd, args, inherit, FALSE,
+ infile, FALSE, outfile, FALSE, errfile, pool);
+}
+
+
struct walk_func_filter_baton_t
{
svn_io_walk_func_t walk_func;
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/dirent_uri.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/dirent_uri.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/dirent_uri.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/dirent_uri.c Wed Dec 29 00:10:25 2010
@@ -2144,6 +2144,7 @@ svn_uri_condense_targets(const char **pc
/* Early exit when there's only one uri to work on. */
if (targets->nelts == 1)
{
+ *pcommon = apr_pstrdup(result_pool, *pcommon);
if (pcondensed_targets)
*pcondensed_targets = apr_array_make(result_pool, 0,
sizeof(const char *));
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/error.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/error.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/error.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/error.c Wed Dec 29 00:10:25 2010
@@ -34,34 +34,46 @@
#include "svn_utf.h"
#ifdef SVN_DEBUG
+/* XXX FIXME: These should be protected by a thread mutex.
+ svn_error__locate and make_error_internal should cooperate
+ in locking and unlocking it. */
+
+/* XXX TODO: Define mutex here #if APR_HAS_THREADS */
+static const char * volatile error_file = NULL;
+static long volatile error_line = -1;
+
/* file_line for the non-debug case. */
static const char SVN_FILE_LINE_UNDEFINED[] = "svn:<undefined>";
#endif /* SVN_DEBUG */
#include "svn_private_config.h"
+#include "private/svn_error_private.h"
-/*** Helpers for creating errors ***/
+/*
+ * Undefine the helpers for creating errors.
+ *
+ * *NOTE*: Any use of these functions in any other function may need
+ * to call svn_error__locate() because the macro that would otherwise
+ * do this is being undefined and the filename and line number will
+ * not be properly set in the static error_file and error_line
+ * variables.
+ */
#undef svn_error_create
#undef svn_error_createf
#undef svn_error_quick_wrap
#undef svn_error_wrap_apr
-
-/* XXX FIXME: These should be protected by a thread mutex.
- svn_error__locate and make_error_internal should cooperate
- in locking and unlocking it. */
-
-/* XXX TODO: Define mutex here #if APR_HAS_THREADS */
-static const char * volatile error_file = NULL;
-static long volatile error_line = -1;
-
+/* Note: This function was historically in the public API, so we need
+ * to define it even when !SVN_DEBUG. */
void
svn_error__locate(const char *file, long line)
{
+#if defined(SVN_DEBUG)
/* XXX TODO: Lock mutex here */
error_file = file;
error_line = line;
+#endif
}
@@ -103,11 +115,11 @@ make_error_internal(apr_status_t apr_err
new_error->apr_err = apr_err;
new_error->child = child;
new_error->pool = pool;
+#if defined(SVN_DEBUG)
new_error->file = error_file;
new_error->line = error_line;
/* XXX TODO: Unlock mutex here */
-#if defined(SVN_DEBUG)
if (! child)
apr_pool_cleanup_register(pool, new_error,
err_abort,
@@ -269,16 +281,16 @@ svn_error_root_cause(svn_error_t *err)
return err;
}
-svn_boolean_t
-svn_error_has_cause(svn_error_t *err, apr_status_t apr_err)
+svn_error_t *
+svn_error_find_cause(svn_error_t *err, apr_status_t apr_err)
{
svn_error_t *child;
for (child = err; child; child = child->child)
if (child->apr_err == apr_err)
- return TRUE;
+ return child;
- return FALSE;
+ return SVN_NO_ERROR;
}
svn_error_t *
@@ -331,8 +343,8 @@ svn_error_clear(svn_error_t *err)
}
}
-/* Is ERR a tracing-only error chain link? */
-static svn_boolean_t is_tracing_link(svn_error_t *err)
+svn_boolean_t
+svn_error__is_tracing_link(svn_error_t *err)
{
#ifdef SVN_ERR__TRACING
/* ### A strcmp()? Really? I think it's the best we can do unless
@@ -349,39 +361,46 @@ svn_error_t *
svn_error_purge_tracing(svn_error_t *err)
{
#ifdef SVN_ERR__TRACING
- svn_error_t *tmp_err = err;
svn_error_t *new_err = NULL, *new_err_leaf = NULL;
if (! err)
return SVN_NO_ERROR;
- while (tmp_err)
+ do
{
+ svn_error_t *tmp_err;
+
/* Skip over any trace-only links. */
- while (tmp_err && is_tracing_link(tmp_err))
- tmp_err = tmp_err->child;
+ while (err && svn_error__is_tracing_link(err))
+ err = err->child;
+
+ /* The link must be a real link in the error chain, otherwise an
+ error chain with trace only links would map into SVN_NO_ERROR. */
+ SVN_ERR_ASSERT(err);
+
+ /* Copy the current error except for its child error pointer
+ into the new error. Share any message and source filename
+ strings from the error. */
+ tmp_err = apr_palloc(err->pool, sizeof(*tmp_err));
+ *tmp_err = *err;
+ tmp_err->child = NULL;
/* Add a new link to the new chain (creating the chain if necessary). */
if (! new_err)
{
new_err = tmp_err;
- new_err_leaf = new_err;
+ new_err_leaf = tmp_err;
}
else
{
new_err_leaf->child = tmp_err;
- new_err_leaf = new_err_leaf->child;
+ new_err_leaf = tmp_err;
}
/* Advance to the next link in the original chain. */
- tmp_err = tmp_err->child;
- }
+ err = err->child;
+ } while (err);
- /* If we get here, there had better be a real link in this error chain. */
- SVN_ERR_ASSERT(new_err_leaf);
-
- /* Tie off the chain, and return its head. */
- new_err_leaf->child = NULL;
return new_err;
#else /* SVN_ERR__TRACING */
return err;
@@ -420,7 +439,7 @@ print_error(svn_error_t *err, FILE *stre
#endif /* SVN_DEBUG */
/* "traced call" */
- if (is_tracing_link(err))
+ if (svn_error__is_tracing_link(err))
{
/* Skip it. We already printed the file-line coordinates. */
}
@@ -550,7 +569,7 @@ const char *
svn_err_best_message(svn_error_t *err, char *buf, apr_size_t bufsize)
{
/* Skip over any trace records. */
- while (is_tracing_link(err))
+ while (svn_error__is_tracing_link(err))
err = err->child;
if (err->message)
return err->message;
@@ -593,6 +612,11 @@ svn_error_raise_on_malfunction(svn_boole
if (!can_return)
abort(); /* Nothing else we can do as a library */
+ /* The filename and line number of the error source needs to be set
+ here because svn_error_createf() is not the macro defined in
+ svn_error.h but the real function. */
+ svn_error__locate(file, line);
+
if (expr)
return svn_error_createf(SVN_ERR_ASSERTION_FAIL, NULL,
_("In file '%s' line %d: assertion failed (%s)"),
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/io.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/io.c Wed Dec 29 00:10:25 2010
@@ -756,7 +756,7 @@ svn_io_copy_file(const char *src,
#endif
SVN_ERR(svn_io_file_open(&from_file, src, APR_READ | APR_BINARY,
- APR_OS_DEFAULT, pool));
+ APR_OS_DEFAULT, pool));
/* For atomicity, we copy to a tmp file and then rename the tmp
file over the real destination. */
@@ -2188,15 +2188,18 @@ handle_child_process_error(apr_pool_t *p
svn_error_t *
-svn_io_start_cmd(apr_proc_t *cmd_proc,
- const char *path,
- const char *cmd,
- const char *const *args,
- svn_boolean_t inherit,
- apr_file_t *infile,
- apr_file_t *outfile,
- apr_file_t *errfile,
- apr_pool_t *pool)
+svn_io_start_cmd2(apr_proc_t *cmd_proc,
+ const char *path,
+ const char *cmd,
+ const char *const *args,
+ svn_boolean_t inherit,
+ svn_boolean_t infile_pipe,
+ apr_file_t *infile,
+ svn_boolean_t outfile_pipe,
+ apr_file_t *outfile,
+ svn_boolean_t errfile_pipe,
+ apr_file_t *errfile,
+ apr_pool_t *pool)
{
apr_status_t apr_err;
apr_procattr_t *cmdproc_attr;
@@ -2204,6 +2207,10 @@ svn_io_start_cmd(apr_proc_t *cmd_proc,
const char **args_native;
const char *cmd_apr;
+ SVN_ERR_ASSERT(!((infile != NULL) && infile_pipe));
+ SVN_ERR_ASSERT(!((outfile != NULL) && outfile_pipe));
+ SVN_ERR_ASSERT(!((errfile != NULL) && errfile_pipe));
+
/* Create the process attributes. */
apr_err = apr_procattr_create(&cmdproc_attr, pool);
if (apr_err)
@@ -2212,7 +2219,7 @@ svn_io_start_cmd(apr_proc_t *cmd_proc,
/* Make sure we invoke cmd directly, not through a shell. */
apr_err = apr_procattr_cmdtype_set(cmdproc_attr,
- inherit?APR_PROGRAM_PATH:APR_PROGRAM);
+ inherit ? APR_PROGRAM_PATH : APR_PROGRAM);
if (apr_err)
return svn_error_wrap_apr(apr_err, _("Can't set process '%s' cmdtype"),
cmd);
@@ -2256,6 +2263,13 @@ svn_io_start_cmd(apr_proc_t *cmd_proc,
(apr_err, _("Can't set process '%s' child errfile"), cmd);
}
+ /* Forward request for pipes to APR. */
+ if (infile_pipe || outfile_pipe || errfile_pipe)
+ apr_procattr_io_set(cmdproc_attr,
+ infile_pipe ? APR_FULL_BLOCK : APR_NO_PIPE,
+ outfile_pipe ? APR_FULL_BLOCK : APR_NO_PIPE,
+ errfile_pipe ? APR_FULL_BLOCK : APR_NO_PIPE);
+
/* Have the child print any problems executing its program to errfile. */
apr_err = apr_pool_userdata_set(errfile, ERRFILE_KEY, NULL, pool);
if (apr_err)
@@ -2347,8 +2361,9 @@ svn_io_run_cmd(const char *path,
{
apr_proc_t cmd_proc;
- SVN_ERR(svn_io_start_cmd(&cmd_proc, path, cmd, args, inherit,
- infile, outfile, errfile, pool));
+ SVN_ERR(svn_io_start_cmd2(&cmd_proc, path, cmd, args, inherit,
+ FALSE, infile, FALSE, outfile, FALSE, errfile,
+ pool));
return svn_io_wait_for_cmd(&cmd_proc, cmd, exitcode, exitwhy, pool);
}
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/prompt.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/prompt.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/prompt.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/prompt.c Wed Dec 29 00:10:25 2010
@@ -418,12 +418,14 @@ plaintext_prompt_helper(svn_boolean_t *m
else
return err;
}
- if (apr_strnatcasecmp(answer, _("yes")) == 0)
+ if (apr_strnatcasecmp(answer, _("yes")) == 0 ||
+ apr_strnatcasecmp(answer, _("y")) == 0)
{
*may_save_plaintext = TRUE;
answered = TRUE;
}
- else if (apr_strnatcasecmp(answer, _("no")) == 0)
+ else if (apr_strnatcasecmp(answer, _("no")) == 0 ||
+ apr_strnatcasecmp(answer, _("n")) == 0)
{
*may_save_plaintext = FALSE;
answered = TRUE;
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/subst.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/subst.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/subst.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_subr/subst.c Wed Dec 29 00:10:25 2010
@@ -606,11 +606,34 @@ translate_keyword(char *buf,
return FALSE;
}
+/* A boolean expression that evaluates to true if the first STR_LEN characters
+ of the string STR are one of the end-of-line strings LF, CR, or CRLF;
+ to false otherwise. */
+#define STRING_IS_EOL(str, str_len) \
+ (((str_len) == 2 && (str)[0] == '\r' && (str)[1] == '\n') || \
+ ((str_len) == 1 && ((str)[0] == '\n' || (str)[0] == '\r')))
+
+/* A boolean expression that evaluates to true if the end-of-line string EOL1,
+ having length EOL1_LEN, and the end-of-line string EOL2, having length
+ EOL2_LEN, are different, assuming that EOL1 and EOL2 are both from the
+ set {"\n", "\r", "\r\n"}; to false otherwise.
+
+ Given that EOL1 and EOL2 are either "\n", "\r", or "\r\n", then if
+ EOL1_LEN is not the same as EOL2_LEN, then EOL1 and EOL2 are of course
+ different. If EOL1_LEN and EOL2_LEN are both 2 then EOL1 and EOL2 are both
+ "\r\n" and *EOL1 == *EOL2. Otherwise, EOL1_LEN and EOL2_LEN are both 1.
+ We need only check the one character for equality to determine whether
+ EOL1 and EOL2 are different in that case. */
+#define DIFFERENT_EOL_STRINGS(eol1, eol1_len, eol2, eol2_len) \
+ (((eol1_len) != (eol2_len)) || (*(eol1) != *(eol2)))
+
/* Translate the newline string NEWLINE_BUF (of length NEWLINE_LEN) to
the newline string EOL_STR (of length EOL_STR_LEN), writing the
result (which is always EOL_STR) to the stream DST.
+ This function assumes that NEWLINE_BUF is either "\n", "\r", or "\r\n".
+
Also check for consistency of the source newline strings across
multiple calls, using SRC_FORMAT (length *SRC_FORMAT_LEN) as a cache
of the first newline found. If the current newline is not the same
@@ -620,6 +643,11 @@ translate_keyword(char *buf,
newline in the file, and copy it to {SRC_FORMAT, *SRC_FORMAT_LEN} to
use for later consistency checks.
+ If TRANSLATED_EOL is not NULL, then set *TRANSLATED_EOL to TRUE if the
+ newline string that was written (EOL_STR) is not the same as the newline
+ string that was translated (NEWLINE_BUF), otherwise leave *TRANSLATED_EOL
+ untouched.
+
Note: all parameters are required even if REPAIR is TRUE.
### We could require that REPAIR must not change across a sequence of
calls, and could then optimize by not using SRC_FORMAT at all if
@@ -633,17 +661,19 @@ translate_newline(const char *eol_str,
const char *newline_buf,
apr_size_t newline_len,
svn_stream_t *dst,
+ svn_boolean_t *translated_eol,
svn_boolean_t repair)
{
+ SVN_ERR_ASSERT(STRING_IS_EOL(newline_buf, newline_len));
+
/* If we've seen a newline before, compare it with our cache to
check for consistency, else cache it for future comparisons. */
if (*src_format_len)
{
/* Comparing with cache. If we are inconsistent and
we are NOT repairing the file, generate an error! */
- if ((! repair) &&
- ((*src_format_len != newline_len) ||
- (strncmp(src_format, newline_buf, newline_len))))
+ if ((! repair) && DIFFERENT_EOL_STRINGS(src_format, *src_format_len,
+ newline_buf, newline_len))
return svn_error_create(SVN_ERR_IO_INCONSISTENT_EOL, NULL, NULL);
}
else
@@ -653,8 +683,18 @@ translate_newline(const char *eol_str,
strncpy(src_format, newline_buf, newline_len);
*src_format_len = newline_len;
}
+
/* Write the desired newline */
- return translate_write(dst, eol_str, eol_str_len);
+ SVN_ERR(translate_write(dst, eol_str, eol_str_len));
+
+ /* Report whether we translated it. Note: Not using DIFFERENT_EOL_STRINGS()
+ * because EOL_STR may not be a valid EOL sequence. */
+ if (translated_eol != NULL &&
+ (eol_str_len != newline_len ||
+ memcmp(eol_str, newline_buf, eol_str_len) != 0))
+ *translated_eol = TRUE;
+
+ return SVN_NO_ERROR;
}
@@ -765,10 +805,12 @@ svn_subst_keywords_differ2(apr_hash_t *a
return FALSE;
}
+
/* Baton for translate_chunk() to store its state in. */
struct translation_baton
{
const char *eol_str;
+ svn_boolean_t *translated_eol;
svn_boolean_t repair;
apr_hash_t *keywords;
svn_boolean_t expand;
@@ -813,6 +855,7 @@ struct translation_baton
*/
static struct translation_baton *
create_translation_baton(const char *eol_str,
+ svn_boolean_t *translated_eol,
svn_boolean_t repair,
apr_hash_t *keywords,
svn_boolean_t expand,
@@ -826,6 +869,7 @@ create_translation_baton(const char *eol
b->eol_str = eol_str;
b->eol_str_len = eol_str ? strlen(eol_str) : 0;
+ b->translated_eol = translated_eol;
b->repair = repair;
b->keywords = keywords;
b->expand = expand;
@@ -888,6 +932,9 @@ eol_unchanged(struct translation_baton *
* To finish a series of chunk translations, flush all buffers by calling
* this routine with a NULL value for BUF.
*
+ * If B->translated_eol is not NULL, then set *B->translated_eol to TRUE if
+ * an end-of-line sequence was changed, otherwise leave it untouched.
+ *
* Use POOL for temporary allocations.
*/
static svn_error_t *
@@ -924,7 +971,8 @@ translate_chunk(svn_stream_t *dst,
SVN_ERR(translate_newline(b->eol_str, b->eol_str_len,
b->src_format,
&b->src_format_len, b->newline_buf,
- b->newline_off, dst, b->repair));
+ b->newline_off, dst, b->translated_eol,
+ b->repair));
b->newline_off = 0;
}
@@ -1070,7 +1118,8 @@ translate_chunk(svn_stream_t *dst,
b->src_format,
&b->src_format_len,
b->newline_buf,
- b->newline_off, dst, b->repair));
+ b->newline_off, dst,
+ b->translated_eol, b->repair));
b->newline_off = 0;
break;
@@ -1086,7 +1135,7 @@ translate_chunk(svn_stream_t *dst,
SVN_ERR(translate_newline(b->eol_str, b->eol_str_len,
b->src_format, &b->src_format_len,
b->newline_buf, b->newline_off,
- dst, b->repair));
+ dst, b->translated_eol, b->repair));
b->newline_off = 0;
}
@@ -1349,14 +1398,20 @@ svn_subst_read_specialfile(svn_stream_t
return SVN_NO_ERROR;
}
-
-svn_stream_t *
-svn_subst_stream_translated(svn_stream_t *stream,
- const char *eol_str,
- svn_boolean_t repair,
- apr_hash_t *keywords,
- svn_boolean_t expand,
- apr_pool_t *result_pool)
+/* Same as svn_subst_stream_translated(), except for the following.
+ *
+ * If TRANSLATED_EOL is not NULL, then reading and/or writing to the stream
+ * will set *TRANSLATED_EOL to TRUE if an end-of-line sequence was changed,
+ * otherwise leave it untouched.
+ */
+static svn_stream_t *
+stream_translated(svn_stream_t *stream,
+ const char *eol_str,
+ svn_boolean_t *translated_eol,
+ svn_boolean_t repair,
+ apr_hash_t *keywords,
+ svn_boolean_t expand,
+ apr_pool_t *result_pool)
{
struct translated_stream_baton *baton
= apr_palloc(result_pool, sizeof(*baton));
@@ -1398,9 +1453,11 @@ svn_subst_stream_translated(svn_stream_t
/* Setup the baton fields */
baton->stream = stream;
baton->in_baton
- = create_translation_baton(eol_str, repair, keywords, expand, result_pool);
+ = create_translation_baton(eol_str, translated_eol, repair, keywords,
+ expand, result_pool);
baton->out_baton
- = create_translation_baton(eol_str, repair, keywords, expand, result_pool);
+ = create_translation_baton(eol_str, translated_eol, repair, keywords,
+ expand, result_pool);
baton->written = FALSE;
baton->readbuf = svn_stringbuf_create("", result_pool);
baton->readbuf_off = 0;
@@ -1417,15 +1474,32 @@ svn_subst_stream_translated(svn_stream_t
return s;
}
+svn_stream_t *
+svn_subst_stream_translated(svn_stream_t *stream,
+ const char *eol_str,
+ svn_boolean_t repair,
+ apr_hash_t *keywords,
+ svn_boolean_t expand,
+ apr_pool_t *result_pool)
+{
+ return stream_translated(stream, eol_str, NULL, repair, keywords, expand,
+ result_pool);
+}
-svn_error_t *
-svn_subst_translate_cstring2(const char *src,
- const char **dst,
- const char *eol_str,
- svn_boolean_t repair,
- apr_hash_t *keywords,
- svn_boolean_t expand,
- apr_pool_t *pool)
+/* Same as svn_subst_translate_cstring2(), except for the following.
+ *
+ * If TRANSLATED_EOL is not NULL, then set *TRANSLATED_EOL to TRUE if an
+ * end-of-line sequence was changed, or to FALSE otherwise.
+ */
+static svn_error_t *
+translate_cstring(const char **dst,
+ svn_boolean_t *translated_eol,
+ const char *src,
+ const char *eol_str,
+ svn_boolean_t repair,
+ apr_hash_t *keywords,
+ svn_boolean_t expand,
+ apr_pool_t *pool)
{
svn_stringbuf_t *dst_stringbuf;
svn_stream_t *dst_stream;
@@ -1442,9 +1516,12 @@ svn_subst_translate_cstring2(const char
dst_stringbuf = svn_stringbuf_create("", pool);
dst_stream = svn_stream_from_stringbuf(dst_stringbuf, pool);
+ if (translated_eol)
+ *translated_eol = FALSE;
+
/* Another wrapper to translate the content. */
- dst_stream = svn_subst_stream_translated(dst_stream, eol_str, repair,
- keywords, expand, pool);
+ dst_stream = stream_translated(dst_stream, eol_str, translated_eol, repair,
+ keywords, expand, pool);
/* Jam the text into the destination stream (to translate it). */
SVN_ERR(svn_stream_write(dst_stream, src, &len));
@@ -1456,6 +1533,19 @@ svn_subst_translate_cstring2(const char
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_subst_translate_cstring2(const char *src,
+ const char **dst,
+ const char *eol_str,
+ svn_boolean_t repair,
+ apr_hash_t *keywords,
+ svn_boolean_t expand,
+ apr_pool_t *pool)
+{
+ return translate_cstring(dst, NULL, src, eol_str, repair, keywords, expand,
+ pool);
+}
+
/* Given a special file at SRC, generate a textual representation of
it in a normal file at DST. Perform all allocations in POOL. */
/* ### this should be folded into svn_subst_copy_and_translate3 */
@@ -1768,14 +1858,16 @@ svn_subst_stream_from_specialfile(svn_st
/*** String translation */
svn_error_t *
-svn_subst_translate_string(svn_string_t **new_value,
- const svn_string_t *value,
- const char *encoding,
- apr_pool_t *pool)
+svn_subst_translate_string2(svn_string_t **new_value,
+ svn_boolean_t *translated_to_utf8,
+ svn_boolean_t *translated_line_endings,
+ const svn_string_t *value,
+ const char *encoding,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
const char *val_utf8;
const char *val_utf8_lf;
- apr_pool_t *scratch_pool = svn_pool_create(pool);
if (value == NULL)
{
@@ -1793,16 +1885,19 @@ svn_subst_translate_string(svn_string_t
SVN_ERR(svn_utf_cstring_to_utf8(&val_utf8, value->data, scratch_pool));
}
- SVN_ERR(svn_subst_translate_cstring2(val_utf8,
- &val_utf8_lf,
- "\n", /* translate to LF */
- FALSE, /* no repair */
- NULL, /* no keywords */
- FALSE, /* no expansion */
- scratch_pool));
+ if (translated_to_utf8)
+ *translated_to_utf8 = (strcmp(value->data, val_utf8) != 0);
+
+ SVN_ERR(translate_cstring(&val_utf8_lf,
+ translated_line_endings,
+ val_utf8,
+ "\n", /* translate to LF */
+ FALSE, /* no repair */
+ NULL, /* no keywords */
+ FALSE, /* no expansion */
+ scratch_pool));
- *new_value = svn_string_create(val_utf8_lf, pool);
- svn_pool_destroy(scratch_pool);
+ *new_value = svn_string_create(val_utf8_lf, result_pool);
return SVN_NO_ERROR;
}
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/entries.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/entries.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/entries.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/entries.c Wed Dec 29 00:10:25 2010
@@ -1578,6 +1578,7 @@ write_entry(struct write_baton **entry_n
apr_int64_t wc_id,
apr_int64_t repos_id,
const svn_wc_entry_t *entry,
+ const svn_wc__text_base_info_t *text_base_info,
const char *local_relpath,
const char *entry_abspath,
const svn_wc_entry_t *this_dir,
@@ -1748,12 +1749,8 @@ write_entry(struct write_baton **entry_n
svn_path_uri_decode(relative_url, result_pool);
}
working_node->copyfrom_revnum = entry->copyfrom_rev;
-#ifdef SVN_WC__OP_DEPTH
working_node->op_depth
= svn_wc__db_op_depth_for_upgrade(local_relpath);
-#else
- working_node->op_depth = 2; /* ### temporary op_depth */
-#endif
}
else if (parent_node->work && parent_node->work->copyfrom_repos_path)
{
@@ -1855,14 +1852,43 @@ write_entry(struct write_baton **entry_n
}
}
- /* If there is a WORKING node file then we don't have the
- revert-base checksum for this file. It will get updated
- later when we transfer the pristine texts. */
- if (entry->kind == svn_node_dir || working_node)
+ if (entry->kind == svn_node_dir)
base_node->checksum = NULL;
else
- SVN_ERR(svn_checksum_parse_hex(&base_node->checksum, svn_checksum_md5,
- entry->checksum, result_pool));
+ {
+ if (text_base_info && text_base_info->revert_base.sha1_checksum)
+ base_node->checksum = text_base_info->revert_base.sha1_checksum;
+ else if (text_base_info && text_base_info->normal_base.sha1_checksum)
+ base_node->checksum = text_base_info->normal_base.sha1_checksum;
+ else
+ base_node->checksum = NULL;
+
+ /* The base MD5 checksum is available in the entry, unless there
+ * is a copied WORKING node. If possible, verify that the entry
+ * checksum matches the base file that we found. */
+#ifdef SVN_DEBUG
+ if (! (working_node && entry->copied))
+ {
+ svn_checksum_t *entry_md5_checksum, *found_md5_checksum;
+ SVN_ERR(svn_checksum_parse_hex(&entry_md5_checksum, svn_checksum_md5,
+ entry->checksum, scratch_pool));
+ if (text_base_info && text_base_info->revert_base.md5_checksum)
+ found_md5_checksum = text_base_info->revert_base.md5_checksum;
+ else if (text_base_info && text_base_info->normal_base.md5_checksum)
+ found_md5_checksum = text_base_info->normal_base.md5_checksum;
+ else
+ found_md5_checksum = NULL;
+ if (entry_md5_checksum && found_md5_checksum)
+ SVN_ERR_ASSERT(svn_checksum_match(entry_md5_checksum,
+ found_md5_checksum));
+ else
+ {
+ /* ### Not sure what conditions this should cover. */
+ /* SVN_ERR_ASSERT(entry->deleted || ...); */
+ }
+ }
+#endif
+ }
if (this_dir->repos)
{
@@ -1946,7 +1972,6 @@ write_entry(struct write_baton **entry_n
}
}
-#ifdef SVN_WC__OP_DEPTH
if (below_working_node)
{
below_working_node->wc_id = wc_id;
@@ -1965,10 +1990,9 @@ write_entry(struct write_baton **entry_n
below_working_node->moved_here = FALSE;
below_working_node->moved_to = FALSE;
- /* We have a problem, the revert_base information isn't
- available in the entry structure. The checksum will get
- updated later when we transfer the pristines. */
- below_working_node->checksum = NULL;
+ /* The revert_base checksum isn't available in the entry structure,
+ so the caller provides it. */
+ below_working_node->checksum = text_base_info->revert_base.sha1_checksum;
below_working_node->translated_size = 0;
below_working_node->changed_rev = SVN_INVALID_REVNUM;
below_working_node->changed_date = 0;
@@ -1978,7 +2002,6 @@ write_entry(struct write_baton **entry_n
below_working_node->properties = NULL;
SVN_ERR(insert_working_node(sdb, below_working_node, scratch_pool));
}
-#endif
/* Insert the working node. */
if (working_node)
@@ -2001,9 +2024,24 @@ write_entry(struct write_baton **entry_n
if (entry->kind == svn_node_dir)
working_node->checksum = NULL;
else
- SVN_ERR(svn_checksum_parse_hex(&working_node->checksum,
- svn_checksum_md5,
- entry->checksum, result_pool));
+ {
+ working_node->checksum = text_base_info->normal_base.sha1_checksum;
+
+ /* If an MD5 checksum is present in the entry, we can verify that
+ * it matches the MD5 of the base file we found earlier. */
+#ifdef SVN_DEBUG
+ if (entry->checksum)
+ {
+ svn_checksum_t *md5_checksum;
+ SVN_ERR(svn_checksum_parse_hex(&md5_checksum, svn_checksum_md5,
+ entry->checksum, result_pool));
+ SVN_ERR_ASSERT(
+ md5_checksum && text_base_info->normal_base.md5_checksum);
+ SVN_ERR_ASSERT(svn_checksum_match(
+ md5_checksum, text_base_info->normal_base.md5_checksum));
+ }
+#endif
+ }
/* All subdirs start of incomplete, and stop being incomplete
when the entries file in the subdir is upgraded. */
@@ -2067,15 +2105,8 @@ write_entry(struct write_baton **entry_n
if (!entry->copied)
{
- if (parent_node->work)
- working_node->op_depth = parent_node->work->op_depth;
- else
-#ifdef SVN_WC__OP_DEPTH
- working_node->op_depth
- = svn_wc__db_op_depth_for_upgrade(local_relpath);
-#else
- working_node->op_depth = 2; /* ### temporary op_depth */
-#endif
+ working_node->op_depth
+ = svn_wc__db_op_depth_for_upgrade(local_relpath);
}
SVN_ERR(insert_working_node(sdb, working_node, scratch_pool));
@@ -2111,6 +2142,7 @@ struct entries_write_baton
const char *dir_abspath;
const char *new_root_abspath;
apr_hash_t *entries;
+ apr_hash_t *text_bases_info;
struct write_baton *parent_node;
struct write_baton *dir_node;
apr_pool_t *result_pool;
@@ -2152,7 +2184,7 @@ entries_write_new_cb(void *baton,
/* Write out "this dir" */
SVN_ERR(write_entry(&ewb->dir_node, ewb->parent_node, db, sdb,
- ewb->wc_id, ewb->repos_id, this_dir, dir_relpath,
+ ewb->wc_id, ewb->repos_id, this_dir, NULL, dir_relpath,
svn_dirent_join(new_root_abspath, dir_relpath,
scratch_pool),
this_dir, FALSE, ewb->result_pool, iterpool));
@@ -2163,6 +2195,8 @@ entries_write_new_cb(void *baton,
const char *name = svn__apr_hash_index_key(hi);
const svn_wc_entry_t *this_entry = svn__apr_hash_index_val(hi);
const char *child_abspath, *child_relpath;
+ svn_wc__text_base_info_t *text_base_info
+ = apr_hash_get(ewb->text_bases_info, name, APR_HASH_KEY_STRING);
svn_pool_clear(iterpool);
@@ -2176,7 +2210,7 @@ entries_write_new_cb(void *baton,
child_relpath = svn_dirent_skip_ancestor(old_root_abspath, child_abspath);
SVN_ERR(write_entry(NULL, ewb->dir_node, db, sdb,
ewb->wc_id, ewb->repos_id,
- this_entry, child_relpath,
+ this_entry, text_base_info, child_relpath,
svn_dirent_join(new_root_abspath, child_relpath,
scratch_pool),
this_dir, TRUE, iterpool, iterpool));
@@ -2197,6 +2231,7 @@ svn_wc__write_upgraded_entries(void **di
const char *dir_abspath,
const char *new_root_abspath,
apr_hash_t *entries,
+ apr_hash_t *text_bases_info,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -2208,6 +2243,7 @@ svn_wc__write_upgraded_entries(void **di
ewb.dir_abspath = dir_abspath;
ewb.new_root_abspath = new_root_abspath;
ewb.entries = entries;
+ ewb.text_bases_info = text_bases_info;
ewb.parent_node = parent_baton;
ewb.result_pool = result_pool;
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/entries.h
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/entries.h?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/entries.h (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/entries.h Wed Dec 29 00:10:25 2010
@@ -80,17 +80,30 @@ svn_error_t *
svn_wc__entry_is_hidden(svn_boolean_t *hidden, const svn_wc_entry_t *entry);
-/* For internal use by entries.c to read/write old-format working copies. */
-svn_error_t *
-svn_wc__read_entries_old(apr_hash_t **entries,
- const char *dir_abspath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool);
+/* The checksums of one pre-1.7 text-base file. If the text-base file
+ * exists, both checksums are filled in, otherwise both fields are NULL. */
+typedef struct svn_wc__text_base_file_info_t
+{
+ svn_checksum_t *sha1_checksum;
+ svn_checksum_t *md5_checksum;
+} svn_wc__text_base_file_info_t;
+
+/* The text-base checksums of the normal base and/or the revert-base of one
+ * pre-1.7 versioned text file. */
+typedef struct svn_wc__text_base_info_t
+{
+ svn_wc__text_base_file_info_t normal_base;
+ svn_wc__text_base_file_info_t revert_base;
+} svn_wc__text_base_info_t;
/* For internal use by upgrade.c to write entries in the wc-ng format.
Return in DIR_BATON the baton to be passed as PARENT_BATON when
upgrading child directories. Pass a NULL PARENT_BATON when upgrading
- the root directory. */
+ the root directory.
+
+ TEXT_BASES_INFO is a hash of information about all the text bases found
+ in this directory's admin area, keyed on (const char *) name of the
+ versioned file, with (svn_wc__text_base_info_t *) values. */
svn_error_t *
svn_wc__write_upgraded_entries(void **dir_baton,
void *parent_baton,
@@ -101,6 +114,7 @@ svn_wc__write_upgraded_entries(void **di
const char *dir_abspath,
const char *new_root_abspath,
apr_hash_t *entries,
+ apr_hash_t *text_bases_info,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/lock.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/lock.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/lock.c Wed Dec 29 00:10:25 2010
@@ -543,18 +543,8 @@ open_single(svn_wc_adm_access_t **adm_ac
/* The format version must match exactly. Note that wc_db will perform
an auto-upgrade if allowed. If it does *not*, then it has decided a
- manual upgrade is required.
-
- Note: if it decided on a manual upgrade, then we "should" never even
- reach this code. An error should have been raised earlier. */
- if (wc_format != SVN_WC__VERSION)
- {
- return svn_error_createf(SVN_ERR_WC_UPGRADE_REQUIRED, NULL,
- _("Working copy format of '%s' is too old (%d); "
- "please run 'svn upgrade'"),
- svn_dirent_local_style(path, scratch_pool),
- wc_format);
- }
+ manual upgrade is required and it should have raised an error. */
+ SVN_ERR_ASSERT(wc_format == SVN_WC__VERSION);
/* Need to create a new lock */
SVN_ERR(adm_access_alloc(&lock, path, db, db_provided, write_lock,
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/node.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/node.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/node.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/node.c Wed Dec 29 00:10:25 2010
@@ -165,6 +165,55 @@ svn_wc__node_get_repos_info(const char *
return SVN_NO_ERROR;
}
+/* Convert DB_KIND into the appropriate NODE_KIND value.
+ * If SHOW_HIDDEN is TRUE, report the node kind as found in the DB
+ * even if DB_STATUS indicates that the node is hidden.
+ * Else, return svn_kind_none for such nodes.
+ *
+ * ### This is a bit ugly. We should consider promoting svn_wc__db_kind_t
+ * ### to the de-facto node kind type instead of converting between them
+ * ### in non-backwards compat code.
+ * ### See also comments at the definition of svn_wc__db_kind_t. */
+static svn_error_t *
+convert_db_kind_to_node_kind(svn_node_kind_t *node_kind,
+ svn_wc__db_kind_t db_kind,
+ svn_wc__db_status_t db_status,
+ svn_boolean_t show_hidden)
+{
+ switch (db_kind)
+ {
+ case svn_wc__db_kind_file:
+ *node_kind = svn_node_file;
+ break;
+ case svn_wc__db_kind_dir:
+ *node_kind = svn_node_dir;
+ break;
+ case svn_wc__db_kind_symlink:
+ *node_kind = svn_node_file;
+ break;
+ case svn_wc__db_kind_unknown:
+ *node_kind = svn_node_unknown;
+ break;
+ default:
+ SVN_ERR_MALFUNCTION();
+ }
+
+ /* Make sure hidden nodes return svn_node_none. */
+ if (! show_hidden)
+ switch (db_status)
+ {
+ case svn_wc__db_status_not_present:
+ case svn_wc__db_status_absent:
+ case svn_wc__db_status_excluded:
+ *node_kind = svn_node_none;
+
+ default:
+ break;
+ }
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_wc_read_kind(svn_node_kind_t *kind,
svn_wc_context_t *wc_ctx,
@@ -192,36 +241,7 @@ svn_wc_read_kind(svn_node_kind_t *kind,
else
SVN_ERR(err);
- switch (db_kind)
- {
- case svn_wc__db_kind_file:
- *kind = svn_node_file;
- break;
- case svn_wc__db_kind_dir:
- *kind = svn_node_dir;
- break;
- case svn_wc__db_kind_symlink:
- *kind = svn_node_file;
- break;
- case svn_wc__db_kind_unknown:
- *kind = svn_node_unknown;
- break;
- default:
- SVN_ERR_MALFUNCTION();
- }
-
- /* Make sure hidden nodes return svn_node_none. */
- if (! show_hidden)
- switch (db_status)
- {
- case svn_wc__db_status_not_present:
- case svn_wc__db_status_absent:
- case svn_wc__db_status_excluded:
- *kind = svn_node_none;
-
- default:
- break;
- }
+ SVN_ERR(convert_db_kind_to_node_kind(kind, db_kind, db_status, show_hidden));
return SVN_NO_ERROR;
}
@@ -648,22 +668,28 @@ walker_helper(svn_wc__db_t *db,
void *cancel_baton,
apr_pool_t *scratch_pool)
{
- const apr_array_header_t *rel_children;
+ apr_hash_t *rel_children_info;
+ apr_hash_index_t *hi;
apr_pool_t *iterpool;
- int i;
if (depth == svn_depth_empty)
return SVN_NO_ERROR;
- SVN_ERR(svn_wc__db_read_children(&rel_children, db, dir_abspath,
- scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__db_read_children_walker_info(&rel_children_info, db,
+ dir_abspath, scratch_pool,
+ scratch_pool));
+
iterpool = svn_pool_create(scratch_pool);
- for (i = 0; i < rel_children->nelts; i++)
+ for (hi = apr_hash_first(scratch_pool, rel_children_info);
+ hi;
+ hi = apr_hash_next(hi))
{
+ const char *child_name = svn__apr_hash_index_key(hi);
+ struct svn_wc__db_walker_info_t *wi = svn__apr_hash_index_val(hi);
+ svn_wc__db_kind_t child_kind = wi->kind;
+ svn_wc__db_status_t child_status = wi->status;
const char *child_abspath;
- svn_wc__db_kind_t child_kind;
- svn_wc__db_status_t child_status;
svn_pool_clear(iterpool);
@@ -671,17 +697,7 @@ walker_helper(svn_wc__db_t *db,
if (cancel_func)
SVN_ERR(cancel_func(cancel_baton));
- child_abspath = svn_dirent_join(dir_abspath,
- APR_ARRAY_IDX(rel_children, i,
- const char *),
- iterpool);
-
- SVN_ERR(svn_wc__db_read_info(&child_status, &child_kind, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL,
- db, child_abspath, iterpool, iterpool));
+ child_abspath = svn_dirent_join(dir_abspath, child_name, iterpool);
if (!show_hidden)
switch (child_status)
@@ -699,9 +715,14 @@ walker_helper(svn_wc__db_t *db,
if (child_kind == svn_wc__db_kind_file
|| depth >= svn_depth_immediates)
{
- /* ### Maybe we should pass kind to the callback?.
- ### almost every callee starts by asking for this */
- SVN_ERR(walk_callback(child_abspath, walk_baton, iterpool));
+ svn_node_kind_t kind;
+
+ SVN_ERR(convert_db_kind_to_node_kind(&kind, child_kind,
+ child_status, show_hidden));
+ /* ### We might want to pass child_status as well because at least
+ * ### one callee is asking for it.
+ * ### But is it OK to use an svn_wc__db type in this API? */
+ SVN_ERR(walk_callback(child_abspath, kind, walk_baton, iterpool));
}
/* Recurse into this directory, if appropriate. */
@@ -737,28 +758,30 @@ svn_wc__internal_walk_children(svn_wc__d
void *cancel_baton,
apr_pool_t *scratch_pool)
{
- svn_wc__db_kind_t kind;
+ svn_wc__db_kind_t db_kind;
+ svn_node_kind_t kind;
svn_wc__db_status_t status;
SVN_ERR_ASSERT(walk_depth >= svn_depth_empty
&& walk_depth <= svn_depth_infinity);
/* Check if the node exists before the first callback */
- SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL,
+ SVN_ERR(svn_wc__db_read_info(&status, &db_kind, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
db, local_abspath, scratch_pool, scratch_pool));
- SVN_ERR(walk_callback(local_abspath, walk_baton, scratch_pool));
+ SVN_ERR(convert_db_kind_to_node_kind(&kind, db_kind, status, show_hidden));
+ SVN_ERR(walk_callback(local_abspath, kind, walk_baton, scratch_pool));
- if (kind == svn_wc__db_kind_file
+ if (db_kind == svn_wc__db_kind_file
|| status == svn_wc__db_status_not_present
|| status == svn_wc__db_status_excluded
|| status == svn_wc__db_status_absent)
return SVN_NO_ERROR;
- if (kind == svn_wc__db_kind_dir)
+ if (db_kind == svn_wc__db_kind_dir)
{
return svn_error_return(
walker_helper(db, local_abspath, show_hidden, walk_callback, walk_baton,
@@ -1317,6 +1340,19 @@ svn_wc__internal_node_get_schedule(svn_w
if (base_status != svn_wc__db_status_not_present)
*schedule = svn_wc_schedule_replace;
}
+ else
+ {
+ svn_boolean_t below_work;
+
+ SVN_ERR(svn_wc__db_temp_below_work(&below_work,
+ db, local_abspath,
+ scratch_pool));
+ /* Unlike base nodes above, not-present is considered a
+ replace since working not-present represents a delete
+ to be committed */
+ if (below_work)
+ *schedule = svn_wc_schedule_replace;
+ }
if (status == svn_wc__db_status_added)
break; /* Local addition */
Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/revision_status.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/revision_status.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/revision_status.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/revision_status.c Wed Dec 29 00:10:25 2010
@@ -52,6 +52,7 @@ struct walk_baton
* Temporary allocations are made in SCRATCH_POOL. */
static svn_error_t *
analyze_status(const char *local_abspath,
+ svn_node_kind_t kind,
void *baton,
apr_pool_t *scratch_pool)
{