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),
