You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/05/16 22:32:54 UTC
svn commit: r1339349 [20/37] - in /subversion/branches/fix-rdump-editor: ./
build/ build/ac-macros/ build/generator/ build/generator/templates/
build/win32/ contrib/client-side/emacs/ contrib/client-side/vim/
contrib/server-side/ notes/ notes/api-errat...
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_ra_serf/xml.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_ra_serf/xml.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_ra_serf/xml.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_ra_serf/xml.c Wed May 16 20:32:43 2012
@@ -24,9 +24,6 @@
#include <apr_uri.h>
-
-#include <expat.h>
-
#include <serf.h>
#include "svn_pools.h"
@@ -37,121 +34,183 @@
#include "svn_config.h"
#include "svn_delta.h"
#include "svn_path.h"
+
#include "svn_private_config.h"
+#include "private/svn_string_private.h"
#include "ra_serf.h"
-void
-svn_ra_serf__define_ns(svn_ra_serf__ns_t **ns_list,
- const char **attrs,
- apr_pool_t *pool)
+struct svn_ra_serf__xml_context_t {
+ /* Current state information. */
+ svn_ra_serf__xml_estate_t *current;
+
+ /* If WAITING.NAMESPACE != NULL, wait for NAMESPACE:NAME element to be
+ closed before looking for transitions from CURRENT->STATE. */
+ svn_ra_serf__dav_props_t waiting;
+
+ /* The transition table. */
+ const svn_ra_serf__xml_transition_t *ttable;
+
+ /* The callback information. */
+ svn_ra_serf__xml_opened_t opened_cb;
+ svn_ra_serf__xml_closed_t closed_cb;
+ void *baton;
+
+ /* Linked list of free states. */
+ svn_ra_serf__xml_estate_t *free_states;
+
+#ifdef SVN_DEBUG
+ /* Used to verify we are not re-entering a callback, specifically to
+ ensure SCRATCH_POOL is not cleared while an outer callback is
+ trying to use it. */
+ svn_boolean_t within_callback;
+#define START_CALLBACK(xmlctx) \
+ do { \
+ svn_ra_serf__xml_context_t *xmlctx__tmp = (xmlctx); \
+ SVN_ERR_ASSERT(!xmlctx__tmp->within_callback); \
+ xmlctx__tmp->within_callback = TRUE; \
+ } while (0)
+#define END_CALLBACK(xmlctx) ((xmlctx)->within_callback = FALSE)
+#else
+#define START_CALLBACK(xmlctx) /* empty */
+#define END_CALLBACK(xmlctx) /* empty */
+#endif /* SVN_DEBUG */
+
+ apr_pool_t *scratch_pool;
+
+};
+
+struct svn_ra_serf__xml_estate_t {
+ /* The current state value. */
+ int state;
+
+ /* The xml tag that opened this state. Waiting for the tag to close. */
+ svn_ra_serf__dav_props_t tag;
+
+ /* Should the CLOSED_CB function be called for custom processing when
+ this tag is closed? */
+ svn_boolean_t custom_close;
+
+ /* A pool may be constructed for this state. */
+ apr_pool_t *state_pool;
+
+ /* The namespaces extent for this state/element. This will start with
+ the parent's NS_LIST, and we will push new namespaces into our
+ local list. The parent will be unaffected by our locally-scoped data. */
+ svn_ra_serf__ns_t *ns_list;
+
+ /* Any collected attribute values. char * -> svn_string_t *. May be NULL
+ if no attributes have been collected. */
+ apr_hash_t *attrs;
+
+ /* Any collected cdata. May be NULL if no cdata is being collected. */
+ svn_stringbuf_t *cdata;
+
+ /* Previous/outer state. */
+ svn_ra_serf__xml_estate_t *prev;
+
+};
+
+
+static void
+define_namespaces(svn_ra_serf__ns_t **ns_list,
+ const char *const *attrs,
+ apr_pool_t *(*get_pool)(void *baton),
+ void *baton)
{
- const char **tmp_attrs = attrs;
+ const char *const *tmp_attrs = attrs;
- while (*tmp_attrs)
+ for (tmp_attrs = attrs; *tmp_attrs != NULL; tmp_attrs += 2)
{
if (strncmp(*tmp_attrs, "xmlns", 5) == 0)
{
- svn_ra_serf__ns_t *new_ns, *cur_ns;
- int found = 0;
+ const svn_ra_serf__ns_t *cur_ns;
+ svn_boolean_t found = FALSE;
+ const char *prefix;
+
+ /* The empty prefix, or a named-prefix. */
+ if (tmp_attrs[0][5] == ':')
+ prefix = &tmp_attrs[0][6];
+ else
+ prefix = "";
/* Have we already defined this ns previously? */
for (cur_ns = *ns_list; cur_ns; cur_ns = cur_ns->next)
{
- if (strcmp(cur_ns->namespace, tmp_attrs[0] + 6) == 0)
+ if (strcmp(cur_ns->namespace, prefix) == 0)
{
- found = 1;
+ found = TRUE;
break;
}
}
if (!found)
{
+ apr_pool_t *pool;
+ svn_ra_serf__ns_t *new_ns;
+
+ if (get_pool)
+ pool = get_pool(baton);
+ else
+ pool = baton;
new_ns = apr_palloc(pool, sizeof(*new_ns));
- new_ns->namespace = apr_pstrdup(pool, tmp_attrs[0] + 6);
+ new_ns->namespace = apr_pstrdup(pool, prefix);
new_ns->url = apr_pstrdup(pool, tmp_attrs[1]);
+ /* Push into the front of NS_LIST. Parent states will point
+ to later in the chain, so will be unaffected by
+ shadowing/other namespaces pushed onto NS_LIST. */
new_ns->next = *ns_list;
-
*ns_list = new_ns;
}
}
- tmp_attrs += 2;
}
}
+
+void
+svn_ra_serf__define_ns(svn_ra_serf__ns_t **ns_list,
+ const char *const *attrs,
+ apr_pool_t *result_pool)
+{
+ define_namespaces(ns_list, attrs, NULL /* get_pool */, result_pool);
+}
+
+
/*
* Look up NAME in the NS_LIST list for previously declared namespace
* definitions and return a DAV_PROPS_T-tuple that has values.
*/
void
svn_ra_serf__expand_ns(svn_ra_serf__dav_props_t *returned_prop_name,
- svn_ra_serf__ns_t *ns_list,
+ const svn_ra_serf__ns_t *ns_list,
const char *name)
{
const char *colon;
- svn_ra_serf__dav_props_t prop_name;
colon = strchr(name, ':');
if (colon)
{
- svn_ra_serf__ns_t *ns;
-
- prop_name.namespace = NULL;
+ const svn_ra_serf__ns_t *ns;
for (ns = ns_list; ns; ns = ns->next)
{
if (strncmp(ns->namespace, name, colon - name) == 0)
{
- prop_name.namespace = ns->url;
- break;
+ returned_prop_name->namespace = ns->url;
+ returned_prop_name->name = colon + 1;
+ return;
}
}
-
- SVN_ERR_ASSERT_NO_RETURN(prop_name.namespace);
-
- prop_name.name = colon + 1;
- }
- else
- {
- /* use default namespace for now */
- prop_name.namespace = "";
- prop_name.name = name;
}
- *returned_prop_name = prop_name;
- return;
+ /* If there is no prefix, or if the prefix is not found, then the
+ name is NOT within a namespace. */
+ returned_prop_name->namespace = "";
+ returned_prop_name->name = name;
}
-void
-svn_ra_serf__expand_string(const char **cur, apr_size_t *cur_len,
- const char *new, apr_size_t new_len,
- apr_pool_t *pool)
-{
- if (!*cur)
- {
- *cur = apr_pstrmemdup(pool, new, new_len);
- *cur_len = new_len;
- }
- else
- {
- char *new_cur;
-
- /* append the data we received before. */
- new_cur = apr_palloc(pool, *cur_len + new_len + 1);
-
- memcpy(new_cur, *cur, *cur_len);
- memcpy(new_cur + *cur_len, new, new_len);
-
- /* NULL-term our new string */
- new_cur[*cur_len + new_len] = '\0';
-
- /* update our length */
- *cur_len += new_len;
- *cur = new_cur;
- }
-}
#define XML_HEADER "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
@@ -350,3 +409,344 @@ void svn_ra_serf__xml_pop_state(svn_ra_s
cur_state->prev = parser->free_state;
parser->free_state = cur_state;
}
+
+
+/* Return a pool for XES to use for self-alloc (and other specifics). */
+static apr_pool_t *
+xes_pool(const svn_ra_serf__xml_estate_t *xes)
+{
+ /* Move up through parent states looking for one with a pool. This
+ will always terminate since the initial state has a pool. */
+ while (xes->state_pool == NULL)
+ xes = xes->prev;
+ return xes->state_pool;
+}
+
+
+static void
+ensure_pool(svn_ra_serf__xml_estate_t *xes)
+{
+ if (xes->state_pool == NULL)
+ xes->state_pool = svn_pool_create(xes_pool(xes));
+}
+
+
+/* This callback is used by define_namespaces() to wait until a pool is
+ required before constructing it. */
+static apr_pool_t *
+lazy_create_pool(void *baton)
+{
+ svn_ra_serf__xml_estate_t *xes = baton;
+
+ ensure_pool(xes);
+ return xes->state_pool;
+}
+
+
+svn_ra_serf__xml_context_t *
+svn_ra_serf__xml_context_create(
+ const svn_ra_serf__xml_transition_t *ttable,
+ svn_ra_serf__xml_opened_t opened_cb,
+ svn_ra_serf__xml_closed_t closed_cb,
+ void *baton,
+ apr_pool_t *result_pool)
+{
+ svn_ra_serf__xml_context_t *xmlctx;
+ svn_ra_serf__xml_estate_t *xes;
+
+ xmlctx = apr_pcalloc(result_pool, sizeof(*xmlctx));
+ xmlctx->ttable = ttable;
+ xmlctx->opened_cb = opened_cb;
+ xmlctx->closed_cb = closed_cb;
+ xmlctx->baton = baton;
+ xmlctx->scratch_pool = svn_pool_create(result_pool);
+
+ xes = apr_pcalloc(result_pool, sizeof(*xes));
+ /* XES->STATE == 0 */
+
+ /* Child states may use this pool to allocate themselves. If a child
+ needs to collect information, then it will construct a subpool and
+ will use that to allocate itself and its collected data. */
+ xes->state_pool = result_pool;
+
+ xmlctx->current = xes;
+
+ return xmlctx;
+}
+
+
+apr_hash_t *
+svn_ra_serf__xml_gather_since(svn_ra_serf__xml_estate_t *xes,
+ int stop_state)
+{
+ apr_hash_t *data;
+
+ ensure_pool(xes);
+
+ data = apr_hash_make(xes->state_pool);
+
+ /* ### gather data */
+
+ return data;
+}
+
+
+void
+svn_ra_serf__xml_note(svn_ra_serf__xml_estate_t *xes,
+ int state,
+ const char *name,
+ const char *value)
+{
+ svn_ra_serf__xml_estate_t *scan;
+
+ for (scan = xes; scan != NULL && scan->state != state; scan = scan->prev)
+ /* pass */ ;
+
+ SVN_ERR_ASSERT_NO_RETURN(scan != NULL);
+
+ /* Make sure the target state has a pool. */
+ ensure_pool(scan);
+
+ /* ... and attribute storage. */
+ if (scan->attrs == NULL)
+ scan->attrs = apr_hash_make(scan->state_pool);
+
+ /* In all likelihood, NAME is a string constant. But we can't really
+ be sure. And it isn't like we're storing a billion of these into
+ the state pool. */
+ apr_hash_set(scan->attrs,
+ apr_pstrdup(scan->state_pool, name), APR_HASH_KEY_STRING,
+ apr_pstrdup(scan->state_pool, value));
+}
+
+
+apr_pool_t *
+svn_ra_serf__xml_state_pool(svn_ra_serf__xml_estate_t *xes)
+{
+ /* If they asked for a pool, then ensure that we have one to provide. */
+ ensure_pool(xes);
+
+ return xes->state_pool;
+}
+
+
+svn_error_t *
+svn_ra_serf__xml_cb_start(svn_ra_serf__xml_context_t *xmlctx,
+ const char *raw_name,
+ const char *const *attrs)
+{
+ svn_ra_serf__xml_estate_t *current = xmlctx->current;
+ svn_ra_serf__dav_props_t elemname;
+ const svn_ra_serf__xml_transition_t *scan;
+ apr_pool_t *new_pool;
+ svn_ra_serf__xml_estate_t *new_xes;
+
+ /* If we're waiting for an element to close, then just ignore all
+ other element-opens. */
+ if (xmlctx->waiting.namespace != NULL)
+ return SVN_NO_ERROR;
+
+ /* Look for xmlns: attributes. Lazily create the state pool if any
+ were found. */
+ define_namespaces(¤t->ns_list, attrs, lazy_create_pool, current);
+
+ svn_ra_serf__expand_ns(&elemname, current->ns_list, raw_name);
+
+ for (scan = xmlctx->ttable; scan->ns != NULL; ++scan)
+ {
+ if (scan->from_state != current->state)
+ continue;
+
+ if (strcmp(elemname.name, scan->name) == 0
+ && strcmp(elemname.namespace, scan->ns) == 0)
+ break;
+ }
+ if (scan->ns == NULL)
+ {
+ xmlctx->waiting = elemname;
+ /* ### return? */
+ return SVN_NO_ERROR;
+ }
+
+ /* We should not be told to collect cdata if the closed_cb will not
+ be called. */
+ SVN_ERR_ASSERT(!scan->collect_cdata || scan->custom_close);
+
+ /* Found a transition. Make it happen. */
+
+ /* ### todo. push state */
+
+ /* ### how to use free states? */
+ /* This state should be allocated in the extent pool. If we will be
+ collecting information for this state, then construct a subpool.
+
+ ### potentially optimize away the subpool if none of the
+ ### attributes are present. subpools are cheap, tho... */
+ new_pool = xes_pool(current);
+ if (scan->collect_cdata || scan->collect_attrs[0])
+ {
+ new_pool = svn_pool_create(new_pool);
+
+ /* Prep the new state. */
+ new_xes = apr_pcalloc(new_pool, sizeof(*new_xes));
+ new_xes->state_pool = new_pool;
+
+ /* If we're supposed to collect cdata, then set up a buffer for
+ this. The existence of this buffer will instruct our cdata
+ callback to collect the cdata. */
+ if (scan->collect_cdata)
+ new_xes->cdata = svn_stringbuf_create_empty(new_pool);
+
+ if (scan->collect_attrs[0] != NULL)
+ {
+ const char *const *saveattr = &scan->collect_attrs[0];
+
+ new_xes->attrs = apr_hash_make(new_pool);
+ for (; *saveattr != NULL; ++saveattr)
+ {
+ const char *name;
+ const char *value;
+
+ if (**saveattr == '?')
+ {
+ name = *saveattr + 1;
+ value = svn_xml_get_attr_value(name, attrs);
+ }
+ else
+ {
+ name = *saveattr;
+ value = svn_xml_get_attr_value(name, attrs);
+ if (value == NULL)
+ return svn_error_createf(SVN_ERR_XML_ATTRIB_NOT_FOUND,
+ NULL,
+ _("Missing XML attribute: '%s'"),
+ name);
+ }
+
+ if (value)
+ apr_hash_set(new_xes->attrs, name, APR_HASH_KEY_STRING, value);
+ }
+ }
+ }
+ else
+ {
+ /* Prep the new state. */
+ new_xes = apr_pcalloc(new_pool, sizeof(*new_xes));
+ /* STATE_POOL remains NULL. */
+ }
+
+ /* Some basic copies to set up the new estate. */
+ new_xes->state = scan->to_state;
+ new_xes->tag = elemname;
+ new_xes->custom_close = scan->custom_close;
+
+ /* Start with the parent's namespace set. */
+ new_xes->ns_list = current->ns_list;
+
+ /* The new state is prepared. Make it current. */
+ new_xes->prev = current;
+ xmlctx->current = new_xes;
+
+ if (scan->custom_open)
+ {
+ START_CALLBACK(xmlctx);
+ SVN_ERR(xmlctx->opened_cb(new_xes, xmlctx->baton,
+ new_xes->state, xmlctx->scratch_pool));
+ END_CALLBACK(xmlctx);
+ svn_pool_clear(xmlctx->scratch_pool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_ra_serf__xml_cb_end(svn_ra_serf__xml_context_t *xmlctx,
+ const char *raw_name)
+{
+ svn_ra_serf__xml_estate_t *xes = xmlctx->current;
+ svn_ra_serf__dav_props_t elemname;
+
+ svn_ra_serf__expand_ns(&elemname, xes->ns_list, raw_name);
+
+ if (xmlctx->waiting.namespace != NULL)
+ {
+ /* If this element is not the closer, then keep waiting... */
+ if (strcmp(elemname.name, xmlctx->waiting.name) != 0
+ || strcmp(elemname.namespace, xmlctx->waiting.namespace) != 0)
+ return SVN_NO_ERROR;
+
+ /* Found it. Stop waiting, and go back for more. */
+ xmlctx->waiting.namespace = NULL;
+ return SVN_NO_ERROR;
+ }
+
+ /* We should be looking at the same tag that opened the current state.
+
+ Unknown elements are simply skipped, so we wouldn't reach this check.
+
+ Known elements push a new state for a given tag. Some other elemname
+ would imply closing an ancestor tag (where did ours go?) or a spurious
+ tag closure. */
+ if (strcmp(elemname.name, xes->tag.name) != 0
+ || strcmp(elemname.namespace, xes->tag.namespace) != 0)
+ return svn_error_create(SVN_ERR_XML_MALFORMED, NULL,
+ _("The response contains invalid XML"));
+
+ if (xes->custom_close)
+ {
+ const svn_string_t *cdata;
+
+ if (xes->cdata)
+ {
+ cdata = svn_stringbuf__morph_into_string(xes->cdata);
+#ifdef SVN_DEBUG
+ /* We might toss the pool holding this structure, but it could also
+ be within a parent pool. In any case, for safety's sake, disable
+ the stringbuf against future Badness. */
+ xes->cdata->pool = NULL;
+#endif
+ }
+ else
+ cdata = NULL;
+
+ START_CALLBACK(xmlctx);
+ SVN_ERR(xmlctx->closed_cb(xes, xmlctx->baton, xes->state,
+ cdata, xes->attrs,
+ xmlctx->scratch_pool));
+ END_CALLBACK(xmlctx);
+ svn_pool_clear(xmlctx->scratch_pool);
+ }
+
+ /* Pop the state. */
+ xmlctx->current = xes->prev;
+
+ /* ### not everything should go on the free state list. XES may go
+ ### away with the state pool. */
+ xes->prev = xmlctx->free_states;
+ xmlctx->free_states = xes;
+
+ /* If there is a STATE_POOL, then toss it. This will get rid of as much
+ memory as possible. Potentially the XES (if we didn't create a pool
+ right away, then XES may be in a parent pool). */
+ if (xes->state_pool)
+ svn_pool_destroy(xes->state_pool);
+
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_ra_serf__xml_cb_cdata(svn_ra_serf__xml_context_t *xmlctx,
+ const char *data,
+ apr_size_t len)
+{
+ /* If we're collecting cdata, but NOT waiting for a closing tag
+ (ie. not within an unknown tag), then copy the cdata. */
+ if (xmlctx->current->cdata != NULL
+ && xmlctx->waiting.namespace == NULL)
+ svn_stringbuf_appendbytes(xmlctx->current->cdata, data, len);
+
+ return SVN_NO_ERROR;
+}
+
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/client.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/client.c Wed May 16 20:32:43 2012
@@ -1152,7 +1152,18 @@ static svn_error_t *ra_svn_get_dir(svn_r
dirent->size = size;/* FIXME: svn_filesize_t */
dirent->has_props = has_props;
dirent->created_rev = crev;
- SVN_ERR(svn_time_from_cstring(&dirent->time, cdate, pool));
+ /* NOTE: the tuple's format string says CDATE may be NULL. But this
+ function does not allow that. The server has always sent us some
+ random date, however, so this just happens to work. But let's
+ be wary of servers that are (improperly) fixed to send NULL.
+
+ Note: they should NOT be "fixed" to send NULL, as that would break
+ any older clients which received that NULL. But we may as well
+ be defensive against a malicous server. */
+ if (cdate == NULL)
+ dirent->time = 0;
+ else
+ SVN_ERR(svn_time_from_cstring(&dirent->time, cdate, pool));
dirent->last_author = cauthor;
apr_hash_set(*dirents, name, APR_HASH_KEY_STRING, dirent);
}
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/cyrus_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/cyrus_auth.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/cyrus_auth.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/cyrus_auth.c Wed May 16 20:32:43 2012
@@ -533,7 +533,7 @@ static svn_error_t *try_auth(svn_ra_svn_
clear_sasl_errno();
result = sasl_client_step(sasl_ctx,
in->data,
- in->len,
+ (const unsigned int) in->len,
&client_interact,
&out, /* Filled in by SASL. */
&outlen);
@@ -620,7 +620,7 @@ static svn_error_t *sasl_read_cb(void *b
return SVN_NO_ERROR;
}
clear_sasl_errno();
- result = sasl_decode(sasl_baton->ctx, buffer, len2,
+ result = sasl_decode(sasl_baton->ctx, buffer, (unsigned int) len2,
&sasl_baton->read_buf,
&sasl_baton->read_len);
if (result != SASL_OK)
@@ -662,7 +662,7 @@ sasl_write_cb(void *baton, const char *b
/* Make sure we don't write too much. */
*len = (*len > sasl_baton->maxsize) ? sasl_baton->maxsize : *len;
clear_sasl_errno();
- result = sasl_encode(sasl_baton->ctx, buffer, *len,
+ result = sasl_encode(sasl_baton->ctx, buffer, (unsigned int) *len,
&sasl_baton->write_buf,
&sasl_baton->write_len);
@@ -755,9 +755,8 @@ svn_error_t *svn_ra_svn__enable_sasl_enc
{
clear_sasl_errno();
result = sasl_decode(sasl_ctx, conn->read_ptr,
- conn->read_end - conn->read_ptr,
- &sasl_baton->read_buf,
- &sasl_baton->read_len);
+ (unsigned int) (conn->read_end - conn->read_ptr),
+ &sasl_baton->read_buf, &sasl_baton->read_len);
if (result != SASL_OK)
return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
get_sasl_error(sasl_ctx, result, pool));
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/editorp.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/editorp.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/editorp.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/editorp.c Wed May 16 20:32:43 2012
@@ -437,7 +437,8 @@ void svn_ra_svn_get_editor(const svn_del
*edit_baton = eb;
svn_error_clear(svn_editor__insert_shims(editor, edit_baton, *editor,
- *edit_baton, conn->shim_callbacks,
+ *edit_baton, NULL, NULL,
+ conn->shim_callbacks,
pool, pool));
}
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/marshal.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/marshal.c Wed May 16 20:32:43 2012
@@ -231,7 +231,7 @@ static svn_error_t *writebuf_output(svn_
/* Write data from the write buffer out to the socket. */
static svn_error_t *writebuf_flush(svn_ra_svn_conn_t *conn, apr_pool_t *pool)
{
- int write_pos = conn->write_pos;
+ apr_size_t write_pos = conn->write_pos;
/* Clear conn->write_pos first in case the block handler does a read. */
conn->write_pos = 0;
@@ -258,19 +258,36 @@ static svn_error_t *writebuf_write(svn_r
return SVN_NO_ERROR;
}
-static svn_error_t *writebuf_printf(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- const char *fmt, ...)
- __attribute__ ((format(printf, 3, 4)));
-static svn_error_t *writebuf_printf(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- const char *fmt, ...)
+static svn_error_t *
+writebuf_write_short_string(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
+ const char *data, apr_size_t len)
+{
+ apr_size_t left = sizeof(conn->write_buf) - conn->write_pos;
+ if (len <= left)
+ {
+ memcpy(conn->write_buf + conn->write_pos, data, len);
+ conn->write_pos += len;
+ return SVN_NO_ERROR;
+ }
+ else
+ return writebuf_write(conn, pool, data, len);
+}
+
+static APR_INLINE svn_error_t *
+writebuf_writechar(svn_ra_svn_conn_t *conn, apr_pool_t *pool, char data)
{
- va_list ap;
- char *str;
+ if (conn->write_pos < sizeof(conn->write_buf))
+ {
+ conn->write_buf[conn->write_pos] = data;
+ conn->write_pos++;
- va_start(ap, fmt);
- str = apr_pvsprintf(pool, fmt, ap);
- va_end(ap);
- return writebuf_write(conn, pool, str, strlen(str));
+ return SVN_NO_ERROR;
+ }
+ else
+ {
+ char temp = data;
+ return writebuf_write(conn, pool, &temp, 1);
+ }
}
/* --- READ BUFFER MANAGEMENT --- */
@@ -417,31 +434,71 @@ static svn_error_t *readbuf_skip_leading
/* --- WRITING DATA ITEMS --- */
+static svn_error_t *write_number(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
+ apr_uint64_t number, char follow)
+{
+ apr_size_t written;
+
+ /* SVN_INT64_BUFFER_SIZE includes space for a terminating NUL that
+ * svn__ui64toa will always append. */
+ if (conn->write_pos + SVN_INT64_BUFFER_SIZE >= sizeof(conn->write_buf))
+ SVN_ERR(writebuf_flush(conn, pool));
+
+ written = svn__ui64toa(conn->write_buf + conn->write_pos, number);
+ conn->write_buf[conn->write_pos + written] = follow;
+ conn->write_pos += written + 1;
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *svn_ra_svn_write_number(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
apr_uint64_t number)
{
- return writebuf_printf(conn, pool, "%" APR_UINT64_T_FMT " ", number);
+ return write_number(conn, pool, number, ' ');
}
svn_error_t *svn_ra_svn_write_string(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
const svn_string_t *str)
{
- SVN_ERR(writebuf_printf(conn, pool, "%" APR_SIZE_T_FMT ":", str->len));
+ if (str->len < 10)
+ {
+ SVN_ERR(writebuf_writechar(conn, pool, (char)str->len + '0'));
+ SVN_ERR(writebuf_writechar(conn, pool, ':'));
+ }
+ else
+ SVN_ERR(write_number(conn, pool, str->len, ':'));
+
SVN_ERR(writebuf_write(conn, pool, str->data, str->len));
- SVN_ERR(writebuf_write(conn, pool, " ", 1));
+ SVN_ERR(writebuf_writechar(conn, pool, ' '));
return SVN_NO_ERROR;
}
svn_error_t *svn_ra_svn_write_cstring(svn_ra_svn_conn_t *conn,
apr_pool_t *pool, const char *s)
{
- return writebuf_printf(conn, pool, "%" APR_SIZE_T_FMT ":%s ", strlen(s), s);
+ apr_size_t len = strlen(s);
+
+ if (len < 10)
+ {
+ SVN_ERR(writebuf_writechar(conn, pool, (char)len + '0'));
+ SVN_ERR(writebuf_writechar(conn, pool, ':'));
+ }
+ else
+ SVN_ERR(write_number(conn, pool, len, ':'));
+
+ SVN_ERR(writebuf_write(conn, pool, s, len));
+ SVN_ERR(writebuf_writechar(conn, pool, ' '));
+
+ return SVN_NO_ERROR;
}
svn_error_t *svn_ra_svn_write_word(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
const char *word)
{
- return writebuf_printf(conn, pool, "%s ", word);
+ SVN_ERR(writebuf_write_short_string(conn, pool, word, strlen(word)));
+ SVN_ERR(writebuf_writechar(conn, pool, ' '));
+
+ return SVN_NO_ERROR;
}
svn_error_t *svn_ra_svn_write_proplist(svn_ra_svn_conn_t *conn,
@@ -474,11 +531,27 @@ svn_error_t *svn_ra_svn_write_proplist(s
svn_error_t *svn_ra_svn_start_list(svn_ra_svn_conn_t *conn, apr_pool_t *pool)
{
+ if (conn->write_pos + 2 <= sizeof(conn->write_buf))
+ {
+ conn->write_buf[conn->write_pos] = '(';
+ conn->write_buf[conn->write_pos+1] = ' ';
+ conn->write_pos += 2;
+ return SVN_NO_ERROR;
+ }
+
return writebuf_write(conn, pool, "( ", 2);
}
svn_error_t *svn_ra_svn_end_list(svn_ra_svn_conn_t *conn, apr_pool_t *pool)
{
+ if (conn->write_pos + 2 <= sizeof(conn->write_buf))
+ {
+ conn->write_buf[conn->write_pos] = ')';
+ conn->write_buf[conn->write_pos+1] = ' ';
+ conn->write_pos += 2;
+ return SVN_NO_ERROR;
+ }
+
return writebuf_write(conn, pool, ") ", 2);
}
@@ -503,50 +576,54 @@ static svn_error_t *vwrite_tuple(svn_ra_
SVN_ERR(svn_ra_svn_start_list(conn, pool));
for (; *fmt; fmt++)
{
- if (*fmt == 'n' && !opt)
- SVN_ERR(svn_ra_svn_write_number(conn, pool, va_arg(ap, apr_uint64_t)));
- else if (*fmt == 'r')
+ if (*fmt == 'c')
{
- rev = va_arg(ap, svn_revnum_t);
- SVN_ERR_ASSERT(opt || SVN_IS_VALID_REVNUM(rev));
- if (SVN_IS_VALID_REVNUM(rev))
- SVN_ERR(svn_ra_svn_write_number(conn, pool, rev));
+ cstr = va_arg(ap, const char *);
+ if (cstr)
+ SVN_ERR(svn_ra_svn_write_cstring(conn, pool, cstr));
+ else
+ SVN_ERR_ASSERT(opt);
}
else if (*fmt == 's')
{
str = va_arg(ap, const svn_string_t *);
- SVN_ERR_ASSERT(opt || str);
if (str)
SVN_ERR(svn_ra_svn_write_string(conn, pool, str));
+ else
+ SVN_ERR_ASSERT(opt);
}
- else if (*fmt == 'c')
+ else if (*fmt == '(' && !opt)
+ SVN_ERR(svn_ra_svn_start_list(conn, pool));
+ else if (*fmt == ')')
{
- cstr = va_arg(ap, const char *);
- SVN_ERR_ASSERT(opt || cstr);
- if (cstr)
- SVN_ERR(svn_ra_svn_write_cstring(conn, pool, cstr));
+ SVN_ERR(svn_ra_svn_end_list(conn, pool));
+ opt = FALSE;
}
+ else if (*fmt == '?')
+ opt = TRUE;
else if (*fmt == 'w')
{
cstr = va_arg(ap, const char *);
- SVN_ERR_ASSERT(opt || cstr);
if (cstr)
SVN_ERR(svn_ra_svn_write_word(conn, pool, cstr));
+ else
+ SVN_ERR_ASSERT(opt);
}
+ else if (*fmt == 'r')
+ {
+ rev = va_arg(ap, svn_revnum_t);
+ if (SVN_IS_VALID_REVNUM(rev))
+ SVN_ERR(svn_ra_svn_write_number(conn, pool, rev));
+ else
+ SVN_ERR_ASSERT(opt);
+ }
+ else if (*fmt == 'n' && !opt)
+ SVN_ERR(svn_ra_svn_write_number(conn, pool, va_arg(ap, apr_uint64_t)));
else if (*fmt == 'b' && !opt)
{
cstr = va_arg(ap, svn_boolean_t) ? "true" : "false";
SVN_ERR(svn_ra_svn_write_word(conn, pool, cstr));
}
- else if (*fmt == '?')
- opt = TRUE;
- else if (*fmt == '(' && !opt)
- SVN_ERR(svn_ra_svn_start_list(conn, pool));
- else if (*fmt == ')')
- {
- SVN_ERR(svn_ra_svn_end_list(conn, pool));
- opt = FALSE;
- }
else if (*fmt == '!' && !*(fmt + 1))
return SVN_NO_ERROR;
else
@@ -668,7 +745,8 @@ static svn_error_t *read_item(svn_ra_svn
if (!svn_ctype_isdigit(c))
break;
val = val * 10 + (c - '0');
- if ((val / 10) != prev_val) /* val wrapped past maximum value */
+ /* val wrapped past maximum value? */
+ if (prev_val >= (APR_UINT64_MAX / 10) && (val / 10) != prev_val)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Number is larger than maximum"));
}
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/ra_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/ra_svn.h?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/ra_svn.h (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_ra_svn/ra_svn.h Wed May 16 20:32:43 2012
@@ -57,8 +57,8 @@ typedef svn_error_t *(*ra_svn_block_hand
void *baton);
/* The size of our per-connection read and write buffers. */
-#define SVN_RA_SVN__READBUF_SIZE 4096
-#define SVN_RA_SVN__WRITEBUF_SIZE 4096
+#define SVN_RA_SVN__READBUF_SIZE (4*4096)
+#define SVN_RA_SVN__WRITEBUF_SIZE (4*4096)
/* Create forward reference */
typedef struct svn_ra_svn__session_baton_t svn_ra_svn__session_baton_t;
@@ -79,7 +79,7 @@ struct svn_ra_svn_conn_st {
char *read_ptr;
char *read_end;
char write_buf[SVN_RA_SVN__WRITEBUF_SIZE];
- int write_pos;
+ apr_size_t write_pos;
const char *uuid;
const char *repos_root;
ra_svn_block_handler_t block_handler;
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_repos/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_repos/commit.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_repos/commit.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_repos/commit.c Wed May 16 20:32:43 2012
@@ -37,8 +37,11 @@
#include "svn_checksum.h"
#include "svn_props.h"
#include "svn_mergeinfo.h"
-#include "repos.h"
#include "svn_private_config.h"
+#include "svn_editor.h"
+
+#include "repos.h"
+
#include "private/svn_fspath.h"
#include "private/svn_repos_private.h"
@@ -128,6 +131,29 @@ struct file_baton
};
+struct ev2_baton
+{
+ /* The repository we are editing. */
+ svn_repos_t *repos;
+
+ /* The authz baton for checks; NULL to skip authz. */
+ svn_authz_t *authz;
+
+ /* The repository name and user for performing authz checks. */
+ const char *authz_repos_name;
+ const char *authz_user;
+
+ /* Callback to provide info about the committed revision. */
+ svn_commit_callback2_t commit_cb;
+ void *commit_baton;
+
+ /* The FS txn editor */
+ svn_editor_t *inner;
+
+ /* The name of the open transaction (so we know what to commit) */
+ const char *txn_name;
+};
+
/* Create and return a generic out-of-dateness error. */
static svn_error_t *
@@ -143,6 +169,40 @@ out_of_date(const char *path, svn_node_k
}
+static svn_error_t *
+invoke_commit_cb(svn_commit_callback2_t commit_cb,
+ void *commit_baton,
+ svn_fs_t *fs,
+ svn_revnum_t revision,
+ const char *post_commit_errstr,
+ apr_pool_t *scratch_pool)
+{
+ /* FS interface returns non-const values. */
+ /* const */ svn_string_t *date;
+ /* const */ svn_string_t *author;
+ svn_commit_info_t *commit_info;
+
+ if (commit_cb == NULL)
+ return SVN_NO_ERROR;
+
+ SVN_ERR(svn_fs_revision_prop(&date, fs, revision, SVN_PROP_REVISION_DATE,
+ scratch_pool));
+ SVN_ERR(svn_fs_revision_prop(&author, fs, revision,
+ SVN_PROP_REVISION_AUTHOR,
+ scratch_pool));
+
+ commit_info = svn_create_commit_info(scratch_pool);
+
+ /* fill up the svn_commit_info structure */
+ commit_info->revision = revision;
+ commit_info->date = date ? date->data : NULL;
+ commit_info->author = author ? author->data : NULL;
+ commit_info->post_commit_err = post_commit_errstr;
+
+ return svn_error_trace(commit_cb(commit_info, commit_baton, scratch_pool));
+}
+
+
/* If EDITOR_BATON contains a valid authz callback, verify that the
REQUIRED access to PATH in ROOT is authorized. Return an error
@@ -631,7 +691,8 @@ svn_repos__post_commit_error_str(svn_err
else
hook_err2 = hook_err1;
- /* This implementation counts on svn_repos_fs_commit_txn() returning
+ /* This implementation counts on svn_repos_fs_commit_txn() and
+ libsvn_repos/commit.c:complete_cb() 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
@@ -703,7 +764,6 @@ close_edit(void *edit_baton,
display it as a warning) and clear the error. */
post_commit_err = svn_repos__post_commit_error_str(err, pool);
svn_error_clear(err);
- err = SVN_NO_ERROR;
}
}
else
@@ -730,41 +790,19 @@ close_edit(void *edit_baton,
svn_fs_abort_txn(eb->txn, pool)));
}
- /* Pass new revision information to the caller's callback. */
- {
- svn_string_t *date, *author;
- svn_commit_info_t *commit_info;
-
- /* Even if there was a post-commit hook failure, it's more serious
- if one of the calls here fails, so we explicitly check for errors
- here, while saving the possible post-commit error for later. */
-
- err = svn_fs_revision_prop(&date, svn_repos_fs(eb->repos),
- new_revision, SVN_PROP_REVISION_DATE,
- pool);
- if (! err)
- {
- err = svn_fs_revision_prop(&author, svn_repos_fs(eb->repos),
- new_revision, SVN_PROP_REVISION_AUTHOR,
- pool);
- }
-
- if ((! err) && eb->commit_callback)
- {
- commit_info = svn_create_commit_info(pool);
-
- /* fill up the svn_commit_info structure */
- commit_info->revision = new_revision;
- commit_info->date = date ? date->data : NULL;
- 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);
- }
- }
+ /* At this point, the post-commit error has been converted to a string.
+ That information will be passed to a callback, if provided. If the
+ callback invocation fails in some way, that failure is returned here.
+ IOW, the post-commit error information is low priority compared to
+ other gunk here. */
- return svn_error_trace(err);
+ /* Pass new revision information to the caller's callback. */
+ return svn_error_trace(invoke_commit_cb(eb->commit_callback,
+ eb->commit_callback_baton,
+ eb->repos->fs,
+ new_revision,
+ post_commit_err,
+ pool));
}
@@ -783,33 +821,6 @@ abort_edit(void *edit_baton,
static svn_error_t *
-rationalize_shim_path(const char **fs_path,
- struct edit_baton *eb,
- const char *path,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- if (svn_path_is_url(path))
- {
- /* This is a copyfrom URL. */
- path = svn_uri_skip_ancestor(eb->repos_url, path, scratch_pool);
- *fs_path = svn_fspath__canonicalize(path, scratch_pool);
- }
- else
- {
- /* This is a base-relative path. */
- if (path[0] != '/')
- /* Get an absolute path for use in the FS. */
- *fs_path = svn_fspath__join(eb->base_path, path, scratch_pool);
- else
- *fs_path = path;
- }
-
- return SVN_NO_ERROR;
-}
-
-
-static svn_error_t *
fetch_props_func(apr_hash_t **props,
void *baton,
const char *path,
@@ -821,7 +832,6 @@ fetch_props_func(apr_hash_t **props,
svn_fs_root_t *fs_root;
svn_error_t *err;
- SVN_ERR(rationalize_shim_path(&path, eb, path, scratch_pool, scratch_pool));
SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs,
svn_fs_txn_base_revision(eb->txn),
scratch_pool));
@@ -852,7 +862,6 @@ fetch_kind_func(svn_kind_t *kind,
if (!SVN_IS_VALID_REVNUM(base_revision))
base_revision = svn_fs_txn_base_revision(eb->txn);
- SVN_ERR(rationalize_shim_path(&path, eb, path, scratch_pool, scratch_pool));
SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs, base_revision, scratch_pool));
SVN_ERR(svn_fs_check_path(&node_kind, fs_root, path, scratch_pool));
@@ -879,7 +888,6 @@ fetch_base_func(const char **filename,
if (!SVN_IS_VALID_REVNUM(base_revision))
base_revision = svn_fs_txn_base_revision(eb->txn);
- SVN_ERR(rationalize_shim_path(&path, eb, path, scratch_pool, scratch_pool));
SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs, base_revision, scratch_pool));
err = svn_fs_file_contents(&contents, fs_root, path, scratch_pool);
@@ -981,7 +989,378 @@ svn_repos_get_commit_editor5(const svn_d
shim_callbacks->fetch_baton = eb;
SVN_ERR(svn_editor__insert_shims(editor, edit_baton, *editor, *edit_baton,
+ eb->repos_url, eb->base_path,
shim_callbacks, pool, pool));
return SVN_NO_ERROR;
}
+
+
+#if 0
+static svn_error_t *
+ev2_check_authz(const struct ev2_baton *eb,
+ const char *relpath,
+ svn_repos_authz_access_t required,
+ apr_pool_t *scratch_pool)
+{
+ const char *fspath;
+ svn_boolean_t allowed;
+
+ if (eb->authz == NULL)
+ return SVN_NO_ERROR;
+
+ if (relpath)
+ fspath = apr_pstrcat(scratch_pool, "/", relpath, NULL);
+ else
+ fspath = NULL;
+
+ SVN_ERR(svn_repos_authz_check_access(eb->authz, eb->authz_repos_name, fspath,
+ eb->authz_user, required,
+ &allowed, scratch_pool));
+ if (!allowed)
+ return svn_error_create(required & svn_authz_write
+ ? SVN_ERR_AUTHZ_UNWRITABLE
+ : SVN_ERR_AUTHZ_UNREADABLE,
+ NULL, "Access denied");
+
+ return SVN_NO_ERROR;
+}
+#endif
+
+
+/* This implements svn_editor_cb_add_directory_t */
+static svn_error_t *
+add_directory_cb(void *baton,
+ const char *relpath,
+ const apr_array_header_t *children,
+ apr_hash_t *props,
+ svn_revnum_t replaces_rev,
+ apr_pool_t *scratch_pool)
+{
+ struct ev2_baton *eb = baton;
+
+ SVN_ERR(svn_editor_add_directory(eb->inner, relpath, children, props,
+ replaces_rev));
+ return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_add_file_t */
+static svn_error_t *
+add_file_cb(void *baton,
+ const char *relpath,
+ const svn_checksum_t *checksum,
+ svn_stream_t *contents,
+ apr_hash_t *props,
+ svn_revnum_t replaces_rev,
+ apr_pool_t *scratch_pool)
+{
+ struct ev2_baton *eb = baton;
+
+ SVN_ERR(svn_editor_add_file(eb->inner, relpath, checksum, contents, props,
+ replaces_rev));
+ return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_add_symlink_t */
+static svn_error_t *
+add_symlink_cb(void *baton,
+ const char *relpath,
+ const char *target,
+ apr_hash_t *props,
+ svn_revnum_t replaces_rev,
+ apr_pool_t *scratch_pool)
+{
+ struct ev2_baton *eb = baton;
+
+ SVN_ERR(svn_editor_add_symlink(eb->inner, relpath, target, props,
+ replaces_rev));
+ return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_add_absent_t */
+static svn_error_t *
+add_absent_cb(void *baton,
+ const char *relpath,
+ svn_kind_t kind,
+ svn_revnum_t replaces_rev,
+ apr_pool_t *scratch_pool)
+{
+ struct ev2_baton *eb = baton;
+
+ SVN_ERR(svn_editor_add_absent(eb->inner, relpath, kind, replaces_rev));
+ return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_alter_directory_t */
+static svn_error_t *
+alter_directory_cb(void *baton,
+ const char *relpath,
+ svn_revnum_t revision,
+ const apr_array_header_t *children,
+ apr_hash_t *props,
+ apr_pool_t *scratch_pool)
+{
+ struct ev2_baton *eb = baton;
+
+ SVN_ERR(svn_editor_alter_directory(eb->inner, relpath, revision,
+ children, props));
+ return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_alter_file_t */
+static svn_error_t *
+alter_file_cb(void *baton,
+ const char *relpath,
+ svn_revnum_t revision,
+ apr_hash_t *props,
+ const svn_checksum_t *checksum,
+ svn_stream_t *contents,
+ apr_pool_t *scratch_pool)
+{
+ struct ev2_baton *eb = baton;
+
+ SVN_ERR(svn_editor_alter_file(eb->inner, relpath, revision, props,
+ checksum, contents));
+ return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_alter_symlink_t */
+static svn_error_t *
+alter_symlink_cb(void *baton,
+ const char *relpath,
+ svn_revnum_t revision,
+ apr_hash_t *props,
+ const char *target,
+ apr_pool_t *scratch_pool)
+{
+ struct ev2_baton *eb = baton;
+
+ SVN_ERR(svn_editor_alter_symlink(eb->inner, relpath, revision, props,
+ target));
+ return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_delete_t */
+static svn_error_t *
+delete_cb(void *baton,
+ const char *relpath,
+ svn_revnum_t revision,
+ apr_pool_t *scratch_pool)
+{
+ struct ev2_baton *eb = baton;
+
+ SVN_ERR(svn_editor_delete(eb->inner, relpath, revision));
+ return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_copy_t */
+static svn_error_t *
+copy_cb(void *baton,
+ const char *src_relpath,
+ svn_revnum_t src_revision,
+ const char *dst_relpath,
+ svn_revnum_t replaces_rev,
+ apr_pool_t *scratch_pool)
+{
+ struct ev2_baton *eb = baton;
+
+ SVN_ERR(svn_editor_copy(eb->inner, src_relpath, src_revision, dst_relpath,
+ replaces_rev));
+ return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_move_t */
+static svn_error_t *
+move_cb(void *baton,
+ const char *src_relpath,
+ svn_revnum_t src_revision,
+ const char *dst_relpath,
+ svn_revnum_t replaces_rev,
+ apr_pool_t *scratch_pool)
+{
+ struct ev2_baton *eb = baton;
+
+ SVN_ERR(svn_editor_move(eb->inner, src_relpath, src_revision, dst_relpath,
+ replaces_rev));
+ return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_rotate_t */
+static svn_error_t *
+rotate_cb(void *baton,
+ const apr_array_header_t *relpaths,
+ const apr_array_header_t *revisions,
+ apr_pool_t *scratch_pool)
+{
+ struct ev2_baton *eb = baton;
+
+ SVN_ERR(svn_editor_rotate(eb->inner, relpaths, revisions));
+ return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_complete_t */
+static svn_error_t *
+complete_cb(void *baton,
+ apr_pool_t *scratch_pool)
+{
+ struct ev2_baton *eb = baton;
+ svn_revnum_t revision;
+ svn_error_t *post_commit_err;
+ const char *conflict_path;
+ svn_error_t *err;
+ const char *post_commit_errstr;
+
+ /* The transaction has been fully edited. Let the pre-commit hook
+ have a look at the thing. */
+ SVN_ERR(svn_repos__hooks_pre_commit(eb->repos, eb->txn_name, scratch_pool));
+
+ /* Hook is done. Let's do the actual commit. */
+ SVN_ERR(svn_fs_editor_commit(&revision, &post_commit_err, &conflict_path,
+ eb->inner, scratch_pool, scratch_pool));
+
+ /* Did a conflict occur during the commit process? */
+ if (conflict_path != NULL)
+ return svn_error_createf(SVN_ERR_FS_CONFLICT, NULL,
+ _("Conflict at '%s'"), conflict_path);
+
+ /* Since did not receive an error during the commit process, and no
+ conflict was specified... we committed a revision. Run the hooks.
+ Other errors may have occurred within the FS (specified by the
+ POST_COMMIT_ERR localvar), but we need to run the hooks. */
+ SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision));
+ err = svn_repos__hooks_post_commit(eb->repos, revision, eb->txn_name,
+ scratch_pool);
+ if (err)
+ err = svn_error_create(SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED, err,
+ _("Commit succeeded, but post-commit hook failed"));
+
+ /* Combine the FS errors with the hook errors, and stringify. */
+ err = svn_error_compose_create(post_commit_err, err);
+ if (err)
+ {
+ post_commit_errstr = svn_repos__post_commit_error_str(err, scratch_pool);
+ svn_error_clear(err);
+ }
+ else
+ {
+ post_commit_errstr = NULL;
+ }
+
+ return svn_error_trace(invoke_commit_cb(eb->commit_cb, eb->commit_baton,
+ eb->repos->fs, revision,
+ post_commit_errstr,
+ scratch_pool));
+}
+
+
+/* This implements svn_editor_cb_abort_t */
+static svn_error_t *
+abort_cb(void *baton,
+ apr_pool_t *scratch_pool)
+{
+ struct ev2_baton *eb = baton;
+
+ SVN_ERR(svn_editor_abort(eb->inner));
+ return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+apply_revprops(svn_fs_t *fs,
+ const char *txn_name,
+ apr_hash_t *revprops,
+ apr_pool_t *scratch_pool)
+{
+ svn_fs_txn_t *txn;
+ const apr_array_header_t *revprops_array;
+
+ /* The FS editor has a TXN inside it, but we can't access it. Open another
+ based on the TXN_NAME. */
+ SVN_ERR(svn_fs_open_txn(&txn, fs, txn_name, scratch_pool));
+
+ /* Validate and apply the revision properties. */
+ revprops_array = svn_prop_hash_to_array(revprops, scratch_pool);
+ SVN_ERR(svn_repos_fs_change_txn_props(txn, revprops_array, scratch_pool));
+
+ /* ### do we need to force the txn to close, or is it enough to wait
+ ### for the pool to be cleared? */
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_repos__get_commit_ev2(svn_editor_t **editor,
+ svn_repos_t *repos,
+ svn_authz_t *authz,
+ const char *authz_repos_name,
+ const char *authz_user,
+ apr_hash_t *revprops,
+ svn_commit_callback2_t commit_cb,
+ void *commit_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ static const svn_editor_cb_many_t editor_cbs = {
+ add_directory_cb,
+ add_file_cb,
+ add_symlink_cb,
+ add_absent_cb,
+ alter_directory_cb,
+ alter_file_cb,
+ alter_symlink_cb,
+ delete_cb,
+ copy_cb,
+ move_cb,
+ rotate_cb,
+ complete_cb,
+ abort_cb
+ };
+ struct ev2_baton *eb;
+ const svn_string_t *author;
+
+ /* Can the user modify the repository at all? */
+ /* ### check against AUTHZ. */
+
+ /* Okay... some access is allowed. Let's run the start-commit hook. */
+ author = apr_hash_get(revprops, SVN_PROP_REVISION_AUTHOR,
+ APR_HASH_KEY_STRING);
+ SVN_ERR(svn_repos__hooks_start_commit(repos, author ? author->data : NULL,
+ repos->client_capabilities,
+ scratch_pool));
+
+ eb = apr_palloc(result_pool, sizeof(*eb));
+ eb->repos = repos;
+ eb->authz = authz;
+ eb->authz_repos_name = authz_repos_name;
+ eb->authz_user = authz_user;
+ eb->commit_cb = commit_cb;
+ eb->commit_baton = commit_baton;
+
+ SVN_ERR(svn_fs_editor_create(&eb->inner, &eb->txn_name,
+ repos->fs, SVN_FS_TXN_CHECK_LOCKS,
+ cancel_func, cancel_baton,
+ result_pool, scratch_pool));
+
+ /* The TXN has been created. Go ahead and apply all revision properties. */
+ SVN_ERR(apply_revprops(repos->fs, eb->txn_name, revprops, scratch_pool));
+
+ /* Wrap the FS editor within our editor. */
+ SVN_ERR(svn_editor_create(editor, eb, cancel_func, cancel_baton,
+ result_pool, scratch_pool));
+ SVN_ERR(svn_editor_setcb_many(*editor, &editor_cbs, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_repos/deprecated.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_repos/deprecated.c Wed May 16 20:32:43 2012
@@ -32,6 +32,8 @@
#include "svn_private_config.h"
+#include "repos.h"
+
@@ -570,8 +572,7 @@ repos_notify_handler(void *baton,
switch (notify->action)
{
case svn_repos_notify_warning:
- len = strlen(notify->warning_str);
- svn_error_clear(svn_stream_write(feedback_stream, notify->warning_str, &len));
+ svn_error_clear(svn_stream_puts(feedback_stream, notify->warning_str));
return;
case svn_repos_notify_dump_rev_end:
@@ -878,3 +879,32 @@ svn_repos_get_fs_build_parser(const svn_
*parser_callbacks = fns_from_fns2(fns2, pool);
return SVN_NO_ERROR;
}
+
+
+svn_error_t *
+svn_repos_fs_begin_txn_for_update(svn_fs_txn_t **txn_p,
+ svn_repos_t *repos,
+ svn_revnum_t rev,
+ const char *author,
+ apr_pool_t *pool)
+{
+ /* ### someday, we might run a read-hook here. */
+
+ /* Begin the transaction. */
+ SVN_ERR(svn_fs_begin_txn2(txn_p, repos->fs, rev, 0, pool));
+
+ /* We pass the author to the filesystem by adding it as a property
+ on the txn. */
+
+ /* User (author). */
+ if (author)
+ {
+ svn_string_t val;
+ val.data = author;
+ val.len = strlen(author);
+ SVN_ERR(svn_fs_change_txn_prop(*txn_p, SVN_PROP_REVISION_AUTHOR,
+ &val, pool));
+ }
+
+ return SVN_NO_ERROR;
+}
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_repos/dump.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_repos/dump.c Wed May 16 20:32:43 2012
@@ -282,11 +282,11 @@ dump_node(struct edit_baton *eb,
SVN_REPOS_DUMPFILE_NODE_PATH ": %s\n",
path));
if (kind == svn_node_file)
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_NODE_KIND ": file\n"));
+ SVN_ERR(svn_stream_puts(eb->stream,
+ SVN_REPOS_DUMPFILE_NODE_KIND ": file\n"));
else if (kind == svn_node_dir)
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_NODE_KIND ": dir\n"));
+ SVN_ERR(svn_stream_puts(eb->stream,
+ SVN_REPOS_DUMPFILE_NODE_KIND ": dir\n"));
/* Remove leading slashes from copyfrom paths. */
if (cmp_path)
@@ -301,9 +301,8 @@ dump_node(struct edit_baton *eb,
if (action == svn_node_action_change)
{
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_NODE_ACTION
- ": change\n"));
+ SVN_ERR(svn_stream_puts(eb->stream,
+ SVN_REPOS_DUMPFILE_NODE_ACTION ": change\n"));
/* either the text or props changed, or possibly both. */
SVN_ERR(svn_fs_revision_root(&compare_root,
@@ -323,9 +322,9 @@ dump_node(struct edit_baton *eb,
if (! is_copy)
{
/* a simple delete+add, implied by a single 'replace' action. */
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_NODE_ACTION
- ": replace\n"));
+ SVN_ERR(svn_stream_puts(eb->stream,
+ SVN_REPOS_DUMPFILE_NODE_ACTION
+ ": replace\n"));
/* definitely need to dump all content for a replace. */
if (kind == svn_node_file)
@@ -338,9 +337,9 @@ dump_node(struct edit_baton *eb,
/* the path & kind headers have already been printed; just
add a delete action, and end the current record.*/
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_NODE_ACTION
- ": delete\n\n"));
+ SVN_ERR(svn_stream_puts(eb->stream,
+ SVN_REPOS_DUMPFILE_NODE_ACTION
+ ": delete\n\n"));
/* recurse: print an additional add-with-history record. */
SVN_ERR(dump_node(eb, path, kind, svn_node_action_add,
@@ -354,9 +353,8 @@ dump_node(struct edit_baton *eb,
}
else if (action == svn_node_action_delete)
{
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_NODE_ACTION
- ": delete\n"));
+ SVN_ERR(svn_stream_puts(eb->stream,
+ SVN_REPOS_DUMPFILE_NODE_ACTION ": delete\n"));
/* we can leave this routine quietly now, don't need to dump
any content. */
@@ -365,8 +363,8 @@ dump_node(struct edit_baton *eb,
}
else if (action == svn_node_action_add)
{
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
+ SVN_ERR(svn_stream_puts(eb->stream,
+ SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
if (! is_copy)
{
@@ -511,9 +509,8 @@ dump_node(struct edit_baton *eb,
saying that our property contents are a delta. */
SVN_ERR(svn_fs_node_proplist(&oldhash, compare_root, compare_path,
pool));
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_PROP_DELTA
- ": true\n"));
+ SVN_ERR(svn_stream_puts(eb->stream,
+ SVN_REPOS_DUMPFILE_PROP_DELTA ": true\n"));
}
else
oldhash = apr_hash_make(pool);
@@ -544,9 +541,8 @@ dump_node(struct edit_baton *eb,
saying our text contents are a delta. */
SVN_ERR(store_delta(&delta_file, &textlen, compare_root,
compare_path, eb->fs_root, path, pool));
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_TEXT_DELTA
- ": true\n"));
+ SVN_ERR(svn_stream_puts(eb->stream,
+ SVN_REPOS_DUMPFILE_TEXT_DELTA ": true\n"));
if (compare_root)
{
@@ -1009,7 +1005,7 @@ get_dump_editor(const svn_delta_editor_t
shim_callbacks->fetch_baton = eb;
SVN_ERR(svn_editor__insert_shims(editor, edit_baton, *editor, *edit_baton,
- shim_callbacks, pool, pool));
+ NULL, NULL, shim_callbacks, pool, pool));
return SVN_NO_ERROR;
}
@@ -1406,7 +1402,7 @@ svn_repos_verify_fs2(svn_repos_t *repos,
for (rev = start_rev; rev <= end_rev; rev++)
{
- svn_delta_editor_t *dump_editor;
+ const svn_delta_editor_t *dump_editor;
void *dump_edit_baton;
const svn_delta_editor_t *cancel_editor;
void *cancel_edit_baton;
@@ -1416,8 +1412,8 @@ svn_repos_verify_fs2(svn_repos_t *repos,
svn_pool_clear(iterpool);
/* Get cancellable dump editor, but with our close_directory handler. */
- SVN_ERR(get_dump_editor((const svn_delta_editor_t **)&dump_editor,
- &dump_edit_baton, fs, rev, "",
+ SVN_ERR(get_dump_editor(&dump_editor, &dump_edit_baton,
+ fs, rev, "",
svn_stream_empty(iterpool),
NULL, NULL,
verify_close_directory,
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_repos/fs-wrap.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_repos/fs-wrap.c Wed May 16 20:32:43 2012
@@ -124,36 +124,6 @@ svn_repos_fs_begin_txn_for_commit(svn_fs
pool);
}
-
-svn_error_t *
-svn_repos_fs_begin_txn_for_update(svn_fs_txn_t **txn_p,
- svn_repos_t *repos,
- svn_revnum_t rev,
- const char *author,
- apr_pool_t *pool)
-{
- /* ### someday, we might run a read-hook here. */
-
- /* Begin the transaction. */
- SVN_ERR(svn_fs_begin_txn2(txn_p, repos->fs, rev, 0, pool));
-
- /* We pass the author to the filesystem by adding it as a property
- on the txn. */
-
- /* User (author). */
- if (author)
- {
- svn_string_t val;
- val.data = author;
- val.len = strlen(author);
- SVN_ERR(svn_fs_change_txn_prop(*txn_p, SVN_PROP_REVISION_AUTHOR,
- &val, pool));
- }
-
- return SVN_NO_ERROR;
-}
-
-
/*** Property wrappers ***/
@@ -162,7 +132,7 @@ svn_repos__validate_prop(const char *nam
const svn_string_t *value,
apr_pool_t *pool)
{
- svn_prop_kind_t kind = svn_property_kind(NULL, name);
+ svn_prop_kind_t kind = svn_property_kind2(name);
/* Disallow setting non-regular properties. */
if (kind != svn_prop_regular_kind)
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_repos/hooks.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_repos/hooks.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_repos/hooks.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_repos/hooks.c Wed May 16 20:32:43 2012
@@ -30,6 +30,7 @@
#include "svn_error.h"
#include "svn_dirent_uri.h"
#include "svn_path.h"
+#include "svn_pools.h"
#include "svn_repos.h"
#include "svn_utf.h"
#include "repos.h"
@@ -172,7 +173,7 @@ env_from_env_hash(apr_hash_t *env_hash,
const char **env;
const char **envp;
- if (!env_hash || apr_hash_count(env_hash) == 0)
+ if (!env_hash)
return NULL;
env = apr_palloc(result_pool,
@@ -212,7 +213,8 @@ run_hook_cmd(svn_string_t **result,
apr_file_t *null_handle;
apr_status_t apr_err;
svn_error_t *err;
- apr_proc_t cmd_proc;
+ apr_proc_t cmd_proc = {0};
+ apr_pool_t *cmd_pool;
if (result)
{
@@ -228,42 +230,39 @@ run_hook_cmd(svn_string_t **result,
(apr_err, _("Can't create null stdout for hook '%s'"), cmd);
}
+ /* Tie resources allocated for the command to a special pool which we can
+ * destroy in order to clean up the stderr pipe opened for the process. */
+ cmd_pool = svn_pool_create(pool);
+
err = svn_io_start_cmd3(&cmd_proc, ".", cmd, args,
env_from_env_hash(hooks_env, pool, pool),
FALSE, FALSE, stdin_handle, result != NULL,
- null_handle, TRUE, NULL, pool);
-
- if (err)
- {
- /* CMD_PROC is not safe to use. Bail. */
- return svn_error_createf
- (SVN_ERR_REPOS_HOOK_FAILURE, err, _("Failed to start '%s' hook"), cmd);
- }
+ null_handle, TRUE, NULL, cmd_pool);
+ if (!err)
+ err = check_hook_result(name, cmd, &cmd_proc, cmd_proc.err, pool);
else
{
- err = check_hook_result(name, cmd, &cmd_proc, cmd_proc.err, pool);
+ /* The command could not be started for some reason. */
+ err = svn_error_createf(SVN_ERR_REPOS_BAD_ARGS, err,
+ _("Failed to start '%s' hook"), cmd);
}
/* 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(cmd_proc.err);
- if (!err && apr_err)
- return svn_error_wrap_apr
- (apr_err, _("Error closing read end of stderr pipe"));
-
- if (result)
+ if (!err && result)
{
svn_stringbuf_t *native_stdout;
- 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"));
-
- *result = svn_stringbuf__morph_into_string(native_stdout);
+ err = svn_stringbuf_from_aprfile(&native_stdout, cmd_proc.out, pool);
+ if (!err)
+ *result = svn_stringbuf__morph_into_string(native_stdout);
}
- else
+
+ /* Close resources allocated by svn_io_start_cmd3(), such as the pipe. */
+ svn_pool_destroy(cmd_pool);
+
+ /* Close the null handle. */
+ if (null_handle)
{
apr_err = apr_file_close(null_handle);
if (!err && apr_err)
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_repos/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_repos/log.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_repos/log.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_repos/log.c Wed May 16 20:32:43 2012
@@ -1742,7 +1742,7 @@ reduce_search(apr_array_header_t *paths,
if (!ranges)
continue;
- /* ranges is ordered, could we use some sort of binay search
+ /* ranges is ordered, could we use some sort of binary search
rather than iterating? */
for (j = 0; j < ranges->nelts; ++j)
{
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_repos/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_repos/replay.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_repos/replay.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_repos/replay.c Wed May 16 20:32:43 2012
@@ -415,7 +415,12 @@ was_readable(svn_boolean_t *readable,
revision root, fspath, and revnum of the copyfrom of CHANGE, which
corresponds to PATH under ROOT. If the copyfrom info is valid
(i.e., is not (NULL, SVN_INVALID_REVNUM)), then initialize SRC_READABLE
- too, consulting AUTHZ_READ_FUNC and AUTHZ_READ_BATON if provided. */
+ too, consulting AUTHZ_READ_FUNC and AUTHZ_READ_BATON if provided.
+
+ NOTE: If the copyfrom information in CHANGE is marked as unknown
+ (meaning, its ->copyfrom_rev and ->copyfrom_path cannot be
+ trusted), this function will also update those members of the
+ CHANGE structure to carry accurate copyfrom information. */
static svn_error_t *
fill_copyfrom(svn_fs_root_t **copyfrom_root,
const char **copyfrom_path,
@@ -698,10 +703,18 @@ path_driver_cb_func(void **dir_baton,
}
}
- /* Handle property modifications. */
if (! do_delete || do_add)
{
- if (change->prop_mod)
+ /* Is this a copy that was downgraded to a raw add? (If so,
+ we'll need to transmit properties and file contents and such
+ for it regardless of what the CHANGE structure's text_mod
+ and prop_mod flags say.) */
+ svn_boolean_t downgraded_copy = (change->copyfrom_known
+ && change->copyfrom_path
+ && (! copyfrom_path));
+
+ /* Handle property modifications. */
+ if (change->prop_mod || downgraded_copy)
{
apr_array_header_t *prop_diffs;
apr_hash_t *old_props;
@@ -731,14 +744,9 @@ path_driver_cb_func(void **dir_baton,
}
}
- /* Handle textual modifications.
-
- Note that this needs to happen in the "copy from a file we
- aren't allowed to see" case since otherwise the caller will
- have no way to actually get the new file's contents, which
- they are apparently allowed to see. */
+ /* Handle textual modifications. */
if (change->node_kind == svn_node_file
- && (change->text_mod || (change->copyfrom_path && ! copyfrom_path)))
+ && (change->text_mod || downgraded_copy))
{
svn_txdelta_window_handler_t delta_handler;
void *delta_handler_baton;
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_repos/reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_repos/reporter.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_repos/reporter.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_repos/reporter.c Wed May 16 20:32:43 2012
@@ -640,14 +640,20 @@ delta_files(report_baton_t *b, void *fil
/* Send the delta stream if desired, or just a NULL window if not. */
SVN_ERR(b->editor->apply_textdelta(file_baton, s_hex_digest, pool,
&dhandler, &dbaton));
- if (b->text_deltas)
+
+ if (dhandler != svn_delta_noop_window_handler)
{
- SVN_ERR(svn_fs_get_file_delta_stream(&dstream, s_root, s_path,
- b->t_root, t_path, pool));
- return svn_txdelta_send_txstream(dstream, dhandler, dbaton, pool);
+ if (b->text_deltas)
+ {
+ SVN_ERR(svn_fs_get_file_delta_stream(&dstream, s_root, s_path,
+ b->t_root, t_path, pool));
+ SVN_ERR(svn_txdelta_send_txstream(dstream, dhandler, dbaton, pool));
+ }
+ else
+ SVN_ERR(dhandler(NULL, dbaton));
}
- else
- return dhandler(NULL, dbaton);
+
+ return SVN_NO_ERROR;
}
/* Determine if the user is authorized to view B->t_root/PATH. */
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_repos/repos.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_repos/repos.c Wed May 16 20:32:43 2012
@@ -36,6 +36,7 @@
#include "svn_version.h"
#include "private/svn_repos_private.h"
+#include "private/svn_subr_private.h"
#include "svn_private_config.h" /* for SVN_TEMPLATE_ROOT_DIR */
#include "repos.h"
@@ -1184,9 +1185,9 @@ create_repos_structure(svn_repos_t *repo
/* Write the top-level README file. */
{
const char * const readme_header =
- "This is a Subversion repository; use the 'svnadmin' tool to examine" NL
- "it. Do not add, delete, or modify files here unless you know how" NL
- "to avoid corrupting the repository." NL
+ "This is a Subversion repository; use the 'svnadmin' and 'svnlook' " NL
+ "tools to examine it. Do not add, delete, or modify files here " NL
+ "unless you know how to avoid corrupting the repository." NL
"" NL;
const char * const readme_bdb_insert =
"The directory \"" SVN_REPOS__DB_DIR "\" contains a Berkeley DB environment." NL
@@ -1968,3 +1969,17 @@ svn_repos_remember_client_capabilities(s
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_repos__fs_type(const char **fs_type,
+ const char *repos_path,
+ apr_pool_t *pool)
+{
+ svn_repos_t repos;
+ repos.path = (char*)repos_path;
+
+ SVN_ERR(check_repos_format(&repos, pool));
+
+ return svn_fs_type(fs_type,
+ svn_dirent_join(repos_path, SVN_REPOS__DB_DIR, pool),
+ pool);
+}
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_repos/rev_hunt.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_repos/rev_hunt.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_repos/rev_hunt.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_repos/rev_hunt.c Wed May 16 20:32:43 2012
@@ -155,7 +155,7 @@ svn_repos_get_committed_info(svn_revnum_
apr_pool_t *pool)
{
apr_hash_t *revprops;
-
+
svn_fs_t *fs = svn_fs_root_fs(root);
/* ### It might be simpler just to declare that revision
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_subr/cache-inprocess.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_subr/cache-inprocess.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_subr/cache-inprocess.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_subr/cache-inprocess.c Wed May 16 20:32:43 2012
@@ -304,7 +304,7 @@ inprocess_cache_set_internal(inprocess_c
cache->data_size -= existing_entry->size;
if (value)
{
- SVN_ERR(cache->serialize_func((char **)&existing_entry->value,
+ SVN_ERR(cache->serialize_func(&existing_entry->value,
&existing_entry->size,
value,
page->page_pool));
@@ -356,7 +356,7 @@ inprocess_cache_set_internal(inprocess_c
new_entry->key = duplicate_key(cache, key, page->page_pool);
if (value)
{
- SVN_ERR(cache->serialize_func((char **)&new_entry->value,
+ SVN_ERR(cache->serialize_func(&new_entry->value,
&new_entry->size,
value,
page->page_pool));
@@ -512,10 +512,10 @@ inprocess_cache_set_partial_internal(inp
SVN_ERR(move_page_to_front(cache, entry->page));
cache->data_size -= entry->size;
- SVN_ERR(func((char **)&entry->value,
- &entry->size,
- baton,
- entry->page->page_pool));
+ SVN_ERR(func(&entry->value,
+ &entry->size,
+ baton,
+ entry->page->page_pool));
cache->data_size += entry->size;
}