You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by da...@apache.org on 2010/09/09 22:26:52 UTC
svn commit: r995566 [12/16] - in /subversion/branches/atomic-revprop: ./
build/ac-macros/ build/generator/ contrib/server-side/ notes/ notes/wc-ng/
subversion/bindings/javahl/native/
subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversi...
Modified: subversion/branches/atomic-revprop/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/wc_db.h?rev=995566&r1=995565&r2=995566&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/wc_db.h Thu Sep 9 20:26:46 2010
@@ -126,7 +126,7 @@ typedef struct svn_wc__db_t svn_wc__db_t
/* Enumerated constants for how to open a WC datastore. */
-typedef enum {
+typedef enum svn_wc__db_openmode_t {
svn_wc__db_openmode_default, /* Open in the default mode (r/w now). */
svn_wc__db_openmode_readonly, /* Changes will definitely NOT be made. */
svn_wc__db_openmode_readwrite /* Changes will definitely be made. */
@@ -148,7 +148,7 @@ typedef enum {
### cannot simply be added. it would surprise too much code.
### (we could probably create svn_node_kind2_t though)
*/
-typedef enum {
+typedef enum svn_wc__db_kind_t {
/* The node is a directory. */
svn_wc__db_kind_dir,
@@ -162,20 +162,11 @@ typedef enum {
deletion, or incomplete status. */
svn_wc__db_kind_unknown,
- /* This directory node is a placeholder; the actual information is
- held within the subdirectory.
-
- Note: users of this API shouldn't see this kind. It will be
- handled internally to wc_db.
-
- ### only used with per-dir .svn subdirectories. */
- svn_wc__db_kind_subdir
-
} svn_wc__db_kind_t;
/* Enumerated values describing the state of a node. */
-typedef enum {
+typedef enum svn_wc__db_status_t {
/* The node is present and has no known modifications applied to it. */
svn_wc__db_status_normal,
@@ -202,32 +193,6 @@ typedef enum {
will be present. */
svn_wc__db_status_deleted,
- /* The information for this directory node is obstructed by something
- in the local filesystem. Full details are not available.
-
- This is only returned by an unshadowed BASE node. If a WORKING node
- is present, then obstructed_delete or obstructed_add is returned as
- appropriate.
-
- ### only used with per-dir .svn subdirectories. */
- svn_wc__db_status_obstructed,
-
- /* The information for this directory node is obstructed by something
- in the local filesystem. Full details are not available.
-
- The directory has been marked for deletion.
-
- ### only used with per-dir .svn subdirectories. */
- svn_wc__db_status_obstructed_delete,
-
- /* The information for this directory node is obstructed by something
- in the local filesystem. Full details are not available.
-
- The directory has been marked for addition.
-
- ### only used with per-dir .svn subdirectories. */
- svn_wc__db_status_obstructed_add,
-
/* This node was named by the server, but no information was provided. */
svn_wc__db_status_absent,
@@ -259,7 +224,7 @@ typedef enum {
/* Lock information. We write/read it all as one, so let's use a struct
for convenience. */
-typedef struct {
+typedef struct svn_wc__db_lock_t {
/* The lock token */
const char *token;
@@ -347,13 +312,17 @@ svn_wc__db_close(svn_wc__db_t *db);
A REPOSITORY row will be constructed for the repository identified by
REPOS_ROOT_URL and REPOS_UUID. Neither of these may be NULL.
- A node will be created for the directory at REPOS_RELPATH will be added.
+ A BASE_NODE row will be created for the directory at REPOS_RELPATH at
+ revision INITIAL_REV.
If INITIAL_REV is greater than zero, then the node will be marked as
"incomplete" because we don't know its children. Contrary, if the
INITIAL_REV is zero, then this directory should represent the root and
we know it has no children, so the node is complete.
- DEPTH is the initial depth of the working copy, it must be a definite
+ ### Is there any benefit to marking it 'complete' if rev==0? Seems like
+ ### an unnecessary special case.
+
+ DEPTH is the initial depth of the working copy; it must be a definite
depth, not svn_depth_unknown.
Use SCRATCH_POOL for temporary allocations.
@@ -422,6 +391,25 @@ svn_wc__db_get_wcroot(const char **wcroo
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
+typedef svn_error_t * (*svn_wc__db_sqlite_lock_cb)(svn_wc__db_t *db,
+ void *baton,
+ apr_pool_t *scratch_pool);
+
+/* Obtain a sqlite lock to efficiently use the working copy database for
+ WRI_ABSPATH and call LOCK_CB with CB_BATON while this lock exist.
+
+ On returning from this function all operations will be committed, but
+ operations might have been committed before returning from this function.
+
+ ### See svn_sqlite__with_lock() for more details.
+ */
+svn_error_t *
+svn_wc__db_with_sqlite_lock(svn_wc__db_t *db,
+ const char *wri_abspath,
+ svn_wc__db_sqlite_lock_cb lock_cb,
+ void *cb_baton,
+ apr_pool_t *scratch_pool);
+
/* @} */
/* Different kinds of trees
@@ -434,11 +422,16 @@ svn_wc__db_get_wcroot(const char **wcroo
/* @defgroup svn_wc__db_base BASE tree management
- BASE should be what we get from the server. The *absolute* pristine copy.
- Nothing can change it -- it is always a reflection of the repository.
+ BASE is what we get from the server. It is the *absolute* pristine copy.
You need to use checkout, update, switch, or commit to alter your view of
the repository.
+ In the BASE tree, each node corresponds to a particular node-rev in the
+ repository. It can be a mixed-revision tree. Each node holds either a
+ copy of the node-rev as it exists in the repository (if presence =
+ 'normal'), or a place-holder (if presence = 'absent' or 'excluded' or
+ 'not-present').
+
@{
*/
@@ -1669,15 +1662,11 @@ svn_wc__db_is_wcroot(svn_boolean_t *is_r
### Assuming the future ability to copy across repositories, should we
### refrain from resetting the copyfrom information in this operation?
-
- ### SINGLE_DB is a temp argument, and should be TRUE if using compressed
- ### metadata. When *all* metadata gets compressed, it should disappear.
*/
svn_error_t *
svn_wc__db_global_relocate(svn_wc__db_t *db,
const char *local_dir_abspath,
const char *repos_root_url,
- svn_boolean_t single_db,
apr_pool_t *scratch_pool);
@@ -2047,6 +2036,7 @@ svn_wc__db_upgrade_begin(svn_sqlite__db_
svn_error_t *
svn_wc__db_upgrade_apply_dav_cache(svn_sqlite__db_t *sdb,
+ const char *dir_relpath,
apr_hash_t *cache_values,
apr_pool_t *scratch_pool);
@@ -2209,28 +2199,6 @@ svn_wc__db_temp_forget_directory(svn_wc_
apr_pool_t *scratch_pool);
-/* A temporary API similar to svn_wc__db_base_add_directory() and
- svn_wc__db_base_add_file(), in that it adds a subdirectory to the given
- DB. * Arguments are the same as those to svn_wc__db_base_add_directory().
-
- Note: Since the subdir node type is a fiction created to satisfy our
- current backward-compat hacks, this is a temporary API expected to
- disappear with that node type does.
-*/
-svn_error_t *
-svn_wc__db_temp_base_add_subdir(svn_wc__db_t *db,
- const char *local_abspath,
- const char *repos_relpath,
- const char *repos_root_url,
- const char *repos_uuid,
- svn_revnum_t revision,
- const apr_hash_t *props,
- svn_revnum_t changed_rev,
- apr_time_t changed_date,
- const char *changed_author,
- svn_depth_t depth,
- apr_pool_t *scratch_pool);
-
svn_error_t *
svn_wc__db_temp_is_dir_deleted(svn_boolean_t *not_present,
svn_revnum_t *base_revision,
@@ -2399,11 +2367,13 @@ svn_wc__db_temp_get_file_external(const
apr_pool_t *scratch_pool);
+#ifndef SVN_WC__SINGLE_DB
/* Remove a stray "subdir" record in the BASE_NODE table. */
svn_error_t *
svn_wc__db_temp_remove_subdir_record(svn_wc__db_t *db,
const char *local_abspath,
apr_pool_t *scratch_pool);
+#endif
/* Set file external information on LOCAL_ABSPATH to REPOS_RELPATH
at PEG_REV with revision REV*/
@@ -2433,6 +2403,7 @@ svn_wc__db_temp_op_set_property_conflict
const char *prej_basename,
apr_pool_t *scratch_pool);
+#ifndef SVN_WC__SINGLE_DB
/* Ensure that the parent stub of LOCAL_ABSPATH contains a BASE_NODE record with
a normal status and optionally remove the WORKING_NODE record for the node;
this assumes that the parent directory is in the incomplete state, or the
@@ -2446,11 +2417,14 @@ svn_wc__db_temp_set_parent_stub_to_norma
const char *local_abspath,
svn_boolean_t delete_working,
apr_pool_t *scratch_pool);
+#endif
/* Sets a base nodes revision and/or repository relative path. If
LOCAL_ABSPATH's rev (REV) is valid, set is revision and if SET_REPOS_RELPATH
is TRUE set its repository relative path to REPOS_RELPATH (and make sure its
REPOS_ROOT_URL and REPOS_ROOT_UUID are still valid).
+
+ ### TODO(SINGLE_DB): Remove the 'update_stub' argument.
*/
svn_error_t *
svn_wc__db_temp_op_set_rev_and_repos_relpath(svn_wc__db_t *db,
@@ -2490,17 +2464,6 @@ svn_wc__db_drop_root(svn_wc__db_t *db,
const char *local_abspath,
apr_pool_t *scratch_pool);
-/* Internal version of svn_wc__node_get_copyfrom_info */
-svn_error_t *
-svn_wc__internal_get_copyfrom_info(const char **copyfrom_root_url,
- const char **copyfrom_repos_relpath,
- const char **copyfrom_url,
- svn_revnum_t *copyfrom_rev,
- svn_boolean_t *is_copy_target,
- svn_wc__db_t *db,
- const char *local_abspath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool);
/* @} */
Modified: subversion/branches/atomic-revprop/subversion/libsvn_wc/workqueue.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/workqueue.c?rev=995566&r1=995565&r2=995566&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/workqueue.c (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/workqueue.c Thu Sep 9 20:26:46 2010
@@ -49,7 +49,6 @@
* (local_abspath, revnum, date, [author], [checksum],
* [dav_cache/wc_props], keep_changelist, [tmp_text_base_abspath]). */
#define OP_POSTCOMMIT "postcommit"
-#define OP_INSTALL_PROPERTIES "install-properties-2"
#define OP_FILE_INSTALL "file-install"
#define OP_FILE_REMOVE "file-remove"
#define OP_FILE_MOVE "file-move"
@@ -60,6 +59,7 @@
#define OP_TMP_SET_TEXT_CONFLICT_MARKERS "tmp-set-text-conflict-markers"
#define OP_TMP_SET_PROPERTY_CONFLICT_MARKER "tmp-set-property-conflict-marker"
#define OP_PRISTINE_GET_TRANSLATED "pristine-get-translated"
+#define OP_POSTUPGRADE "postupgrade"
/* For work queue debugging. Generates output about its operation. */
/* #define DEBUG_WORK_QUEUE */
@@ -184,6 +184,7 @@ run_revert(svn_wc__db_t *db,
const char *local_abspath;
svn_boolean_t replaced;
svn_wc__db_kind_t kind;
+ svn_wc__db_status_t status;
const char *parent_abspath;
svn_boolean_t conflicted;
@@ -197,7 +198,7 @@ run_revert(svn_wc__db_t *db,
(yet) allowed. If we read any conflict files, then we (obviously) have
not removed them from the metadata (yet). */
SVN_ERR(svn_wc__db_read_info(
- NULL, &kind, NULL, NULL, NULL, NULL,
+ &status, &kind, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
&conflicted, NULL,
@@ -349,8 +350,22 @@ run_revert(svn_wc__db_t *db,
/* ### A working copy root can't have a working node and trying
### to delete it fails because the root doesn't have a stub. */
if (!is_wc_root)
- SVN_ERR(svn_wc__db_temp_op_remove_working(db, local_abspath,
- scratch_pool));
+ {
+ const char *op_root_abspath = NULL;
+
+ /* If the node is not the operation root, we should not delete
+ the working node */
+ if (status == svn_wc__db_status_added)
+ SVN_ERR(svn_wc__db_scan_addition(NULL, &op_root_abspath, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ db, local_abspath,
+ scratch_pool, scratch_pool));
+
+ if (!op_root_abspath
+ || (strcmp(op_root_abspath, local_abspath) == 0))
+ SVN_ERR(svn_wc__db_temp_op_remove_working(db, local_abspath,
+ scratch_pool));
+ }
}
return SVN_NO_ERROR;
@@ -369,14 +384,6 @@ verify_pristine_present(svn_wc__db_t *db
{
const svn_checksum_t *base_checksum;
- SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
- &base_checksum, NULL, NULL, NULL,
- db, local_abspath,
- scratch_pool, scratch_pool));
- if (base_checksum != NULL)
- return SVN_NO_ERROR;
-
SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, &base_checksum,
NULL, NULL, NULL, NULL, NULL, NULL,
@@ -386,6 +393,14 @@ verify_pristine_present(svn_wc__db_t *db
if (base_checksum != NULL)
return SVN_NO_ERROR;
+ SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ &base_checksum, NULL, NULL, NULL,
+ db, local_abspath,
+ scratch_pool, scratch_pool));
+ if (base_checksum != NULL)
+ return SVN_NO_ERROR;
+
/* A real file must have either a regular or a revert text-base.
If it has neither, we could be looking at the situation described
in issue #2101, in which case all we can do is deliver the expected
@@ -719,7 +734,9 @@ remove_base_node(svn_wc__db_t *db,
if (base_status == svn_wc__db_status_normal
&& wrk_status != svn_wc__db_status_added
+#ifndef SVN_WC__SINGLE_DB
&& wrk_status != svn_wc__db_status_obstructed_add
+#endif
&& wrk_status != svn_wc__db_status_excluded)
{
#ifndef SVN_WC__SINGLE_DB
@@ -756,7 +773,9 @@ remove_base_node(svn_wc__db_t *db,
SVN_ERR(svn_wc__db_temp_op_remove_entry(db, local_abspath, scratch_pool));
}
else if (wrk_status == svn_wc__db_status_added
+#ifndef SVN_WC__SINGLE_DB
|| wrk_status == svn_wc__db_status_obstructed_add
+#endif
|| (have_work && wrk_status == svn_wc__db_status_excluded))
/* ### deletes of working additions should fall in this case, but
### we can't express these without the 4th tree */
@@ -1279,7 +1298,10 @@ log_do_committed(svn_wc__db_t *db,
/* Committing a deletion should remove the local nodes. */
if (child_status == svn_wc__db_status_deleted
- || child_status == svn_wc__db_status_obstructed_delete)
+#ifndef SVN_WC__SINGLE_DB
+ || child_status == svn_wc__db_status_obstructed_delete
+#endif
+ )
{
SVN_ERR(svn_wc__internal_remove_from_revision_control(
db, child_abspath,
@@ -1321,9 +1343,6 @@ log_do_committed(svn_wc__db_t *db,
set_read_write = TRUE;
}
}
-
- /* Install LOCAL_ABSPATHs working props as base props. */
- SVN_ERR(svn_wc__working_props_committed(db, local_abspath, pool));
}
/* If it's a file, install the tree changes and the file's text. */
@@ -1445,9 +1464,11 @@ log_do_committed(svn_wc__db_t *db,
return SVN_NO_ERROR;
}
+#ifndef SVN_WC__SINGLE_DB
/* Make sure we have a parent stub in a clean/unmodified state. */
SVN_ERR(svn_wc__db_temp_set_parent_stub_to_normal(db, local_abspath,
TRUE, scratch_pool));
+#endif
return SVN_NO_ERROR;
}
@@ -1590,118 +1611,33 @@ svn_wc__wq_add_postcommit(svn_wc__db_t *
}
/* ------------------------------------------------------------------------ */
+/* OP_POSTUPGRADE */
-/* OP_INSTALL_PROPERTIES */
-
-/* See props.h */
-#ifdef SVN__SUPPORT_BASE_MERGE
-
-/* Process the OP_INSTALL_PROPERTIES work item WORK_ITEM.
- * See svn_wc__wq_add_install_properties() which generates this work item.
- * Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_install_properties(svn_wc__db_t *db,
- const svn_skel_t *work_item,
- const char *wri_abspath,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *scratch_pool)
+run_postupgrade(svn_wc__db_t *db,
+ const svn_skel_t *work_item,
+ const char *wri_abspath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
{
- const svn_skel_t *arg = work_item->children->next;
- const char *local_abspath;
- apr_hash_t *base_props;
- apr_hash_t *actual_props;
-
- /* We need a NUL-terminated path, so copy it out of the skel. */
- local_abspath = apr_pstrmemdup(scratch_pool, arg->data, arg->len);
-
- arg = arg->next;
- if (arg->is_atom)
- base_props = NULL;
- else
- SVN_ERR(svn_skel__parse_proplist(&base_props, arg, scratch_pool));
-
- arg = arg->next;
- if (arg->is_atom)
- actual_props = NULL;
- else
- SVN_ERR(svn_skel__parse_proplist(&actual_props, arg, scratch_pool));
-
- if (base_props != NULL)
- {
- svn_boolean_t written = FALSE;
-
- {
- svn_error_t *err;
-
- /* Try writing to the WORKING tree first. */
- err = svn_wc__db_temp_working_set_props(db, local_abspath,
- base_props,
- scratch_pool);
- if (err)
- {
- if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
- return svn_error_return(err);
- svn_error_clear(err);
- /* The WORKING node is not present. */
- }
- else
- {
- /* The WORKING node is present, and we wrote the props. */
- written = TRUE;
- }
- }
-
- if (!written)
- SVN_ERR(svn_wc__db_temp_base_set_props(db, local_abspath,
- base_props, scratch_pool));
- }
-
- /* Okay. It's time to save the ACTUAL props. */
- SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, actual_props,
- NULL, NULL, scratch_pool));
+ SVN_ERR(svn_wc__wipe_postupgrade(wri_abspath, FALSE,
+ cancel_func, cancel_baton, scratch_pool));
return SVN_NO_ERROR;
}
-
svn_error_t *
-svn_wc__wq_add_install_properties(svn_wc__db_t *db,
- const char *local_abspath,
- apr_hash_t *base_props,
- apr_hash_t *actual_props,
- apr_pool_t *scratch_pool)
+svn_wc__wq_build_postupgrade(svn_skel_t **work_item,
+ apr_pool_t *result_pool)
{
- svn_skel_t *work_item = svn_skel__make_empty_list(scratch_pool);
- svn_skel_t *props;
-
- if (actual_props != NULL)
- {
- SVN_ERR(svn_skel__unparse_proplist(&props, actual_props, scratch_pool));
- svn_skel__prepend(props, work_item);
- }
- else
- svn_skel__prepend_str("", work_item, scratch_pool);
-
- if (base_props != NULL)
- {
- SVN_ERR(svn_skel__unparse_proplist(&props, base_props, scratch_pool));
- svn_skel__prepend(props, work_item);
- }
- else
- svn_skel__prepend_str("", work_item, scratch_pool);
-
- svn_skel__prepend_str(local_abspath, work_item, scratch_pool);
- svn_skel__prepend_str(OP_INSTALL_PROPERTIES, work_item, scratch_pool);
+ *work_item = svn_skel__make_empty_list(result_pool);
- SVN_ERR(svn_wc__db_wq_add(db, local_abspath, work_item, scratch_pool));
+ svn_skel__prepend_str(OP_POSTUPGRADE, *work_item, result_pool);
return SVN_NO_ERROR;
}
-#endif /* SVN__SUPPORT_BASE_MERGE */
-
-
/* ------------------------------------------------------------------------ */
/* OP_FILE_INSTALL */
@@ -2486,16 +2422,12 @@ static const struct work_item_dispatch d
{ OP_TMP_SET_TEXT_CONFLICT_MARKERS, run_set_text_conflict_markers },
{ OP_TMP_SET_PROPERTY_CONFLICT_MARKER, run_set_property_conflict_marker },
{ OP_PRISTINE_GET_TRANSLATED, run_pristine_get_translated },
+ { OP_POSTUPGRADE, run_postupgrade },
#ifndef SVN_WC__SINGLE_DB
{ OP_KILLME, run_killme },
#endif
-/* See props.h */
-#ifdef SVN__SUPPORT_BASE_MERGE
- { OP_INSTALL_PROPERTIES, run_install_properties },
-#endif
-
/* Sentinel. */
{ NULL }
};
Modified: subversion/branches/atomic-revprop/subversion/libsvn_wc/workqueue.h
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/workqueue.h?rev=995566&r1=995565&r2=995566&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/workqueue.h (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/workqueue.h Thu Sep 9 20:26:46 2010
@@ -301,17 +301,9 @@ svn_wc__wq_add_postcommit(svn_wc__db_t *
svn_boolean_t no_unlock,
apr_pool_t *scratch_pool);
-
-/* See props.h */
-#ifdef SVN__SUPPORT_BASE_MERGE
svn_error_t *
-svn_wc__wq_add_install_properties(svn_wc__db_t *db,
- const char *local_abspath,
- apr_hash_t *pristine_props,
- apr_hash_t *actual_props,
- apr_pool_t *scratch_pool);
-#endif
-
+svn_wc__wq_build_postupgrade(svn_skel_t **work_item,
+ apr_pool_t *scratch_pool);
#ifdef __cplusplus
}
Modified: subversion/branches/atomic-revprop/subversion/mod_dav_svn/dav_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/mod_dav_svn/dav_svn.h?rev=995566&r1=995565&r2=995566&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/mod_dav_svn/dav_svn.h (original)
+++ subversion/branches/atomic-revprop/subversion/mod_dav_svn/dav_svn.h Thu Sep 9 20:26:46 2010
@@ -37,6 +37,7 @@
#include "svn_path.h"
#include "svn_xml.h"
#include "private/svn_dav_protocol.h"
+#include "private/svn_skel.h"
#include "mod_authz_svn.h"
#ifdef __cplusplus
@@ -419,7 +420,7 @@ dav_svn__store_activity(const dav_svn_re
const char *txn_name);
-/* HTTP protocol v2: client does POST against 'me' resource. */
+/* POST request handler. (Used by HTTP protocol v2 clients only.) */
int dav_svn__method_post(request_rec *r);
@@ -640,6 +641,23 @@ dav_svn__get_deleted_rev_report(const da
const apr_xml_doc *doc,
ap_filter_t *output);
+
+/*** posts/ ***/
+
+/* The list of Subversion's custom POSTs. */
+/* ### should move these report names to a public header to share with
+ ### the client (and third parties). */
+static const char * dav_svn__posts_list[] = {
+ "create-txn",
+ NULL
+};
+
+/* The various POST handlers, defined in posts/, and used by repos.c. */
+dav_error *
+dav_svn__post_create_txn(const dav_resource *resource,
+ svn_skel_t *request_skel,
+ ap_filter_t *output);
+
/*** authz.c ***/
/* A baton needed by dav_svn__authz_read_func(). */
@@ -890,6 +908,13 @@ dav_svn__final_flush_or_error(request_re
*/
int dav_svn__error_response_tag(request_rec *r, dav_error *err);
+
+/* Set *SKEL to a parsed skel read from the body of request R, and
+ * allocated in POOL.
+ */
+int dav_svn__parse_request_skel(svn_skel_t **skel, request_rec *r,
+ apr_pool_t *pool);
+
/*** mirror.c ***/
/* Perform the fixup hook for the R request. */
Modified: subversion/branches/atomic-revprop/subversion/mod_dav_svn/deadprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/mod_dav_svn/deadprops.c?rev=995566&r1=995565&r2=995566&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/mod_dav_svn/deadprops.c (original)
+++ subversion/branches/atomic-revprop/subversion/mod_dav_svn/deadprops.c Thu Sep 9 20:26:46 2010
@@ -392,7 +392,7 @@ db_output_value(dav_db *db,
const svn_string_t *enc_propval
= svn_base64_encode_string2(propval, TRUE, pool);
xml_safe = enc_propval->data;
- encoding = apr_pstrcat(pool, " V:encoding=\"base64\"", NULL);
+ encoding = " V:encoding=\"base64\"";
}
else
{
Propchange: subversion/branches/atomic-revprop/subversion/mod_dav_svn/posts/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Sep 9 20:26:46 2010
@@ -0,0 +1 @@
+.libs
Modified: subversion/branches/atomic-revprop/subversion/mod_dav_svn/reports/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/mod_dav_svn/reports/log.c?rev=995566&r1=995565&r2=995566&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/mod_dav_svn/reports/log.c (original)
+++ subversion/branches/atomic-revprop/subversion/mod_dav_svn/reports/log.c Thu Sep 9 20:26:46 2010
@@ -311,7 +311,17 @@ dav_svn__log_report(const dav_resource *
else if (strcmp(child->name, "end-revision") == 0)
end = SVN_STR_TO_REV(dav_xml_get_cdata(child, resource->pool, 1));
else if (strcmp(child->name, "limit") == 0)
- limit = atoi(dav_xml_get_cdata(child, resource->pool, 1));
+ {
+ serr = svn_cstring_atoi(&limit,
+ dav_xml_get_cdata(child, resource->pool, 1));
+ if (serr)
+ {
+ derr = dav_svn__convert_err(serr, HTTP_BAD_REQUEST,
+ "Malformed CDATA in element "
+ "\"limit\"", resource->pool);
+ goto cleanup;
+ }
+ }
else if (strcmp(child->name, "discover-changed-paths") == 0)
discover_changed_paths = TRUE; /* presence indicates positivity */
else if (strcmp(child->name, "strict-node-history") == 0)
Modified: subversion/branches/atomic-revprop/subversion/mod_dav_svn/reports/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/mod_dav_svn/reports/replay.c?rev=995566&r1=995565&r2=995566&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/mod_dav_svn/reports/replay.c (original)
+++ subversion/branches/atomic-revprop/subversion/mod_dav_svn/reports/replay.c Thu Sep 9 20:26:46 2010
@@ -466,10 +466,18 @@ dav_svn__replay_report(const dav_resourc
}
else if (strcmp(child->name, "send-deltas") == 0)
{
+ apr_int64_t parsed_val;
+
cdata = dav_xml_get_cdata(child, resource->pool, 1);
if (! cdata)
return malformed_element_error("send-deltas", resource->pool);
- send_deltas = atoi(cdata);
+ err = svn_cstring_strtoi64(&parsed_val, cdata, 0, 1, 10);
+ if (err)
+ {
+ svn_error_clear(err);
+ return malformed_element_error("send-deltas", resource->pool);
+ }
+ send_deltas = parsed_val ? TRUE : FALSE;
}
}
}
Modified: subversion/branches/atomic-revprop/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/mod_dav_svn/repos.c?rev=995566&r1=995565&r2=995566&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/mod_dav_svn/repos.c (original)
+++ subversion/branches/atomic-revprop/subversion/mod_dav_svn/repos.c Thu Sep 9 20:26:46 2010
@@ -44,6 +44,7 @@
#include "svn_sorts.h"
#include "svn_version.h"
#include "svn_props.h"
+#include "svn_ctype.h"
#include "mod_dav_svn.h"
#include "svn_ra.h" /* for SVN_RA_CAPABILITY_* */
#include "svn_dirent_uri.h"
@@ -1519,7 +1520,7 @@ static const char *get_entry(apr_pool_t
/* Look for 'var = value' --- and make sure the var is in lcase. */
- for (cp = parm; (*cp && !apr_isspace(*cp) && *cp != '='); ++cp)
+ for (cp = parm; (*cp && !svn_ctype_isspace(*cp) && *cp != '='); ++cp)
{
*cp = apr_tolower(*cp);
}
@@ -1530,7 +1531,7 @@ static const char *get_entry(apr_pool_t
}
*cp++ = '\0'; /* Delimit var */
- while (*cp && (apr_isspace(*cp) || *cp == '='))
+ while (*cp && (svn_ctype_isspace(*cp) || *cp == '='))
{
++cp;
}
@@ -1544,7 +1545,7 @@ static const char *get_entry(apr_pool_t
}
else
{
- for (end = cp; (*end && !apr_isspace(*end)); end++);
+ for (end = cp; (*end && !svn_ctype_isspace(*end)); end++);
}
if (*end)
{
@@ -4263,58 +4264,73 @@ dav_svn__create_version_resource(dav_res
}
-/* POST handler for HTTP protocol v2.
-
- Currently we allow POSTs only against the "me resource", which may
- in the future act as a dispatcher of sorts for handling potentially
- many different kinds of operations as specified by the body of the
- POST request itself.
-
- ### TODO: Define what the format of those POST bodies might be. If
- ### XML, we have access to Apache's streamy XML parsing code, but
- ### ... it's XML. Meh. If skels, we get skels! But we need to
- ### write our own streamy skel parsing routine around a brigade
- ### read loop. Ewww...
- ###
- ### Today we only support transaction creation requests, but we
- ### could conceivable support the likes of a multi-path lock
- ### and/or unlock request, or some other thing for which stock
- ### WebDAV doesn't work or doesn't work well enough.
- ###
- ### Fortunately, today we don't use the POST body at all, and we'll
- ### be able to get away with not defining the body format in the
- ### future thanks to the following:
-
- As a special consideration, an empty POST body is interpreted as a
- simple request to create a new commit transaction based on the HEAD
- revision. The new transaction name will be returned via a custom
- response header SVN_DAV_TXN_NAME_HEADER.
-*/
+
+static dav_error *
+handle_post_request(request_rec *r,
+ dav_resource *resource,
+ ap_filter_t *output)
+{
+ svn_skel_t *request_skel;
+ int status;
+ apr_pool_t *pool = resource->pool;
+
+ /* Make sure our skel-based request parses okay, has an initial atom
+ that identifies what kind of action is expected, and that that
+ action is something we understand. */
+ status = dav_svn__parse_request_skel(&request_skel, r, pool);
+
+ if (status != OK)
+ return dav_new_error(pool, status, 0,
+ "Error parsing skel POST request body.");
+
+ if (svn_skel__list_length(request_skel) < 1)
+ return dav_new_error(pool, HTTP_BAD_REQUEST, 0,
+ "Unable to identify skel POST request flavor.");
+
+ if (svn_skel__matches_atom(request_skel->children, "create-txn"))
+ {
+ return dav_svn__post_create_txn(resource, request_skel, output);
+ }
+ else
+ {
+ return dav_new_error(pool, HTTP_BAD_REQUEST, 0,
+ "Unsupported skel POST request flavor.");
+ }
+ /* NOTREACHED */
+}
+
int dav_svn__method_post(request_rec *r)
{
dav_resource *resource;
dav_error *derr;
- const char *txn_name;
+ const char *content_type;
+ /* We only allow POSTs against the "me resource" right now. */
derr = get_resource(r, dav_svn__get_root_dir(r),
"ignored", 0, &resource);
if (derr != NULL)
return derr->status;
-
if (resource->info->restype != DAV_SVN_RESTYPE_ME)
return HTTP_BAD_REQUEST;
- /* Create a Subversion repository transaction based on HEAD. */
- derr = dav_svn__create_txn(resource->info->repos, &txn_name, resource->pool);
+ /* Pass skel-type POST request handling off to a dispatcher; any
+ other type of request is considered bogus. */
+ content_type = apr_table_get(r->headers_in, "content-type");
+ if (content_type && (strcmp(content_type, SVN_SKEL_MIME_TYPE) == 0))
+ {
+ derr = handle_post_request(r, resource, r->output_filters);
+ }
+ else
+ {
+ derr = dav_new_error(resource->pool, HTTP_BAD_REQUEST, 0,
+ "Unsupported POST request type.");
+ }
+
+ /* If something went wrong above, we'll generate a response back to
+ the client with (hopefully) some helpful information. */
if (derr)
return dav_svn__error_response_tag(r, derr);
-
- /* Build a "201 Created" response with header that tells the client
- our new transaction's name. */
- apr_table_set(resource->info->r->headers_out, SVN_DAV_TXN_NAME_HEADER,
- txn_name);
- r->status = HTTP_CREATED;
-
+
return OK;
}
Modified: subversion/branches/atomic-revprop/subversion/mod_dav_svn/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/mod_dav_svn/util.c?rev=995566&r1=995565&r2=995566&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/mod_dav_svn/util.c (original)
+++ subversion/branches/atomic-revprop/subversion/mod_dav_svn/util.c Thu Sep 9 20:26:46 2010
@@ -28,6 +28,7 @@
#include <mod_dav.h>
#include <http_protocol.h>
+#include <http_core.h>
#include "svn_error.h"
#include "svn_fs.h"
@@ -611,3 +612,140 @@ dav_svn__error_response_tag(request_rec
*/
return DONE;
}
+
+
+/* Set *REQUEST_STR to a string containing the contents of the body of
+ request R, allocated from POOL.
+
+ NOTE: This was shamelessly stolen and modified from Apache's
+ ap_xml_parse_input(). */
+static int
+request_body_to_string(svn_string_t **request_str,
+ request_rec *r,
+ apr_pool_t *pool)
+{
+ apr_bucket_brigade *brigade;
+ int seen_eos;
+ apr_status_t status;
+ apr_off_t total_read = 0;
+ apr_off_t limit_req_body = ap_get_limit_req_body(r);
+ int result = HTTP_BAD_REQUEST;
+ const char *content_length_str;
+ char *endp;
+ apr_off_t content_length;
+ svn_stringbuf_t *buf;
+
+ *request_str = NULL;
+
+ content_length_str = apr_table_get(r->headers_in, "Content-Length");
+ if (content_length_str)
+ {
+ if (apr_strtoff(&content_length, content_length_str, &endp, 10)
+ || endp == content_length_str || *endp || content_length < 0)
+ {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Invalid Content-Length");
+ return HTTP_REQUEST_ENTITY_TOO_LARGE;
+ }
+ }
+ else
+ content_length = 0;
+
+ if (limit_req_body && (limit_req_body < content_length))
+ {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Requested content-length of %" APR_OFF_T_FMT " is larger "
+ "than the configured limit of %" APR_OFF_T_FMT,
+ content_length, limit_req_body);
+ return HTTP_REQUEST_ENTITY_TOO_LARGE;
+ }
+
+ if (content_length)
+ {
+ buf = svn_stringbuf_create_ensure(content_length, pool);
+ }
+ else
+ {
+ buf = svn_stringbuf_create("", pool);
+ }
+
+ brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+ seen_eos = 0;
+ total_read = 0;
+
+ do
+ {
+ apr_bucket *bucket;
+
+ status = ap_get_brigade(r->input_filters, brigade, AP_MODE_READBYTES,
+ APR_BLOCK_READ, 2048);
+ if (status != APR_SUCCESS)
+ goto cleanup;
+
+ for (bucket = APR_BRIGADE_FIRST(brigade);
+ bucket != APR_BRIGADE_SENTINEL(brigade);
+ bucket = APR_BUCKET_NEXT(bucket))
+ {
+ const char *data;
+ apr_size_t len;
+
+ if (APR_BUCKET_IS_EOS(bucket))
+ {
+ seen_eos = 1;
+ break;
+ }
+
+ if (APR_BUCKET_IS_METADATA(bucket))
+ continue;
+
+ status = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
+ if (status != APR_SUCCESS)
+ goto cleanup;
+
+ total_read += len;
+ if (limit_req_body && total_read > limit_req_body)
+ {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Request body is larger than the configured "
+ "limit of %lu", (unsigned long)limit_req_body);
+ result = HTTP_REQUEST_ENTITY_TOO_LARGE;
+ goto cleanup;
+ }
+
+ svn_stringbuf_appendbytes(buf, data, len);
+ }
+
+ apr_brigade_cleanup(brigade);
+ }
+ while (!seen_eos);
+
+ apr_brigade_destroy(brigade);
+
+ /* Make an svn_string_t from our svn_stringbuf_t. */
+ *request_str = svn_string_create("", pool);
+ (*request_str)->data = buf->data;
+ (*request_str)->len = buf->len;
+ return OK;
+
+ cleanup:
+ apr_brigade_destroy(brigade);
+
+ /* Apache will supply a default error, plus the error log above. */
+ return result;
+}
+
+int
+dav_svn__parse_request_skel(svn_skel_t **skel,
+ request_rec *r,
+ apr_pool_t *pool)
+{
+ svn_string_t *skel_str;
+ int status;
+
+ *skel = NULL;
+ status = request_body_to_string(&skel_str, r, pool);
+ if (status != OK)
+ return OK;
+
+ *skel = svn_skel__parse(skel_str->data, skel_str->len, pool);
+ return OK;
+}
Modified: subversion/branches/atomic-revprop/subversion/mod_dav_svn/version.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/mod_dav_svn/version.c?rev=995566&r1=995565&r2=995566&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/mod_dav_svn/version.c (original)
+++ subversion/branches/atomic-revprop/subversion/mod_dav_svn/version.c Thu Sep 9 20:26:46 2010
@@ -41,6 +41,7 @@
#include "private/svn_log.h"
#include "dav_svn.h"
+#include "mod_dav_svn.h"
svn_error_t *
@@ -1015,6 +1016,22 @@ deliver_report(request_rec *r,
if (doc->root->ns == ns)
{
+ const char *cleaned_uri, *relative_path, *repos_path;
+ int trailing_slash;
+ /* During SVNPathAuthz short_circuit
+ * resource->info->repos->repo_name becomes NULL.*/
+ if (resource->info->repos->repo_name == NULL)
+ {
+ dav_error *err;
+ err = dav_svn_split_uri(r, r->uri, dav_svn__get_root_dir(r),
+ &cleaned_uri, &trailing_slash,
+ &(resource->info->repos->repo_name),
+ &relative_path, &repos_path);
+ if (err)
+ {
+ return err;
+ }
+ }
/* ### note that these report names should have symbols... */
if (strcmp(doc->root->name, "update-report") == 0)