You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/08/11 00:07:31 UTC
svn commit: r984234 [5/20] - in /subversion/branches/ignore-mergeinfo: ./
build/ build/ac-macros/ build/generator/ notes/ notes/api-errata/
notes/obliterate/ notes/obliterate/fspec-cc1/ notes/rename-tracking/
notes/svnpatch/ notes/tree-conflicts/ notes...
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/merge.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/merge.c Tue Aug 10 22:07:24 2010
@@ -368,7 +368,7 @@ is_path_conflicted_by_merge(merge_cmd_ba
}
/* Return a state indicating whether the WC metadata matches the
- * node kind on disk of the local path PATH.
+ * node kind on disk of the local path LOCAL_ABSPATH.
* Use MERGE_B to determine the dry-run details; particularly, if a dry run
* noted that it deleted this path, assume matching node kinds (as if both
* kinds were svn_node_none).
@@ -379,26 +379,25 @@ is_path_conflicted_by_merge(merge_cmd_ba
* - Return 'missing' if there is no node on disk but one is expected.
* Also return 'missing' for absent nodes (not here due to authz).*/
static svn_wc_notify_state_t
-obstructed_or_missing(const char *path,
+obstructed_or_missing(const char *local_abspath,
const char *local_dir_abspath,
const merge_cmd_baton_t *merge_b,
apr_pool_t *pool)
{
svn_error_t *err;
svn_node_kind_t kind_expected, kind_on_disk;
- const char *local_abspath;
+
+ SVN_ERR_ASSERT_NO_RETURN(svn_dirent_is_absolute(local_abspath));
/* In a dry run, make as if nodes "deleted" by the dry run appear so. */
- if (merge_b->dry_run && dry_run_deleted_p(merge_b, path))
+ if (merge_b->dry_run && dry_run_deleted_p(merge_b, local_abspath))
return svn_wc_notify_state_inapplicable;
/* Since this function returns no svn_error_t, we make all errors look like
* no node found in the wc. */
- err = svn_dirent_get_absolute(&local_abspath, path, pool);
- if (!err)
- err = svn_wc_read_kind(&kind_expected, merge_b->ctx->wc_ctx,
- local_abspath, FALSE, pool);
+ err = svn_wc_read_kind(&kind_expected, merge_b->ctx->wc_ctx,
+ local_abspath, FALSE, pool);
if (err)
{
@@ -1063,7 +1062,7 @@ static svn_error_t *
merge_props_changed(const char *local_dir_abspath,
svn_wc_notify_state_t *state,
svn_boolean_t *tree_conflicted,
- const char *path,
+ const char *local_abspath,
const apr_array_header_t *propchanges,
apr_hash_t *original_props,
void *baton,
@@ -1074,9 +1073,8 @@ merge_props_changed(const char *local_di
svn_client_ctx_t *ctx = merge_b->ctx;
apr_pool_t *subpool = svn_pool_create(merge_b->pool);
svn_error_t *err;
- const char *local_abspath;
- SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, subpool));
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
if (tree_conflicted)
*tree_conflicted = FALSE;
@@ -1085,8 +1083,8 @@ merge_props_changed(const char *local_di
{
svn_wc_notify_state_t obstr_state;
- obstr_state = obstructed_or_missing(path, local_dir_abspath, merge_b,
- subpool);
+ obstr_state = obstructed_or_missing(local_abspath, local_dir_abspath,
+ merge_b, subpool);
if (obstr_state != svn_wc_notify_state_inapplicable)
{
if (state)
@@ -1274,9 +1272,9 @@ merge_file_changed(const char *local_dir
svn_wc_notify_state_t *content_state,
svn_wc_notify_state_t *prop_state,
svn_boolean_t *tree_conflicted,
- const char *mine,
- const char *older,
- const char *yours,
+ const char *mine_abspath,
+ const char *older_abspath,
+ const char *yours_abspath,
svn_revnum_t older_rev,
svn_revnum_t yours_rev,
const char *mimetype1,
@@ -1290,19 +1288,10 @@ merge_file_changed(const char *local_dir
apr_pool_t *subpool = svn_pool_create(merge_b->pool);
svn_boolean_t merge_required = TRUE;
enum svn_wc_merge_outcome_t merge_outcome;
- const char *older_abspath;
- const char *yours_abspath;
- const char *mine_abspath;
- if (older)
- SVN_ERR(svn_dirent_get_absolute(&older_abspath, older, merge_b->pool));
- else
- older_abspath = NULL;
- if (yours)
- SVN_ERR(svn_dirent_get_absolute(&yours_abspath, yours, merge_b->pool));
- else
- yours_abspath = NULL;
- SVN_ERR(svn_dirent_get_absolute(&mine_abspath, mine, merge_b->pool));
+ SVN_ERR_ASSERT(mine_abspath && svn_dirent_is_absolute(mine_abspath));
+ SVN_ERR_ASSERT(!older_abspath || svn_dirent_is_absolute(older_abspath));
+ SVN_ERR_ASSERT(!yours_abspath || svn_dirent_is_absolute(yours_abspath));
if (tree_conflicted)
*tree_conflicted = FALSE;
@@ -1326,8 +1315,8 @@ merge_file_changed(const char *local_dir
{
svn_wc_notify_state_t obstr_state;
- obstr_state = obstructed_or_missing(mine, local_dir_abspath, merge_b,
- subpool);
+ obstr_state = obstructed_or_missing(mine_abspath, local_dir_abspath,
+ merge_b, subpool);
if (obstr_state != svn_wc_notify_state_inapplicable)
{
if (content_state)
@@ -1347,7 +1336,7 @@ merge_file_changed(const char *local_dir
SVN_ERR(svn_wc_read_kind(&wc_kind, merge_b->ctx->wc_ctx, mine_abspath,
FALSE, subpool));
- SVN_ERR(svn_io_check_path(mine, &kind, subpool));
+ SVN_ERR(svn_io_check_path(mine_abspath, &kind, subpool));
/* If the file isn't there due to depth restrictions, do not flag
* a conflict. Non-inheritable mergeinfo will be recorded, allowing
@@ -1415,7 +1404,7 @@ merge_file_changed(const char *local_dir
SVN_ERR(merge_props_changed(local_dir_abspath, prop_state,
&tree_conflicted2,
- mine, prop_changes, original_props,
+ mine_abspath, prop_changes, original_props,
baton, scratch_pool));
/* If the prop change caused a tree-conflict, just bail. */
@@ -1440,7 +1429,7 @@ merge_file_changed(const char *local_dir
return SVN_NO_ERROR;
}
- if (older)
+ if (older_abspath)
{
svn_boolean_t has_local_mods;
SVN_ERR(svn_wc_text_modified_p2(&has_local_mods, merge_b->ctx->wc_ctx,
@@ -1466,14 +1455,14 @@ merge_file_changed(const char *local_dir
svn_boolean_t same_contents;
SVN_ERR(svn_io_files_contents_same_p(&same_contents,
(older_revision_exists ?
- older : yours),
- mine, subpool));
+ older_abspath : yours_abspath),
+ mine_abspath, subpool));
if (same_contents)
{
if (older_revision_exists && !merge_b->dry_run)
{
- SVN_ERR(svn_io_copy_file(yours, mine, FALSE, subpool));
- SVN_ERR(svn_io_remove_file2(yours, TRUE, subpool));
+ SVN_ERR(svn_io_file_move(yours_abspath, mine_abspath,
+ subpool));
}
merge_outcome = svn_wc_merge_merged;
merge_required = FALSE;
@@ -1541,9 +1530,9 @@ merge_file_added(const char *local_dir_a
svn_wc_notify_state_t *content_state,
svn_wc_notify_state_t *prop_state,
svn_boolean_t *tree_conflicted,
- const char *mine,
- const char *older,
- const char *yours,
+ const char *mine_abspath,
+ const char *older_abspath,
+ const char *yours_abspath,
svn_revnum_t rev1,
svn_revnum_t rev2,
const char *mimetype1,
@@ -1561,7 +1550,8 @@ merge_file_added(const char *local_dir_a
svn_node_kind_t kind;
int i;
apr_hash_t *file_props;
- const char *mine_abspath;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(mine_abspath));
/* Easy out: We are only applying mergeinfo differences. */
if (merge_b->record_only)
@@ -1576,8 +1566,6 @@ merge_file_added(const char *local_dir_a
return SVN_NO_ERROR;
}
- SVN_ERR(svn_dirent_get_absolute(&mine_abspath, mine, subpool));
-
/* In most cases, we just leave prop_state as unknown, and let the
content_state what happened, so we set prop_state here to avoid that
below. */
@@ -1622,7 +1610,7 @@ merge_file_added(const char *local_dir_a
if (! local_dir_abspath)
{
if (merge_b->dry_run && merge_b->added_path
- && svn_dirent_is_child(merge_b->added_path, mine, subpool))
+ && svn_dirent_is_child(merge_b->added_path, mine_abspath, NULL))
{
if (content_state)
*content_state = svn_wc_notify_state_changed;
@@ -1643,8 +1631,8 @@ merge_file_added(const char *local_dir_a
{
svn_wc_notify_state_t obstr_state;
- obstr_state = obstructed_or_missing(mine, local_dir_abspath, merge_b,
- subpool);
+ obstr_state = obstructed_or_missing(mine_abspath, local_dir_abspath,
+ merge_b, subpool);
if (obstr_state != svn_wc_notify_state_inapplicable)
{
if (content_state)
@@ -1656,7 +1644,7 @@ merge_file_added(const char *local_dir_a
parent_abspath = local_dir_abspath;
- SVN_ERR(svn_io_check_path(mine, &kind, subpool));
+ SVN_ERR(svn_io_check_path(mine_abspath, &kind, subpool));
switch (kind)
{
case svn_node_none:
@@ -1675,7 +1663,7 @@ merge_file_added(const char *local_dir_a
if (merge_b->same_repos)
{
const char *child = svn_dirent_is_child(merge_b->target_abspath,
- mine, subpool);
+ mine_abspath, subpool);
if (child != NULL)
copyfrom_url = svn_path_url_add_component2(
merge_b->merge_source.url2,
@@ -1688,7 +1676,8 @@ merge_file_added(const char *local_dir_a
copyfrom_url, subpool));
new_base_props = file_props;
new_props = NULL; /* inherit from new_base_props */
- SVN_ERR(svn_stream_open_readonly(&new_base_contents, yours,
+ SVN_ERR(svn_stream_open_readonly(&new_base_contents,
+ yours_abspath,
subpool, subpool));
new_contents = NULL; /* inherit from new_base_contents */
}
@@ -1699,7 +1688,7 @@ merge_file_added(const char *local_dir_a
new_base_props = apr_hash_make(subpool);
new_props = file_props;
new_base_contents = svn_stream_empty(subpool);
- SVN_ERR(svn_stream_open_readonly(&new_contents, yours,
+ SVN_ERR(svn_stream_open_readonly(&new_contents, yours_abspath,
subpool, subpool));
}
@@ -1763,7 +1752,8 @@ merge_file_added(const char *local_dir_a
SVN_ERR(svn_wc_read_kind(&wc_kind, merge_b->ctx->wc_ctx,
mine_abspath, FALSE, subpool));
- if ((wc_kind != svn_node_none) && dry_run_deleted_p(merge_b, mine))
+ if ((wc_kind != svn_node_none)
+ && dry_run_deleted_p(merge_b, mine_abspath))
*content_state = svn_wc_notify_state_changed;
else
/* this will make the repos_editor send a 'skipped' message */
@@ -1772,7 +1762,7 @@ merge_file_added(const char *local_dir_a
break;
case svn_node_file:
{
- if (dry_run_deleted_p(merge_b, mine))
+ if (dry_run_deleted_p(merge_b, mine_abspath))
{
if (content_state)
*content_state = svn_wc_notify_state_changed;
@@ -1872,9 +1862,9 @@ static svn_error_t *
merge_file_deleted(const char *local_dir_abspath,
svn_wc_notify_state_t *state,
svn_boolean_t *tree_conflicted,
- const char *mine,
- const char *older,
- const char *yours,
+ const char *mine_abspath,
+ const char *older_abspath,
+ const char *yours_abspath,
const char *mimetype1,
const char *mimetype2,
apr_hash_t *original_props,
@@ -1884,7 +1874,6 @@ merge_file_deleted(const char *local_dir
merge_cmd_baton_t *merge_b = baton;
apr_pool_t *subpool = svn_pool_create(merge_b->pool);
svn_node_kind_t kind;
- const char *mine_abspath;
/* Easy out: We are only applying mergeinfo differences. */
if (merge_b->record_only)
@@ -1897,8 +1886,6 @@ merge_file_deleted(const char *local_dir
return SVN_NO_ERROR;
}
- SVN_ERR(svn_dirent_get_absolute(&mine_abspath, mine, subpool));
-
if (tree_conflicted)
*tree_conflicted = FALSE;
@@ -1918,8 +1905,8 @@ merge_file_deleted(const char *local_dir
{
svn_wc_notify_state_t obstr_state;
- obstr_state = obstructed_or_missing(mine, local_dir_abspath, merge_b,
- subpool);
+ obstr_state = obstructed_or_missing(mine_abspath, local_dir_abspath,
+ merge_b, subpool);
if (obstr_state != svn_wc_notify_state_inapplicable)
{
if (state)
@@ -1929,15 +1916,12 @@ merge_file_deleted(const char *local_dir
}
}
- SVN_ERR(svn_io_check_path(mine, &kind, subpool));
+ SVN_ERR(svn_io_check_path(mine_abspath, &kind, subpool));
switch (kind)
{
case svn_node_file:
{
svn_boolean_t same;
- const char *older_abspath;
-
- SVN_ERR(svn_dirent_get_absolute(&older_abspath, older, subpool));
/* If the files are identical, attempt deletion */
SVN_ERR(files_same_p(&same, older_abspath, original_props,
@@ -1946,7 +1930,7 @@ merge_file_deleted(const char *local_dir
{
/* Passing NULL for the notify_func and notify_baton because
repos_diff.c:delete_entry() will do it for us. */
- SVN_ERR(svn_client__wc_delete(mine, TRUE,
+ SVN_ERR(svn_client__wc_delete(mine_abspath, TRUE,
merge_b->dry_run, FALSE, NULL, NULL,
merge_b->ctx, subpool));
if (state)
@@ -2013,7 +1997,7 @@ static svn_error_t *
merge_dir_added(const char *local_dir_abspath,
svn_wc_notify_state_t *state,
svn_boolean_t *tree_conflicted,
- const char *path,
+ const char *local_abspath,
svn_revnum_t rev,
const char *copyfrom_path,
svn_revnum_t copyfrom_revision,
@@ -2026,7 +2010,6 @@ merge_dir_added(const char *local_dir_ab
const char *copyfrom_url = NULL, *child;
svn_revnum_t copyfrom_rev = SVN_INVALID_REVNUM;
const char *parent_abspath;
- const char *local_abspath;
svn_boolean_t is_versioned;
svn_boolean_t is_deleted;
svn_error_t *err;
@@ -2042,7 +2025,6 @@ merge_dir_added(const char *local_dir_ab
return SVN_NO_ERROR;
}
- SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, subpool));
parent_abspath = local_dir_abspath;
if (tree_conflicted)
@@ -2057,7 +2039,7 @@ merge_dir_added(const char *local_dir_ab
if (state)
{
if (merge_b->dry_run && merge_b->added_path
- && svn_dirent_is_child(merge_b->added_path, path, subpool))
+ && svn_dirent_is_child(merge_b->added_path, local_abspath, NULL))
*state = svn_wc_notify_state_changed;
else
*state = svn_wc_notify_state_missing;
@@ -2070,7 +2052,7 @@ merge_dir_added(const char *local_dir_ab
return SVN_NO_ERROR;
}
- child = svn_dirent_is_child(merge_b->target_abspath, path, subpool);
+ child = svn_dirent_is_child(merge_b->target_abspath, local_abspath, NULL);
SVN_ERR_ASSERT(child != NULL);
/* If this is a merge from the same repository as our working copy,
@@ -2105,14 +2087,14 @@ merge_dir_added(const char *local_dir_ab
is_versioned = TRUE;
}
- SVN_ERR(svn_io_check_path(path, &kind, subpool));
+ SVN_ERR(svn_io_check_path(local_abspath, &kind, subpool));
/* Check for an obstructed or missing node on disk. */
{
svn_wc_notify_state_t obstr_state;
- obstr_state = obstructed_or_missing(path, local_dir_abspath, merge_b,
- subpool);
+ obstr_state = obstructed_or_missing(local_abspath, local_dir_abspath,
+ merge_b, subpool);
/* In this case of adding a directory, we have an exception to the usual
* "skip if it's inconsistent" rule. If the directory exists on disk
@@ -2137,10 +2119,10 @@ merge_dir_added(const char *local_dir_ab
case svn_node_none:
/* Unversioned or schedule-delete */
if (merge_b->dry_run)
- merge_b->added_path = apr_pstrdup(merge_b->pool, path);
+ merge_b->added_path = apr_pstrdup(merge_b->pool, local_abspath);
else
{
- SVN_ERR(svn_io_make_dir_recursively(path, subpool));
+ SVN_ERR(svn_io_make_dir_recursively(local_abspath, subpool));
SVN_ERR(svn_wc_add4(merge_b->ctx->wc_ctx, local_abspath,
svn_depth_infinity,
copyfrom_url, copyfrom_rev,
@@ -2168,14 +2150,14 @@ merge_dir_added(const char *local_dir_ab
NULL, NULL, /* no notification func! */
subpool));
else
- merge_b->added_path = apr_pstrdup(merge_b->pool, path);
+ merge_b->added_path = apr_pstrdup(merge_b->pool, local_abspath);
if (state)
*state = svn_wc_notify_state_changed;
}
else
{
/* The dir is known to Subversion as already existing. */
- if (dry_run_deleted_p(merge_b, path))
+ if (dry_run_deleted_p(merge_b, local_abspath))
{
if (state)
*state = svn_wc_notify_state_changed;
@@ -2198,7 +2180,7 @@ merge_dir_added(const char *local_dir_ab
if (merge_b->dry_run)
merge_b->added_path = NULL;
- if (is_versioned && dry_run_deleted_p(merge_b, path))
+ if (is_versioned && dry_run_deleted_p(merge_b, local_abspath))
{
/* ### TODO: Retain record of this dir being added to
### avoid problems from subsequent edits which try to
@@ -2235,7 +2217,7 @@ static svn_error_t *
merge_dir_deleted(const char *local_dir_abspath,
svn_wc_notify_state_t *state,
svn_boolean_t *tree_conflicted,
- const char *path,
+ const char *local_abspath,
void *baton,
apr_pool_t *scratch_pool)
{
@@ -2243,7 +2225,6 @@ merge_dir_deleted(const char *local_dir_
apr_pool_t *subpool = svn_pool_create(merge_b->pool);
svn_node_kind_t kind;
svn_error_t *err;
- const char *local_abspath;
svn_boolean_t is_versioned;
svn_boolean_t is_deleted;
@@ -2258,8 +2239,6 @@ merge_dir_deleted(const char *local_dir_
return SVN_NO_ERROR;
}
- SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, subpool));
-
if (tree_conflicted)
*tree_conflicted = FALSE;
@@ -2303,8 +2282,8 @@ merge_dir_deleted(const char *local_dir_
{
svn_wc_notify_state_t obstr_state;
- obstr_state = obstructed_or_missing(path, local_dir_abspath, merge_b,
- subpool);
+ obstr_state = obstructed_or_missing(local_abspath, local_dir_abspath,
+ merge_b, subpool);
if (obstr_state != svn_wc_notify_state_inapplicable)
{
if (state)
@@ -2315,7 +2294,7 @@ merge_dir_deleted(const char *local_dir_
}
/* Switch on the on-disk state of this path */
- SVN_ERR(svn_io_check_path(path, &kind, subpool));
+ SVN_ERR(svn_io_check_path(local_abspath, &kind, subpool));
switch (kind)
{
case svn_node_dir:
@@ -2331,7 +2310,7 @@ merge_dir_deleted(const char *local_dir_
/* Passing NULL for the notify_func and notify_baton because
repos_diff.c:delete_entry() will do it for us. */
- err = svn_client__wc_delete(path, merge_b->force,
+ err = svn_client__wc_delete(local_abspath, merge_b->force,
merge_b->dry_run, FALSE,
NULL, NULL,
merge_b->ctx, subpool);
@@ -4571,8 +4550,8 @@ record_skips(const char *mergeinfo_path,
might be an unversioned obstruction. */
SVN_ERR(svn_wc_status3(&status, merge_b->ctx->wc_ctx,
skipped_abspath, pool, pool));
- if (status->text_status == svn_wc_status_none
- || status->text_status == svn_wc_status_unversioned)
+ if (status->node_status == svn_wc_status_none
+ || status->node_status == svn_wc_status_unversioned)
continue;
/* Add an empty range list for this path.
@@ -9636,10 +9615,12 @@ calculate_left_hand_side(const char **ur
hi = apr_hash_next(hi))
{
const char *path = svn__apr_hash_index_key(hi);
+ const char *path_rel_to_session =
+ svn_relpath_skip_ancestor(target_repos_rel_path, path);
SVN_ERR(svn_client__repos_location_segments(&segments,
target_ra_session,
- "",
+ path_rel_to_session,
target_rev, target_rev,
SVN_INVALID_REVNUM,
ctx, subpool));
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/patch.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/patch.c Tue Aug 10 22:07:24 2010
@@ -297,10 +297,10 @@ resolve_target_path(patch_target_t *targ
else
return svn_error_return(err);
}
- else if (status->text_status == svn_wc_status_ignored ||
- status->text_status == svn_wc_status_unversioned ||
- status->text_status == svn_wc_status_missing ||
- status->text_status == svn_wc_status_obstructed)
+ else if (status->node_status == svn_wc_status_ignored ||
+ status->node_status == svn_wc_status_unversioned ||
+ status->node_status == svn_wc_status_missing ||
+ status->node_status == svn_wc_status_obstructed)
{
target->skipped = TRUE;
return SVN_NO_ERROR;
@@ -1483,8 +1483,8 @@ find_existing_children(void *baton,
{
struct status_baton *btn = baton;
- if (status->text_status != svn_wc_status_none
- && status->text_status != svn_wc_status_deleted
+ if (status->node_status != svn_wc_status_none
+ && status->node_status != svn_wc_status_deleted
&& strcmp(abspath, btn->parent_path))
{
APR_ARRAY_PUSH(btn->existing_targets,
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/ra.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/ra.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/ra.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/ra.c Tue Aug 10 22:07:24 2010
@@ -588,7 +588,8 @@ svn_client__repos_locations(const char *
SVN_ERR(svn_dirent_get_absolute(&local_abspath_or_url, path, subpool));
SVN_ERR(svn_wc__node_get_url(&node_url, ctx->wc_ctx,
local_abspath_or_url, pool, subpool));
- SVN_ERR(svn_wc__node_get_copyfrom_info(©from_url, ©from_rev,
+ SVN_ERR(svn_wc__node_get_copyfrom_info(NULL, NULL,
+ ©from_url, ©from_rev,
NULL, ctx->wc_ctx,
local_abspath_or_url,
pool, subpool));
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/status.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/status.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/status.c Tue Aug 10 22:07:24 2010
@@ -51,19 +51,28 @@
accordingly. */
struct status_baton
{
- svn_boolean_t deleted_in_repos; /* target is deleted in repos */
- apr_hash_t *changelist_hash; /* keys are changelist names */
- svn_wc_status_func4_t real_status_func; /* real status function */
- void *real_status_baton; /* real status baton */
- const char *anchor_abspath; /* Absolute path of anchor */
- const char *anchor_relpath; /* Relative path of anchor */
- apr_hash_t *ignored_props; /* props to ignore mods to */
- svn_wc_context_t *wc_ctx; /* working copy context */
- svn_boolean_t no_ignore; /* Same as svn_client_status5() */
- svn_boolean_t get_all; /* Same as svn_client_status5() */
+ svn_boolean_t deleted_in_repos; /* target is deleted in repos */
+ apr_hash_t *changelist_hash; /* keys are changelist names */
+ svn_client_status_func_t real_status_func; /* real status function */
+ void *real_status_baton; /* real status baton */
+ const char *anchor_abspath; /* Absolute path of anchor */
+ const char *anchor_relpath; /* Relative path of anchor */
+ apr_hash_t *ignored_props; /* props to ignore mods to */
+ svn_wc_context_t *wc_ctx; /* working copy context */
+ svn_boolean_t no_ignore; /* Same as svn_client_status5() */
+ svn_boolean_t get_all; /* Same as svn_client_status5() */
};
+/* Create svn_client_status_t from svn_wc_satus3_t */
+static svn_error_t *
+create_client_status(svn_client_status_t **cst,
+ svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ const svn_wc_status3_t *status,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
/* A status callback function which wraps the *real* status
function/baton. This sucker takes care of any status tweaks we
need to make (such as noting that the target of the status is
@@ -78,6 +87,7 @@ tweak_status(void *baton,
{
struct status_baton *sb = baton;
const char *path = local_abspath;
+ svn_client_status_t *cst;
/* If we know that the target was deleted in HEAD of the repository,
we need to note that fact in all the status structures that come
@@ -134,8 +144,11 @@ tweak_status(void *baton,
}
}
+ SVN_ERR(create_client_status(&cst, sb->wc_ctx, local_abspath, status,
+ scratch_pool, scratch_pool));
+
/* Call the real status function/baton. */
- return sb->real_status_func(sb->real_status_baton, path, status,
+ return sb->real_status_func(sb->real_status_baton, path, cst,
scratch_pool);
}
@@ -146,6 +159,7 @@ typedef struct report_baton_t {
/* The common ancestor URL of all paths included in the report. */
char *ancestor;
void *set_locks_baton;
+ svn_depth_t depth;
svn_client_ctx_t *ctx;
/* Pool to store locks in. */
apr_pool_t *pool;
@@ -186,14 +200,17 @@ reporter_link_path(void *report_baton, c
const char *ancestor;
apr_size_t len;
- ancestor = svn_dirent_get_longest_ancestor(url, rb->ancestor, pool);
+ ancestor = svn_uri_get_longest_ancestor(url, rb->ancestor, pool);
/* If we got a shorter ancestor, truncate our current ancestor.
Note that svn_dirent_get_longest_ancestor will allocate its return
value even if it identical to one of its arguments. */
len = strlen(ancestor);
if (len < strlen(rb->ancestor))
- rb->ancestor[len] = '\0';
+ {
+ rb->ancestor[len] = '\0';
+ rb->depth = svn_depth_infinity;
+ }
return rb->wrapped_reporter->link_path(rb->wrapped_report_baton, path, url,
revision, depth, start_empty,
@@ -220,7 +237,7 @@ reporter_finish_report(void *report_bato
/* The locks need to live throughout the edit. Note that if the
server doesn't support lock discovery, we'll just not do locky
stuff. */
- err = svn_ra_get_locks(ras, &locks, "", rb->pool);
+ err = svn_ra_get_locks2(ras, &locks, "", rb->depth, rb->pool);
if (err && ((err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED)
|| (err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE)))
{
@@ -266,10 +283,9 @@ static svn_ra_reporter3_t lock_fetch_rep
svn_error_t *
svn_client_status5(svn_revnum_t *result_rev,
+ svn_client_ctx_t *ctx,
const char *path,
const svn_opt_revision_t *revision,
- svn_wc_status_func4_t status_func,
- void *status_baton,
svn_depth_t depth,
svn_boolean_t get_all,
svn_boolean_t update,
@@ -277,7 +293,8 @@ svn_client_status5(svn_revnum_t *result_
svn_boolean_t ignore_externals,
svn_boolean_t ignore_mergeinfo,
const apr_array_header_t *changelists,
- svn_client_ctx_t *ctx,
+ svn_client_status_func_t status_func,
+ void *status_baton,
apr_pool_t *pool) /* ### aka scratch_pool */
{
struct status_baton sb;
@@ -499,8 +516,8 @@ svn_client_status5(svn_revnum_t *result_
/* Do the deed. Let the RA layer drive the status editor. */
SVN_ERR(svn_ra_do_status2(ra_session, &rb.wrapped_reporter,
&rb.wrapped_report_baton,
- target_basename, revnum, depth, editor,
- edit_baton, pool));
+ target_basename, revnum, svn_depth_unknown,
+ editor, edit_baton, pool));
/* Init the report baton. */
rb.ancestor = apr_pstrdup(pool, URL); /* Edited later */
@@ -508,6 +525,11 @@ svn_client_status5(svn_revnum_t *result_
rb.ctx = ctx;
rb.pool = pool;
+ if (depth == svn_depth_unknown)
+ rb.depth = svn_depth_infinity;
+ else
+ rb.depth = depth;
+
SVN_ERR(svn_ra_has_capability(ra_session, &server_supports_depth,
SVN_RA_CAPABILITY_DEPTH, pool));
@@ -573,11 +595,155 @@ svn_client_status5(svn_revnum_t *result_
in the future.
*/
if (SVN_DEPTH_IS_RECURSIVE(depth) && (! ignore_externals))
- SVN_ERR(svn_client__do_external_status(externals_store.externals_new,
- status_func, status_baton,
+ SVN_ERR(svn_client__do_external_status(ctx, externals_store.externals_new,
depth, get_all,
update, no_ignore, ignored_props,
- ctx, pool));
+ status_func, status_baton, pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_client_status_t *
+svn_client_status_dup(const svn_client_status_t *status,
+ apr_pool_t *result_pool)
+{
+ svn_client_status_t *st = apr_palloc(result_pool, sizeof(*st));
+
+ *st = *status;
+
+ if (status->local_abspath)
+ st->local_abspath = apr_pstrdup(result_pool, status->local_abspath);
+
+ if (status->repos_root_url)
+ st->repos_root_url = apr_pstrdup(result_pool, status->repos_root_url);
+
+ if (status->repos_relpath)
+ st->repos_relpath = apr_pstrdup(result_pool, status->repos_relpath);
+
+ if (status->changed_author)
+ st->changed_author = apr_pstrdup(result_pool, status->changed_author);
+
+ if (status->lock)
+ st->lock = svn_lock_dup(status->lock, result_pool);
+
+ if (status->changelist)
+ st->changelist = apr_pstrdup(result_pool, status->changelist);
+
+ if (status->repos_lock)
+ st->repos_lock = svn_lock_dup(status->repos_lock, result_pool);
+
+ if (status->backwards_compatibility_baton)
+ {
+ const svn_wc_status3_t *wc_st = status->backwards_compatibility_baton;
+
+ st->backwards_compatibility_baton = svn_wc_dup_status3(wc_st,
+ result_pool);
+ }
+
+ return st;
+}
+
+/* Create a svn_client_status_t structure *CST for LOCAL_ABSPATH, shallow
+ * copying data from *STATUS wherever possible and retrieving the other values
+ * where needed. Peform temporary allocations in SCRATCH_POOL and allocate the
+ * result in RESULT_POOL
+ */
+static svn_error_t *
+create_client_status(svn_client_status_t **cst,
+ svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ const svn_wc_status3_t *status,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ *cst = apr_pcalloc(result_pool, sizeof(**cst));
+
+ (*cst)->kind = status->kind;
+ (*cst)->local_abspath = local_abspath;
+ (*cst)->versioned = status->versioned;
+
+ (*cst)->conflicted = status->conflicted;
+
+ (*cst)->node_status = status->node_status;
+ (*cst)->text_status = status->text_status;
+ (*cst)->prop_status = status->prop_status;
+
+ (*cst)->switched = status->switched;
+
+ if (status->kind == svn_node_dir)
+ SVN_ERR(svn_wc_locked2(NULL, &(*cst)->locked, wc_ctx, local_abspath,
+ scratch_pool));
+
+ (*cst)->copied = status->copied;
+ (*cst)->revision = status->revision;
+
+ (*cst)->changed_rev = status->changed_rev;
+ (*cst)->changed_date = status->changed_date;
+ (*cst)->changed_author = status->changed_author;
+
+ (*cst)->repos_root_url = status->repos_root_url;
+ (*cst)->repos_relpath = status->repos_relpath;
+
+ (*cst)->switched = status->switched;
+ (*cst)->file_external = FALSE;
+
+ if (status->versioned
+ && status->switched
+ && status->kind == svn_node_file)
+ {
+ svn_boolean_t is_file_external;
+ SVN_ERR(svn_wc__node_is_file_external(&is_file_external, wc_ctx,
+ local_abspath, scratch_pool));
+
+ if (is_file_external)
+ {
+ (*cst)->file_external = is_file_external;
+ (*cst)->switched = FALSE; /* ### Keep switched true now? */
+ }
+ }
+
+ (*cst)->lock = status->lock;
+
+ (*cst)->changelist = status->changelist;
+ (*cst)->depth = status->depth;
+
+ /* Out of date information */
+ (*cst)->ood_kind = status->ood_kind;
+ (*cst)->repos_node_status = status->repos_node_status;
+ (*cst)->repos_text_status = status->repos_text_status;
+ (*cst)->repos_prop_status = status->repos_prop_status;
+ (*cst)->repos_lock = status->repos_lock;
+
+ (*cst)->ood_changed_rev = status->ood_changed_rev;
+ (*cst)->ood_changed_date = status->ood_changed_date;
+ (*cst)->ood_changed_author = status->ood_changed_author;
+
+ /* When changing the value of backwards_compatibility_baton, also
+ change its use in status4_wrapper_func in deprecated.c */
+ (*cst)->backwards_compatibility_baton = status;
+
+ if (status->versioned && status->conflicted)
+ {
+ svn_boolean_t text_conflicted, prop_conflicted, tree_conflicted;
+
+ /* Note: This checks the on disk markers to automatically hide
+ text/property conflicts that are hidden by removing their
+ markers */
+ SVN_ERR(svn_wc_conflicted_p3(&text_conflicted, &prop_conflicted,
+ &tree_conflicted, wc_ctx, local_abspath,
+ scratch_pool));
+
+ if (text_conflicted)
+ (*cst)->text_status = svn_wc_status_conflicted;
+
+ if (prop_conflicted)
+ (*cst)->prop_status = svn_wc_status_conflicted;
+
+ /* ### Also set this for tree_conflicts? */
+ if (text_conflicted || prop_conflicted)
+ (*cst)->node_status = svn_wc_status_conflicted;
+ }
return SVN_NO_ERROR;
}
+
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/update.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/update.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/update.c Tue Aug 10 22:07:24 2010
@@ -70,7 +70,7 @@ file_fetcher(void *baton,
struct ff_baton *ffb = (struct ff_baton *)baton;
const char *dirpath, *base_name, *session_url, *old_session_url;
- svn_relpath_split(path, &dirpath, &base_name, pool);
+ svn_relpath_split(&dirpath, &base_name, path, pool);
session_url = svn_path_url_add_component2(ffb->repos_root,
dirpath, pool);
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/url.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/url.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/url.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/url.c Tue Aug 10 22:07:24 2010
@@ -146,7 +146,8 @@ svn_client__entry_location(const char **
|| peg_rev_kind == svn_opt_revision_head)
return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL, NULL);
- SVN_ERR(svn_wc__node_get_copyfrom_info(©from_url, ©from_rev,
+ SVN_ERR(svn_wc__node_get_copyfrom_info(NULL, NULL,
+ ©from_url, ©from_rev,
NULL, wc_ctx, local_abspath,
result_pool, scratch_pool));
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/path_driver.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/path_driver.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/path_driver.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/path_driver.c Tue Aug 10 22:07:24 2010
@@ -215,9 +215,9 @@ svn_delta_path_driver(const svn_delta_ed
/*** Step C - Open any directories between the common ancestor
and the parent of the current path. ***/
if (*path == '/')
- svn_uri_split(path, &pdir, &bname, iterpool);
+ svn_uri_split(&pdir, &bname, path, iterpool);
else
- svn_relpath_split(path, &pdir, &bname, iterpool);
+ svn_relpath_split(&pdir, &bname, path, iterpool);
if (strlen(pdir) > common_len)
{
const char *piece = pdir + common_len + 1;
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/text_delta.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/text_delta.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/text_delta.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/text_delta.c Tue Aug 10 22:07:24 2010
@@ -564,6 +564,73 @@ size_buffer(char **buf, apr_size_t *buf_
return SVN_NO_ERROR;
}
+/* Copy LEN bytes from SOURCE to TARGET, optimizing for the case where LEN
+ * is often very small. Return a pointer to the first byte after the copied
+ * target range, unlike standard memcpy(), as a potential further
+ * optimization for the caller.
+ *
+ * memcpy() is hard to tune for a wide range of buffer lengths. Therefore,
+ * it is often tuned for high throughput on large buffers and relatively
+ * low latency for mid-sized buffers (tens of bytes). However, the overhead
+ * for very small buffers (<10 bytes) is still high. Even passing the
+ * parameters, for instance, may take as long as copying 3 bytes.
+ *
+ * Because short copy sequences seem to be a common case, at least in
+ * "format 2" FSFS repositories, we copy them directly. Larger buffer sizes
+ * aren't hurt measurably by the exta 'if' clause. */
+static APR_INLINE char *
+fast_memcpy(char *target, const char *source, apr_size_t len)
+{
+ if (len > 7)
+ {
+ memcpy(target, source, len);
+ target += len;
+ }
+ else
+ {
+ /* memcpy is not exactly fast for small block sizes.
+ * Since they are common, let's run optimized code for them. */
+ const char *end = source + len;
+ for (; source != end; source++)
+ *(target++) = *source;
+ }
+
+ return target;
+}
+
+/* Copy LEN bytes from SOURCE to TARGET. Unlike memmove() or memcpy(),
+ * create repeating patterns if the source and target ranges overlap.
+ * Return a pointer to the first byte after the copied target range. */
+static APR_INLINE char *
+patterning_copy(char *target, const char *source, apr_size_t len)
+{
+ const char *end = source + len;
+
+ /* On the majority of machines (x86 / x64), unaligned access is much
+ * cheaper than repeated aligned access. Therefore, use chunky copies on
+ * these machines when feasible.
+ * For those machines, GCC, ICC and MSC will define one of the following: */
+#if defined(_M_IX86) || defined(_M_X64) || defined(i386) || defined(__x86_64)
+
+ if (end + sizeof(apr_uint32_t) <= target)
+ {
+ /* Source and target are at least 4 bytes apart, so we can copy in
+ * 4-byte chunks. */
+ for (; source + sizeof(apr_uint32_t) <= end;
+ source += sizeof(apr_uint32_t),
+ target += sizeof(apr_uint32_t))
+ *(apr_uint32_t *)(target) = *(apr_uint32_t *)(source);
+ }
+
+#endif
+
+ /* fall through to byte-wise copy (either for the below-chunk-size tail
+ * or the whole copy) */
+ for (; source != end; source++)
+ *(target++) = *source;
+
+ return target;
+}
void
svn_txdelta_apply_instructions(svn_txdelta_window_t *window,
@@ -571,7 +638,7 @@ svn_txdelta_apply_instructions(svn_txdel
apr_size_t *tlen)
{
const svn_txdelta_op_t *op;
- apr_size_t i, j, tpos = 0;
+ apr_size_t tpos = 0;
for (op = window->ops; op < window->ops + window->num_ops; op++)
{
@@ -586,25 +653,26 @@ svn_txdelta_apply_instructions(svn_txdel
case svn_txdelta_source:
/* Copy from source area. */
assert(op->offset + op->length <= window->sview_len);
- memcpy(tbuf + tpos, sbuf + op->offset, buf_len);
+ fast_memcpy(tbuf + tpos, sbuf + op->offset, buf_len);
break;
case svn_txdelta_target:
- /* Copy from target area. Don't use memcpy() since its
- semantics aren't guaranteed for overlapping memory areas,
- and target copies are allowed to overlap to generate
- repeated data. */
+ /* Copy from target area. We can't use memcpy() or the like
+ * since we need a specific semantics for overlapping copies:
+ * they must result in repeating patterns.
+ * Note that most copies won't have overlapping source and
+ * target ranges (they are just a result of self-compressed
+ * data) but a small percentage will. */
assert(op->offset < tpos);
- for (i = op->offset, j = tpos; i < op->offset + buf_len; i++)
- tbuf[j++] = tbuf[i];
+ patterning_copy(tbuf + tpos, tbuf + op->offset, buf_len);
break;
case svn_txdelta_new:
/* Copy from window new area. */
assert(op->offset + op->length <= window->new_data->len);
- memcpy(tbuf + tpos,
- window->new_data->data + op->offset,
- buf_len);
+ fast_memcpy(tbuf + tpos,
+ window->new_data->data + op->offset,
+ buf_len);
break;
default:
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/parse-diff.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/parse-diff.c Tue Aug 10 22:07:24 2010
@@ -100,14 +100,14 @@ parse_range(svn_linenum_t *start, svn_li
}
/* Try to parse a hunk header in string HEADER, putting parsed information
- * into HUNK. Return TRUE if the header parsed correctly.
+ * into HUNK. Return TRUE if the header parsed correctly. ATAT is the
+ * character string used to delimit the hunk header.
* If REVERSE is TRUE, invert the hunk header while parsing it.
* Do all allocations in POOL. */
static svn_boolean_t
parse_hunk_header(const char *header, svn_hunk_t *hunk,
- svn_boolean_t reverse, apr_pool_t *pool)
+ const char *atat, svn_boolean_t reverse, apr_pool_t *pool)
{
- static const char * const atat = "@@";
const char *p;
svn_stringbuf_t *range;
@@ -233,7 +233,7 @@ reverse_diff_transformer(svn_stringbuf_t
/* ### Pass the already parsed hunk via the baton?
* ### Maybe we should really make svn_stream_readline() a proper stream
* ### method and override it instead of adding special callbacks? */
- if (parse_hunk_header(line, &hunk, FALSE, scratch_pool))
+ if (parse_hunk_header(line, &hunk, "@@", FALSE, scratch_pool))
{
*buf = svn_stringbuf_createf(result_pool,
"@@ -%lu,%lu +%lu,%lu @@",
@@ -242,6 +242,15 @@ reverse_diff_transformer(svn_stringbuf_t
hunk.original_start,
hunk.original_length);
}
+ else if (parse_hunk_header(line, &hunk, "##", FALSE, scratch_pool))
+ {
+ *buf = svn_stringbuf_createf(result_pool,
+ "## -%lu,%lu +%lu,%lu ##",
+ hunk.modified_start,
+ hunk.modified_length,
+ hunk.original_start,
+ hunk.original_length);
+ }
else if (line[0] == '+')
{
*buf = svn_stringbuf_create(line, result_pool);
@@ -258,14 +267,31 @@ reverse_diff_transformer(svn_stringbuf_t
return SVN_NO_ERROR;
}
+/* Parse PROP_NAME from HEADER as the part after the INDICATOR line. */
+static svn_error_t *
+parse_prop_name(const char **prop_name, const char *header,
+ const char *indicator, apr_pool_t *result_pool)
+{
+ SVN_ERR(svn_utf_cstring_to_utf8(prop_name,
+ header + strlen(indicator),
+ result_pool));
+
+ /* ### Are we guarenteed that there are no trailing or leading
+ * ### whitespaces in the name? */
+
+ return SVN_NO_ERROR;
+}
+
/* Return the next *HUNK from a PATCH, using STREAM to read data
- * from the patch file. If no hunk can be found, set *HUNK to NULL.
- * If REVERSE is TRUE, invert the hunk while parsing it. If
- * IGNORE_WHiTESPACES is TRUE, let lines without leading spaces be
- * recognized as context lines. Allocate results in RESULT_POOL. Use
- * SCRATCH_POOL for all other allocations. */
+ * from the patch file. If no hunk can be found, set *HUNK to NULL. If we
+ * have a property hunk, PROP_NAME will be set. If we have a text hunk,
+ * PROP_NAME will be NULL. If REVERSE is TRUE, invert the hunk while
+ * parsing it. If IGNORE_WHiTESPACES is TRUE, let lines without leading
+ * spaces be recognized as context lines. Allocate results in RESULT_POOL.
+ * Use SCRATCH_POOL for all other allocations. */
static svn_error_t *
parse_next_hunk(svn_hunk_t **hunk,
+ const char **prop_name,
svn_patch_t *patch,
svn_stream_t *stream,
svn_boolean_t reverse,
@@ -274,7 +300,8 @@ parse_next_hunk(svn_hunk_t **hunk,
apr_pool_t *scratch_pool)
{
static const char * const minus = "--- ";
- static const char * const atat = "@@";
+ static const char * const text_atat = "@@";
+ static const char * const prop_atat = "##";
svn_stringbuf_t *line;
svn_boolean_t eof, in_hunk, hunk_seen;
apr_off_t pos, last_line;
@@ -289,6 +316,12 @@ parse_next_hunk(svn_hunk_t **hunk,
svn_boolean_t changed_line_seen;
apr_pool_t *iterpool;
+ /* We only set this if we have a property hunk.
+ * ### prop_name acts as both a state flag inside this function and a
+ * ### qualifier to discriminate between props and text hunks. Is that
+ * ### kind of overloading ok? */
+ *prop_name = NULL;
+
if (apr_file_eof(patch->patch_file) == APR_EOF)
{
/* No more hunks here. */
@@ -407,18 +440,47 @@ parse_next_hunk(svn_hunk_t **hunk,
}
else
{
- if (starts_with(line->data, atat))
+ if (starts_with(line->data, text_atat))
{
/* Looks like we have a hunk header, try to rip it apart. */
- in_hunk = parse_hunk_header(line->data, *hunk, reverse,
- iterpool);
+ in_hunk = parse_hunk_header(line->data, *hunk, text_atat,
+ reverse, iterpool);
if (in_hunk)
{
original_lines = (*hunk)->original_length;
modified_lines = (*hunk)->modified_length;
+ *prop_name = NULL;
}
+ }
+ else if (starts_with(line->data, prop_atat) && *prop_name)
+ {
+ /* Looks like we have a property hunk header, try to rip it
+ * apart. */
+ in_hunk = parse_hunk_header(line->data, *hunk, prop_atat,
+ reverse, iterpool);
+ if (in_hunk)
+ {
+ original_lines = (*hunk)->original_length;
+ modified_lines = (*hunk)->modified_length;
+ }
+ }
+ else if (starts_with(line->data, "Added: "))
+ {
+ SVN_ERR(parse_prop_name(prop_name, line->data, "Added: ",
+ result_pool));
}
- else if (starts_with(line->data, minus))
+ else if (starts_with(line->data, "Deleted: "))
+ {
+ SVN_ERR(parse_prop_name(prop_name, line->data, "Deleted: ",
+ result_pool));
+ }
+ else if (starts_with(line->data, "Modified: "))
+ {
+ SVN_ERR(parse_prop_name(prop_name, line->data, "Modified: ",
+ result_pool));
+ }
+ else if (starts_with(line->data, minus)
+ || starts_with(line->data, "git --diff "))
/* This could be a header of another patch. Bail out. */
break;
}
@@ -517,6 +579,268 @@ close_hunk(const svn_hunk_t *hunk)
return SVN_NO_ERROR;
}
+enum parse_state
+{
+ state_start,
+ state_git_diff_seen,
+ /* if we have an add || del || cp src+dst || mv src+dst */
+ state_git_tree_seen,
+ state_git_minus_seen,
+ state_git_plus_seen,
+ state_move_from_seen,
+ state_copy_from_seen,
+ state_minus_seen,
+ state_unidiff_found,
+ state_add_seen,
+ state_del_seen,
+ state_git_header_found
+};
+
+struct transition
+{
+ const char *line;
+ enum parse_state state;
+ svn_error_t *(*fn)(enum parse_state *state, const char *line,
+ svn_patch_t *patch, apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+};
+
+/* UTF-8 encode and canonicalize the content of LINE as FILE_NAME. */
+static svn_error_t *
+grab_filename(const char **file_name, const char *line, apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const char *utf8_path;
+ const char *canon_path;
+
+ /* Grab the filename and encode it in UTF-8. */
+ /* TODO: Allow specifying the patch file's encoding.
+ * For now, we assume its encoding is native. */
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_path,
+ line,
+ scratch_pool));
+
+ /* Canonicalize the path name. */
+ canon_path = svn_dirent_canonicalize(utf8_path, scratch_pool);
+
+ *file_name = apr_pstrdup(result_pool, canon_path);
+
+ return SVN_NO_ERROR;
+}
+
+/* Parse the '--- ' line of a regular unidiff. */
+static svn_error_t *
+diff_minus(enum parse_state *state, const char *line, svn_patch_t *patch,
+ apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+ /* If we can find a tab, it separates the filename from
+ * the rest of the line which we can discard. */
+ char *tab = strchr(line, '\t');
+ if (tab)
+ *tab = '\0';
+
+ SVN_ERR(grab_filename(&patch->old_filename, line + strlen("--- "),
+ result_pool, scratch_pool));
+
+ *state = state_minus_seen;
+
+ return SVN_NO_ERROR;
+}
+
+/* Parse the '+++ ' line of a regular unidiff. */
+static svn_error_t *
+diff_plus(enum parse_state *state, const char *line, svn_patch_t *patch,
+ apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+ /* If we can find a tab, it separates the filename from
+ * the rest of the line which we can discard. */
+ char *tab = strchr(line, '\t');
+ if (tab)
+ *tab = '\0';
+
+ SVN_ERR(grab_filename(&patch->new_filename, line + strlen("+++ "),
+ result_pool, scratch_pool));
+
+ *state = state_unidiff_found;
+
+ return SVN_NO_ERROR;
+}
+
+/* Parse the first line of a git extended unidiff. */
+static svn_error_t *
+git_start(enum parse_state *state, const char *line, svn_patch_t *patch,
+ apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+ const char *old_path;
+ const char *new_path;
+ char *end_old_path;
+ char *slash;
+
+ /* ### Add handling of escaped paths
+ * http://www.kernel.org/pub/software/scm/git/docs/git-diff.html:
+ *
+ * TAB, LF, double quote and backslash characters in pathnames are
+ * represented as \t, \n, \" and \\, respectively. If there is need for
+ * such substitution then the whole pathname is put in double quotes.
+ */
+
+ /* Our line should look like this: 'git --diff a/path b/path'.
+ * If we find any deviations from that format, we return with state reset
+ * to start.
+ *
+ * ### We can't handle paths with spaces!
+ */
+ slash = strchr(line, '/');
+
+ if (! slash)
+ {
+ *state = state_start;
+ return SVN_NO_ERROR;
+ }
+
+ old_path = slash + 1;
+
+ if (! *old_path)
+ {
+ *state = state_start;
+ return SVN_NO_ERROR;
+ }
+
+ end_old_path = strchr(old_path, ' ');
+
+ if (end_old_path)
+ *end_old_path = '\0';
+ else
+ {
+ *state = state_start;
+ return SVN_NO_ERROR;
+ }
+
+ /* The new path begins after the first slash after the old path. */
+ slash = strchr(end_old_path + 1, '/');
+
+ if (! slash)
+ {
+ *state = state_start;
+ return SVN_NO_ERROR;
+ }
+
+ /* The path starts after the slash */
+ new_path = slash + 1;
+
+ if (! *new_path)
+ {
+ *state = state_start;
+ return SVN_NO_ERROR;
+ }
+
+ SVN_ERR(grab_filename(&patch->old_filename, old_path,
+ result_pool, scratch_pool));
+
+ SVN_ERR(grab_filename(&patch->new_filename, new_path,
+ result_pool, scratch_pool));
+
+ /* We assume that the path is only modified until we've found a 'tree'
+ * header */
+ patch->operation = svn_diff_op_modified;
+
+ *state = state_git_diff_seen;
+ return SVN_NO_ERROR;
+}
+
+/* Parse the '--- ' line of a git extended unidiff. */
+static svn_error_t *
+git_minus(enum parse_state *state, const char *line, svn_patch_t *patch,
+ apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+ /* ### Check that the path is consistent with the 'git --diff ' line. */
+
+ *state = state_git_minus_seen;
+ return SVN_NO_ERROR;
+}
+
+/* Parse the '+++ ' line of a git extended unidiff. */
+static svn_error_t *
+git_plus(enum parse_state *state, const char *line, svn_patch_t *patch,
+ apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+ /* ### Check that the path is consistent with the 'git --diff ' line. */
+
+ *state = state_git_header_found;
+ return SVN_NO_ERROR;
+}
+
+/* Parse the 'move from ' line of a git extended unidiff. */
+static svn_error_t *
+git_move_from(enum parse_state *state, const char *line, svn_patch_t *patch,
+ apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+ /* ### Check that the path is consistent with the 'git --diff ' line. */
+
+ *state = state_move_from_seen;
+ return SVN_NO_ERROR;
+}
+
+/* Parse the 'move to ' line fo a git extended unidiff. */
+static svn_error_t *
+git_move_to(enum parse_state *state, const char *line, svn_patch_t *patch,
+ apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+ /* ### Check that the path is consistent with the 'git --diff ' line. */
+
+ patch->operation = svn_diff_op_moved;
+
+ *state = state_git_tree_seen;
+ return SVN_NO_ERROR;
+}
+
+/* Parse the 'copy from ' line of a git extended unidiff. */
+static svn_error_t *
+git_copy_from(enum parse_state *state, const char *line, svn_patch_t *patch,
+ apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+ /* ### Check that the path is consistent with the 'git --diff ' line. */
+
+ *state = state_copy_from_seen;
+ return SVN_NO_ERROR;
+}
+
+/* Parse the 'copy to ' line of a git extended unidiff. */
+static svn_error_t *
+git_copy_to(enum parse_state *state, const char *line, svn_patch_t *patch,
+ apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+ /* ### Check that the path is consistent with the 'git --diff ' line. */
+
+ patch->operation = svn_diff_op_copied;
+
+ *state = state_git_tree_seen;
+ return SVN_NO_ERROR;
+}
+
+/* Parse the 'new file ' line of a git extended unidiff. */
+static svn_error_t *
+git_new_file(enum parse_state *state, const char *line, svn_patch_t *patch,
+ apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+ patch->operation = svn_diff_op_added;
+
+ *state = state_git_header_found;
+ return SVN_NO_ERROR;
+}
+
+/* Parse the 'deleted file ' line of a git extended unidiff. */
+static svn_error_t *
+git_deleted_file(enum parse_state *state, const char *line, svn_patch_t *patch,
+ apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+ patch->operation = svn_diff_op_deleted;
+
+ *state = state_git_header_found;
+ return SVN_NO_ERROR;
+}
+
+
svn_error_t *
svn_diff_parse_next_patch(svn_patch_t **patch,
apr_file_t *patch_file,
@@ -525,15 +849,39 @@ svn_diff_parse_next_patch(svn_patch_t **
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- static const char * const minus = "--- ";
- static const char * const plus = "+++ ";
- const char *indicator;
const char *fname;
svn_stream_t *stream;
- svn_boolean_t eof, in_header;
- svn_hunk_t *hunk;
+ apr_off_t pos, last_line;
+ svn_boolean_t eof;
+ svn_boolean_t line_after_tree_header_read = FALSE;
+
apr_pool_t *iterpool;
+ enum parse_state state = state_start;
+
+ /* ### dannas: As I've understood the git diff format, the first line
+ * ### contains both paths and the paths in the headers that follow are only
+ * ### there to ensure that the path is valid. Not sure though, the
+ * ### research continues... */
+
+ /* Our table consisting of:
+ * Input Required state function to call */
+ struct transition transitions[] =
+ {
+ {"--- ", state_start, diff_minus},
+ {"+++ ", state_minus_seen, diff_plus},
+ {"git --diff", state_start, git_start},
+ {"--- a/", state_git_diff_seen, git_minus},
+ {"--- a/", state_git_tree_seen, git_minus},
+ {"+++ b/", state_git_minus_seen, git_plus},
+ {"move from ", state_git_diff_seen, git_move_from},
+ {"move to ", state_move_from_seen, git_move_to},
+ {"copy from ", state_git_diff_seen, git_copy_from},
+ {"copy to ", state_copy_from_seen, git_copy_to},
+ {"new file ", state_git_diff_seen, git_new_file},
+ {"deleted file ", state_git_diff_seen, git_deleted_file},
+ };
+
if (apr_file_eof(patch_file) == APR_EOF)
{
/* No more patches here. */
@@ -554,66 +902,74 @@ svn_diff_parse_next_patch(svn_patch_t **
* make sure it is disowned. */
stream = svn_stream_from_aprfile2(patch_file, TRUE, scratch_pool);
- indicator = minus;
- in_header = FALSE;
+ /* Get current seek position -- APR has no ftell() :( */
+ pos = 0;
+ SVN_ERR(svn_io_file_seek((*patch)->patch_file, APR_CUR, &pos, scratch_pool));
+
iterpool = svn_pool_create(scratch_pool);
+
do
{
svn_stringbuf_t *line;
+ int i;
svn_pool_clear(iterpool);
- /* Read a line from the stream. */
+ /* Remember the current line's offset, and read the line. */
+ last_line = pos;
SVN_ERR(svn_stream_readline_detect_eol(stream, &line, NULL, &eof,
iterpool));
- /* See if we have a diff header. */
- if (line->len > strlen(indicator) && starts_with(line->data, indicator))
+ if (! eof)
{
- const char *utf8_path;
- const char *canon_path;
+ /* Update line offset for next iteration.
+ * APR has no ftell() :( */
+ pos = 0;
+ SVN_ERR(svn_io_file_seek((*patch)->patch_file, APR_CUR, &pos, iterpool));
+ }
- /* If we can find a tab, it separates the filename from
- * the rest of the line which we can discard. */
- char *tab = strchr(line->data, '\t');
- if (tab)
- *tab = '\0';
-
- /* Grab the filename and encode it in UTF-8. */
- /* TODO: Allow specifying the patch file's encoding.
- * For now, we assume its encoding is native. */
- SVN_ERR(svn_utf_cstring_to_utf8(&utf8_path,
- line->data + strlen(indicator),
- iterpool));
-
- /* Canonicalize the path name. */
- canon_path = svn_dirent_canonicalize(utf8_path, iterpool);
-
- if ((! in_header) && strcmp(indicator, minus) == 0)
- {
- /* First line of header contains old filename. */
- if (reverse)
- (*patch)->new_filename = apr_pstrdup(result_pool, canon_path);
- else
- (*patch)->old_filename = apr_pstrdup(result_pool, canon_path);
- indicator = plus;
- in_header = TRUE;
- }
- else if (in_header && strcmp(indicator, plus) == 0)
- {
- /* Second line of header contains new filename. */
- if (reverse)
- (*patch)->old_filename = apr_pstrdup(result_pool, canon_path);
- else
- (*patch)->new_filename = apr_pstrdup(result_pool, canon_path);
- in_header = FALSE;
- break; /* All good! */
+ /* Run the state machine. */
+ for (i = 0; i < sizeof(transitions)/sizeof(transitions[0]); i++)
+ {
+ if (line->len > strlen(transitions[i].line)
+ && starts_with(line->data, transitions[i].line)
+ && state == transitions[i].state)
+ {
+ SVN_ERR(transitions[i].fn(&state, line->data, *patch,
+ result_pool, iterpool));
+ break;
}
- else
- in_header = FALSE;
}
+
+ if (state == state_unidiff_found
+ || state == state_git_header_found)
+ {
+ /* We have a valid diff header, yay! */
+ break;
+ }
+ else if (state == state_git_tree_seen
+ && line_after_tree_header_read)
+ {
+ /* We have a valid diff header for a patch with only tree changes.
+ * Rewind to the start of the line just read, so subsequent calls
+ * to this function don't end up skipping the line -- it may
+ * contain a patch. */
+ SVN_ERR(svn_io_file_seek((*patch)->patch_file, APR_SET, &last_line,
+ scratch_pool));
+ break;
+ }
+ else if (state == state_git_tree_seen)
+ line_after_tree_header_read = TRUE;
+
+ } while (! eof);
+
+ if (reverse)
+ {
+ const char *temp;
+ temp = (*patch)->old_filename;
+ (*patch)->old_filename = (*patch)->new_filename;
+ (*patch)->new_filename = temp;
}
- while (! eof);
if ((*patch)->old_filename == NULL || (*patch)->new_filename == NULL)
{
@@ -622,16 +978,38 @@ svn_diff_parse_next_patch(svn_patch_t **
}
else
{
+ svn_hunk_t *hunk;
+ const char *prop_name;
+
/* Parse hunks. */
(*patch)->hunks = apr_array_make(result_pool, 10, sizeof(svn_hunk_t *));
+ (*patch)->property_hunks = apr_hash_make(result_pool);
do
{
svn_pool_clear(iterpool);
- SVN_ERR(parse_next_hunk(&hunk, *patch, stream, reverse,
- ignore_whitespace, result_pool, iterpool));
- if (hunk)
+ SVN_ERR(parse_next_hunk(&hunk, &prop_name, *patch, stream,
+ reverse, ignore_whitespace,
+ result_pool, iterpool));
+ if (hunk && prop_name)
+ {
+ apr_array_header_t *hunks;
+
+ hunks = apr_hash_get((*patch)->property_hunks, prop_name,
+ APR_HASH_KEY_STRING);
+ if (! hunks)
+ {
+ hunks = apr_array_make(result_pool, 1,
+ sizeof(svn_hunk_t *));
+ apr_hash_set((*patch)->property_hunks, prop_name,
+ APR_HASH_KEY_STRING, hunks);
+ }
+
+ APR_ARRAY_PUSH(hunks, svn_hunk_t *) = hunk;
+ }
+ else if (hunk)
APR_ARRAY_PUSH((*patch)->hunks, svn_hunk_t *) = hunk;
+
}
while (hunk);
}
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs/fs-loader.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs/fs-loader.c Tue Aug 10 22:07:24 2010
@@ -1199,11 +1199,21 @@ svn_fs_revision_proplist(apr_hash_t **ta
}
svn_error_t *
+svn_fs_change_rev_prop2(svn_fs_t *fs, svn_revnum_t rev, const char *name,
+ const svn_string_t *const *old_value_p,
+ const svn_string_t *value, apr_pool_t *pool)
+{
+ return svn_error_return(fs->vtable->change_rev_prop(fs, rev, name,
+ old_value_p,
+ value, pool));
+}
+
+svn_error_t *
svn_fs_change_rev_prop(svn_fs_t *fs, svn_revnum_t rev, const char *name,
const svn_string_t *value, apr_pool_t *pool)
{
- return svn_error_return(fs->vtable->change_rev_prop(fs, rev, name, value,
- pool));
+ return svn_error_return(
+ svn_fs_change_rev_prop2(fs, rev, name, NULL, value, pool));
}
svn_error_t *
@@ -1291,16 +1301,29 @@ svn_fs_get_lock(svn_lock_t **lock, svn_f
}
svn_error_t *
+svn_fs_get_locks2(svn_fs_t *fs, const char *path, svn_depth_t depth,
+ svn_fs_get_locks_callback_t get_locks_func,
+ void *get_locks_baton, apr_pool_t *pool)
+{
+ SVN_ERR_ASSERT((depth == svn_depth_empty) ||
+ (depth == svn_depth_files) ||
+ (depth == svn_depth_immediates) ||
+ (depth == svn_depth_infinity));
+ return svn_error_return(fs->vtable->get_locks(fs, path, depth,
+ get_locks_func,
+ get_locks_baton, pool));
+}
+
+svn_error_t *
svn_fs_get_locks(svn_fs_t *fs, const char *path,
svn_fs_get_locks_callback_t get_locks_func,
- void *get_locks_baton,
- apr_pool_t *pool)
+ void *get_locks_baton, apr_pool_t *pool)
{
- return svn_error_return(fs->vtable->get_locks(fs, path, get_locks_func,
- get_locks_baton, pool));
+ return svn_error_return(svn_fs_get_locks2(fs, path, svn_depth_infinity,
+ get_locks_func, get_locks_baton,
+ pool));
}
-
/* --- History functions --- */
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs/fs-loader.h?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs/fs-loader.h Tue Aug 10 22:07:24 2010
@@ -158,6 +158,7 @@ typedef struct fs_vtable_t
svn_revnum_t rev, apr_pool_t *pool);
svn_error_t *(*change_rev_prop)(svn_fs_t *fs, svn_revnum_t rev,
const char *name,
+ const svn_string_t *const *old_value_p,
const svn_string_t *value,
apr_pool_t *pool);
svn_error_t *(*get_uuid)(svn_fs_t *fs, const char **uuid, apr_pool_t *pool);
@@ -189,7 +190,7 @@ typedef struct fs_vtable_t
svn_boolean_t break_lock, apr_pool_t *pool);
svn_error_t *(*get_lock)(svn_lock_t **lock, svn_fs_t *fs,
const char *path, apr_pool_t *pool);
- svn_error_t *(*get_locks)(svn_fs_t *fs, const char *path,
+ svn_error_t *(*get_locks)(svn_fs_t *fs, const char *path, svn_depth_t depth,
svn_fs_get_locks_callback_t get_locks_func,
void *get_locks_baton,
apr_pool_t *pool);
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/locks-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/locks-table.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/locks-table.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/locks-table.c Tue Aug 10 22:07:24 2010
@@ -191,6 +191,7 @@ get_lock(svn_lock_t **lock_p,
svn_error_t *
svn_fs_bdb__locks_get(svn_fs_t *fs,
const char *path,
+ svn_depth_t depth,
svn_fs_get_locks_callback_t get_locks_func,
void *get_locks_baton,
trail_t *trail,
@@ -225,9 +226,11 @@ svn_fs_bdb__locks_get(svn_fs_t *fs,
SVN_ERR(get_locks_func(get_locks_baton, lock, pool));
}
+ /* If we're only looking at PATH itself (depth = empty), stop here. */
+ if (depth == svn_depth_empty)
+ return SVN_NO_ERROR;
+
/* Now go hunt for possible children of PATH. */
- if (strcmp(path, "/") != 0)
- lookup_path = apr_pstrcat(pool, path, "/", NULL);
svn_fs_base__trail_debug(trail, "lock-tokens", "cursor");
db_err = bfd->lock_tokens->cursor(bfd->lock_tokens, trail->db_txn,
@@ -246,6 +249,8 @@ svn_fs_bdb__locks_get(svn_fs_t *fs,
/* As long as the prefix of the returned KEY matches LOOKUP_PATH we
know it is either LOOKUP_PATH or a decendant thereof. */
+ if (strcmp(path, "/") != 0)
+ lookup_path = apr_pstrcat(pool, path, "/", NULL);
while ((! db_err)
&& strncmp(lookup_path, key.data, strlen(lookup_path)) == 0)
{
@@ -260,6 +265,18 @@ svn_fs_bdb__locks_get(svn_fs_t *fs,
child_path = apr_pstrmemdup(subpool, key.data, key.size);
lock_token = apr_pstrmemdup(subpool, value.data, value.size);
+ if ((depth == svn_depth_files) || (depth == svn_depth_immediates))
+ {
+ /* On the assumption that we only store locks for files,
+ depth=files and depth=immediates should boil down to the
+ same set of results. So just see if CHILD_PATH is an
+ immediate child of PATH. If not, we don't care about
+ this item. */
+ const char *rel_uri = svn_uri_is_child(path, child_path, subpool);
+ if (!rel_uri || (svn_path_component_count(rel_uri) != 1))
+ goto loop_it;
+ }
+
/* Get the lock for CHILD_PATH. */
err = get_lock(&lock, fs, child_path, lock_token, trail, subpool);
if (err)
@@ -279,6 +296,7 @@ svn_fs_bdb__locks_get(svn_fs_t *fs,
}
}
+ loop_it:
svn_fs_base__result_dbt(&key);
svn_fs_base__result_dbt(&value);
db_err = svn_bdb_dbc_get(cursor, &key, &value, DB_NEXT);
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/locks-table.h
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/locks-table.h?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/locks-table.h (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/locks-table.h Tue Aug 10 22:07:24 2010
@@ -86,12 +86,16 @@ svn_error_t *svn_fs_bdb__lock_get(svn_lo
in FS. Pass each lock to GET_LOCKS_FUNC callback along with
GET_LOCKS_BATON.
+ Use DEPTH to filter the reported locks to only those within the
+ requested depth of PATH.
+
This function promises to auto-expire any locks encountered while
building the hash. That means that the caller can trust that each
returned lock hasn't yet expired.
*/
svn_error_t *svn_fs_bdb__locks_get(svn_fs_t *fs,
const char *path,
+ svn_depth_t depth,
svn_fs_get_locks_callback_t get_locks_func,
void *get_locks_baton,
trail_t *trail,
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/dag.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/dag.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/dag.c Tue Aug 10 22:07:24 2010
@@ -251,7 +251,7 @@ txn_body_dag_init_fs(void *baton,
/* Set a date on revision 0. */
date.data = svn_time_to_cstring(apr_time_now(), trail->pool);
date.len = strlen(date.data);
- return svn_fs_base__set_rev_prop(fs, 0, SVN_PROP_REVISION_DATE, &date,
+ return svn_fs_base__set_rev_prop(fs, 0, SVN_PROP_REVISION_DATE, NULL, &date,
trail, trail->pool);
}
@@ -1644,7 +1644,7 @@ svn_fs_base__dag_commit_txn(svn_revnum_t
date.data = svn_time_to_cstring(apr_time_now(), pool);
date.len = strlen(date.data);
return svn_fs_base__set_rev_prop(fs, *new_rev, SVN_PROP_REVISION_DATE,
- &date, trail, pool);
+ NULL, &date, trail, pool);
}
/* Modify all entries in the "node-origins" table that have a txn-id of
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/lock.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/lock.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/lock.c Tue Aug 10 22:07:24 2010
@@ -396,6 +396,7 @@ svn_fs_base__get_lock(svn_lock_t **lock,
struct locks_get_args
{
const char *path;
+ svn_depth_t depth;
svn_fs_get_locks_callback_t get_locks_func;
void *get_locks_baton;
};
@@ -405,7 +406,7 @@ static svn_error_t *
txn_body_get_locks(void *baton, trail_t *trail)
{
struct locks_get_args *args = baton;
- return svn_fs_bdb__locks_get(trail->fs, args->path,
+ return svn_fs_bdb__locks_get(trail->fs, args->path, args->depth,
args->get_locks_func, args->get_locks_baton,
trail, trail->pool);
}
@@ -414,6 +415,7 @@ txn_body_get_locks(void *baton, trail_t
svn_error_t *
svn_fs_base__get_locks(svn_fs_t *fs,
const char *path,
+ svn_depth_t depth,
svn_fs_get_locks_callback_t get_locks_func,
void *get_locks_baton,
apr_pool_t *pool)
@@ -422,6 +424,7 @@ svn_fs_base__get_locks(svn_fs_t *fs,
SVN_ERR(svn_fs__check_fs(fs, TRUE));
args.path = svn_fs__canonicalize_abspath(path, pool);
+ args.depth = depth;
args.get_locks_func = get_locks_func;
args.get_locks_baton = get_locks_baton;
return svn_fs_base__retry_txn(fs, txn_body_get_locks, &args, FALSE, pool);
@@ -490,7 +493,8 @@ svn_fs_base__allow_locked_operation(cons
if (recurse)
{
/* Discover all locks at or below the path. */
- SVN_ERR(svn_fs_bdb__locks_get(trail->fs, path, get_locks_callback,
+ SVN_ERR(svn_fs_bdb__locks_get(trail->fs, path, svn_depth_infinity,
+ get_locks_callback,
trail->fs, trail, pool));
}
else
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/lock.h
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/lock.h?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/lock.h (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/lock.h Tue Aug 10 22:07:24 2010
@@ -64,6 +64,7 @@ svn_error_t *svn_fs_base__get_lock(svn_l
svn_error_t *
svn_fs_base__get_locks(svn_fs_t *fs,
const char *path,
+ svn_depth_t depth,
svn_fs_get_locks_callback_t get_locks_func,
void *get_locks_baton,
apr_pool_t *pool);
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/revs-txns.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/revs-txns.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/revs-txns.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/revs-txns.c Tue Aug 10 22:07:24 2010
@@ -241,6 +241,7 @@ svn_error_t *
svn_fs_base__set_rev_prop(svn_fs_t *fs,
svn_revnum_t rev,
const char *name,
+ const svn_string_t *const *old_value_p,
const svn_string_t *value,
trail_t *trail,
apr_pool_t *pool)
@@ -259,6 +260,23 @@ svn_fs_base__set_rev_prop(svn_fs_t *fs,
txn->proplist = apr_hash_make(pool);
/* Set the property. */
+ if (old_value_p)
+ {
+ const svn_string_t *wanted_value = *old_value_p;
+ const svn_string_t *present_value = apr_hash_get(txn->proplist, name,
+ APR_HASH_KEY_STRING);
+ if ((!wanted_value != !present_value)
+ || (wanted_value && present_value
+ && !svn_string_compare(wanted_value, present_value)))
+ {
+ /* What we expected isn't what we found. */
+ return svn_error_createf(SVN_ERR_BAD_PROPERTY_VALUE, NULL,
+ _("revprop '%s' has unexpected value in "
+ "filesystem"),
+ name);
+ }
+ /* Fall through. */
+ }
apr_hash_set(txn->proplist, name, APR_HASH_KEY_STRING, value);
/* Overwrite the revision. */
@@ -269,6 +287,7 @@ svn_fs_base__set_rev_prop(svn_fs_t *fs,
struct change_rev_prop_args {
svn_revnum_t rev;
const char *name;
+ const svn_string_t *const *old_value_p;
const svn_string_t *value;
};
@@ -279,7 +298,7 @@ txn_body_change_rev_prop(void *baton, tr
struct change_rev_prop_args *args = baton;
return svn_fs_base__set_rev_prop(trail->fs, args->rev,
- args->name, args->value,
+ args->name, args->old_value_p, args->value,
trail, trail->pool);
}
@@ -288,6 +307,7 @@ svn_error_t *
svn_fs_base__change_rev_prop(svn_fs_t *fs,
svn_revnum_t rev,
const char *name,
+ const svn_string_t *const *old_value_p,
const svn_string_t *value,
apr_pool_t *pool)
{
@@ -297,6 +317,7 @@ svn_fs_base__change_rev_prop(svn_fs_t *f
args.rev = rev;
args.name = name;
+ args.old_value_p = old_value_p;
args.value = value;
return svn_fs_base__retry_txn(fs, txn_body_change_rev_prop, &args,
TRUE, pool);
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/revs-txns.h
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/revs-txns.h?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/revs-txns.h (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/revs-txns.h Tue Aug 10 22:07:24 2010
@@ -61,6 +61,7 @@ svn_error_t *svn_fs_base__rev_get_txn_id
svn_error_t *svn_fs_base__set_rev_prop(svn_fs_t *fs,
svn_revnum_t rev,
const char *name,
+ const svn_string_t *const *old_value_p,
const svn_string_t *value,
trail_t *trail,
apr_pool_t *pool);
@@ -180,6 +181,7 @@ svn_error_t *svn_fs_base__revision_propl
svn_error_t *svn_fs_base__change_rev_prop(svn_fs_t *fs, svn_revnum_t rev,
const char *name,
+ const svn_string_t *const *old_value_p,
const svn_string_t *value,
apr_pool_t *pool);