You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2015/01/21 17:22:22 UTC
svn commit: r1653578 [16/18] - in /subversion/branches/pin-externals: ./
notes/ subversion/bindings/swig/ subversion/bindings/swig/include/
subversion/bindings/swig/perl/native/ subversion/bindings/swig/perl/native/t/
subversion/bindings/swig/python/te...
Modified: subversion/branches/pin-externals/subversion/libsvn_wc/wc_db_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_wc/wc_db_private.h?rev=1653578&r1=1653577&r2=1653578&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/libsvn_wc/wc_db_private.h (original)
+++ subversion/branches/pin-externals/subversion/libsvn_wc/wc_db_private.h Wed Jan 21 16:22:19 2015
@@ -216,6 +216,13 @@ svn_wc__db_util_open_db(svn_sqlite__db_t
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
+/* Like svn_wc__db_wq_add() but taking WCROOT */
+svn_error_t *
+svn_wc__db_wq_add_internal(svn_wc__db_wcroot_t *wcroot,
+ const svn_skel_t *work_item,
+ apr_pool_t *scratch_pool);
+
+
/* Like svn_wc__db_read_info(), but taking WCROOT+LOCAL_RELPATH instead of
DB+LOCAL_ABSPATH, and outputting repos ids instead of URL+UUID. */
svn_error_t *
Modified: subversion/branches/pin-externals/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_wc/wc_db_update_move.c?rev=1653578&r1=1653577&r2=1653578&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/branches/pin-externals/subversion/libsvn_wc/wc_db_update_move.c Wed Jan 21 16:22:19 2015
@@ -101,6 +101,20 @@
#include "token-map.h"
/* Helper functions */
+/* Return the absolute path, in local path style, of LOCAL_RELPATH
+ in WCROOT. */
+static const char *
+path_for_error_message(const svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *result_pool)
+{
+ const char *local_abspath
+ = svn_dirent_join(wcroot->abspath, local_relpath, result_pool);
+
+ return svn_dirent_local_style(local_abspath, result_pool);
+}
+
+/* Ensure that there is a working copy lock for LOCAL_RELPATH in WCROOT */
static svn_error_t *
verify_write_lock(svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
@@ -114,11 +128,8 @@ verify_write_lock(svn_wc__db_wcroot_t *w
{
return svn_error_createf(SVN_ERR_WC_NOT_LOCKED, NULL,
_("No write-lock in '%s'"),
- svn_dirent_local_style(
- svn_dirent_join(wcroot->abspath,
- local_relpath,
- scratch_pool),
- scratch_pool));
+ path_for_error_message(wcroot, local_relpath,
+ scratch_pool));
}
return SVN_NO_ERROR;
@@ -308,7 +319,7 @@ mark_tree_conflict(const char *local_rel
&& conflict_operation != svn_wc_operation_switch)
return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
_("'%s' already in conflict"),
- svn_dirent_local_style(local_relpath,
+ path_for_error_message(wcroot, local_relpath,
scratch_pool));
if (tree_conflicted)
@@ -332,7 +343,8 @@ mark_tree_conflict(const char *local_rel
existing_abspath))))
return svn_error_createf(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
_("'%s' already in conflict"),
- svn_dirent_local_style(local_relpath,
+ path_for_error_message(wcroot,
+ local_relpath,
scratch_pool));
/* Already a suitable tree-conflict. */
@@ -396,28 +408,33 @@ mark_tree_conflict(const char *local_rel
/* Checks if a specific local path is shadowed as seen from the move root */
static svn_error_t *
check_node_shadowed(svn_boolean_t *shadowed,
- update_move_baton_t *b,
+ svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
+ const char *move_root_dst_relpath,
apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
- int op_depth = -1;
- *shadowed = FALSE;
/* ### This should really be optimized by using something smart
in the baton */
- SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_SELECT_WORKING_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", b->wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+
SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
if (have_row)
- op_depth = svn_sqlite__column_int(stmt, 0);
- SVN_ERR(svn_sqlite__reset(stmt));
+ {
+ int op_depth = -1;
- *shadowed = (op_depth > relpath_depth(b->move_root_dst_relpath));
+ *shadowed = (op_depth > relpath_depth(move_root_dst_relpath));
+ }
+ else
+ *shadowed = FALSE;
+ SVN_ERR(svn_sqlite__reset(stmt));
return SVN_NO_ERROR;
}
@@ -576,8 +593,7 @@ tc_editor_add_directory(update_move_bato
SVN_ERR(svn_wc__wq_build_dir_install(&work_item, b->db, abspath,
scratch_pool, scratch_pool));
- SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_item,
- scratch_pool));
+ SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_item, scratch_pool));
/* Fall through */
case svn_node_dir:
break;
@@ -663,8 +679,7 @@ tc_editor_add_file(update_move_baton_t *
TRUE /* record_file_info */,
scratch_pool, scratch_pool));
- SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_item,
- scratch_pool));
+ SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_item, scratch_pool));
SVN_ERR(update_move_list_add(b->wcroot, relpath,
svn_wc_notify_update_add,
@@ -867,8 +882,8 @@ tc_editor_alter_directory(update_move_ba
SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, dst_relpath,
conflict_skel,
scratch_pool));
- SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_items,
- scratch_pool));
+ SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_items,
+ scratch_pool));
}
SVN_ERR(update_move_list_add(b->wcroot, dst_relpath,
@@ -1003,8 +1018,7 @@ update_working_file(update_move_baton_t
work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
}
- SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_items,
- scratch_pool));
+ SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_items, scratch_pool));
SVN_ERR(update_move_list_add(b->wcroot, local_relpath,
svn_wc_notify_update_update,
@@ -1182,8 +1196,7 @@ tc_editor_delete(update_move_baton_t *b,
b->wcroot->abspath, del_abspath,
iterpool, iterpool);
if (!err)
- err = svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_item,
- iterpool);
+ err = svn_wc__db_wq_add_internal(b->wcroot, work_item, iterpool);
if (err)
return svn_error_compose_create(err, svn_sqlite__reset(stmt));
@@ -1205,8 +1218,7 @@ tc_editor_delete(update_move_baton_t *b,
SVN_ERR(svn_wc__wq_build_file_remove(&work_item, b->db,
b->wcroot->abspath, local_abspath,
iterpool, iterpool));
- SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_item,
- iterpool));
+ SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_item, iterpool));
if (!is_conflicted)
SVN_ERR(update_move_list_add(b->wcroot, relpath,
@@ -1221,23 +1233,23 @@ tc_editor_delete(update_move_baton_t *b,
/* Delete handling for both WORKING and shadowed nodes */
static svn_error_t *
-delete_move_leaf(update_move_baton_t *b,
- const char *relpath,
+delete_move_leaf(svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ int op_depth,
apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
- int op_depth = relpath_depth(b->move_root_dst_relpath);
- const char *parent_relpath = svn_relpath_dirname(relpath, scratch_pool);
svn_boolean_t have_row;
int op_depth_below;
- /* Deleting the ROWS is valid so long as we update the parent before
+ /* Deleting the ROWS is valid as long as we update the parent before
committing the transaction. The removed rows could have been
replacing a lower layer in which case we need to add base-deleted
rows. */
- SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_SELECT_HIGHEST_WORKING_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, parent_relpath,
+ SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
+ svn_relpath_dirname(local_relpath, scratch_pool),
op_depth));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
if (have_row)
@@ -1246,30 +1258,38 @@ delete_move_leaf(update_move_baton_t *b,
if (have_row)
{
/* Remove non-shadowing nodes. */
- SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_DELETE_NO_LOWER_LAYER));
- SVN_ERR(svn_sqlite__bindf(stmt, "isdd", b->wcroot->wc_id, relpath,
+ SVN_ERR(svn_sqlite__bindf(stmt, "isdd", wcroot->wc_id, local_relpath,
op_depth, op_depth_below));
SVN_ERR(svn_sqlite__step_done(stmt));
/* Convert remaining shadowing nodes to presence='base-deleted'. */
- SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_REPLACE_WITH_BASE_DELETED));
- SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, relpath,
+ SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
op_depth));
SVN_ERR(svn_sqlite__step_done(stmt));
}
else
{
- SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_DELETE_WORKING_OP_DEPTH));
- SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, relpath,
+ SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
op_depth));
SVN_ERR(svn_sqlite__step_done(stmt));
}
- /* Retract any base-delete. */
- SVN_ERR(svn_wc__db_retract_parent_delete(b->wcroot, relpath, op_depth,
+ /* Retract any base-delete for descendants. */
+ {
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_DELETE_WORKING_BASE_DELETE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
+ op_depth));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+ }
+ /* And for the node itself */
+ SVN_ERR(svn_wc__db_retract_parent_delete(wcroot, local_relpath, op_depth,
scratch_pool));
return SVN_NO_ERROR;
@@ -1492,6 +1512,9 @@ update_moved_away_node(update_move_baton
apr_array_header_t *src_children, *dst_children;
int dst_op_depth = relpath_depth(move_root_dst_relpath);
+ SVN_ERR(verify_write_lock(wcroot, src_relpath, scratch_pool));
+ SVN_ERR(verify_write_lock(wcroot, dst_relpath, scratch_pool));
+
SVN_ERR(get_info(&src_props, &src_checksum, &src_children, &src_kind,
src_relpath, src_op_depth,
wcroot, scratch_pool, scratch_pool));
@@ -1508,7 +1531,9 @@ update_moved_away_node(update_move_baton
/* And perform some work that in some ways belongs in
replace_moved_layer() after creating all conflicts */
- SVN_ERR(delete_move_leaf(b, dst_relpath, scratch_pool));
+ SVN_ERR(delete_move_leaf(b->wcroot, dst_relpath,
+ relpath_depth(b->move_root_dst_relpath),
+ scratch_pool));
}
if (src_kind != svn_node_none && src_kind != dst_kind)
@@ -1609,8 +1634,8 @@ update_moved_away_node(update_move_baton
iterpool);
if (!child_shadowed)
- SVN_ERR(check_node_shadowed(&child_shadowed, b, dst_child_relpath,
- iterpool));
+ SVN_ERR(check_node_shadowed(&child_shadowed, wcroot, dst_child_relpath,
+ b->move_root_dst_relpath, iterpool));
SVN_ERR(update_moved_away_node(b, wcroot, src_child_relpath,
dst_child_relpath, src_op_depth,
@@ -1641,6 +1666,9 @@ replace_moved_layer(const char *src_relp
svn_boolean_t have_row;
int dst_op_depth = relpath_depth(dst_relpath);
+ SVN_ERR(verify_write_lock(wcroot, src_relpath, scratch_pool));
+ SVN_ERR(verify_write_lock(wcroot, dst_relpath, scratch_pool));
+
/* Replace entire subtree at one op-depth. */
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_SELECT_LOCAL_RELPATH_OP_DEPTH));
@@ -1719,10 +1747,8 @@ drive_tree_conflict_editor(update_move_b
operation != svn_wc_operation_switch)
return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
_("Cannot auto-resolve tree-conflict on '%s'"),
- svn_dirent_local_style(
- svn_dirent_join(wcroot->abspath,
- src_relpath, scratch_pool),
- scratch_pool));
+ path_for_error_message(wcroot, src_relpath,
+ scratch_pool));
/* We walk the move source (i.e. the post-update tree), comparing each node
* with the equivalent node at the move destination and applying the update
@@ -1780,22 +1806,17 @@ suitable_for_move(svn_wc__db_wcroot_t *w
svn_sqlite__reset(stmt),
_("Cannot apply update because move source "
"%s' is a mixed-revision working copy"),
- svn_dirent_local_style(svn_dirent_join(
- wcroot->abspath,
- local_relpath,
- scratch_pool),
- scratch_pool));
+ path_for_error_message(wcroot, local_relpath,
+ scratch_pool));
if (strcmp(relpath, svn_sqlite__column_text(stmt, 1, NULL)))
return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE,
svn_sqlite__reset(stmt),
_("Cannot apply update because move source "
"'%s' is a switched subtree"),
- svn_dirent_local_style(svn_dirent_join(
- wcroot->abspath,
- local_relpath,
- scratch_pool),
- scratch_pool));
+ path_for_error_message(wcroot,
+ local_relpath,
+ scratch_pool));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
}
@@ -1840,10 +1861,8 @@ update_moved_away_conflict_victim(svn_wc
if (umb.move_root_dst_relpath == NULL)
return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
_("The node '%s' has not been moved away"),
- svn_dirent_local_style(
- svn_dirent_join(wcroot->abspath, victim_relpath,
- scratch_pool),
- scratch_pool));
+ path_for_error_message(wcroot, victim_relpath,
+ scratch_pool));
move_root_dst_abspath
= svn_dirent_join(wcroot->abspath, umb.move_root_dst_relpath,
@@ -1869,10 +1888,8 @@ update_moved_away_conflict_victim(svn_wc
if (!have_row)
return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
_("'%s' is not deleted"),
- svn_dirent_local_style(
- svn_dirent_join(wcroot->abspath, victim_relpath,
- scratch_pool),
- scratch_pool));
+ path_for_error_message(wcroot, victim_relpath,
+ scratch_pool));
if (src_op_depth == 0)
SVN_ERR(suitable_for_move(wcroot, victim_relpath, scratch_pool));
@@ -2045,8 +2062,8 @@ bump_mark_tree_conflict(svn_wc__db_wcroo
svn_wc_conflict_version_t *old_version;
svn_wc_conflict_version_t *new_version;
- SVN_ERR(verify_write_lock(wcroot, move_src_op_root_relpath, scratch_pool));
- SVN_ERR(verify_write_lock(wcroot, move_dst_op_root_relpath, scratch_pool));
+ /* Verify precondition: We are allowed to set a tree conflict here. */
+ SVN_ERR(verify_write_lock(wcroot, move_src_root_relpath, scratch_pool));
/* Read new (post-update) information from the new move source BASE node. */
SVN_ERR(svn_wc__db_base_get_info_internal(NULL, &new_kind, &new_rev,
@@ -2058,7 +2075,14 @@ bump_mark_tree_conflict(svn_wc__db_wcroo
SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, &repos_uuid,
wcroot->sdb, repos_id, scratch_pool));
- /* Read old (pre-update) information from the move destination node. */
+ /* Read old (pre-update) information from the move destination node.
+
+ This potentially touches nodes that aren't locked by us, but that is not
+ a problem because we have a SQLite write lock here, and all sqlite
+ operations that affect move stability use a sqlite lock as well.
+ (And affecting the move itself requires a write lock on the node that
+ we do own the lock for: the move source)
+ */
SVN_ERR(svn_wc__db_depth_get_info(NULL, &old_kind, &old_rev,
&old_repos_relpath, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
@@ -2066,6 +2090,21 @@ bump_mark_tree_conflict(svn_wc__db_wcroo
relpath_depth(move_dst_op_root_relpath),
scratch_pool, scratch_pool));
+ if (strcmp(move_src_root_relpath, move_src_op_root_relpath))
+ {
+ /* We have information for the op-root, but need it for the node that
+ we are putting the tree conflict on. Luckily we know that we have
+ a clean BASE */
+
+ const char *rpath = svn_relpath_skip_ancestor(move_src_op_root_relpath,
+ move_src_root_relpath);
+
+ old_repos_relpath = svn_relpath_join(old_repos_relpath, rpath,
+ scratch_pool);
+ new_repos_relpath = svn_relpath_join(new_repos_relpath, rpath,
+ scratch_pool);
+ }
+
old_version = svn_wc_conflict_version_create2(
repos_root_url, repos_uuid, old_repos_relpath, old_rev,
old_kind, scratch_pool);
@@ -2332,10 +2371,26 @@ svn_wc__db_bump_moved_away(svn_wc__db_wc
{
if (strcmp(move_src_root_relpath, local_relpath))
{
- SVN_ERR(bump_mark_tree_conflict(wcroot, move_src_root_relpath,
- move_src_op_root_relpath,
- move_dst_op_root_relpath,
- db, scratch_pool));
+ /* An ancestor of the path that was updated is moved away.
+
+ If we have a lock on that ancestor, we can mark a tree
+ conflict on it, if we don't we ignore this case. A future
+ update of the ancestor will handle this. */
+ svn_boolean_t locked;
+
+ SVN_ERR(svn_wc__db_wclock_owns_lock_internal(
+ &locked, wcroot,
+ move_src_root_relpath,
+ FALSE, scratch_pool));
+
+ if (locked)
+ {
+ SVN_ERR(bump_mark_tree_conflict(wcroot,
+ move_src_root_relpath,
+ move_src_op_root_relpath,
+ move_dst_op_root_relpath,
+ db, scratch_pool));
+ }
return SVN_NO_ERROR;
}
}
@@ -2524,16 +2579,29 @@ break_moved_away_children_internal(svn_w
const char *src_relpath = svn_sqlite__column_text(stmt, 0, NULL);
const char *dst_relpath = svn_sqlite__column_text(stmt, 1, NULL);
int src_op_depth = svn_sqlite__column_int(stmt, 2);
+ svn_error_t *err;
svn_pool_clear(iterpool);
- SVN_ERR(break_move(wcroot, src_relpath, src_op_depth, dst_relpath,
- iterpool));
- SVN_ERR(update_move_list_add(wcroot, src_relpath,
- svn_wc_notify_move_broken,
- svn_node_unknown,
- svn_wc_notify_state_inapplicable,
- svn_wc_notify_state_inapplicable));
+ err = break_move(wcroot, src_relpath, src_op_depth, dst_relpath,
+ iterpool);
+
+ if (! err)
+ {
+ err = update_move_list_add(wcroot, src_relpath,
+ svn_wc_notify_move_broken,
+ svn_node_unknown,
+ svn_wc_notify_state_inapplicable,
+ svn_wc_notify_state_inapplicable);
+ }
+
+ if (err)
+ {
+ return svn_error_trace(
+ svn_error_compose_create(err,
+ svn_sqlite__reset(stmt)));
+ }
+
SVN_ERR(svn_sqlite__step(&have_row, stmt));
}
svn_pool_destroy(iterpool);
@@ -2546,21 +2614,26 @@ break_moved_away_children_internal(svn_w
svn_error_t *
svn_wc__db_resolve_break_moved_away(svn_wc__db_t *db,
const char *local_abspath,
+ const char *src_op_root_abspath,
svn_wc_notify_func2_t notify_func,
void *notify_baton,
apr_pool_t *scratch_pool)
{
svn_wc__db_wcroot_t *wcroot;
const char *local_relpath;
+ const char *src_relpath;
SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
db, local_abspath,
scratch_pool, scratch_pool));
VERIFY_USABLE_WCROOT(wcroot);
+ src_relpath = svn_dirent_skip_ancestor(wcroot->abspath, src_op_root_abspath);
+ SVN_ERR_ASSERT(src_relpath != NULL);
+
SVN_WC__DB_WITH_TXN(
svn_wc__db_resolve_break_moved_away_internal(wcroot, local_relpath,
- relpath_depth(local_relpath),
+ relpath_depth(src_relpath),
scratch_pool),
wcroot);
@@ -2586,6 +2659,7 @@ svn_wc__db_resolve_break_moved_away(svn_
svn_error_t *
svn_wc__db_resolve_break_moved_away_children(svn_wc__db_t *db,
const char *local_abspath,
+ const char *src_op_root_abspath,
svn_wc_notify_func2_t notify_func,
void *notify_baton,
apr_pool_t *scratch_pool)
Modified: subversion/branches/pin-externals/subversion/mod_authz_svn/mod_authz_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/mod_authz_svn/mod_authz_svn.c?rev=1653578&r1=1653577&r2=1653578&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/mod_authz_svn/mod_authz_svn.c (original)
+++ subversion/branches/pin-externals/subversion/mod_authz_svn/mod_authz_svn.c Wed Jan 21 16:22:19 2015
@@ -244,15 +244,26 @@ static const command_rec authz_svn_cmds[
* per-module loglevel configuration. It expands to FILE and LINE
* in older server versions. ALLOWED is boolean.
* REPOS_PATH and DEST_REPOS_PATH are information
- * about the request. DEST_REPOS_PATH may be NULL. */
+ * about the request. DEST_REPOS_PATH may be NULL.
+ * Non-zero IS_SUBREQ_BYPASS means that this authorization check was
+ * implicitly requested using 'subrequest bypass' callback from
+ * mod_dav_svn.
+ */
static void
log_access_verdict(LOG_ARGS_SIGNATURE,
- const request_rec *r, int allowed,
+ const request_rec *r, int allowed, int is_subreq_bypass,
const char *repos_path, const char *dest_repos_path)
{
- int level = allowed ? APLOG_INFO : APLOG_WARNING;
+ int level = allowed ? APLOG_INFO : APLOG_ERR;
const char *verdict = allowed ? "granted" : "denied";
+ /* Use less important log level for implicit sub-request authorization
+ checks. */
+ if (is_subreq_bypass)
+ level = APLOG_INFO;
+ else if (r->main && r->method_number == M_GET)
+ level = APLOG_INFO;
+
if (r->user)
{
if (dest_repos_path)
@@ -361,7 +372,7 @@ get_access_conf(request_rec *r, authz_sv
svn_error_t *svn_err = SVN_NO_ERROR;
dav_error *dav_err;
- dav_err = dav_svn_get_repos_path(r, conf->base_path, &repos_path);
+ dav_err = dav_svn_get_repos_path2(r, conf->base_path, &repos_path, scratch_pool);
if (dav_err)
{
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "%s", dav_err->desc);
@@ -749,7 +760,7 @@ subreq_bypass2(request_rec *r,
if (!conf->anonymous
|| (! (conf->access_file || conf->repo_relative_access_file)))
{
- log_access_verdict(APLOG_MARK, r, 0, repos_path, NULL);
+ log_access_verdict(APLOG_MARK, r, 0, TRUE, repos_path, NULL);
return HTTP_FORBIDDEN;
}
@@ -778,12 +789,12 @@ subreq_bypass2(request_rec *r,
}
if (!authz_access_granted)
{
- log_access_verdict(APLOG_MARK, r, 0, repos_path, NULL);
+ log_access_verdict(APLOG_MARK, r, 0, TRUE, repos_path, NULL);
return HTTP_FORBIDDEN;
}
}
- log_access_verdict(APLOG_MARK, r, 1, repos_path, NULL);
+ log_access_verdict(APLOG_MARK, r, 1, TRUE, repos_path, NULL);
return OK;
}
@@ -858,7 +869,7 @@ access_checker(request_rec *r)
return DECLINED;
if (!authn_required)
- log_access_verdict(APLOG_MARK, r, 0, repos_path, dest_repos_path);
+ log_access_verdict(APLOG_MARK, r, 0, FALSE, repos_path, dest_repos_path);
return HTTP_FORBIDDEN;
}
@@ -866,7 +877,7 @@ access_checker(request_rec *r)
if (status != OK)
return status;
- log_access_verdict(APLOG_MARK, r, 1, repos_path, dest_repos_path);
+ log_access_verdict(APLOG_MARK, r, 1, FALSE, repos_path, dest_repos_path);
return OK;
}
@@ -893,7 +904,7 @@ check_user_id(request_rec *r)
if (status == OK)
{
apr_table_setn(r->notes, "authz_svn-anon-ok", (const char*)1);
- log_access_verdict(APLOG_MARK, r, 1, repos_path, dest_repos_path);
+ log_access_verdict(APLOG_MARK, r, 1, FALSE, repos_path, dest_repos_path);
return OK;
}
@@ -923,7 +934,7 @@ auth_checker(request_rec *r)
{
if (conf->authoritative)
{
- log_access_verdict(APLOG_MARK, r, 0, repos_path, dest_repos_path);
+ log_access_verdict(APLOG_MARK, r, 0, FALSE, repos_path, dest_repos_path);
ap_note_auth_failure(r);
return HTTP_FORBIDDEN;
}
@@ -933,7 +944,7 @@ auth_checker(request_rec *r)
if (status != OK)
return status;
- log_access_verdict(APLOG_MARK, r, 1, repos_path, dest_repos_path);
+ log_access_verdict(APLOG_MARK, r, 1, FALSE, repos_path, dest_repos_path);
return OK;
}
Modified: subversion/branches/pin-externals/subversion/mod_dav_svn/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/mod_dav_svn/merge.c?rev=1653578&r1=1653577&r2=1653578&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/mod_dav_svn/merge.c (original)
+++ subversion/branches/pin-externals/subversion/mod_dav_svn/merge.c Wed Jan 21 16:22:19 2015
@@ -136,12 +136,13 @@ do_resources(const dav_svn_repos *repos,
const void *key;
void *val;
const char *path;
+ apr_ssize_t path_len;
svn_fs_path_change2_t *change;
svn_boolean_t send_self;
svn_boolean_t send_parent;
svn_pool_clear(subpool);
- apr_hash_this(hi, &key, NULL, &val);
+ apr_hash_this(hi, &key, &path_len, &val);
path = key;
change = val;
@@ -170,14 +171,14 @@ do_resources(const dav_svn_repos *repos,
{
/* If we haven't already sent this path, send it (and then
remember that we sent it). */
- if (! svn_hash_gets(sent, path))
+ if (! apr_hash_get(sent, path, path_len))
{
svn_node_kind_t kind;
SVN_ERR(svn_fs_check_path(&kind, root, path, subpool));
SVN_ERR(send_response(repos, root, path,
kind == svn_node_dir,
output, bb, subpool));
- svn_hash_sets(sent, path, (void *)1);
+ apr_hash_set(sent, path, path_len, (void *)1);
}
}
if (send_parent)
Modified: subversion/branches/pin-externals/subversion/mod_dav_svn/mod_dav_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/mod_dav_svn/mod_dav_svn.c?rev=1653578&r1=1653577&r2=1653578&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/mod_dav_svn/mod_dav_svn.c (original)
+++ subversion/branches/pin-externals/subversion/mod_dav_svn/mod_dav_svn.c Wed Jan 21 16:22:19 2015
@@ -662,9 +662,10 @@ dav_svn__get_fs_parent_path(request_rec
AP_MODULE_DECLARE(dav_error *)
-dav_svn_get_repos_path(request_rec *r,
- const char *root_path,
- const char **repos_path)
+dav_svn_get_repos_path2(request_rec *r,
+ const char *root_path,
+ const char **repos_path,
+ apr_pool_t *pool)
{
const char *fs_path;
@@ -692,19 +693,26 @@ dav_svn_get_repos_path(request_rec *r,
/* Split the svn URI to get the name of the repository below
the parent path. */
- derr = dav_svn_split_uri(r, r->uri, root_path,
- &ignored_cleaned_uri, &ignored_had_slash,
- &repos_name,
- &ignored_relative, &ignored_path_in_repos);
+ derr = dav_svn_split_uri2(r, r->uri, root_path,
+ &ignored_cleaned_uri, &ignored_had_slash,
+ &repos_name,
+ &ignored_relative, &ignored_path_in_repos, pool);
if (derr)
return derr;
/* Construct the full path from the parent path base directory
and the repository name. */
- *repos_path = svn_dirent_join(fs_parent_path, repos_name, r->pool);
+ *repos_path = svn_dirent_join(fs_parent_path, repos_name, pool);
return NULL;
}
+AP_MODULE_DECLARE(dav_error *)
+dav_svn_get_repos_path(request_rec *r,
+ const char *root_path,
+ const char **repos_path)
+{
+ return dav_svn_get_repos_path2(r, root_path, repos_path, r->pool);
+}
const char *
dav_svn__get_repo_name(request_rec *r)
@@ -1324,8 +1332,8 @@ static const command_rec cmds[] =
AP_INIT_TAKE1("SVNInMemoryCacheSize", SVNInMemoryCacheSize_cmd, NULL,
RSRC_CONF,
"specifies the maximum size in kB per process of Subversion's "
- "in-memory object cache (default value is 16384; 0 deactivates "
- "the cache)."),
+ "in-memory object cache (default value is 16384; 0 switches "
+ "to dynamically sized caches)."),
/* per server */
AP_INIT_TAKE1("SVNCompressionLevel", SVNCompressionLevel_cmd, NULL,
RSRC_CONF,
Modified: subversion/branches/pin-externals/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/mod_dav_svn/repos.c?rev=1653578&r1=1653577&r2=1653578&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/mod_dav_svn/repos.c (original)
+++ subversion/branches/pin-externals/subversion/mod_dav_svn/repos.c Wed Jan 21 16:22:19 2015
@@ -1209,14 +1209,15 @@ static void log_warning(void *baton, svn
AP_MODULE_DECLARE(dav_error *)
-dav_svn_split_uri(request_rec *r,
- const char *uri_to_split,
- const char *root_path,
- const char **cleaned_uri,
- int *trailing_slash,
- const char **repos_basename,
- const char **relative_path,
- const char **repos_path)
+dav_svn_split_uri2(request_rec *r,
+ const char *uri_to_split,
+ const char *root_path,
+ const char **cleaned_uri,
+ int *trailing_slash,
+ const char **repos_basename,
+ const char **relative_path,
+ const char **repos_path,
+ apr_pool_t *pool)
{
apr_size_t len1;
int had_slash;
@@ -1232,7 +1233,7 @@ dav_svn_split_uri(request_rec *r,
if ((fs_path == NULL) && (fs_parent_path == NULL))
{
/* ### are SVN_ERR_APMOD codes within the right numeric space? */
- return dav_svn__new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR,
+ return dav_svn__new_error(pool, HTTP_INTERNAL_SERVER_ERROR,
SVN_ERR_APMOD_MISSING_PATH_TO_FS,
"The server is misconfigured: "
"either an SVNPath or SVNParentPath "
@@ -1241,7 +1242,7 @@ dav_svn_split_uri(request_rec *r,
}
/* make a copy so that we can do some work on it */
- uri = apr_pstrdup(r->pool, uri_to_split);
+ uri = apr_pstrdup(pool, uri_to_split);
/* remove duplicate slashes, and make sure URI has no trailing '/' */
ap_no2slash(uri);
@@ -1256,7 +1257,7 @@ dav_svn_split_uri(request_rec *r,
*trailing_slash = FALSE;
/* return the first item. */
- *cleaned_uri = apr_pstrdup(r->pool, uri);
+ *cleaned_uri = apr_pstrdup(pool, uri);
/* The URL space defined by the SVN provider is always a virtual
space. Construct the path relative to the configured Location
@@ -1297,7 +1298,7 @@ dav_svn_split_uri(request_rec *r,
if (fs_path != NULL)
{
/* the repos_basename is the last component of root_path. */
- *repos_basename = svn_dirent_basename(root_path, r->pool);
+ *repos_basename = svn_dirent_basename(root_path, pool);
/* 'relative' is already correct for SVNPath; the root_path
already contains the name of the repository, so relative is
@@ -1315,7 +1316,7 @@ dav_svn_split_uri(request_rec *r,
if (relative[1] == '\0')
{
/* ### are SVN_ERR_APMOD codes within the right numeric space? */
- return dav_svn__new_error(r->pool, HTTP_FORBIDDEN,
+ return dav_svn__new_error(pool, HTTP_FORBIDDEN,
SVN_ERR_APMOD_MALFORMED_URI,
"The URI does not contain the name "
"of a repository.");
@@ -1332,7 +1333,7 @@ dav_svn_split_uri(request_rec *r,
}
else
{
- magic_component = apr_pstrndup(r->pool, relative + 1,
+ magic_component = apr_pstrndup(pool, relative + 1,
magic_end - relative - 1);
relative = magic_end;
}
@@ -1342,7 +1343,7 @@ dav_svn_split_uri(request_rec *r,
}
/* We can return 'relative' at this point too. */
- *relative_path = apr_pstrdup(r->pool, relative);
+ *relative_path = apr_pstrdup(pool, relative);
/* Code to remove the !svn junk from the front of the relative path,
mainly stolen from parse_uri(). This code assumes that
@@ -1363,7 +1364,7 @@ dav_svn_split_uri(request_rec *r,
if (ch == '\0')
{
/* relative is just "!svn", which is malformed. */
- return dav_svn__new_error(r->pool, HTTP_NOT_FOUND,
+ return dav_svn__new_error(pool, HTTP_NOT_FOUND,
SVN_ERR_APMOD_MALFORMED_URI,
"Nothing follows the svn special_uri.");
}
@@ -1390,7 +1391,7 @@ dav_svn_split_uri(request_rec *r,
*repos_path = NULL;
else
return dav_svn__new_error(
- r->pool, HTTP_NOT_FOUND,
+ pool, HTTP_NOT_FOUND,
SVN_ERR_APMOD_MALFORMED_URI,
"Missing info after special_uri.");
}
@@ -1414,7 +1415,7 @@ dav_svn_split_uri(request_rec *r,
/* Did we break from the loop prematurely? */
if (j != (defn->numcomponents - 1))
return dav_svn__new_error(
- r->pool, HTTP_NOT_FOUND,
+ pool, HTTP_NOT_FOUND,
SVN_ERR_APMOD_MALFORMED_URI,
"Not enough components after "
"special_uri.");
@@ -1428,13 +1429,13 @@ dav_svn_split_uri(request_rec *r,
else
{
/* Found a slash after the special components. */
- *repos_path = apr_pstrdup(r->pool, start - 1);
+ *repos_path = apr_pstrdup(pool, start - 1);
}
}
else
{
return
- dav_svn__new_error(r->pool, HTTP_NOT_FOUND,
+ dav_svn__new_error(pool, HTTP_NOT_FOUND,
SVN_ERR_APMOD_MALFORMED_URI,
"Unknown data after special_uri.");
}
@@ -1445,7 +1446,7 @@ dav_svn_split_uri(request_rec *r,
if (defn->name == NULL)
return
- dav_svn__new_error(r->pool, HTTP_NOT_FOUND,
+ dav_svn__new_error(pool, HTTP_NOT_FOUND,
SVN_ERR_APMOD_MALFORMED_URI,
"Couldn't match subdir after special_uri.");
}
@@ -1454,13 +1455,27 @@ dav_svn_split_uri(request_rec *r,
{
/* There's no "!svn/" at all, so the relative path is already
a valid path within the repository. */
- *repos_path = apr_pstrdup(r->pool, relative - 1);
+ *repos_path = apr_pstrdup(pool, relative - 1);
}
}
return NULL;
}
+AP_MODULE_DECLARE(dav_error *)
+dav_svn_split_uri(request_rec *r,
+ const char *uri_to_split,
+ const char *root_path,
+ const char **cleaned_uri,
+ int *trailing_slash,
+ const char **repos_basename,
+ const char **relative_path,
+ const char **repos_path)
+{
+ return dav_svn_split_uri2(r, uri_to_split, root_path, cleaned_uri,
+ trailing_slash, repos_basename, relative_path,
+ repos_path, r->pool);
+}
/* Context for cleanup handler. */
struct cleanup_fs_access_baton
Modified: subversion/branches/pin-externals/subversion/svn/conflict-callbacks.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/svn/conflict-callbacks.c?rev=1653578&r1=1653577&r2=1653578&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/svn/conflict-callbacks.c (original)
+++ subversion/branches/pin-externals/subversion/svn/conflict-callbacks.c Wed Jan 21 16:22:19 2015
@@ -695,6 +695,10 @@ handle_text_conflict(svn_wc_conflict_res
b->path_prefix, desc->local_abspath,
scratch_pool)));
+ /* ### TODO This whole feature availability check is grossly outdated.
+ DIFF_ALLOWED needs either to be redefined or to go away.
+ */
+
/* Diffing can happen between base and merged, to show conflict
markers to the user (this is the typical 3-way merge
scenario), or if no base is available, we can show a diff
@@ -714,9 +718,15 @@ handle_text_conflict(svn_wc_conflict_res
*next_option++ = "p";
if (diff_allowed)
{
- *next_option++ = "df";
+ /* We need one more path for this feature. */
+ if (desc->my_abspath)
+ *next_option++ = "df";
+
*next_option++ = "e";
- *next_option++ = "m";
+
+ /* We need one more path for this feature. */
+ if (desc->my_abspath)
+ *next_option++ = "m";
if (knows_something)
*next_option++ = "r";
@@ -781,7 +791,8 @@ handle_text_conflict(svn_wc_conflict_res
}
else if (strcmp(opt->code, "df") == 0)
{
- if (! diff_allowed)
+ /* Re-check preconditions. */
+ if (! diff_allowed || desc->my_abspath)
{
SVN_ERR(svn_cmdline_fprintf(stderr, iterpool,
_("Invalid option; there's no "
@@ -805,6 +816,15 @@ handle_text_conflict(svn_wc_conflict_res
{
svn_error_t *err;
+ /* Re-check preconditions. */
+ if (! desc->my_abspath)
+ {
+ SVN_ERR(svn_cmdline_fprintf(stderr, iterpool,
+ _("Invalid option; there's no "
+ "base path to merge.\n\n")));
+ continue;
+ }
+
err = svn_cl__merge_file_externally(desc->base_abspath,
desc->their_abspath,
desc->my_abspath,
Modified: subversion/branches/pin-externals/subversion/svnadmin/svnadmin.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/svnadmin/svnadmin.c?rev=1653578&r1=1653577&r2=1653578&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/svnadmin/svnadmin.c (original)
+++ subversion/branches/pin-externals/subversion/svnadmin/svnadmin.c Wed Jan 21 16:22:19 2015
@@ -1271,7 +1271,7 @@ subcommand_freeze(apr_getopt_t *os, void
}
b.command = APR_ARRAY_IDX(args, 0, const char *);
- b.args = apr_palloc(pool, sizeof(char *) * args->nelts + 1);
+ b.args = apr_palloc(pool, sizeof(char *) * (args->nelts + 1));
for (i = 0; i < args->nelts; ++i)
b.args[i] = APR_ARRAY_IDX(args, i, const char *);
b.args[args->nelts] = NULL;
Modified: subversion/branches/pin-externals/subversion/svndumpfilter/svndumpfilter.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/svndumpfilter/svndumpfilter.c?rev=1653578&r1=1653577&r2=1653578&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/svndumpfilter/svndumpfilter.c (original)
+++ subversion/branches/pin-externals/subversion/svndumpfilter/svndumpfilter.c Wed Jan 21 16:22:19 2015
@@ -43,6 +43,7 @@
#include "svn_mergeinfo.h"
#include "svn_version.h"
+#include "private/svn_repos_private.h"
#include "private/svn_mergeinfo_private.h"
#include "private/svn_cmdline_private.h"
#include "private/svn_sorts_private.h"
@@ -240,7 +241,6 @@ struct revision_baton_t
/* Does this revision have node or prop changes? */
svn_boolean_t has_nodes;
- svn_boolean_t has_props;
/* Did we drop any nodes? */
svn_boolean_t had_dropped_nodes;
@@ -253,7 +253,7 @@ struct revision_baton_t
svn_revnum_t rev_actual;
/* Pointers to dumpfile data. */
- svn_stringbuf_t *header;
+ apr_hash_t *original_headers;
apr_hash_t *props;
};
@@ -278,7 +278,7 @@ struct node_baton_t
svn_filesize_t tcl;
/* Pointers to dumpfile data. */
- svn_stringbuf_t *header;
+ apr_array_header_t *headers;
svn_stringbuf_t *props;
/* Expect deltas? */
@@ -287,6 +287,8 @@ struct node_baton_t
/* We might need the node path in a parse error message. */
char *node_path;
+
+ apr_pool_t *node_pool;
};
@@ -310,6 +312,24 @@ magic_header_record(int version, void *p
}
+/* Return a deep copy of a (char * -> char *) hash. */
+static apr_hash_t *
+headers_dup(apr_hash_t *headers,
+ apr_pool_t *pool)
+{
+ apr_hash_t *new_hash = apr_hash_make(pool);
+ apr_hash_index_t *hi;
+
+ for (hi = apr_hash_first(pool, headers); hi; hi = apr_hash_next(hi))
+ {
+ const char *key = apr_hash_this_key(hi);
+ const char *val = apr_hash_this_val(hi);
+
+ svn_hash_sets(new_hash, apr_pstrdup(pool, key), apr_pstrdup(pool, val));
+ }
+ return new_hash;
+}
+
/* New revision: set up revision_baton, decide if we skip it. */
static svn_error_t *
new_revision_record(void **revision_baton,
@@ -318,21 +338,16 @@ new_revision_record(void **revision_bato
apr_pool_t *pool)
{
struct revision_baton_t *rb;
- apr_hash_index_t *hi;
const char *rev_orig;
- svn_stream_t *header_stream;
*revision_baton = apr_palloc(pool, sizeof(struct revision_baton_t));
rb = *revision_baton;
rb->pb = parse_baton;
rb->has_nodes = FALSE;
- rb->has_props = FALSE;
rb->had_dropped_nodes = FALSE;
rb->writing_begun = FALSE;
- rb->header = svn_stringbuf_create_empty(pool);
rb->props = apr_hash_make(pool);
-
- header_stream = svn_stream_from_stringbuf(rb->header, pool);
+ rb->original_headers = headers_dup(headers, pool);
rev_orig = svn_hash_gets(headers, SVN_REPOS_DUMPFILE_REVISION_NUMBER);
rb->rev_orig = SVN_STR_TO_REV(rev_orig);
@@ -342,28 +357,6 @@ new_revision_record(void **revision_bato
else
rb->rev_actual = rb->rev_orig;
- SVN_ERR(svn_stream_printf(header_stream, pool,
- SVN_REPOS_DUMPFILE_REVISION_NUMBER ": %ld\n",
- rb->rev_actual));
-
- for (hi = apr_hash_first(pool, headers); hi; hi = apr_hash_next(hi))
- {
- const char *key = apr_hash_this_key(hi);
- const char *val = apr_hash_this_val(hi);
-
- if ((!strcmp(key, SVN_REPOS_DUMPFILE_CONTENT_LENGTH))
- || (!strcmp(key, SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH))
- || (!strcmp(key, SVN_REPOS_DUMPFILE_REVISION_NUMBER)))
- continue;
-
- /* passthru: put header into header stringbuf. */
-
- SVN_ERR(svn_stream_printf(header_stream, pool, "%s: %s\n",
- key, val));
- }
-
- SVN_ERR(svn_stream_close(header_stream));
-
return SVN_NO_ERROR;
}
@@ -375,12 +368,8 @@ new_revision_record(void **revision_bato
static svn_error_t *
output_revision(struct revision_baton_t *rb)
{
- int bytes_used;
- char buf[SVN_KEYLINE_MAXLEN];
- apr_hash_index_t *hi;
svn_boolean_t write_out_rev = FALSE;
apr_pool_t *hash_pool = apr_hash_pool_get(rb->props);
- svn_stringbuf_t *props = svn_stringbuf_create_empty(hash_pool);
apr_pool_t *subpool = svn_pool_create(hash_pool);
rb->writing_begun = TRUE;
@@ -398,7 +387,6 @@ output_revision(struct revision_baton_t
&& (! rb->pb->drop_all_empty_revs))
{
apr_hash_t *old_props = rb->props;
- rb->has_props = TRUE;
rb->props = apr_hash_make(hash_pool);
svn_hash_sets(rb->props, SVN_PROP_REVISION_DATE,
svn_hash_gets(old_props, SVN_PROP_REVISION_DATE));
@@ -407,39 +395,6 @@ output_revision(struct revision_baton_t
"padding."), hash_pool));
}
- /* Now, "rasterize" the props to a string, and append the property
- information to the header string. */
- if (rb->has_props)
- {
- for (hi = apr_hash_first(subpool, rb->props);
- hi;
- hi = apr_hash_next(hi))
- {
- const char *pname = apr_hash_this_key(hi);
- const svn_string_t *pval = apr_hash_this_val(hi);
-
- write_prop_to_stringbuf(props, pname, pval);
- }
- svn_stringbuf_appendcstr(props, "PROPS-END\n");
- svn_stringbuf_appendcstr(rb->header,
- SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH);
- bytes_used = apr_snprintf(buf, sizeof(buf), ": %" APR_SIZE_T_FMT,
- props->len);
- svn_stringbuf_appendbytes(rb->header, buf, bytes_used);
- svn_stringbuf_appendbyte(rb->header, '\n');
- }
-
- svn_stringbuf_appendcstr(rb->header, SVN_REPOS_DUMPFILE_CONTENT_LENGTH);
- bytes_used = apr_snprintf(buf, sizeof(buf), ": %" APR_SIZE_T_FMT, props->len);
- svn_stringbuf_appendbytes(rb->header, buf, bytes_used);
- svn_stringbuf_appendbyte(rb->header, '\n');
-
- /* put an end to headers */
- svn_stringbuf_appendbyte(rb->header, '\n');
-
- /* put an end to revision */
- svn_stringbuf_appendbyte(props, '\n');
-
/* write out the revision */
/* Revision is written out in the following cases:
1. If the revision has nodes or
@@ -459,10 +414,12 @@ output_revision(struct revision_baton_t
if (write_out_rev)
{
/* This revision is a keeper. */
- SVN_ERR(svn_stream_write(rb->pb->out_stream,
- rb->header->data, &(rb->header->len)));
- SVN_ERR(svn_stream_write(rb->pb->out_stream,
- props->data, &(props->len)));
+ SVN_ERR(svn_repos__dump_revision_record(rb->pb->out_stream,
+ rb->rev_actual,
+ rb->original_headers,
+ rb->props,
+ FALSE /*props_section_always*/,
+ subpool));
/* Stash the oldest original rev not dropped. */
if (rb->rev_orig > 0
@@ -544,6 +501,7 @@ new_node_record(void **node_baton,
*node_baton = apr_palloc(pool, sizeof(struct node_baton_t));
nb = *node_baton;
nb->rb = rev_baton;
+ nb->node_pool = pool;
pb = nb->rb->pb;
node_path = svn_hash_gets(headers, SVN_REPOS_DUMPFILE_NODE_PATH);
@@ -615,7 +573,7 @@ new_node_record(void **node_baton,
nb->has_text_delta = FALSE;
nb->writing_begun = FALSE;
nb->tcl = tcl ? svn__atoui64(tcl) : 0;
- nb->header = svn_stringbuf_create_empty(pool);
+ nb->headers = svn_repos__dumpfile_headers_create(pool);
nb->props = svn_stringbuf_create_empty(pool);
nb->node_path = apr_pstrdup(pool, node_path);
@@ -627,23 +585,20 @@ new_node_record(void **node_baton,
/* A node record is required to begin with 'Node-path', skip the
leading '/' to match the form used by 'svnadmin dump'. */
- SVN_ERR(svn_stream_printf(nb->rb->pb->out_stream,
- pool, "%s: %s\n",
- SVN_REPOS_DUMPFILE_NODE_PATH, node_path + 1));
+ svn_repos__dumpfile_header_push(
+ nb->headers, SVN_REPOS_DUMPFILE_NODE_PATH, node_path + 1);
/* Node-kind is next and is optional. */
kind = svn_hash_gets(headers, SVN_REPOS_DUMPFILE_NODE_KIND);
if (kind)
- SVN_ERR(svn_stream_printf(nb->rb->pb->out_stream,
- pool, "%s: %s\n",
- SVN_REPOS_DUMPFILE_NODE_KIND, kind));
+ svn_repos__dumpfile_header_push(
+ nb->headers, SVN_REPOS_DUMPFILE_NODE_KIND, kind);
/* Node-action is next and required. */
action = svn_hash_gets(headers, SVN_REPOS_DUMPFILE_NODE_ACTION);
if (action)
- SVN_ERR(svn_stream_printf(nb->rb->pb->out_stream,
- pool, "%s: %s\n",
- SVN_REPOS_DUMPFILE_NODE_ACTION, action));
+ svn_repos__dumpfile_header_push(
+ nb->headers, SVN_REPOS_DUMPFILE_NODE_ACTION, action);
else
return svn_error_createf(SVN_ERR_INCOMPLETE_DATA, 0,
_("Missing Node-action for path '%s'"),
@@ -690,18 +645,14 @@ new_node_record(void **node_baton,
return svn_error_createf
(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
_("No valid copyfrom revision in filtered stream"));
- SVN_ERR(svn_stream_printf
- (nb->rb->pb->out_stream, pool,
- SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV ": %ld\n",
- cf_renum_val->rev));
+ svn_repos__dumpfile_header_pushf(
+ nb->headers, SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV,
+ "%ld", cf_renum_val->rev);
continue;
}
/* passthru: put header straight to output */
-
- SVN_ERR(svn_stream_printf(nb->rb->pb->out_stream,
- pool, "%s: %s\n",
- key, val));
+ svn_repos__dumpfile_header_push(nb->headers, key, val);
}
}
@@ -709,61 +660,62 @@ new_node_record(void **node_baton,
}
-/* Output node header and props to dumpstream
- This will be called by set_fulltext() after setting nb->has_text to TRUE,
- if the node has any text, or by close_node() otherwise. This must only
- be called if nb->writing_begun is FALSE. */
-static svn_error_t *
-output_node(struct node_baton_t *nb)
-{
- int bytes_used;
- char buf[SVN_KEYLINE_MAXLEN];
+/* Output node headers and props.
+ *
+ * Write HEADERS, content length headers, a blank line, and the properties
+ * content section PROPS_STR (if non-null) to DUMP_STREAM.
+ *
+ * HEADERS is an array of headers as struct {const char *key, *val;}.
+ * Write them all in the given order.
+ *
+ * PROPS_STR is the property content block, including a terminating
+ * 'PROPS_END\n' line. Iff PROPS_STR is non-null, write a
+ * Prop-content-length header and the prop content block.
+ *
+ * Iff HAS_TEXT is true, write a Text-content length, using the value
+ * TEXT_CONTENT_LENGTH.
+ *
+ * Always write a Content-length header, its value being the sum of the
+ * Prop- and Text- content length headers.
+ * ### TODO: Make it optional (only written if props and/or text present).
+ */
+static svn_error_t *
+output_node_record(svn_stream_t *dump_stream,
+ apr_array_header_t *headers,
+ svn_stringbuf_t *props_str,
+ svn_boolean_t has_text,
+ svn_filesize_t text_content_length,
+ apr_pool_t *scratch_pool)
+{
+ svn_filesize_t content_length = 0;
+
+ /* add content-length headers */
+ if (props_str)
+ {
+ svn_repos__dumpfile_header_pushf(
+ headers, SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH,
+ "%" APR_SIZE_T_FMT, props_str->len);
+ content_length += props_str->len;
+ }
+ if (has_text)
+ {
+ svn_repos__dumpfile_header_pushf(
+ headers, SVN_REPOS_DUMPFILE_TEXT_CONTENT_LENGTH,
+ "%" SVN_FILESIZE_T_FMT, text_content_length);
+ content_length += text_content_length;
+ }
+ svn_repos__dumpfile_header_pushf(
+ headers, SVN_REPOS_DUMPFILE_CONTENT_LENGTH,
+ "%" SVN_FILESIZE_T_FMT, content_length);
- nb->writing_begun = TRUE;
-
- /* when there are no props nb->props->len would be zero and won't mess up
- Content-Length. */
- if (nb->has_props)
- svn_stringbuf_appendcstr(nb->props, "PROPS-END\n");
-
- /* 1. recalculate & check text-md5 if present. Passed through right now. */
-
- /* 2. recalculate and add content-lengths */
-
- if (nb->has_props)
- {
- svn_stringbuf_appendcstr(nb->header,
- SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH);
- bytes_used = apr_snprintf(buf, sizeof(buf), ": %" APR_SIZE_T_FMT,
- nb->props->len);
- svn_stringbuf_appendbytes(nb->header, buf, bytes_used);
- svn_stringbuf_appendbyte(nb->header, '\n');
- }
- if (nb->has_text)
- {
- svn_stringbuf_appendcstr(nb->header,
- SVN_REPOS_DUMPFILE_TEXT_CONTENT_LENGTH);
- bytes_used = apr_snprintf(buf, sizeof(buf), ": %" SVN_FILESIZE_T_FMT,
- nb->tcl);
- svn_stringbuf_appendbytes(nb->header, buf, bytes_used);
- svn_stringbuf_appendbyte(nb->header, '\n');
- }
- svn_stringbuf_appendcstr(nb->header, SVN_REPOS_DUMPFILE_CONTENT_LENGTH);
- bytes_used = apr_snprintf(buf, sizeof(buf), ": %" SVN_FILESIZE_T_FMT,
- (svn_filesize_t) (nb->props->len + nb->tcl));
- svn_stringbuf_appendbytes(nb->header, buf, bytes_used);
- svn_stringbuf_appendbyte(nb->header, '\n');
-
- /* put an end to headers */
- svn_stringbuf_appendbyte(nb->header, '\n');
-
- /* 3. output all the stuff */
-
- SVN_ERR(svn_stream_write(nb->rb->pb->out_stream,
- nb->header->data , &(nb->header->len)));
- SVN_ERR(svn_stream_write(nb->rb->pb->out_stream,
- nb->props->data , &(nb->props->len)));
+ /* write the headers */
+ SVN_ERR(svn_repos__dump_headers(dump_stream, headers, TRUE, scratch_pool));
+ /* write the props */
+ if (props_str)
+ {
+ SVN_ERR(svn_stream_write(dump_stream, props_str->data, &props_str->len));
+ }
return SVN_NO_ERROR;
}
@@ -791,10 +743,16 @@ adjust_mergeinfo(svn_string_t **final_va
start of all history. E.g. if we dump -r100:400 then dumpfilter the
result with --skip-missing-merge-sources, any mergeinfo with revision
100 implies a change of -r99:100, but r99 is part of the history we
- want filtered. This is analogous to how r1 is always meaningless as
- a merge source revision.
+ want filtered.
If the oldest rev is r0 then there is nothing to filter. */
+
+ /* ### This seems to cater only for use cases where the revisions being
+ processed are not following on from revisions that will already
+ exist in the destination repository. If the revisions being
+ processed do follow on, then we might want to keep the mergeinfo
+ that refers to those older revisions. */
+
if (rb->pb->skip_missing_merge_sources && rb->pb->oldest_original_rev > 0)
SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
&mergeinfo, mergeinfo,
@@ -852,7 +810,7 @@ adjust_mergeinfo(svn_string_t **final_va
svn_hash_sets(final_mergeinfo, merge_source, rangelist);
}
- SVN_ERR(svn_mergeinfo_sort(final_mergeinfo, subpool));
+ SVN_ERR(svn_mergeinfo__canonicalize_ranges(final_mergeinfo, subpool));
SVN_ERR(svn_mergeinfo_to_string(final_val, final_mergeinfo, pool));
svn_pool_destroy(subpool);
@@ -868,7 +826,6 @@ set_revision_property(void *revision_bat
struct revision_baton_t *rb = revision_baton;
apr_pool_t *hash_pool = apr_hash_pool_get(rb->props);
- rb->has_props = TRUE;
svn_hash_sets(rb->props,
apr_pstrdup(hash_pool, name),
svn_string_dup(value, hash_pool));
@@ -887,6 +844,9 @@ set_node_property(void *node_baton,
if (nb->do_skip)
return SVN_NO_ERROR;
+ /* Try to detect if a delta-mode property occurs unexpectedly. HAS_PROPS
+ can be false here only if the parser didn't call remove_node_props(),
+ so this may indicate a bug rather than bad data. */
if (! (nb->has_props || nb->has_prop_delta))
return svn_error_createf(SVN_ERR_STREAM_MALFORMED_DATA, NULL,
_("Delta property block detected, but deltas "
@@ -932,14 +892,17 @@ delete_node_property(void *node_baton, c
}
+/* The parser calls this method if the node record has a non-delta
+ * property content section, before any calls to set_node_property().
+ * If the node record uses property deltas, this is not called.
+ */
static svn_error_t *
remove_node_props(void *node_baton)
{
struct node_baton_t *nb = node_baton;
/* In this case, not actually indicating that the node *has* props,
- rather that we know about all the props that it has, since it now
- has none. */
+ rather that it has a property content section. */
nb->has_props = TRUE;
return SVN_NO_ERROR;
@@ -955,7 +918,19 @@ set_fulltext(svn_stream_t **stream, void
{
nb->has_text = TRUE;
if (! nb->writing_begun)
- SVN_ERR(output_node(nb));
+ {
+ nb->writing_begun = TRUE;
+ if (nb->has_props)
+ {
+ svn_stringbuf_appendcstr(nb->props, "PROPS-END\n");
+ }
+ SVN_ERR(output_node_record(nb->rb->pb->out_stream,
+ nb->headers,
+ nb->has_props ? nb->props : NULL,
+ nb->has_text,
+ nb->tcl,
+ nb->node_pool));
+ }
*stream = nb->rb->pb->out_stream;
}
@@ -976,7 +951,19 @@ close_node(void *node_baton)
/* If the node was not flushed already to output its text, do it now. */
if (! nb->writing_begun)
- SVN_ERR(output_node(nb));
+ {
+ nb->writing_begun = TRUE;
+ if (nb->has_props)
+ {
+ svn_stringbuf_appendcstr(nb->props, "PROPS-END\n");
+ }
+ SVN_ERR(output_node_record(nb->rb->pb->out_stream,
+ nb->headers,
+ nb->has_props ? nb->props : NULL,
+ nb->has_text,
+ nb->tcl,
+ nb->node_pool));
+ }
/* put an end to node. */
SVN_ERR(svn_stream_write(nb->rb->pb->out_stream, "\n\n", &len));
Modified: subversion/branches/pin-externals/subversion/svnfsfs/stats-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/svnfsfs/stats-cmd.c?rev=1653578&r1=1653577&r2=1653578&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/svnfsfs/stats-cmd.c (original)
+++ subversion/branches/pin-externals/subversion/svnfsfs/stats-cmd.c Wed Jan 21 16:22:19 2015
@@ -31,6 +31,35 @@
#include "svn_private_config.h"
#include "svnfsfs.h"
+/* Return the string, allocated in RESULT_POOL, describing the value 2**I.
+ */
+static const char *
+print_two_power(int i,
+ apr_pool_t *result_pool)
+{
+ /* These are the SI prefixes for base-1000, the binary ones with base-1024
+ are too clumsy and require appending B for "byte" to be intelligible,
+ e.g. "MiB".
+
+ Therefore, we ignore the official standard and revert to the traditional
+ contextual use were the base-1000 prefixes are understood as base-1024
+ when it came to data sizes.
+ */
+ const char *si_prefixes = " kMGTPEZY";
+
+ int number = (1 << (i % 10));
+ int thousands = i / 10;
+
+ char si_prefix = ((thousands >= 0) && (thousands < strlen(si_prefixes)))
+ ? si_prefixes[thousands]
+ : '?';
+
+ if (si_prefix == ' ')
+ return apr_psprintf(result_pool, "%d", number);
+
+ return apr_psprintf(result_pool, "%d%c", number, si_prefix);
+}
+
/* Print statistics for the given group of representations to console.
* Use POOL for allocations.
*/
@@ -88,8 +117,8 @@ print_histogram(svn_fs_fs__histogram_t *
/* display histogram lines */
for (i = last; i >= first; --i)
- printf(_(" [2^%2d, 2^%2d) %15s (%2d%%) bytes in %12s (%2d%%) items\n"),
- i-1, i,
+ printf(_(" %4s .. < %-4s %19s (%2d%%) bytes in %12s (%2d%%) items\n"),
+ print_two_power(i-1, pool), print_two_power(i, pool),
svn__ui64toa_sep(histogram->lines[i].sum, ',', pool),
(int)(histogram->lines[i].sum * 100 / histogram->total.sum),
svn__ui64toa_sep(histogram->lines[i].count, ',', pool),