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/10/30 02:33:40 UTC
svn commit: r1536950 [3/6] - in /subversion/branches/log-addressing: ./
build/ build/ac-macros/ build/generator/ notes/http-and-webdav/
subversion/bindings/javahl/ subversion/bindings/javahl/native/
subversion/bindings/javahl/src/org/apache/subversion/...
Modified: subversion/branches/log-addressing/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra_serf/util.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra_serf/util.c Wed Oct 30 01:33:37 2013
@@ -48,6 +48,7 @@
#include "private/svn_dep_compat.h"
#include "private/svn_fspath.h"
#include "private/svn_subr_private.h"
+#include "private/svn_auth_private.h"
#include "ra_serf.h"
@@ -270,26 +271,70 @@ ssl_server_cert(void *baton, int failure
svn_auth_iterstate_t *state;
const char *realmstring;
apr_uint32_t svn_failures;
- apr_hash_t *issuer, *subject, *serf_cert;
- apr_array_header_t *san;
+ apr_hash_t *issuer;
+ apr_hash_t *subject = NULL;
+ apr_hash_t *serf_cert = NULL;
void *creds;
int found_matching_hostname = 0;
- /* Implicitly approve any non-server certs. */
- if (serf_ssl_cert_depth(cert) > 0)
+ svn_failures = (ssl_convert_serf_failures(failures)
+ | conn->server_cert_failures);
+
+ if (serf_ssl_cert_depth(cert) == 0)
{
- if (failures)
- conn->server_cert_failures |= ssl_convert_serf_failures(failures);
- return APR_SUCCESS;
+ /* If the depth is 0, the hostname must match the certificate.
+
+ ### This should really be handled by serf, which should pass an error
+ for this case, but that has backwards compatibility issues. */
+ apr_array_header_t *san;
+
+ serf_cert = serf_ssl_cert_certificate(cert, scratch_pool);
+
+ san = svn_hash_gets(serf_cert, "subjectAltName");
+ /* Try to find matching server name via subjectAltName first... */
+ if (san) {
+ int i;
+ for (i = 0; i < san->nelts; i++) {
+ const char *s = APR_ARRAY_IDX(san, i, const char*);
+ if (apr_fnmatch(s, conn->session->session_url.hostname,
+ APR_FNM_PERIOD | APR_FNM_CASE_BLIND) == APR_SUCCESS)
+ {
+ found_matching_hostname = 1;
+ break;
+ }
+ }
+ }
+
+ /* Match server certificate CN with the hostname of the server */
+ if (!found_matching_hostname)
+ {
+ const char *hostname = NULL;
+
+ subject = serf_ssl_cert_subject(cert, scratch_pool);
+
+ if (subject)
+ hostname = svn_hash_gets(subject, "CN");
+
+ if (!hostname
+ || apr_fnmatch(hostname, conn->session->session_url.hostname,
+ APR_FNM_PERIOD | APR_FNM_CASE_BLIND) != APR_SUCCESS)
+ {
+ svn_failures |= SVN_AUTH_SSL_CNMISMATCH;
+ }
+ }
}
+ if (!svn_failures)
+ return SVN_NO_ERROR;
+
/* Extract the info from the certificate */
- subject = serf_ssl_cert_subject(cert, scratch_pool);
+ if (! subject)
+ subject = serf_ssl_cert_subject(cert, scratch_pool);
issuer = serf_ssl_cert_issuer(cert, scratch_pool);
- serf_cert = serf_ssl_cert_certificate(cert, scratch_pool);
+ if (! serf_cert)
+ serf_cert = serf_ssl_cert_certificate(cert, scratch_pool);
cert_info.hostname = svn_hash_gets(subject, "CN");
- san = svn_hash_gets(serf_cert, "subjectAltName");
cert_info.fingerprint = svn_hash_gets(serf_cert, "sha1");
if (! cert_info.fingerprint)
cert_info.fingerprint = apr_pstrdup(scratch_pool, "<unknown>");
@@ -302,32 +347,56 @@ ssl_server_cert(void *baton, int failure
cert_info.issuer_dname = convert_organisation_to_str(issuer, scratch_pool);
cert_info.ascii_cert = serf_ssl_cert_export(cert, scratch_pool);
- svn_failures = (ssl_convert_serf_failures(failures)
- | conn->server_cert_failures);
+ /* Handle any non-server certs. */
+ if (serf_ssl_cert_depth(cert) > 0)
+ {
+ svn_error_t *err;
- /* Try to find matching server name via subjectAltName first... */
- if (san) {
- int i;
- for (i = 0; i < san->nelts; i++) {
- char *s = APR_ARRAY_IDX(san, i, char*);
- if (apr_fnmatch(s, conn->session->session_url.hostname,
- APR_FNM_PERIOD | APR_FNM_CASE_BLIND) == APR_SUCCESS)
- {
- found_matching_hostname = 1;
- cert_info.hostname = s;
- break;
- }
- }
- }
+ svn_auth_set_parameter(conn->session->wc_callbacks->auth_baton,
+ SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO,
+ &cert_info);
+
+ svn_auth_set_parameter(conn->session->wc_callbacks->auth_baton,
+ SVN_AUTH_PARAM_SSL_SERVER_FAILURES,
+ &svn_failures);
+
+ realmstring = apr_psprintf(scratch_pool, "AUTHORITY:%s",
+ cert_info.fingerprint);
+
+ err = svn_auth_first_credentials(&creds, &state,
+ SVN_AUTH_CRED_SSL_SERVER_AUTHORITY,
+ realmstring,
+ conn->session->wc_callbacks->auth_baton,
+ scratch_pool);
- /* Match server certificate CN with the hostname of the server */
- if (!found_matching_hostname && cert_info.hostname)
- {
- if (apr_fnmatch(cert_info.hostname, conn->session->session_url.hostname,
- APR_FNM_PERIOD | APR_FNM_CASE_BLIND) == APR_FNM_NOMATCH)
+ svn_auth_set_parameter(conn->session->wc_callbacks->auth_baton,
+ SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO, NULL);
+
+ svn_auth_set_parameter(conn->session->wc_callbacks->auth_baton,
+ SVN_AUTH_PARAM_SSL_SERVER_FAILURES, NULL);
+
+ if (err)
+ {
+ if (err->apr_err != SVN_ERR_AUTHN_NO_PROVIDER)
+ return svn_error_trace(err);
+
+ /* No provider registered that handles server authorities */
+ svn_error_clear(err);
+ creds = NULL;
+ }
+
+ if (creds)
{
- svn_failures |= SVN_AUTH_SSL_CNMISMATCH;
+ server_creds = creds;
+ SVN_ERR(svn_auth_save_credentials(state, scratch_pool));
+
+ svn_failures &= ~server_creds->accepted_failures;
}
+
+ if (svn_failures)
+ conn->server_cert_failures |= svn_failures;
+
+ return APR_SUCCESS;
}
svn_auth_set_parameter(conn->session->wc_callbacks->auth_baton,
@@ -348,13 +417,27 @@ ssl_server_cert(void *baton, int failure
if (creds)
{
server_creds = creds;
+ svn_failures &= ~server_creds->accepted_failures;
SVN_ERR(svn_auth_save_credentials(state, scratch_pool));
}
+ while (svn_failures && creds)
+ {
+ SVN_ERR(svn_auth_next_credentials(&creds, state, scratch_pool));
+
+ if (creds)
+ {
+ server_creds = creds;
+ svn_failures &= ~server_creds->accepted_failures;
+ SVN_ERR(svn_auth_save_credentials(state, scratch_pool));
+ }
+ }
+
svn_auth_set_parameter(conn->session->wc_callbacks->auth_baton,
SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO, NULL);
- if (!server_creds)
+ /* Are there non accepted failures left? */
+ if (svn_failures)
{
svn_stringbuf_t *errmsg;
int reasons = 0;
Modified: subversion/branches/log-addressing/subversion/libsvn_ra_serf/util_error.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra_serf/util_error.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra_serf/util_error.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra_serf/util_error.c Wed Oct 30 01:33:37 2013
@@ -88,7 +88,8 @@ svn_ra_serf__wrap_err(apr_status_t statu
}
if (err_msg)
{
- err->message = apr_pstrcat(err->pool, msg, ": ", err_msg, NULL);
+ err->message = apr_pstrcat(err->pool, msg, ": ", err_msg,
+ SVN_VA_NULL);
}
else
{
Modified: subversion/branches/log-addressing/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra_svn/client.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra_svn/client.c Wed Oct 30 01:33:37 2013
@@ -678,7 +678,7 @@ static svn_error_t *open_session(svn_ra_
&client_string, pool));
if (client_string)
sess->useragent = apr_pstrcat(pool, SVN_RA_SVN__DEFAULT_USERAGENT " ",
- client_string, (char *)NULL);
+ client_string, SVN_VA_NULL);
else
sess->useragent = SVN_RA_SVN__DEFAULT_USERAGENT;
@@ -1340,7 +1340,14 @@ static svn_error_t *ra_svn_get_dir(svn_r
SVN_ERR(svn_ra_svn__parse_tuple(elt->u.list, pool, "cwnbr(?c)(?c)",
&name, &kind, &size, &has_props,
&crev, &cdate, &cauthor));
- name = svn_relpath_canonicalize(name, pool);
+
+ /* Nothing to sanitize here. Any multi-segment path is simply
+ illegal in the hash returned by svn_ra_get_dir2. */
+ if (strchr(name, '/'))
+ return svn_error_createf(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
+ _("Invalid directory entry name '%s'"),
+ name);
+
dirent = svn_dirent_create(pool);
dirent->kind = svn_node_kind_from_word(kind);
dirent->size = size;/* FIXME: svn_filesize_t */
Modified: subversion/branches/log-addressing/subversion/libsvn_ra_svn/cyrus_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra_svn/cyrus_auth.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra_svn/cyrus_auth.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra_svn/cyrus_auth.c Wed Oct 30 01:33:37 2013
@@ -488,7 +488,7 @@ static svn_error_t *try_auth(svn_ra_svn_
pmech - mechstring);
const char *tail = pmech + strlen(mech);
- mechstring = apr_pstrcat(pool, head, tail, (char *)NULL);
+ mechstring = apr_pstrcat(pool, head, tail, SVN_VA_NULL);
again = TRUE;
}
}
@@ -807,10 +807,10 @@ svn_error_t *svn_ra_svn__get_addresses(c
/* Format the IP address and port number like this: a.b.c.d;port */
*local_addrport = apr_pstrcat(pool, local_addr, ";",
apr_itoa(pool, (int)local_sa->port),
- (char *)NULL);
+ SVN_VA_NULL);
*remote_addrport = apr_pstrcat(pool, remote_addr, ";",
apr_itoa(pool, (int)remote_sa->port),
- (char *)NULL);
+ SVN_VA_NULL);
}
return SVN_NO_ERROR;
}
@@ -849,7 +849,7 @@ svn_ra_svn__do_cyrus_auth(svn_ra_svn__se
mechstring = apr_pstrcat(pool,
mechstring,
i == 0 ? "" : " ",
- elt->u.word, (char *)NULL);
+ elt->u.word, SVN_VA_NULL);
}
}
Modified: subversion/branches/log-addressing/subversion/libsvn_ra_svn/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra_svn/deprecated.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra_svn/deprecated.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra_svn/deprecated.c Wed Oct 30 01:33:37 2013
@@ -232,3 +232,27 @@ svn_ra_svn_write_cmd_failure(svn_ra_svn_
{
return svn_error_trace(svn_ra_svn__write_cmd_failure(conn, pool, err));
}
+
+/* From marshal.c */
+svn_ra_svn_conn_t *
+svn_ra_svn_create_conn2(apr_socket_t *sock,
+ apr_file_t *in_file,
+ apr_file_t *out_file,
+ int compression_level,
+ apr_pool_t *pool)
+{
+ return svn_ra_svn_create_conn3(sock, in_file, out_file,
+ compression_level, 0, 0, pool);
+}
+
+/* backward-compatible implementation using the default compression level */
+svn_ra_svn_conn_t *
+svn_ra_svn_create_conn(apr_socket_t *sock,
+ apr_file_t *in_file,
+ apr_file_t *out_file,
+ apr_pool_t *pool)
+{
+ return svn_ra_svn_create_conn3(sock, in_file, out_file,
+ SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, 0, 0,
+ pool);
+}
Modified: subversion/branches/log-addressing/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_ra_svn/marshal.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_ra_svn/marshal.c Wed Oct 30 01:33:37 2013
@@ -119,6 +119,16 @@ svn_ra_svn_conn_t *svn_ra_svn_create_con
&& apr_sockaddr_ip_get(&conn->remote_ip, sa) == APR_SUCCESS))
conn->remote_ip = NULL;
svn_ra_svn__stream_timeout(conn->stream, get_timeout(conn));
+
+ /* We are using large r/w buffers already.
+ * So, once we decide to actually send data, we want it to go over
+ * the wire a.s.a.p.. So disable Nagle's algorithm.
+ *
+ * We ignore the result of this call since it safe to continue even
+ * if we keep delaying. The only negative effect is increased
+ * latency (can be additional 5 .. 10ms depending on circumstances).
+ */
+ apr_socket_opt_set(sock, APR_TCP_NODELAY, 1);
}
else
{
@@ -129,27 +139,6 @@ svn_ra_svn_conn_t *svn_ra_svn_create_con
return conn;
}
-svn_ra_svn_conn_t *svn_ra_svn_create_conn2(apr_socket_t *sock,
- apr_file_t *in_file,
- apr_file_t *out_file,
- int compression_level,
- apr_pool_t *pool)
-{
- return svn_ra_svn_create_conn3(sock, in_file, out_file,
- compression_level, 0, 0, pool);
-}
-
-/* backward-compatible implementation using the default compression level */
-svn_ra_svn_conn_t *svn_ra_svn_create_conn(apr_socket_t *sock,
- apr_file_t *in_file,
- apr_file_t *out_file,
- apr_pool_t *pool)
-{
- return svn_ra_svn_create_conn3(sock, in_file, out_file,
- SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, 0, 0,
- pool);
-}
-
svn_error_t *svn_ra_svn_set_capabilities(svn_ra_svn_conn_t *conn,
const apr_array_header_t *list)
{
Modified: subversion/branches/log-addressing/subversion/libsvn_repos/authz.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_repos/authz.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_repos/authz.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_repos/authz.c Wed Oct 30 01:33:37 2013
@@ -36,6 +36,7 @@
#include "svn_config.h"
#include "svn_ctype.h"
#include "private/svn_fspath.h"
+#include "private/svn_repos_private.h"
#include "repos.h"
@@ -352,7 +353,7 @@ authz_get_path_access(svn_config_t *cfg,
baton.user = user;
/* Try to locate a repository-specific block first. */
- qualified_path = apr_pstrcat(pool, repos_name, ":", path, (char *)NULL);
+ qualified_path = apr_pstrcat(pool, repos_name, ":", path, SVN_VA_NULL);
svn_config_enumerate2(cfg, qualified_path,
authz_parse_line, &baton, pool);
@@ -395,7 +396,7 @@ authz_get_tree_access(svn_config_t *cfg,
baton.required_access = required_access;
baton.repos_path = path;
baton.qualified_repos_path = apr_pstrcat(pool, repos_name,
- ":", path, (char *)NULL);
+ ":", path, SVN_VA_NULL);
/* Default to access granted if no rules say otherwise. */
baton.access = TRUE;
@@ -454,7 +455,7 @@ authz_get_any_access(svn_config_t *cfg,
baton.access = FALSE; /* Deny access by default. */
baton.repos_path = "/";
baton.qualified_repos_path = apr_pstrcat(pool, repos_name,
- ":/", (char *)NULL);
+ ":/", SVN_VA_NULL);
/* We could have used svn_config_enumerate2 for "repos_name:/".
* However, this requires access for root explicitly (which the user
Modified: subversion/branches/log-addressing/subversion/libsvn_repos/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_repos/commit.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_repos/commit.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_repos/commit.c Wed Oct 30 01:33:37 2013
@@ -1013,7 +1013,7 @@ ev2_check_authz(const struct ev2_baton *
return SVN_NO_ERROR;
if (relpath)
- fspath = apr_pstrcat(scratch_pool, "/", relpath, NULL);
+ fspath = apr_pstrcat(scratch_pool, "/", relpath, SVN_VA_NULL);
else
fspath = NULL;
Modified: subversion/branches/log-addressing/subversion/libsvn_repos/config_pool.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_repos/config_pool.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_repos/config_pool.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_repos/config_pool.c Wed Oct 30 01:33:37 2013
@@ -434,7 +434,7 @@ add_checksum(svn_repos__config_pool_t *c
}
/* Set *CFG to the configuration stored in URL@HEAD and cache it in
- * CONFIG_POOL.
+ * CONFIG_POOL. ### Always returns a NULL CFG.
*
* RESULT_POOL determines the lifetime of the returned reference and
* SCRATCH_POOL is being used for temporary allocations.
@@ -463,7 +463,6 @@ find_repos_config(svn_config_t **cfg,
/* Search for a repository in the full path. */
repos_root_dirent = svn_repos_find_root_path(dirent, scratch_pool);
- return SVN_NO_ERROR;
/* Attempt to open a repository at repos_root_dirent. */
SVN_ERR(svn_repos_open2(&repos, repos_root_dirent, NULL, scratch_pool));
Modified: subversion/branches/log-addressing/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_repos/dump.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_repos/dump.c Wed Oct 30 01:33:37 2013
@@ -45,6 +45,269 @@
/*----------------------------------------------------------------------*/
+/* To be able to check whether a path exists in the current revision
+ (as changes come in), we need to track the relevant tree changes.
+
+ In particular, we remember deletions, additions and copies including
+ their copy-from info. Since the dump performs a pre-order tree walk,
+ we only need to store the data for the stack of parent folders.
+
+ The problem that we are trying to solve is that the dump receives
+ transforming operations whose validity depends on previous operations
+ in the same revision but cannot be checked against the final state
+ as stored in the repository as that is the state *after* we applied
+ the respective tree changes.
+
+ Note that the tracker functions don't perform any sanity or validity
+ checks. Those higher-level tests have to be done in the calling code.
+ However, there is no way to corrupt the data structure using the
+ provided functions.
+ */
+
+/* Single entry in the path tracker. Not all levels along the path
+ hierarchy do need to have an instance of this struct but only those
+ that got changed by a tree modification.
+
+ Please note that the path info in this struct is stored in re-usable
+ stringbuf objects such that we don't need to allocate more memory than
+ the longest path we encounter.
+ */
+typedef struct path_tracker_entry_t
+{
+ /* path in the current tree */
+ svn_stringbuf_t *path;
+
+ /* copy-from path (must be empty if COPYFROM_REV is SVN_INVALID_REVNUM) */
+ svn_stringbuf_t *copyfrom_path;
+
+ /* copy-from revision (SVN_INVALID_REVNUM for additions / replacements
+ that don't copy history, i.e. with no sub-tree) */
+ svn_revnum_t copyfrom_rev;
+
+ /* if FALSE, PATH has been deleted */
+ svn_boolean_t exists;
+} path_tracker_entry_t;
+
+/* Tracks all tree modifications above the current path.
+ */
+typedef struct path_tracker_t
+{
+ /* Container for all relevant tree changes in depth order.
+ May contain more entries than DEPTH to allow for reusing memory.
+ Only entries 0 .. DEPTH-1 are valid.
+ */
+ apr_array_header_t *stack;
+
+ /* Number of relevant entries in STACK. May be 0 */
+ int depth;
+
+ /* Revision that we current track. If DEPTH is 0, paths are exist in
+ REVISION exactly when they exist in REVISION-1. This applies only
+ to the current state of our tree walk.
+ */
+ svn_revnum_t revision;
+
+ /* Allocate container entries here. */
+ apr_pool_t *pool;
+} path_tracker_t;
+
+/* Return a new path tracker object for REVISION, allocated in POOL.
+ */
+static path_tracker_t *
+tracker_create(svn_revnum_t revision,
+ apr_pool_t *pool)
+{
+ path_tracker_t *result = apr_pcalloc(pool, sizeof(*result));
+ result->stack = apr_array_make(pool, 16, sizeof(path_tracker_entry_t));
+ result->revision = revision;
+ result->pool = pool;
+
+ return result;
+}
+
+/* Remove all entries from TRACKER that are not relevant to PATH anymore.
+ * If ALLOW_EXACT_MATCH is FALSE, keep only entries that pertain to
+ * parent folders but not to PATH itself.
+ *
+ * This internal function implicitly updates the tracker state during the
+ * tree by removing "past" entries. Other functions will add entries when
+ * we encounter a new tree change.
+ */
+static void
+tracker__trim(path_tracker_t *tracker,
+ const char *path,
+ svn_boolean_t allow_exact_match)
+{
+ /* remove everything that is unrelated to PATH.
+ Note that TRACKER->STACK is depth-ordered,
+ i.e. stack[N] is a (maybe indirect) parent of stack[N+1]
+ for N+1 < DEPTH.
+ */
+ for (; tracker->depth; --tracker->depth)
+ {
+ path_tracker_entry_t *parent = &APR_ARRAY_IDX(tracker->stack,
+ tracker->depth - 1,
+ path_tracker_entry_t);
+ const char *rel_path
+ = svn_dirent_skip_ancestor(parent->path->data, path);
+
+ /* always keep parents. Keep exact matches when allowed. */
+ if (rel_path && (allow_exact_match || *rel_path != '\0'))
+ break;
+ }
+}
+
+/* Using TRACKER, check what path at what revision in the repository must
+ be checked to decide that whether PATH exists. Return the info in
+ *ORIG_PATH and *ORIG_REV, respectively.
+
+ If the path is known to not exist, *ORIG_PATH will be NULL and *ORIG_REV
+ will be SVN_INVALID_REVNUM. If *ORIG_REV is SVN_INVALID_REVNUM, PATH
+ has just been added in the revision currently being tracked.
+
+ Use POOL for allocations. Note that *ORIG_PATH may be allocated in POOL,
+ a reference to internal data with the same lifetime as TRACKER or just
+ PATH.
+ */
+static void
+tracker_lookup(const char **orig_path,
+ svn_revnum_t *orig_rev,
+ path_tracker_t *tracker,
+ const char *path,
+ apr_pool_t *pool)
+{
+ tracker__trim(tracker, path, TRUE);
+ if (tracker->depth == 0)
+ {
+ /* no tree changes -> paths are the same as in the previous rev. */
+ *orig_path = path;
+ *orig_rev = tracker->revision - 1;
+ }
+ else
+ {
+ path_tracker_entry_t *parent = &APR_ARRAY_IDX(tracker->stack,
+ tracker->depth - 1,
+ path_tracker_entry_t);
+ if (parent->exists)
+ {
+ const char *rel_path
+ = svn_dirent_skip_ancestor(parent->path->data, path);
+
+ if (parent->copyfrom_rev != SVN_INVALID_REVNUM)
+ {
+ /* parent is a copy with history. Translate path. */
+ *orig_path = svn_dirent_join(parent->copyfrom_path->data,
+ rel_path, pool);
+ *orig_rev = parent->copyfrom_rev;
+ }
+ else if (*rel_path == '\0')
+ {
+ /* added in this revision with no history */
+ *orig_path = path;
+ *orig_rev = tracker->revision;
+ }
+ else
+ {
+ /* parent got added but not this path */
+ *orig_path = NULL;
+ *orig_rev = SVN_INVALID_REVNUM;
+ }
+ }
+ else
+ {
+ /* (maybe parent) path has been deleted */
+ *orig_path = NULL;
+ *orig_rev = SVN_INVALID_REVNUM;
+ }
+ }
+}
+
+/* Return a reference to the stack entry in TRACKER for PATH. If no
+ suitable entry exists, add one. Implicitly updates the tracked tree
+ location.
+
+ Only the PATH member of the result is being updated. All other members
+ will have undefined values.
+ */
+static path_tracker_entry_t *
+tracker__add_entry(path_tracker_t *tracker,
+ const char *path)
+{
+ path_tracker_entry_t *entry;
+ tracker__trim(tracker, path, FALSE);
+
+ if (tracker->depth == tracker->stack->nelts)
+ {
+ entry = apr_array_push(tracker->stack);
+ entry->path = svn_stringbuf_create_empty(tracker->pool);
+ entry->copyfrom_path = svn_stringbuf_create_empty(tracker->pool);
+ }
+ else
+ {
+ entry = &APR_ARRAY_IDX(tracker->stack, tracker->depth,
+ path_tracker_entry_t);
+ }
+
+ svn_stringbuf_set(entry->path, path);
+ ++tracker->depth;
+
+ return entry;
+}
+
+/* Update the TRACKER with a copy from COPYFROM_PATH@COPYFROM_REV to
+ PATH in the tracked revision.
+ */
+static void
+tracker_path_copy(path_tracker_t *tracker,
+ const char *path,
+ const char *copyfrom_path,
+ svn_revnum_t copyfrom_rev)
+{
+ path_tracker_entry_t *entry = tracker__add_entry(tracker, path);
+
+ svn_stringbuf_set(entry->copyfrom_path, copyfrom_path);
+ entry->copyfrom_rev = copyfrom_rev;
+ entry->exists = TRUE;
+}
+
+/* Update the TRACKER with a plain addition of PATH (without history).
+ */
+static void
+tracker_path_add(path_tracker_t *tracker,
+ const char *path)
+{
+ path_tracker_entry_t *entry = tracker__add_entry(tracker, path);
+
+ svn_stringbuf_setempty(entry->copyfrom_path);
+ entry->copyfrom_rev = SVN_INVALID_REVNUM;
+ entry->exists = TRUE;
+}
+
+/* Update the TRACKER with a replacement of PATH with a plain addition
+ (without history).
+ */
+static void
+tracker_path_replace(path_tracker_t *tracker,
+ const char *path)
+{
+ /* this will implicitly purge all previous sub-tree info from STACK.
+ Thus, no need to tack the deletion explicitly. */
+ tracker_path_add(tracker, path);
+}
+
+/* Update the TRACKER with a deletion of PATH.
+ */
+static void
+tracker_path_delete(path_tracker_t *tracker,
+ const char *path)
+{
+ path_tracker_entry_t *entry = tracker__add_entry(tracker, path);
+
+ svn_stringbuf_setempty(entry->copyfrom_path);
+ entry->copyfrom_rev = SVN_INVALID_REVNUM;
+ entry->exists = FALSE;
+}
+
/* Compute the delta between OLDROOT/OLDPATH and NEWROOT/NEWPATH and
store it into a new temporary file *TEMPFILE. OLDROOT may be NULL,
@@ -138,6 +401,10 @@ struct edit_baton
respective node has already been verified as readable and being
of the type stored as value in the cache. */
svn_cache__t *verified_dirents_cache;
+
+ /* Structure allows us to verify the paths currently being dumped.
+ If NULL, validity checks are being skipped. */
+ path_tracker_t *path_tracker;
};
struct dir_baton
@@ -224,6 +491,95 @@ make_dir_baton(const char *path,
return new_db;
}
+static svn_error_t *
+fetch_kind_func(svn_node_kind_t *kind,
+ void *baton,
+ const char *path,
+ svn_revnum_t base_revision,
+ apr_pool_t *scratch_pool);
+
+/* Return an error when PATH in REVISION does not exist or is of a
+ different kind than EXPECTED_KIND. If the latter is svn_node_unknown,
+ skip that check. Use EB for context information. If REVISION is the
+ current revision, use EB's path tracker to follow renames, deletions,
+ etc.
+
+ Use SCRATCH_POOL for temporary allocations.
+ No-op if EB's path tracker has not been initialized.
+ */
+static svn_error_t *
+node_must_exist(struct edit_baton *eb,
+ const char *path,
+ svn_revnum_t revision,
+ svn_node_kind_t expected_kind,
+ apr_pool_t *scratch_pool)
+{
+ svn_node_kind_t kind = svn_node_none;
+
+ /* in case the caller is trying something stupid ... */
+ if (eb->path_tracker == NULL)
+ return SVN_NO_ERROR;
+
+ /* paths pertaining to the revision currently being processed must
+ be translated / checked using our path tracker. */
+ if (revision == eb->path_tracker->revision)
+ tracker_lookup(&path, &revision, eb->path_tracker, path, scratch_pool);
+
+ /* determine the node type (default: no such node) */
+ if (path)
+ SVN_ERR(fetch_kind_func(&kind, eb, path, revision, scratch_pool));
+
+ /* check results */
+ if (kind == svn_node_none)
+ return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
+ _("Path '%s' not found in r%ld."),
+ path, revision);
+
+ if (expected_kind != kind && expected_kind != svn_node_unknown)
+ return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
+ _("Unexpected node kind %d for '%s' at r%ld. "
+ "Expected kind was %d."),
+ kind, path, revision, expected_kind);
+
+ return SVN_NO_ERROR;
+}
+
+/* Return an error when PATH exists in REVISION. Use EB for context
+ information. If REVISION is the current revision, use EB's path
+ tracker to follow renames, deletions, etc.
+
+ Use SCRATCH_POOL for temporary allocations.
+ No-op if EB's path tracker has not been initialized.
+ */
+static svn_error_t *
+node_must_not_exist(struct edit_baton *eb,
+ const char *path,
+ svn_revnum_t revision,
+ apr_pool_t *scratch_pool)
+{
+ svn_node_kind_t kind = svn_node_none;
+
+ /* in case the caller is trying something stupid ... */
+ if (eb->path_tracker == NULL)
+ return SVN_NO_ERROR;
+
+ /* paths pertaining to the revision currently being processed must
+ be translated / checked using our path tracker. */
+ if (revision == eb->path_tracker->revision)
+ tracker_lookup(&path, &revision, eb->path_tracker, path, scratch_pool);
+
+ /* determine the node type (default: no such node) */
+ if (path)
+ SVN_ERR(fetch_kind_func(&kind, eb, path, revision, scratch_pool));
+
+ /* check results */
+ if (kind != svn_node_none)
+ return svn_error_createf(SVN_ERR_FS_ALREADY_EXISTS, NULL,
+ _("Path '%s' exists in r%ld."),
+ path, revision);
+
+ return SVN_NO_ERROR;
+}
/* This helper is the main "meat" of the editor -- it does all the
work of writing a node record.
@@ -311,6 +667,11 @@ dump_node(struct edit_baton *eb,
if (action == svn_node_action_change)
{
+ if (eb->path_tracker)
+ SVN_ERR_W(node_must_exist(eb, path, eb->current_rev, kind, pool),
+ apr_psprintf(pool, _("Change invalid path '%s' in r%ld"),
+ path, eb->current_rev));
+
SVN_ERR(svn_stream_puts(eb->stream,
SVN_REPOS_DUMPFILE_NODE_ACTION ": change\n"));
@@ -329,8 +690,18 @@ dump_node(struct edit_baton *eb,
}
else if (action == svn_node_action_replace)
{
+ if (eb->path_tracker)
+ SVN_ERR_W(node_must_exist(eb, path, eb->current_rev,
+ svn_node_unknown, pool),
+ apr_psprintf(pool,
+ _("Replacing non-existent path '%s' in r%ld"),
+ path, eb->current_rev));
+
if (! is_copy)
{
+ if (eb->path_tracker)
+ tracker_path_replace(eb->path_tracker, path);
+
/* a simple delete+add, implied by a single 'replace' action. */
SVN_ERR(svn_stream_puts(eb->stream,
SVN_REPOS_DUMPFILE_NODE_ACTION
@@ -343,6 +714,20 @@ dump_node(struct edit_baton *eb,
}
else
{
+ if (eb->path_tracker)
+ {
+ SVN_ERR_W(node_must_exist(eb, compare_path, compare_rev,
+ kind, pool),
+ apr_psprintf(pool,
+ _("Replacing path '%s' in r%ld "
+ "with invalid path"),
+ path, eb->current_rev));
+
+ /* we will call dump_node again with an addition further
+ down the road */
+ tracker_path_delete(eb->path_tracker, path);
+ }
+
/* more complex: delete original, then add-with-history. */
/* the path & kind headers have already been printed; just
@@ -363,6 +748,14 @@ dump_node(struct edit_baton *eb,
}
else if (action == svn_node_action_delete)
{
+ if (eb->path_tracker)
+ {
+ SVN_ERR_W(node_must_exist(eb, path, eb->current_rev, kind, pool),
+ apr_psprintf(pool, _("Deleting invalid path '%s' in r%ld"),
+ path, eb->current_rev));
+ tracker_path_delete(eb->path_tracker, path);
+ }
+
SVN_ERR(svn_stream_puts(eb->stream,
SVN_REPOS_DUMPFILE_NODE_ACTION ": delete\n"));
@@ -373,11 +766,20 @@ dump_node(struct edit_baton *eb,
}
else if (action == svn_node_action_add)
{
+ if (eb->path_tracker)
+ SVN_ERR_W(node_must_not_exist(eb, path, eb->current_rev, pool),
+ apr_psprintf(pool,
+ _("Adding already existing path '%s' in r%ld"),
+ path, eb->current_rev));
+
SVN_ERR(svn_stream_puts(eb->stream,
SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
if (! is_copy)
{
+ if (eb->path_tracker)
+ tracker_path_add(eb->path_tracker, path);
+
/* Dump all contents for a simple 'add'. */
if (kind == svn_node_file)
must_dump_text = TRUE;
@@ -385,6 +787,18 @@ dump_node(struct edit_baton *eb,
}
else
{
+ if (eb->path_tracker)
+ {
+ SVN_ERR_W(node_must_exist(eb, compare_path, compare_rev,
+ kind, pool),
+ apr_psprintf(pool,
+ _("Copying from invalid path to "
+ "'%s' in r%ld"),
+ path, eb->current_rev));
+ tracker_path_copy(eb->path_tracker, path, compare_path,
+ compare_rev);
+ }
+
if (!eb->verify && cmp_rev < eb->oldest_dumped_rev
&& eb->notify_func)
{
@@ -995,6 +1409,14 @@ get_dump_editor(const svn_delta_editor_t
eb->found_old_mergeinfo = found_old_mergeinfo;
eb->verified_dirents_cache = verified_dirents_cache;
+ /* In non-verification mode, we will allow anything to be dumped because
+ it might be an incremental dump with possible manual intervention.
+ Also, this might be the last resort when it comes to data recovery.
+
+ Else, make sure that all paths exists at their respective revisions.
+ */
+ eb->path_tracker = verify ? tracker_create(to_rev, pool) : NULL;
+
/* Set up the editor. */
dump_editor->open_root = open_root;
dump_editor->delete_entry = delete_entry;
@@ -1313,7 +1735,7 @@ verify_directory_entry(void *baton, cons
type defined in the DIRENT. */
if (db->edit_baton->verified_dirents_cache)
{
- svn_node_kind_t kind;
+ svn_node_kind_t *kind;
svn_boolean_t found;
unparsed_id = svn_fs_unparse_id(dirent->id, pool);
@@ -1323,7 +1745,7 @@ verify_directory_entry(void *baton, cons
if (found)
{
- if (kind == dirent->kind)
+ if (*kind == dirent->kind)
return SVN_NO_ERROR;
else
{
@@ -1333,7 +1755,7 @@ verify_directory_entry(void *baton, cons
svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
_("Unexpected node kind %d for '%s'. "
"Expected kind was %d."),
- dirent->kind, path, kind);
+ dirent->kind, path, *kind);
}
}
}
@@ -1494,7 +1916,7 @@ deserialize_node_kind(void **out,
apr_size_t data_len,
apr_pool_t *pool)
{
- *(svn_node_kind_t *)out = *(svn_node_kind_t *)data;
+ *out = data;
return SVN_NO_ERROR;
}
Modified: subversion/branches/log-addressing/subversion/libsvn_repos/hooks.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_repos/hooks.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_repos/hooks.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_repos/hooks.c Wed Oct 30 01:33:37 2013
@@ -335,7 +335,7 @@ check_hook_cmd(const char *hook, svn_boo
for (extn = check_extns; *extn; ++extn)
{
const char *const hook_path =
- (**extn ? apr_pstrcat(pool, hook, *extn, (char *)NULL) : hook);
+ (**extn ? apr_pstrcat(pool, hook, *extn, SVN_VA_NULL) : hook);
svn_node_kind_t kind;
if (!(err = svn_io_check_resolved_path(hook_path, &kind, pool))
Modified: subversion/branches/log-addressing/subversion/libsvn_repos/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_repos/log.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_repos/log.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_repos/log.c Wed Oct 30 01:33:37 2013
@@ -42,7 +42,6 @@
#include "private/svn_mergeinfo_private.h"
#include "private/svn_subr_private.h"
-
svn_error_t *
svn_repos_check_revision_access(svn_repos_revision_access_level_t *access_level,
@@ -69,8 +68,7 @@ svn_repos_check_revision_access(svn_repo
/* Fetch the changes associated with REVISION. */
SVN_ERR(svn_fs_revision_root(&rev_root, fs, revision, pool));
- SVN_ERR(svn_fs_paths_changed3(&changes, rev_root,
- svn_move_behavior_explicit_moves, pool));
+ SVN_ERR(svn_fs_paths_changed2(&changes, rev_root, pool));
/* No changed paths? We're done. */
if (apr_hash_count(changes) == 0)
@@ -155,6 +153,147 @@ svn_repos_check_revision_access(svn_repo
return SVN_NO_ERROR;
}
+/* Return TRUE, if CHANGE deleted the node previously found at its target
+ path. */
+static svn_boolean_t
+is_deletion(svn_log_changed_path2_t *change)
+{
+ /* We need a 'N' action here ... */
+ return change->action == 'E'
+ || change->action == 'R'
+ || change->action == 'D';
+}
+
+/* Change all moves in CHANGES to ADD. Use POOL for temporary allocations.
+ */
+static void
+turn_moves_into_copies(apr_hash_t *changes,
+ apr_pool_t *pool)
+{
+ apr_hash_index_t *hi;
+ for (hi = apr_hash_first(pool, changes); hi; hi = apr_hash_next(hi))
+ {
+ const char *key;
+ apr_ssize_t klen;
+ svn_log_changed_path2_t *change;
+ apr_hash_this(hi, (const void **)&key, &klen, (void**)&change);
+
+ switch (change->action)
+ {
+ case 'V':
+ change->action = 'A';
+ break;
+
+ case 'E':
+ change->action = 'R';
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+/* Replace ADDs with MOVes, if they are unique, have a matching deletion
+ * and if the copy-from revision is REVISION-1. Use POOL for temporary
+ * allocations.
+ */
+static void
+turn_unique_copies_into_moves(apr_hash_t *changes,
+ svn_revnum_t revision,
+ apr_pool_t *pool)
+{
+ apr_hash_index_t *hi;
+ apr_hash_t *unique_copy_sources;
+ const char **sources;
+ int i;
+
+ /* find all copy-from paths (ADD and MOV alike) */
+
+ svn_boolean_t any_deletion = FALSE;
+ apr_array_header_t *copy_sources
+ = apr_array_make(pool, apr_hash_count(changes), sizeof(const char*));
+
+ for (hi = apr_hash_first(pool, changes); hi; hi = apr_hash_next(hi))
+ {
+ svn_log_changed_path2_t *change;
+ apr_hash_this(hi, NULL, NULL, (void**)&change);
+
+ if (change->copyfrom_path && change->copyfrom_rev == revision-1)
+ APR_ARRAY_PUSH(copy_sources, const char *)
+ = change->copyfrom_path;
+
+ any_deletion |= is_deletion(change);
+ }
+
+ /* no suitable copy-from or no deletion -> no moves */
+
+ if (!copy_sources->nelts || !any_deletion)
+ return;
+
+ /* identify copy-from paths that have been mentioned exactly once */
+
+ sources = (const char **)copy_sources->elts;
+ qsort(sources, copy_sources->nelts, copy_sources->elt_size,
+ (int (*)(const void *, const void *))svn_sort_compare_paths);
+
+ unique_copy_sources = apr_hash_make(pool);
+ for (i = 0; i < copy_sources->nelts; ++i)
+ if ( (i == 0 || strcmp(sources[i-1], sources[i]))
+ && (i == copy_sources->nelts-1 || strcmp(sources[i+1], sources[i])))
+ {
+ apr_hash_set(unique_copy_sources, sources[i],
+ APR_HASH_KEY_STRING, sources[i]);
+ }
+
+ /* no unique copy-from paths -> no moves */
+
+ if (!apr_hash_count(unique_copy_sources))
+ return;
+
+ /* Replace all additions, replacements with a unique copy-from path,
+ the correct copy-from rev and a matching deletion in this revision,
+ with moves and move-replacements, respectively. */
+
+ for (hi = apr_hash_first(pool, changes); hi; hi = apr_hash_next(hi))
+ {
+ const char *key;
+ apr_ssize_t klen;
+ svn_log_changed_path2_t *change, *copy_from_change;
+
+ apr_hash_this(hi, (const void **)&key, &klen, (void**)&change);
+ if ( change->copyfrom_rev != revision-1
+ || !change->copyfrom_path
+ || !apr_hash_get(unique_copy_sources, change->copyfrom_path,
+ APR_HASH_KEY_STRING))
+ continue;
+
+ copy_from_change = apr_hash_get(changes, change->copyfrom_path,
+ APR_HASH_KEY_STRING);
+ if (!copy_from_change || !is_deletion(copy_from_change))
+ continue;
+
+ /* There is a deletion of the ADD's copy-from path in *REVISION*.
+ This can either be the same as in REVISION-1 (o.k.) or must have
+ been replaced by some other node. However, that would imply that
+ it still got deleted as part of the replacement, i.e. both cases
+ are o.k. */
+
+ switch (change->action)
+ {
+ case 'A':
+ change->action = 'V';
+ break;
+
+ case 'R':
+ change->action = 'E';
+ break;
+
+ default:
+ break;
+ }
+ }
+}
/* Store as keys in CHANGED the paths of all node in ROOT that show a
* significant change. "Significant" means that the text or
@@ -201,7 +340,7 @@ detect_changed(apr_hash_t **changed,
*changed = svn_hash__make(pool);
if (changes == NULL)
- SVN_ERR(svn_fs_paths_changed3(&changes, root, move_behavior, pool));
+ SVN_ERR(svn_fs_paths_changed2(&changes, root, pool));
if (apr_hash_count(changes) == 0)
/* No paths changed in this revision? Uh, sure, I guess the
@@ -368,6 +507,23 @@ detect_changed(apr_hash_t **changed,
return svn_error_create(SVN_ERR_AUTHZ_UNREADABLE,
NULL, NULL);
+ /* at least some paths are readable. Post-process them. */
+ switch(move_behavior)
+ {
+ case svn_move_behavior_no_moves:
+ turn_moves_into_copies(*changed, pool);
+ break;
+
+ case svn_move_behavior_auto_moves:
+ turn_unique_copies_into_moves(*changed,
+ svn_fs_revision_root_revision(root),
+ pool);
+ break;
+
+ default:
+ break;
+ }
+
if (found_unreadable)
/* At least one changed-path was unreadable. */
return svn_error_create(SVN_ERR_AUTHZ_PARTIALLY_READABLE,
@@ -577,9 +733,7 @@ next_history_rev(const apr_array_header_
catalogs describing how mergeinfo values on paths (which are the
keys of those catalogs) were changed in REV. If *PREFETCHED_CAHNGES
already contains the changed paths for REV, use that. Otherwise,
- request that data and return it in *PREFETCHED_CHANGES.
- MOVE_BEHAVIOR is a simple pass-through parameter that tells the FS
- layer which changes to report as moves instead of additions. */
+ request that data and return it in *PREFETCHED_CHANGES. */
/* ### TODO: This would make a *great*, useful public function,
### svn_repos_fs_mergeinfo_changed()! -- cmpilato */
static svn_error_t *
@@ -588,7 +742,6 @@ fs_mergeinfo_changed(svn_mergeinfo_catal
apr_hash_t **prefetched_changes,
svn_fs_t *fs,
svn_revnum_t rev,
- svn_move_behavior_t move_behavior,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
@@ -609,8 +762,7 @@ fs_mergeinfo_changed(svn_mergeinfo_catal
narrow down our search. */
SVN_ERR(svn_fs_revision_root(&root, fs, rev, scratch_pool));
if (*prefetched_changes == NULL)
- SVN_ERR(svn_fs_paths_changed3(prefetched_changes, root, move_behavior,
- scratch_pool));
+ SVN_ERR(svn_fs_paths_changed2(prefetched_changes, root, scratch_pool));
/* No changed paths? We're done. */
if (apr_hash_count(*prefetched_changes) == 0)
@@ -802,9 +954,7 @@ fs_mergeinfo_changed(svn_mergeinfo_catal
*ADDED_MERGEINFO and deleted mergeinfo in *DELETED_MERGEINFO.
If *PREFETCHED_CAHNGES already contains the changed paths for
REV, use that. Otherwise, request that data and return it in
- *PREFETCHED_CHANGES. MOVE_BEHAVIOR tells the FS layer which
- changes to report as moves instead of additions.
- Use POOL for all allocations. */
+ *PREFETCHED_CHANGES. Use POOL for all allocations. */
static svn_error_t *
get_combined_mergeinfo_changes(svn_mergeinfo_t *added_mergeinfo,
svn_mergeinfo_t *deleted_mergeinfo,
@@ -812,7 +962,6 @@ get_combined_mergeinfo_changes(svn_merge
svn_fs_t *fs,
const apr_array_header_t *paths,
svn_revnum_t rev,
- svn_move_behavior_t move_behavior,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -842,7 +991,7 @@ get_combined_mergeinfo_changes(svn_merge
err = fs_mergeinfo_changed(&deleted_mergeinfo_catalog,
&added_mergeinfo_catalog,
prefetched_changes,
- fs, rev, move_behavior,
+ fs, rev,
scratch_pool, scratch_pool);
if (err)
{
@@ -2050,7 +2199,7 @@ do_logs(svn_fs_t *fs,
&deleted_mergeinfo,
&changes,
fs, cur_paths,
- current, move_behavior,
+ current,
iterpool, iterpool));
has_children = (apr_hash_count(added_mergeinfo) > 0
|| apr_hash_count(deleted_mergeinfo) > 0);
Modified: subversion/branches/log-addressing/subversion/libsvn_repos/reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_repos/reporter.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_repos/reporter.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_repos/reporter.c Wed Oct 30 01:33:37 2013
@@ -842,7 +842,7 @@ add_file_smartly(report_baton_t *b,
starting with '/', so make sure o_path always starts with a '/'
too. */
if (*o_path != '/')
- o_path = apr_pstrcat(pool, "/", o_path, (char *)NULL);
+ o_path = apr_pstrcat(pool, "/", o_path, SVN_VA_NULL);
SVN_ERR(svn_fs_closest_copy(&closest_copy_root, &closest_copy_path,
b->t_root, o_path, pool));
Modified: subversion/branches/log-addressing/subversion/libsvn_repos/rev_hunt.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_repos/rev_hunt.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_repos/rev_hunt.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_repos/rev_hunt.c Wed Oct 30 01:33:37 2013
@@ -661,7 +661,7 @@ svn_repos_trace_node_locations(svn_fs_t
/* Ensure that FS_PATH is absolute, because our path-math below will
depend on that being the case. */
if (*fs_path != '/')
- fs_path = apr_pstrcat(pool, "/", fs_path, (char *)NULL);
+ fs_path = apr_pstrcat(pool, "/", fs_path, SVN_VA_NULL);
/* Another sanity check. */
if (authz_read_func)
@@ -878,7 +878,7 @@ svn_repos_node_location_segments(svn_rep
/* Ensure that PATH is absolute, because our path-math will depend
on that being the case. */
if (*path != '/')
- path = apr_pstrcat(pool, "/", path, (char *)NULL);
+ path = apr_pstrcat(pool, "/", path, SVN_VA_NULL);
/* Auth check. */
if (authz_read_func)
@@ -942,7 +942,7 @@ svn_repos_node_location_segments(svn_rep
/* authz_read_func requires path to have a leading slash. */
const char *abs_path = apr_pstrcat(subpool, "/", segment->path,
- (char *)NULL);
+ SVN_VA_NULL);
SVN_ERR(svn_fs_revision_root(&cur_rev_root, fs,
segment->range_end, subpool));
Modified: subversion/branches/log-addressing/subversion/libsvn_subr/auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_subr/auth.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_subr/auth.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_subr/auth.c Wed Oct 30 01:33:37 2013
@@ -35,6 +35,7 @@
#include "svn_config.h"
#include "svn_dso.h"
#include "svn_version.h"
+#include "private/svn_auth_private.h"
#include "private/svn_dep_compat.h"
#include "auth.h"
@@ -194,7 +195,7 @@ make_cache_key(const char *cred_kind,
const char *realmstring,
apr_pool_t *pool)
{
- return apr_pstrcat(pool, cred_kind, ":", realmstring, (char *)NULL);
+ return apr_pstrcat(pool, cred_kind, ":", realmstring, SVN_VA_NULL);
}
svn_error_t *
@@ -542,6 +543,11 @@ svn_auth_get_platform_specific_provider(
{
svn_auth_get_windows_ssl_server_trust_provider(provider, pool);
}
+ else if (strcmp(provider_name, "windows") == 0 &&
+ strcmp(provider_type, "ssl_server_authority") == 0)
+ {
+ svn_auth__get_windows_ssl_server_authority_provider(provider, pool);
+ }
#endif
}
@@ -652,5 +658,22 @@ svn_auth_get_platform_specific_client_pr
}
}
+ /* Windows has two providers without a store to allow easy access to
+ SSL servers. We enable these unconditionally.
+ (This behavior was moved here from svn_cmdline_create_auth_baton()) */
+ SVN_ERR(svn_auth_get_platform_specific_provider(&provider,
+ "windows",
+ "ssl_server_trust",
+ pool));
+ SVN__MAYBE_ADD_PROVIDER(*providers, provider);
+
+ /* The windows ssl authority certificate CRYPTOAPI provider. */
+ SVN_ERR(svn_auth_get_platform_specific_provider(&provider,
+ "windows",
+ "ssl_server_authority",
+ pool));
+
+ SVN__MAYBE_ADD_PROVIDER(*providers, provider);
+
return SVN_NO_ERROR;
}
Modified: subversion/branches/log-addressing/subversion/libsvn_subr/cache-memcache.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_subr/cache-memcache.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_subr/cache-memcache.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_subr/cache-memcache.c Wed Oct 30 01:33:37 2013
@@ -99,7 +99,7 @@ build_key(const char **mc_key,
}
long_key = apr_pstrcat(pool, "SVN:", cache->prefix, ":", encoded_suffix,
- (char *)NULL);
+ SVN_VA_NULL);
long_key_len = strlen(long_key);
/* We don't want to have a key that's too big. If it was going to
@@ -120,7 +120,7 @@ build_key(const char **mc_key,
apr_pstrmemdup(pool, long_key,
MEMCACHED_KEY_UNHASHED_LEN),
svn_checksum_to_cstring_display(checksum, pool),
- (char *)NULL);
+ SVN_VA_NULL);
}
*mc_key = long_key;
Modified: subversion/branches/log-addressing/subversion/libsvn_subr/checksum.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_subr/checksum.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_subr/checksum.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_subr/checksum.c Wed Oct 30 01:33:37 2013
@@ -324,7 +324,7 @@ svn_checksum_serialize(const svn_checksu
return apr_pstrcat(result_pool,
ckind_str,
svn_checksum_to_cstring(checksum, scratch_pool),
- (char *)NULL);
+ SVN_VA_NULL);
}
Modified: subversion/branches/log-addressing/subversion/libsvn_subr/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_subr/cmdline.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_subr/cmdline.c Wed Oct 30 01:33:37 2013
@@ -34,6 +34,7 @@
#else
#include <crtdbg.h>
#include <io.h>
+#include <conio.h>
#endif
#include <apr.h> /* for STDIN_FILENO */
@@ -77,6 +78,14 @@ static const char *input_encoding = NULL
/* The stdout encoding. If null, it's the same as the native encoding. */
static const char *output_encoding = NULL;
+#elif defined(WIN32) && defined(_MSC_VER)
+/* For now limit this code to Visual C++, as the result is highly dependent
+ on the CRT implementation */
+#define USE_WIN32_CONSOLE_SHORTCUT
+
+/* When TRUE, stdout/stderr is directly connected to a console */
+static svn_boolean_t shortcut_stdout_to_console = FALSE;
+static svn_boolean_t shortcut_stderr_to_console = FALSE;
#endif
@@ -254,6 +263,31 @@ svn_cmdline_init(const char *progname, F
return EXIT_FAILURE;
}
+#ifdef USE_WIN32_CONSOLE_SHORTCUT
+ if (_isatty(STDOUT_FILENO))
+ {
+ DWORD ignored;
+ HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
+
+ /* stdout is a char device handle, but is it the console? */
+ if (GetConsoleMode(stdout_handle, &ignored))
+ shortcut_stdout_to_console = TRUE;
+
+ /* Don't close stdout_handle */
+ }
+ if (_isatty(STDERR_FILENO))
+ {
+ DWORD ignored;
+ HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
+
+ /* stderr is a char device handle, but is it the console? */
+ if (GetConsoleMode(stderr_handle, &ignored))
+ shortcut_stderr_to_console = TRUE;
+
+ /* Don't close stderr_handle */
+ }
+#endif
+
return EXIT_SUCCESS;
}
@@ -347,6 +381,45 @@ svn_cmdline_fputs(const char *string, FI
svn_error_t *err;
const char *out;
+#ifdef USE_WIN32_CONSOLE_SHORTCUT
+ /* For legacy reasons the Visual C++ runtime converts output to the console
+ from the native 'ansi' encoding, to unicode, then back to 'ansi' and then
+ onwards to the console which is implemented as unicode.
+
+ For operations like 'svn status -v' this may cause about 70% of the total
+ processing time, with absolutely no gain.
+
+ For this specific scenario this shortcut exists. It has the nice side
+ effect of allowing full unicode output to the console.
+
+ Note that this shortcut is not used when the output is redirected, as in
+ that case the data is put on the pipe/file after the first conversion to
+ ansi. In this case the most expensive conversion is already avoided.
+ */
+ if ((stream == stdout && shortcut_stdout_to_console)
+ || (stream == stderr && shortcut_stderr_to_console))
+ {
+ WCHAR *result;
+
+ if (string[0] == '\0')
+ return SVN_NO_ERROR;
+
+ SVN_ERR(svn_cmdline_fflush(stream)); /* Flush existing output */
+
+ SVN_ERR(svn_utf__win32_utf8_to_utf16(&result, string, NULL, pool));
+
+ if (_cputws(result))
+ {
+ if (apr_get_os_error())
+ {
+ return svn_error_wrap_apr(apr_get_os_error(), _("Write error"));
+ }
+ }
+
+ return SVN_NO_ERROR;
+ }
+#endif
+
err = svn_cmdline_cstring_from_utf8(&out, string, pool);
if (err)
@@ -518,15 +591,6 @@ svn_cmdline_create_auth_baton(svn_auth_b
svn_auth_get_username_provider(&provider, pool);
APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
- /* The server-cert, client-cert, and client-cert-password providers. */
- SVN_ERR(svn_auth_get_platform_specific_provider(&provider,
- "windows",
- "ssl_server_trust",
- pool));
-
- if (provider)
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
svn_auth_get_ssl_server_trust_file_provider(&provider, pool);
APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
svn_auth_get_ssl_client_cert_file_provider(&provider, pool);
Modified: subversion/branches/log-addressing/subversion/libsvn_subr/config.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_subr/config.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_subr/config.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_subr/config.c Wed Oct 30 01:33:37 2013
@@ -39,6 +39,7 @@
#include "config_impl.h"
#include "private/svn_dep_compat.h"
+#include "private/svn_subr_private.h"
@@ -264,9 +265,9 @@ get_category_config(svn_config_t **cfg,
{
#ifdef WIN32
sys_reg_path = apr_pstrcat(pool, SVN_REGISTRY_SYS_CONFIG_PATH,
- category, NULL);
+ category, SVN_VA_NULL);
usr_reg_path = apr_pstrcat(pool, SVN_REGISTRY_USR_CONFIG_PATH,
- category, NULL);
+ category, SVN_VA_NULL);
#endif /* WIN32 */
err = svn_config__sys_config_path(&sys_cfg_path, category, pool);
@@ -652,6 +653,33 @@ svn_config_create_option(cfg_option_t **
*opt = o;
}
+svn_boolean_t
+svn_config__is_expanded(svn_config_t *cfg,
+ const char *section,
+ const char *option)
+{
+ cfg_option_t *opt;
+
+ if (cfg == NULL)
+ return FALSE;
+
+ /* does the option even exist? */
+ opt = find_option(cfg, section, option, NULL);
+ if (opt == NULL)
+ return FALSE;
+
+ /* already expanded? */
+ if (opt->expanded)
+ return TRUE;
+
+ /* needs expansion? */
+ if (opt->value && strchr(opt->value, '%'))
+ return FALSE;
+
+ /* no expansion necessary */
+ return TRUE;
+}
+
void
svn_config_get(svn_config_t *cfg, const char **valuep,
@@ -701,7 +729,9 @@ svn_config_set(svn_config_t *cfg,
* Since we should never try to modify r/o data, trigger an assertion
* in debug mode.
*/
- assert(!cfg->read_only);
+#ifdef SVN_DEBUG
+ SVN_ERR_ASSERT_NO_RETURN(!cfg->read_only);
+#endif
if (cfg->read_only)
return;
Modified: subversion/branches/log-addressing/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_subr/config_file.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_subr/config_file.c Wed Oct 30 01:33:37 2013
@@ -395,7 +395,8 @@ svn_config__sys_config_path(const char *
const char *folder;
SVN_ERR(svn_config__win_config_path(&folder, TRUE, pool));
*path_p = svn_dirent_join_many(pool, folder,
- SVN_CONFIG__SUBDIRECTORY, fname, NULL);
+ SVN_CONFIG__SUBDIRECTORY, fname,
+ SVN_VA_NULL);
}
#elif defined(__HAIKU__)
@@ -408,11 +409,13 @@ svn_config__sys_config_path(const char *
return SVN_NO_ERROR;
*path_p = svn_dirent_join_many(pool, folder,
- SVN_CONFIG__SYS_DIRECTORY, fname, NULL);
+ SVN_CONFIG__SYS_DIRECTORY, fname,
+ SVN_VA_NULL);
}
#else /* ! WIN32 && !__HAIKU__ */
- *path_p = svn_dirent_join_many(pool, SVN_CONFIG__SYS_DIRECTORY, fname, NULL);
+ *path_p = svn_dirent_join_many(pool, SVN_CONFIG__SYS_DIRECTORY, fname,
+ SVN_VA_NULL);
#endif /* WIN32 */
@@ -460,6 +463,12 @@ svn_config__set_read_only(svn_config_t *
cfg->read_only = TRUE;
}
+svn_boolean_t
+svn_config__is_read_only(svn_config_t *cfg)
+{
+ return cfg->read_only;
+}
+
svn_error_t *
@@ -1303,7 +1312,7 @@ svn_config_get_user_config_path(const ch
if (config_dir)
{
- *path = svn_dirent_join_many(pool, config_dir, fname, NULL);
+ *path = svn_dirent_join_many(pool, config_dir, fname, SVN_VA_NULL);
return SVN_NO_ERROR;
}
@@ -1312,7 +1321,7 @@ svn_config_get_user_config_path(const ch
const char *folder;
SVN_ERR(svn_config__win_config_path(&folder, FALSE, pool));
*path = svn_dirent_join_many(pool, folder,
- SVN_CONFIG__SUBDIRECTORY, fname, NULL);
+ SVN_CONFIG__SUBDIRECTORY, fname, SVN_VA_NULL);
}
#elif defined(__HAIKU__)
@@ -1325,7 +1334,8 @@ svn_config_get_user_config_path(const ch
return SVN_NO_ERROR;
*path = svn_dirent_join_many(pool, folder,
- SVN_CONFIG__USR_DIRECTORY, fname, NULL);
+ SVN_CONFIG__USR_DIRECTORY, fname,
+ SVN_VA_NULL);
}
#else /* ! WIN32 && !__HAIKU__ */
@@ -1335,7 +1345,7 @@ svn_config_get_user_config_path(const ch
return SVN_NO_ERROR;
*path = svn_dirent_join_many(pool,
svn_dirent_canonicalize(homedir, pool),
- SVN_CONFIG__USR_DIRECTORY, fname, NULL);
+ SVN_CONFIG__USR_DIRECTORY, fname, SVN_VA_NULL);
}
#endif /* WIN32 */
Modified: subversion/branches/log-addressing/subversion/libsvn_subr/config_win.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_subr/config_win.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_subr/config_win.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_subr/config_win.c Wed Oct 30 01:33:37 2013
@@ -44,10 +44,11 @@
#include "svn_path.h"
#include "svn_pools.h"
#include "svn_utf.h"
+#include "private/svn_utf_private.h"
svn_error_t *
svn_config__win_config_path(const char **folder, int system_path,
- apr_pool_t *pool)
+ apr_pool_t *result_pool)
{
/* ### Adding CSIDL_FLAG_CREATE here, because those folders really
must exist. I'm not too sure about the SHGFP_TYPE_CURRENT
@@ -56,8 +57,6 @@ svn_config__win_config_path(const char *
| CSIDL_FLAG_CREATE);
WCHAR folder_ucs2[MAX_PATH];
- int inwords, outbytes, outlength;
- char *folder_utf8;
if (S_OK != SHGetFolderPathW(NULL, csidl, NULL, SHGFP_TYPE_CURRENT,
folder_ucs2))
@@ -66,26 +65,8 @@ svn_config__win_config_path(const char *
? "Can't determine the system config path"
: "Can't determine the user's config path"));
- /* ### When mapping from UCS-2 to UTF-8, we need at most 3 bytes
- per wide char, plus extra space for the nul terminator. */
- inwords = lstrlenW(folder_ucs2);
- outbytes = outlength = 3 * (inwords + 1);
-
- folder_utf8 = apr_palloc(pool, outlength);
-
- outbytes = WideCharToMultiByte(CP_UTF8, 0, folder_ucs2, inwords,
- folder_utf8, outbytes, NULL, NULL);
-
- if (outbytes == 0)
- return svn_error_wrap_apr(apr_get_os_error(),
- "Can't convert config path to UTF-8");
-
- /* Note that WideCharToMultiByte does _not_ terminate the
- outgoing buffer. */
- folder_utf8[outbytes] = '\0';
- *folder = folder_utf8;
-
- return SVN_NO_ERROR;
+ return svn_error_trace(svn_utf__win32_utf16_to_utf8(folder, folder_ucs2,
+ NULL, result_pool));
}
@@ -97,6 +78,8 @@ svn_config__win_config_path(const char *
#define SVN_REG_DEFAULT_NAME_SIZE 2048
#define SVN_REG_DEFAULT_VALUE_SIZE 8192
+/* ### This function should be converted to use the unicode functions
+ ### instead of the ansi functions */
static svn_error_t *
parse_section(svn_config_t *cfg, HKEY hkey, const char *section,
svn_stringbuf_t *option, svn_stringbuf_t *value)
Modified: subversion/branches/log-addressing/subversion/libsvn_subr/dirent_uri.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_subr/dirent_uri.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_subr/dirent_uri.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_subr/dirent_uri.c Wed Oct 30 01:33:37 2013
@@ -2398,7 +2398,7 @@ svn_uri_get_dirent_from_file_url(const c
"no path"), url);
/* We still know that the path starts with a slash. */
- *dirent = apr_pstrcat(pool, "//", hostname, dup_path, NULL);
+ *dirent = apr_pstrcat(pool, "//", hostname, dup_path, SVN_VA_NULL);
}
else
*dirent = dup_path;
@@ -2431,18 +2431,18 @@ svn_uri_get_file_url_from_dirent(const c
if (dirent[0] == '/' && dirent[1] == '\0')
dirent = NULL; /* "file://" is the canonical form of "file:///" */
- *url = apr_pstrcat(pool, "file://", dirent, (char *)NULL);
+ *url = apr_pstrcat(pool, "file://", dirent, SVN_VA_NULL);
#else
if (dirent[0] == '/')
{
/* Handle UNC paths //server/share -> file://server/share */
assert(dirent[1] == '/'); /* Expect UNC, not non-absolute */
- *url = apr_pstrcat(pool, "file:", dirent, NULL);
+ *url = apr_pstrcat(pool, "file:", dirent, SVN_VA_NULL);
}
else
{
- char *uri = apr_pstrcat(pool, "file:///", dirent, NULL);
+ char *uri = apr_pstrcat(pool, "file:///", dirent, SVN_VA_NULL);
apr_size_t len = 8 /* strlen("file:///") */ + strlen(dirent);
/* "C:/" is a canonical dirent on Windows,
@@ -2476,7 +2476,7 @@ svn_fspath__canonicalize(const char *fsp
return "/";
return apr_pstrcat(pool, "/", svn_relpath_canonicalize(fspath, pool),
- (char *)NULL);
+ SVN_VA_NULL);
}
@@ -2509,7 +2509,7 @@ svn_fspath__dirname(const char *fspath,
return apr_pstrdup(pool, fspath);
else
return apr_pstrcat(pool, "/", svn_relpath_dirname(fspath + 1, pool),
- (char *)NULL);
+ SVN_VA_NULL);
}
@@ -2553,9 +2553,9 @@ svn_fspath__join(const char *fspath,
if (relpath[0] == '\0')
result = apr_pstrdup(result_pool, fspath);
else if (fspath[1] == '\0')
- result = apr_pstrcat(result_pool, "/", relpath, (char *)NULL);
+ result = apr_pstrcat(result_pool, "/", relpath, SVN_VA_NULL);
else
- result = apr_pstrcat(result_pool, fspath, "/", relpath, (char *)NULL);
+ result = apr_pstrcat(result_pool, fspath, "/", relpath, SVN_VA_NULL);
assert(svn_fspath__is_canonical(result));
return result;
@@ -2574,7 +2574,7 @@ svn_fspath__get_longest_ancestor(const c
svn_relpath_get_longest_ancestor(fspath1 + 1,
fspath2 + 1,
result_pool),
- (char *)NULL);
+ SVN_VA_NULL);
assert(svn_fspath__is_canonical(result));
return result;
Modified: subversion/branches/log-addressing/subversion/libsvn_subr/error.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_subr/error.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_subr/error.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_subr/error.c Wed Oct 30 01:33:37 2013
@@ -202,7 +202,8 @@ svn_error_wrap_apr(apr_status_t status,
va_end(ap);
if (msg_apr)
{
- err->message = apr_pstrcat(err->pool, msg, ": ", msg_apr, NULL);
+ err->message = apr_pstrcat(err->pool, msg, ": ", msg_apr,
+ SVN_VA_NULL);
}
else
{
Modified: subversion/branches/log-addressing/subversion/libsvn_subr/file.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_subr/file.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_subr/file.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_subr/file.c Wed Oct 30 01:33:37 2013
@@ -184,7 +184,7 @@ reclaim_shared_handle(shared_handle_pool
shared_handle_t *) = NULL;
/* implicitly closes the file */
- apr_pool_clear(result->pool);
+ svn_pool_clear(result->pool);
return result;
}
@@ -331,7 +331,7 @@ close_handle(shared_handle_pool_t *handl
shared_handle_t *handle)
{
/* implicitly closes the file */
- apr_pool_clear(handle->pool);
+ svn_pool_clear(handle->pool);
handle_pool->last_open = handle->previous;
handle->next = handle_pool->first_unused;
Modified: subversion/branches/log-addressing/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_subr/io.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_subr/io.c Wed Oct 30 01:33:37 2013
@@ -47,10 +47,6 @@
#include <apr_portable.h>
#include <apr_md5.h>
-#ifdef WIN32
-#include <arch/win32/apr_arch_file_io.h>
-#endif
-
#if APR_HAVE_FCNTL_H
#include <fcntl.h>
#endif
@@ -70,6 +66,8 @@
#include "private/svn_atomic.h"
#include "private/svn_io_private.h"
+#include "private/svn_utf_private.h"
+#include "private/svn_dep_compat.h"
#define SVN_SLEEP_ENV_VAR "SVN_I_LOVE_CORRUPTED_WORKING_COPIES_SO_DISABLE_SLEEP_FOR_TIMESTAMPS"
@@ -150,7 +148,7 @@ static volatile svn_atomic_t win_dynamic
/* Pointer to GetFinalPathNameByHandleW function from kernel32.dll. */
typedef DWORD (WINAPI *GETFINALPATHNAMEBYHANDLE)(
HANDLE hFile,
- apr_wchar_t *lpszFilePath,
+ WCHAR *lpszFilePath,
DWORD cchFilePath,
DWORD dwFlags);
@@ -1693,27 +1691,13 @@ io_set_file_perms(const char *path,
#endif /* !WIN32 && !__OS2__ */
#ifdef WIN32
-#if APR_HAS_UNICODE_FS
-/* copy of the apr function utf8_to_unicode_path since apr doesn't export this one */
-static apr_status_t io_utf8_to_unicode_path(apr_wchar_t* retstr, apr_size_t retlen,
- const char* srcstr)
-{
- /* TODO: The computations could preconvert the string to determine
- * the true size of the retstr, but that's a memory over speed
- * tradeoff that isn't appropriate this early in development.
- *
- * Allocate the maximum string length based on leading 4
- * characters of \\?\ (allowing nearly unlimited path lengths)
- * plus the trailing null, then transform /'s into \\'s since
- * the \\?\ form doesn't allow '/' path separators.
- *
- * Note that the \\?\ form only works for local drive paths, and
- * \\?\UNC\ is needed UNC paths.
- */
- apr_size_t srcremains = strlen(srcstr) + 1;
- apr_wchar_t *t = retstr;
- apr_status_t rv;
-
+/* This is semantically the same as the APR utf8_to_unicode_path
+ function, but reimplemented here because APR does not export it. */
+static svn_error_t*
+io_utf8_to_unicode_path(const WCHAR **result,
+ const char *source,
+ apr_pool_t *result_pool)
+{
/* This is correct, we don't twist the filename if it will
* definitely be shorter than 248 characters. It merits some
* performance testing to see if this has any effect, but there
@@ -1728,132 +1712,119 @@ static apr_status_t io_utf8_to_unicode_p
* Note that a utf-8 name can never result in more wide chars
* than the original number of utf-8 narrow chars.
*/
- if (srcremains > 248) {
- if (srcstr[1] == ':' && (srcstr[2] == '/' || srcstr[2] == '\\')) {
- wcscpy (retstr, L"\\\\?\\");
- retlen -= 4;
- t += 4;
- }
- else if ((srcstr[0] == '/' || srcstr[0] == '\\')
- && (srcstr[1] == '/' || srcstr[1] == '\\')
- && (srcstr[2] != '?')) {
- /* Skip the slashes */
- srcstr += 2;
- srcremains -= 2;
- wcscpy (retstr, L"\\\\?\\UNC\\");
- retlen -= 8;
- t += 8;
+ const WCHAR *prefix = NULL;
+ const int srclen = strlen(source);
+ WCHAR *buffer;
+
+ if (srclen > 248)
+ {
+ if (svn_ctype_isalpha(source[0]) && source[1] == ':'
+ && (source[2] == '/' || source[2] == '\\'))
+ {
+ /* This is an ordinary absolute path. */
+ prefix = L"\\\\?\\";
+ }
+ else if ((source[0] == '/' || source[0] == '\\')
+ && (source[1] == '/' || source[1] == '\\')
+ && source[2] != '?')
+ {
+ /* This is a UNC path */
+ source += 2; /* Skip the leading slashes */
+ prefix = L"\\\\?\\UNC\\";
}
}
- if (rv = apr_conv_utf8_to_ucs2(srcstr, &srcremains, t, &retlen)) {
- return (rv == APR_INCOMPLETE) ? APR_EINVAL : rv;
- }
- if (srcremains) {
- return APR_ENAMETOOLONG;
- }
- for (; *t; ++t)
- if (*t == L'/')
- *t = L'\\';
- return APR_SUCCESS;
-}
-
-/* copy of the apr function unicode_to_utf8_path since apr doesn't export this
- * one */
-static apr_status_t io_unicode_to_utf8_path(char* retstr, apr_size_t retlen,
- const apr_wchar_t* srcstr)
-{
+ SVN_ERR(svn_utf__win32_utf8_to_utf16(&(const WCHAR*)buffer, source,
+ prefix, result_pool));
+
+ /* Convert slashes to backslashes because the \\?\ path format
+ does not allow backslashes as path separators. */
+ *result = buffer;
+ for (; *buffer; ++buffer)
+ {
+ if (*buffer == '/')
+ *buffer = '\\';
+ }
+ return SVN_NO_ERROR;
+}
+
+/* This is semantically the same as the APR unicode_to_utf8_path
+ function, but reimplemented here because APR does not export it. */
+static svn_error_t *
+io_unicode_to_utf8_path(const char **result,
+ const WCHAR *source,
+ apr_pool_t *result_pool)
+{
+ const char *utf8_buffer;
+ char *buffer;
+
+ SVN_ERR(svn_utf__win32_utf16_to_utf8(&utf8_buffer, source,
+ NULL, result_pool));
+ if (!*utf8_buffer)
+ {
+ *result = utf8_buffer;
+ return SVN_NO_ERROR;
+ }
+
+ /* We know that the non-empty buffer returned from the UTF-16 to
+ UTF-8 conversion function is in fact writable. */
+ buffer = (char*)utf8_buffer;
+
/* Skip the leading 4 characters if the path begins \\?\, or substitute
* // for the \\?\UNC\ path prefix, allocating the maximum string
* length based on the remaining string, plus the trailing null.
* then transform \\'s back into /'s since the \\?\ form never
* allows '/' path seperators, and APR always uses '/'s.
*/
- apr_size_t srcremains = wcslen(srcstr) + 1;
- apr_status_t rv;
- char *t = retstr;
- if (srcstr[0] == L'\\' && srcstr[1] == L'\\' &&
- srcstr[2] == L'?' && srcstr[3] == L'\\') {
- if (srcstr[4] == L'U' && srcstr[5] == L'N' &&
- srcstr[6] == L'C' && srcstr[7] == L'\\') {
- srcremains -= 8;
- srcstr += 8;
- retstr[0] = '\\';
- retstr[1] = '\\';
- retlen -= 2;
- t += 2;
- }
- else {
- srcremains -= 4;
- srcstr += 4;
- }
- }
-
- if ((rv = apr_conv_ucs2_to_utf8(srcstr, &srcremains, t, &retlen))) {
- return rv;
- }
- if (srcremains) {
- return APR_ENAMETOOLONG;
- }
- return APR_SUCCESS;
+ if (0 == strncmp(buffer, "\\\\?\\", 4))
+ {
+ buffer += 4;
+ if (0 == strncmp(buffer, "UNC\\", 4))
+ {
+ buffer += 2;
+ *buffer = '/';
+ }
+ }
+
+ *result = buffer;
+ for (; *buffer; ++buffer)
+ {
+ if (*buffer == '\\')
+ *buffer = '/';
+ }
+ return SVN_NO_ERROR;
}
-#endif
-static apr_status_t io_win_file_attrs_set(const char *fname,
- DWORD attributes,
- DWORD attr_mask,
- apr_pool_t *pool)
+static svn_error_t *
+io_win_file_attrs_set(const char *fname,
+ DWORD attributes,
+ DWORD attr_mask,
+ apr_pool_t *pool)
{
/* this is an implementation of apr_file_attrs_set() but one
that uses the proper Windows attributes instead of the apr
attributes. This way, we can apply any Windows file and
folder attributes even if apr doesn't implement them */
DWORD flags;
- apr_status_t rv;
-#if APR_HAS_UNICODE_FS
- apr_wchar_t wfname[APR_PATH_MAX];
-#endif
+ const WCHAR *wfname;
-#if APR_HAS_UNICODE_FS
- IF_WIN_OS_IS_UNICODE
- {
- if (rv = io_utf8_to_unicode_path(wfname,
- sizeof(wfname) / sizeof(wfname[0]),
- fname))
- return rv;
- flags = GetFileAttributesW(wfname);
- }
-#endif
-#if APR_HAS_ANSI_FS
- ELSE_WIN_OS_IS_ANSI
- {
- flags = GetFileAttributesA(fname);
- }
-#endif
+ SVN_ERR(io_utf8_to_unicode_path(&wfname, fname, pool));
+ flags = GetFileAttributesW(wfname);
if (flags == 0xFFFFFFFF)
- return apr_get_os_error();
+ return svn_error_wrap_apr(apr_get_os_error(),
+ _("Can't get attributes of file '%s'"),
+ svn_dirent_local_style(fname, pool));
flags &= ~attr_mask;
flags |= (attributes & attr_mask);
-#if APR_HAS_UNICODE_FS
- IF_WIN_OS_IS_UNICODE
- {
- rv = SetFileAttributesW(wfname, flags);
- }
-#endif
-#if APR_HAS_ANSI_FS
- ELSE_WIN_OS_IS_ANSI
- {
- rv = SetFileAttributesA(fname, flags);
- }
-#endif
-
- if (rv == 0)
- return apr_get_os_error();
+ if (!SetFileAttributesW(wfname, flags))
+ return svn_error_wrap_apr(apr_get_os_error(),
+ _("Can't set attributes of file '%s'"),
+ svn_dirent_local_style(fname, pool));
- return APR_SUCCESS;
+ return SVN_NO_ERROR;;
}
static svn_error_t *win_init_dynamic_imports(void *baton, apr_pool_t *pool)
@@ -1869,7 +1840,6 @@ static svn_error_t * io_win_read_link(sv
const char *path,
apr_pool_t *pool)
{
-#if APR_HAS_UNICODE_FS
SVN_ERR(svn_atomic__init_once(&win_dynamic_imports_state,
win_init_dynamic_imports, NULL, pool));
@@ -1879,8 +1849,8 @@ static svn_error_t * io_win_read_link(sv
apr_status_t status;
apr_file_t *file;
apr_os_file_t filehand;
- apr_wchar_t wdest[APR_PATH_MAX];
- char buf[APR_PATH_MAX];
+ WCHAR wdest[APR_PATH_MAX];
+ const char *data;
/* reserve one char for terminating zero. */
DWORD wdest_len = sizeof(wdest)/sizeof(wdest[0]) - 1;
@@ -1914,18 +1884,20 @@ static svn_error_t * io_win_read_link(sv
/* GetFinaPathNameByHandleW doesn't add terminating NUL. */
wdest[rv] = 0;
+ SVN_ERR(io_unicode_to_utf8_path(&data, wdest, pool));
- status = io_unicode_to_utf8_path(buf, sizeof(buf), wdest);
- if (status)
- return svn_error_wrap_apr(status,
- _("Can't read contents of link"));
-
- *dest = svn_string_create(buf, pool);
+ /* The result is already in the correct pool, so avoid copying
+ it to create the string. */
+ *dest = svn_string_create_empty(pool);
+ if (*data)
+ {
+ (*dest)->data = data;
+ (*dest)->len = strlen(data);
+ }
return SVN_NO_ERROR;
}
else
-#endif
{
return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
_("Symbolic links are not supported on this "
@@ -1933,7 +1905,7 @@ static svn_error_t * io_win_read_link(sv
}
}
-#endif
+#endif /* WIN32 */
svn_error_t *
svn_io_set_file_read_write_carefully(const char *path,
@@ -3199,7 +3171,8 @@ svn_io_run_diff3_3(int *exitcode,
svn_config_get(cfg, &diff_cmd, SVN_CONFIG_SECTION_HELPERS,
SVN_CONFIG_OPTION_DIFF_CMD, SVN_CLIENT_DIFF);
SVN_ERR(cstring_to_utf8(&diff_utf8, diff_cmd, pool));
- args[i++] = apr_pstrcat(pool, "--diff-program=", diff_utf8, NULL);
+ args[i++] = apr_pstrcat(pool, "--diff-program=", diff_utf8,
+ SVN_VA_NULL);
#ifndef NDEBUG
++nargs;
#endif
@@ -4081,22 +4054,26 @@ dir_make(const char *path, apr_fileperms
APR_FILE_ATTR_HIDDEN,
APR_FILE_ATTR_HIDDEN,
pool);
-#else
- /* on Windows, use our wrapper so we can also set the
- FILE_ATTRIBUTE_NOT_CONTENT_INDEXED attribute */
- status = io_win_file_attrs_set(path_apr,
- FILE_ATTRIBUTE_HIDDEN |
- FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
- FILE_ATTRIBUTE_HIDDEN |
- FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
- pool);
-
-#endif
if (status)
return svn_error_wrap_apr(status, _("Can't hide directory '%s'"),
svn_dirent_local_style(path, pool));
+#else
+ /* on Windows, use our wrapper so we can also set the
+ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED attribute */
+ svn_error_t *err =
+ io_win_file_attrs_set(path_apr,
+ FILE_ATTRIBUTE_HIDDEN |
+ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
+ FILE_ATTRIBUTE_HIDDEN |
+ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
+ pool);
+ if (err)
+ return svn_error_createf(err->apr_err, err,
+ _("Can't hide directory '%s'"),
+ svn_dirent_local_style(path, pool));
+#endif /* WIN32 */
}
-#endif
+#endif /* APR_FILE_ATTR_HIDDEN */
/* Windows does not implement sgid. Skip here because retrieving
the file permissions via APR_FINFO_PROT | APR_FINFO_OWNER is documented
Modified: subversion/branches/log-addressing/subversion/libsvn_subr/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_subr/log.c?rev=1536950&r1=1536949&r2=1536950&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_subr/log.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_subr/log.c Wed Oct 30 01:33:37 2013
@@ -45,7 +45,7 @@ log_depth(svn_depth_t depth, apr_pool_t
{
if (depth == svn_depth_unknown)
return "";
- return apr_pstrcat(pool, " depth=", svn_depth_to_word(depth), (char *)NULL);
+ return apr_pstrcat(pool, " depth=", svn_depth_to_word(depth), SVN_VA_NULL);
}
static const char *