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/10 20:06:33 UTC
svn commit: r984153 [17/39] - in /subversion/branches/ignore-mergeinfo: ./
build/ build/ac-macros/ build/generator/ build/generator/templates/
build/hudson/ build/hudson/jobs/subversion-1.6.x-solaris/
build/hudson/jobs/subversion-1.6.x-ubuntu/ build/hu...
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/revert.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/revert.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/revert.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/revert.c Tue Aug 10 18:06:17 2010
@@ -41,7 +41,17 @@
/*** Code. ***/
-/* Attempt to revert PATH.
+struct revert_with_write_lock_baton {
+ const char *local_abspath;
+ svn_depth_t depth;
+ svn_boolean_t use_commit_times;
+ const apr_array_header_t *changelists;
+ svn_client_ctx_t *ctx;
+};
+
+/* (Note: All arguments are in the baton above.)
+
+ Attempt to revert LOCAL_ABSPATH.
If DEPTH is svn_depth_empty, revert just the properties on the
directory; else if svn_depth_files, revert the properties and any
@@ -56,34 +66,23 @@
CHANGELISTS is empty (or altogether NULL), no changelist filtering occurs.
Consult CTX to determine whether or not to revert timestamp to the
- time of last commit ('use-commit-times = yes'). Use POOL for
- temporary allocation.
+ time of last commit ('use-commit-times = yes').
If PATH is unversioned, return SVN_ERR_UNVERSIONED_RESOURCE. */
static svn_error_t *
-revert(const char *path,
- svn_depth_t depth,
- svn_boolean_t use_commit_times,
- const apr_array_header_t *changelists,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool)
+revert(void *baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool)
{
- const char *local_abspath, *anchor_abspath;
+ struct revert_with_write_lock_baton *b = baton;
svn_error_t *err;
- SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
-
- SVN_ERR(svn_wc__acquire_write_lock(&anchor_abspath, ctx->wc_ctx,
- local_abspath, pool, pool));
-
- err = svn_wc_revert4(ctx->wc_ctx,
- local_abspath,
- depth,
- use_commit_times,
- changelists,
- ctx->cancel_func, ctx->cancel_baton,
- ctx->notify_func2, ctx->notify_baton2,
- pool);
+ err = svn_wc_revert4(b->ctx->wc_ctx,
+ b->local_abspath,
+ b->depth,
+ b->use_commit_times,
+ b->changelists,
+ b->ctx->cancel_func, b->ctx->cancel_baton,
+ b->ctx->notify_func2, b->ctx->notify_baton2,
+ scratch_pool);
if (err)
{
@@ -92,19 +91,19 @@ revert(const char *path,
if (err->apr_err == SVN_ERR_ENTRY_NOT_FOUND
|| err->apr_err == SVN_ERR_UNVERSIONED_RESOURCE)
{
- if (ctx->notify_func2)
- (*ctx->notify_func2)
- (ctx->notify_baton2,
- svn_wc_create_notify(path, svn_wc_notify_skip, pool),
- pool);
+ if (b->ctx->notify_func2)
+ (*b->ctx->notify_func2)
+ (b->ctx->notify_baton2,
+ svn_wc_create_notify(b->local_abspath, svn_wc_notify_skip,
+ scratch_pool),
+ scratch_pool);
svn_error_clear(err);
}
else
return svn_error_return(err);
}
- return svn_error_return(
- svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath, pool));
+ return SVN_NO_ERROR;
}
@@ -120,6 +119,7 @@ svn_client_revert2(const apr_array_heade
int i;
svn_config_t *cfg;
svn_boolean_t use_commit_times;
+ struct revert_with_write_lock_baton baton;
cfg = ctx->config ? apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG,
APR_HASH_KEY_STRING) : NULL;
@@ -134,6 +134,7 @@ svn_client_revert2(const apr_array_heade
for (i = 0; i < paths->nelts; i++)
{
const char *path = APR_ARRAY_IDX(paths, i, const char *);
+ const char *local_abspath;
svn_pool_clear(subpool);
@@ -142,7 +143,15 @@ svn_client_revert2(const apr_array_heade
&& ((err = ctx->cancel_func(ctx->cancel_baton))))
goto errorful;
- err = revert(path, depth, use_commit_times, changelists, ctx, subpool);
+ SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
+
+ baton.local_abspath = local_abspath;
+ baton.depth = depth;
+ baton.use_commit_times = use_commit_times;
+ baton.changelists = changelists;
+ baton.ctx = ctx;
+ err = svn_wc__call_with_write_lock(revert, &baton, ctx->wc_ctx,
+ local_abspath, pool, pool);
if (err)
goto errorful;
}
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/switch.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/switch.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/switch.c Tue Aug 10 18:06:17 2010
@@ -55,21 +55,22 @@
*/
-svn_error_t *
-svn_client__switch_internal(svn_revnum_t *result_rev,
- const char *path,
- const char *switch_url,
- const svn_opt_revision_t *peg_revision,
- const svn_opt_revision_t *revision,
- svn_wc_adm_access_t *adm_access,
- svn_depth_t depth,
- svn_boolean_t depth_is_sticky,
- svn_boolean_t *timestamp_sleep,
- svn_boolean_t ignore_externals,
- svn_boolean_t allow_unver_obstructions,
- svn_boolean_t innerswitch,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool)
+static svn_error_t *
+switch_internal(svn_revnum_t *result_rev,
+ const char *path,
+ const char *local_abspath,
+ const char *anchor_abspath,
+ const char *switch_url,
+ const svn_opt_revision_t *peg_revision,
+ const svn_opt_revision_t *revision,
+ svn_depth_t depth,
+ svn_boolean_t depth_is_sticky,
+ svn_boolean_t *timestamp_sleep,
+ svn_boolean_t ignore_externals,
+ svn_boolean_t allow_unver_obstructions,
+ svn_boolean_t innerswitch,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
{
const svn_ra_reporter3_t *reporter;
void *report_baton;
@@ -77,8 +78,6 @@ svn_client__switch_internal(svn_revnum_t
svn_ra_session_t *ra_session;
svn_revnum_t revnum;
svn_error_t *err = SVN_NO_ERROR;
- svn_wc_adm_access_t *dir_access;
- const svn_boolean_t close_adm_access = ! adm_access;
const char *diff3_cmd;
svn_boolean_t use_commit_times;
svn_boolean_t sleep_here = FALSE;
@@ -86,18 +85,14 @@ svn_client__switch_internal(svn_revnum_t
const svn_delta_editor_t *switch_editor;
void *switch_edit_baton;
const char *preserved_exts_str;
- const char *anchor_abspath;
apr_array_header_t *preserved_exts;
svn_boolean_t server_supports_depth;
- const char *local_abspath;
svn_client__external_func_baton_t efb;
svn_config_t *cfg = ctx->config ? apr_hash_get(ctx->config,
SVN_CONFIG_CATEGORY_CONFIG,
APR_HASH_KEY_STRING)
: NULL;
- SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
-
/* An unknown depth can't be sticky. */
if (depth == svn_depth_unknown)
depth_is_sticky = FALSE;
@@ -125,49 +120,16 @@ svn_client__switch_internal(svn_revnum_t
: NULL;
/* Sanity check. Without these, the switch is meaningless. */
- SVN_ERR_ASSERT(path);
SVN_ERR_ASSERT(switch_url && (switch_url[0] != '\0'));
- /* ### Need to lock the whole target tree to invalidate wcprops. Does
- non-recursive switch really need to invalidate the whole tree? */
- if (innerswitch)
- {
- SVN_ERR(svn_wc__adm_open_in_context(&adm_access, ctx->wc_ctx,
- path, TRUE, -1, ctx->cancel_func,
- ctx->cancel_baton, pool));
- dir_access = adm_access;
- target = "";
- anchor = svn_wc_adm_access_path(adm_access);
- }
- else if (adm_access)
- {
- svn_wc_adm_access_t *a = adm_access;
- const char *dir_access_path;
-
- /* This is a little hacky, but open two new read-only access
- baton's to get the anchor and target access batons that would
- be used if a locked access baton was not available. */
- SVN_ERR(svn_wc_adm_open_anchor(&adm_access, &dir_access, &target, path,
- FALSE, -1, ctx->cancel_func,
- ctx->cancel_baton, pool));
- anchor = svn_wc_adm_access_path(adm_access);
- dir_access_path = svn_wc_adm_access_path(dir_access);
- SVN_ERR(svn_wc_adm_close2(adm_access, pool));
-
- SVN_ERR(svn_wc_adm_retrieve(&adm_access, a, anchor, pool));
- SVN_ERR(svn_wc_adm_retrieve(&dir_access, a, dir_access_path, pool));
- }
+ if (strcmp(local_abspath, anchor_abspath))
+ svn_dirent_split(path, &anchor, &target, pool);
else
{
- SVN_ERR(svn_wc__adm_open_anchor_in_context(&adm_access, &dir_access,
- &target, ctx->wc_ctx, path,
- TRUE, -1, ctx->cancel_func,
- ctx->cancel_baton, pool));
-
- anchor = svn_wc_adm_access_path(adm_access);
+ target = "";
+ anchor = path;
}
- SVN_ERR(svn_dirent_get_absolute(&anchor_abspath, anchor, pool));
SVN_ERR(svn_wc__node_get_url(&url, ctx->wc_ctx, anchor_abspath, pool, pool));
if (! url)
return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
@@ -188,10 +150,6 @@ svn_client__switch_internal(svn_revnum_t
pool));
/* Target excluded, we are done now */
-
- if (close_adm_access)
- SVN_ERR(svn_wc_adm_close2(adm_access, pool));
-
return SVN_NO_ERROR;
}
@@ -256,13 +214,15 @@ svn_client__switch_internal(svn_revnum_t
PATH. When we call reporter->finish_report, the update_editor
will be driven by svn_repos_dir_delta2.
- We pass NULL for traversal_info because this is a switch, not an
- update, and therefore we don't want to handle any externals
- except the ones directly affected by the switch. */
+ We pass in an external_func for recording all externals. It
+ shouldn't be needed for a switch if it wasn't for the relative
+ externals of type '../path'. All of those must be resolved to
+ the new location. */
err = svn_wc_crawl_revisions5(ctx->wc_ctx, local_abspath, reporter,
report_baton, TRUE, depth, (! depth_is_sticky),
(! server_supports_depth),
- use_commit_times, NULL, NULL,
+ use_commit_times,
+ svn_client__external_info_gatherer, &efb,
ctx->notify_func2, ctx->notify_baton2, pool);
if (err)
@@ -278,7 +238,7 @@ svn_client__switch_internal(svn_revnum_t
handling external items (and any errors therefrom) doesn't delay
the primary operation. */
if (SVN_DEPTH_IS_RECURSIVE(depth) && (! ignore_externals))
- err = svn_client__handle_externals(adm_access, efb.externals_old,
+ err = svn_client__handle_externals(efb.externals_old,
efb.externals_new, efb.ambient_depths,
switch_url, path, source_root, depth,
use_sleep, ctx, pool);
@@ -292,9 +252,6 @@ svn_client__switch_internal(svn_revnum_t
if (err)
return svn_error_return(err);
- if (close_adm_access)
- SVN_ERR(svn_wc_adm_close2(adm_access, pool));
-
/* Let everyone know we're finished here. */
if (ctx->notify_func2)
{
@@ -316,6 +273,57 @@ svn_client__switch_internal(svn_revnum_t
}
svn_error_t *
+svn_client__switch_internal(svn_revnum_t *result_rev,
+ const char *path,
+ const char *switch_url,
+ const svn_opt_revision_t *peg_revision,
+ const svn_opt_revision_t *revision,
+ svn_depth_t depth,
+ svn_boolean_t depth_is_sticky,
+ svn_boolean_t *timestamp_sleep,
+ svn_boolean_t ignore_externals,
+ svn_boolean_t allow_unver_obstructions,
+ svn_boolean_t innerswitch,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
+{
+ const char *local_abspath, *anchor_abspath;
+ svn_boolean_t acquired_lock;
+ svn_error_t *err, *err1, *err2;
+
+ SVN_ERR_ASSERT(path);
+
+ SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
+
+ /* Rely on svn_wc__acquire_write_lock setting ANCHOR_ABSPATH even
+ when it returns SVN_ERR_WC_LOCKED */
+ err = svn_wc__acquire_write_lock(&anchor_abspath, ctx->wc_ctx,
+ local_abspath, pool, pool);
+ if (err && err->apr_err != SVN_ERR_WC_LOCKED)
+ return svn_error_return(err);
+ else if (err)
+ {
+ svn_error_clear(err);
+ acquired_lock = FALSE;
+ }
+ else
+ acquired_lock = TRUE;
+
+ err1 = switch_internal(result_rev, path, local_abspath, anchor_abspath,
+ switch_url, peg_revision, revision,
+ depth, depth_is_sticky,
+ timestamp_sleep, ignore_externals,
+ allow_unver_obstructions, innerswitch, ctx, pool);
+
+ if (acquired_lock)
+ err2 = svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath, pool);
+ else
+ err2 = SVN_NO_ERROR;
+
+ return svn_error_compose_create(err1, err2);
+}
+
+svn_error_t *
svn_client_switch2(svn_revnum_t *result_rev,
const char *path,
const char *switch_url,
@@ -329,7 +337,7 @@ svn_client_switch2(svn_revnum_t *result_
apr_pool_t *pool)
{
return svn_client__switch_internal(result_rev, path, switch_url,
- peg_revision, revision, NULL, depth,
+ peg_revision, revision, depth,
depth_is_sticky, NULL, ignore_externals,
allow_unver_obstructions, FALSE, ctx,
pool);
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=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/update.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/update.c Tue Aug 10 18:06:17 2010
@@ -79,19 +79,21 @@ file_fetcher(void *baton,
}
-svn_error_t *
-svn_client__update_internal(svn_revnum_t *result_rev,
- const char *path,
- const svn_opt_revision_t *revision,
- svn_depth_t depth,
- svn_boolean_t depth_is_sticky,
- svn_boolean_t ignore_externals,
- svn_boolean_t allow_unver_obstructions,
- svn_boolean_t *timestamp_sleep,
- svn_boolean_t send_copyfrom_args,
- svn_boolean_t innerupdate,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool)
+static svn_error_t *
+update_internal(svn_revnum_t *result_rev,
+ const char *path,
+ const char *local_abspath,
+ const char *anchor_abspath,
+ const svn_opt_revision_t *revision,
+ svn_depth_t depth,
+ svn_boolean_t depth_is_sticky,
+ svn_boolean_t ignore_externals,
+ svn_boolean_t allow_unver_obstructions,
+ svn_boolean_t *timestamp_sleep,
+ svn_boolean_t send_copyfrom_args,
+ svn_boolean_t innerupdate,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
{
const svn_delta_editor_t *update_editor;
void *update_edit_baton;
@@ -102,19 +104,15 @@ svn_client__update_internal(svn_revnum_t
const char *repos_root;
svn_error_t *err;
svn_revnum_t revnum;
- svn_wc_traversal_info_t *traversal_info = svn_wc_init_traversal_info(pool);
- svn_wc_adm_access_t *adm_access;
svn_boolean_t use_commit_times;
svn_boolean_t sleep_here = FALSE;
svn_boolean_t *use_sleep = timestamp_sleep ? timestamp_sleep : &sleep_here;
const char *diff3_cmd;
svn_ra_session_t *ra_session;
- svn_wc_adm_access_t *dir_access;
const char *preserved_exts_str;
apr_array_header_t *preserved_exts;
struct ff_baton *ffb;
- const char *local_abspath;
- const char *anchor_abspath;
+ svn_client__external_func_baton_t efb;
svn_boolean_t server_supports_depth;
svn_config_t *cfg = ctx->config ? apr_hash_get(ctx->config,
SVN_CONFIG_CATEGORY_CONFIG,
@@ -124,44 +122,18 @@ svn_client__update_internal(svn_revnum_t
if (depth == svn_depth_unknown)
depth_is_sticky = FALSE;
- /* Sanity check. Without this, the update is meaningless. */
- SVN_ERR_ASSERT(path);
-
- if (svn_path_is_url(path))
- return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
- _("Path '%s' is not a directory"),
- path);
-
- SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
-
- if (!innerupdate)
+ if (strcmp(local_abspath, anchor_abspath))
{
- /* Use PATH to get the update's anchor and targets and get a write lock.
- */
- SVN_ERR(svn_wc__adm_open_anchor_in_context(&adm_access, &dir_access,
- &target, ctx->wc_ctx, path,
- TRUE,
- -1, /* recursive lock */
- ctx->cancel_func,
- ctx->cancel_baton, pool));
+ target = svn_dirent_basename(local_abspath, pool);
+ anchor = svn_dirent_basename(path, pool);
}
else
{
- /* Assume the exact root is specified (required for externals to work,
- as these would otherwise try to open the parent working copy again) */
- SVN_ERR(svn_wc__adm_open_in_context(&adm_access, ctx->wc_ctx, path, TRUE,
- -1, /* recursive lock */
- ctx->cancel_func, ctx->cancel_baton,
- pool));
- dir_access = adm_access;
target = "";
+ anchor = path;
}
- anchor = svn_wc_adm_access_path(adm_access);
- SVN_ERR(svn_dirent_get_absolute(&anchor_abspath, anchor, pool));
-
/* Get full URL from the ANCHOR. */
-
SVN_ERR(svn_wc__node_get_url(&anchor_url, ctx->wc_ctx, anchor_abspath,
pool, pool));
if (! anchor_url)
@@ -183,7 +155,8 @@ svn_client__update_internal(svn_revnum_t
pool));
/* Target excluded, we are done now */
- SVN_ERR(svn_wc_adm_close2(adm_access, pool));
+ SVN_ERR(svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath,
+ pool));
return SVN_NO_ERROR;
}
@@ -239,19 +212,25 @@ svn_client__update_internal(svn_revnum_t
ffb->repos_root = repos_root;
ffb->pool = pool;
+ /* Build a baton for the externals-info-gatherer callback. */
+ efb.externals_new = apr_hash_make(pool);
+ efb.externals_old = apr_hash_make(pool);
+ efb.ambient_depths = apr_hash_make(pool);
+ efb.result_pool = pool;
+
/* Fetch the update editor. If REVISION is invalid, that's okay;
the RA driver will call editor->set_target_revision later on. */
- SVN_ERR(svn_wc_get_update_editor3(&revnum, adm_access, target,
- use_commit_times, depth, depth_is_sticky,
- allow_unver_obstructions,
- ctx->notify_func2, ctx->notify_baton2,
- ctx->cancel_func, ctx->cancel_baton,
- ctx->conflict_func, ctx->conflict_baton,
- file_fetcher, ffb,
+ SVN_ERR(svn_wc_get_update_editor4(&update_editor, &update_edit_baton,
+ &revnum, ctx->wc_ctx, anchor_abspath,
+ target, use_commit_times, depth,
+ depth_is_sticky, allow_unver_obstructions,
diff3_cmd, preserved_exts,
- &update_editor, &update_edit_baton,
- traversal_info,
- pool));
+ file_fetcher, ffb,
+ ctx->conflict_func, ctx->conflict_baton,
+ svn_client__external_info_gatherer, &efb,
+ ctx->cancel_func, ctx->cancel_baton,
+ ctx->notify_func2, ctx->notify_baton2,
+ pool, pool));
/* Tell RA to do an update of URL+TARGET to REVISION; if we pass an
invalid revnum, that means RA will use the latest revision. */
@@ -269,12 +248,13 @@ svn_client__update_internal(svn_revnum_t
/* Drive the reporter structure, describing the revisions within
PATH. When we call reporter->finish_report, the
update_editor will be driven by svn_repos_dir_delta2. */
- err = svn_wc_crawl_revisions4(path, dir_access, reporter, report_baton,
- TRUE, depth, (! depth_is_sticky),
+ err = svn_wc_crawl_revisions5(ctx->wc_ctx, local_abspath, reporter,
+ report_baton, TRUE, depth, (! depth_is_sticky),
(! server_supports_depth),
use_commit_times,
- ctx->notify_func2, ctx->notify_baton2,
- traversal_info, pool);
+ svn_client__external_info_gatherer,
+ &efb, ctx->notify_func2, ctx->notify_baton2,
+ pool);
if (err)
{
@@ -290,21 +270,18 @@ svn_client__update_internal(svn_revnum_t
the primary operation. */
if (SVN_DEPTH_IS_RECURSIVE(depth) && (! ignore_externals))
{
- apr_hash_t *externals_old, *externals_new, *ambient_depths;
-
- svn_wc_edited_externals(&externals_old, &externals_new, traversal_info);
- svn_wc_traversed_depths(&ambient_depths, traversal_info);
-
- SVN_ERR(svn_client__handle_externals(adm_access, externals_old,
- externals_new, ambient_depths,
- anchor_url, anchor, repos_root,
+ SVN_ERR(svn_client__handle_externals(efb.externals_old,
+ efb.externals_new,
+ efb.ambient_depths,
+ anchor_url, anchor,
+ repos_root,
depth, use_sleep, ctx, pool));
}
if (sleep_here)
svn_io_sleep_for_timestamps(path, pool);
- SVN_ERR(svn_wc_adm_close2(adm_access, pool));
+ SVN_ERR(svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath, pool));
/* Let everyone know we're finished here. */
if (ctx->notify_func2)
@@ -327,6 +304,56 @@ svn_client__update_internal(svn_revnum_t
}
svn_error_t *
+svn_client__update_internal(svn_revnum_t *result_rev,
+ const char *path,
+ const svn_opt_revision_t *revision,
+ svn_depth_t depth,
+ svn_boolean_t depth_is_sticky,
+ svn_boolean_t ignore_externals,
+ svn_boolean_t allow_unver_obstructions,
+ svn_boolean_t *timestamp_sleep,
+ svn_boolean_t send_copyfrom_args,
+ svn_boolean_t innerupdate,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
+{
+ const char *local_abspath, *anchor_abspath;
+ svn_error_t *err1, *err2;
+
+ SVN_ERR_ASSERT(path);
+
+ if (svn_path_is_url(path))
+ return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
+ _("Path '%s' is not a directory"),
+ path);
+
+ SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
+
+ if (!innerupdate)
+ {
+ SVN_ERR(svn_wc__acquire_write_lock(&anchor_abspath, ctx->wc_ctx,
+ local_abspath, pool, pool));
+ }
+ else
+ {
+ SVN_ERR(svn_wc__acquire_write_lock(NULL, ctx->wc_ctx,
+ local_abspath, pool, pool));
+ anchor_abspath = local_abspath;
+ }
+
+ err1 = update_internal(result_rev, path, local_abspath, anchor_abspath,
+ revision, depth, depth_is_sticky,
+ ignore_externals, allow_unver_obstructions,
+ timestamp_sleep, send_copyfrom_args,
+ innerupdate, ctx, pool);
+
+ err2 = svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath, pool);
+
+ return svn_error_compose_create(err1, err2);
+}
+
+
+svn_error_t *
svn_client_update3(apr_array_header_t **result_revs,
const apr_array_header_t *paths,
const svn_opt_revision_t *revision,
@@ -366,7 +393,7 @@ svn_client_update3(apr_array_header_t **
}
else if (err)
{
- /* SVN_ERR_WC_NOT_DIRECTORY: it's not versioned */
+ /* SVN_ERR_WC_NOT_WORKING_COPY: it's not versioned */
svn_error_clear(err);
err = SVN_NO_ERROR;
result_rev = SVN_INVALID_REVNUM;
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/util.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/util.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/util.c Tue Aug 10 18:06:17 2010
@@ -50,9 +50,9 @@ string_hash_dup(apr_hash_t *hash, apr_po
for (hi = apr_hash_first(pool, hash); hi; hi = apr_hash_next(hi))
{
- const char *key = apr_pstrdup(pool, svn_apr_hash_index_key(hi));
- apr_ssize_t klen = svn_apr_hash_index_klen(hi);
- svn_string_t *val = svn_string_dup(svn_apr_hash_index_val(hi), pool);
+ const char *key = apr_pstrdup(pool, svn__apr_hash_index_key(hi));
+ apr_ssize_t klen = svn__apr_hash_index_klen(hi);
+ svn_string_t *val = svn_string_dup(svn__apr_hash_index_val(hi), pool);
apr_hash_set(new_hash, key, klen, val);
}
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/compat.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/compat.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/compat.c Tue Aug 10 18:06:17 2010
@@ -33,7 +33,7 @@ struct file_rev_handler_wrapper_baton {
svn_file_rev_handler_old_t handler;
};
-/* This implements svn_repos_file_rev_handler2_t. */
+/* This implements svn_file_rev_handler_t. */
static svn_error_t *
file_rev_handler_wrapper(void *baton,
const char *path,
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/compose_delta.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/compose_delta.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/compose_delta.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/compose_delta.c Tue Aug 10 18:06:17 2010
@@ -160,36 +160,49 @@ create_offset_index(const svn_txdelta_wi
}
/* Find the index of the delta op thet defines that data at OFFSET in
- NDX. */
+ NDX. HINT is an arbitrary positin within NDX and doesn't even need
+ to be valid. To effectively speed up the search, use the last result
+ as hint because most lookups come as a sequence of decreasing values
+ for OFFSET and they concentrate on the lower end of the array. */
static int
-search_offset_index(const offset_index_t *ndx, apr_size_t offset)
+search_offset_index(const offset_index_t *ndx, apr_size_t offset, int hint)
{
int lo, hi, op;
assert(offset < ndx->offs[ndx->length]);
- for (lo = 0, hi = ndx->length, op = (lo + hi)/2;
- lo < hi;
- op = (lo + hi)/2)
- {
- const apr_size_t this_offset = ndx->offs[op];
- const apr_size_t next_offset = ndx->offs[op + 1];
- if (offset < this_offset)
- hi = op;
- else if (offset > next_offset)
- lo = op;
+ lo = 0;
+ hi = ndx->length;
+
+ /* If we got a valid hint, use it to reduce the range to cover.
+ Note that this will only be useful if either the hint is a
+ hit (i.e. equals the desired result) or narrows the range
+ length by a factor larger than 2. */
+
+ if (hint < hi)
+ {
+ if (offset < ndx->offs[hint])
+ hi = hint;
+ else if (offset < ndx->offs[hint+1])
+ return hint;
else
- {
- /* this_offset <= offset <= next_offset */
- if (offset == next_offset)
- ++op;
- break;
- }
+ lo = hint+1;
}
- assert(ndx->offs[op] <= offset && offset < ndx->offs[op + 1]);
- return op;
+ /* ordinary binary search */
+
+ for (op = (lo + hi)/2; lo != hi; op = (lo + hi)/2)
+ {
+ if (offset < ndx->offs[op])
+ hi = op;
+ else
+ lo = ++op;
+ }
+
+ --lo;
+ assert(ndx->offs[lo] <= offset && offset < ndx->offs[lo + 1]);
+ return lo;
}
@@ -614,28 +627,33 @@ build_range_list(apr_size_t offset, apr_
/* Copy the instructions from WINDOW that define the range [OFFSET,
LIMIT) in WINDOW's target stream to TARGET_OFFSET in the window
- represented by BUILD_BATON. Use NDX to find the instructions in
- WINDOW. Allocate space in BUILD_BATON from POOL. */
+ represented by BUILD_BATON. HINT is a position in the instructions
+ array that helps finding the position for OFFSET. A safe default
+ is 0. Use NDX to find the instructions in WINDOW. Allocate space
+ in BUILD_BATON from POOL. */
static void
-copy_source_ops(apr_size_t offset, apr_size_t limit,
+copy_source_ops(apr_size_t offset, apr_size_t limit,
apr_size_t target_offset,
+ int hint,
svn_txdelta__ops_baton_t *build_baton,
const svn_txdelta_window_t *window,
const offset_index_t *ndx,
apr_pool_t *pool)
{
- const int first_op = search_offset_index(ndx, offset);
- const int last_op = search_offset_index(ndx, limit - 1);
- int op_ndx;
-
- for (op_ndx = first_op; op_ndx <= last_op; ++op_ndx)
+ int op_ndx = search_offset_index(ndx, offset, hint);
+ for (;; ++op_ndx)
{
const svn_txdelta_op_t *const op = &window->ops[op_ndx];
const apr_size_t *const off = &ndx->offs[op_ndx];
+ apr_size_t fix_offset;
+ apr_size_t fix_limit;
+
+ if (off[0] >= limit)
+ break;
- const apr_size_t fix_offset = (offset > off[0] ? offset - off[0] : 0);
- const apr_size_t fix_limit = (off[1] > limit ? off[1] - limit : 0);
+ fix_offset = (offset > off[0] ? offset - off[0] : 0);
+ fix_limit = (off[1] > limit ? off[1] - limit : 0);
/* It would be extremely weird if the fixed-up op had zero length. */
assert(fix_offset + fix_limit < op->length);
@@ -667,6 +685,7 @@ copy_source_ops(apr_size_t offset, apr_s
copy_source_ops(op->offset + fix_offset,
op->offset + op->length - fix_limit,
target_offset,
+ op_ndx,
build_baton, window, ndx, pool);
}
else
@@ -692,6 +711,7 @@ copy_source_ops(apr_size_t offset, apr_s
copy_source_ops(op->offset + ptn_overlap,
op->offset + ptn_overlap + length,
tgt_off,
+ op_ndx,
build_baton, window, ndx, pool);
fix_off += length;
tgt_off += length;
@@ -707,6 +727,7 @@ copy_source_ops(apr_size_t offset, apr_s
copy_source_ops(op->offset,
op->offset + length,
tgt_off,
+ op_ndx,
build_baton, window, ndx, pool);
fix_off += length;
tgt_off += length;
@@ -788,7 +809,7 @@ svn_txdelta_compose_windows(const svn_tx
range->limit - range->offset,
NULL, pool);
else
- copy_source_ops(range->offset, range->limit, tgt_off,
+ copy_source_ops(range->offset, range->limit, tgt_off, 0,
&build_baton, window_A, offset_index,
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=984153&r1=984152&r2=984153&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 18:06:17 2010
@@ -133,7 +133,7 @@ svn_error_t *
svn_delta_path_driver(const svn_delta_editor_t *editor,
void *edit_baton,
svn_revnum_t revision,
- apr_array_header_t *paths,
+ const apr_array_header_t *paths,
svn_delta_path_driver_cb_func_t callback_func,
void *callback_baton,
apr_pool_t *pool)
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff.h
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff.h?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff.h (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff.h Tue Aug 10 18:06:17 2010
@@ -91,7 +91,7 @@ typedef enum svn_diff__normalize_state_t
svn_diff__lcs_t *
svn_diff__lcs(svn_diff__position_t *position_list1, /* pointer to tail (ring) */
svn_diff__position_t *position_list2, /* pointer to tail (ring) */
- apr_pool_t *pool);
+ apr_pool_t *pool);
/*
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff_file.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff_file.c Tue Aug 10 18:06:17 2010
@@ -302,10 +302,11 @@ datasource_get_next_token(apr_uint32_t *
had_cr = (*eol == '\r');
eol++;
/* If we have the whole eol sequence in the chunk... */
- if (!had_cr || eol != endp)
+ if (!(had_cr && eol == endp))
{
+ /* Also skip past the '\n' in an '\r\n' sequence. */
if (had_cr && *eol == '\n')
- ++eol;
+ eol++;
break;
}
}
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/lcs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/lcs.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/lcs.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/lcs.c Tue Aug 10 18:06:17 2010
@@ -30,7 +30,7 @@
/*
- * Calculate the Longest Common Subsequence between two datasources.
+ * Calculate the Longest Common Subsequence (LCS) between two datasources.
* This function is what makes the diff code tick.
*
* The LCS algorithm implemented here is described by Sun Wu,
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=984153&r1=984152&r2=984153&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 18:06:17 2010
@@ -31,9 +31,7 @@
#include "svn_pools.h"
#include "svn_utf.h"
#include "svn_dirent_uri.h"
-
-#include "private/svn_diff_private.h"
-
+#include "svn_diff.h"
/* Helper macro for readability */
#define starts_with(str, start) \
@@ -47,7 +45,7 @@ parse_offset(svn_linenum_t *offset, cons
{
apr_int64_t parsed_offset;
- errno = 0; /* clear errno for safety */
+ errno = 0; /* apr_atoi64() in APR-0.9 does not always set errno */
parsed_offset = apr_atoi64(number);
if (errno == ERANGE || parsed_offset < 0)
return FALSE;
@@ -103,9 +101,11 @@ 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.
+ * 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, apr_pool_t *pool)
+parse_hunk_header(const char *header, svn_hunk_t *hunk,
+ svn_boolean_t reverse, apr_pool_t *pool)
{
static const char * const atat = "@@";
const char *p;
@@ -132,8 +132,16 @@ parse_hunk_header(const char *header, sv
return FALSE;
/* Try to parse the first range. */
- if (! parse_range(&hunk->original_start, &hunk->original_length, range->data))
- return FALSE;
+ if (reverse)
+ {
+ if (! parse_range(&hunk->modified_start, &hunk->modified_length, range->data))
+ return FALSE;
+ }
+ else
+ {
+ if (! parse_range(&hunk->original_start, &hunk->original_length, range->data))
+ return FALSE;
+ }
/* Clear the stringbuf so we can reuse it for the second range. */
svn_stringbuf_setempty(range);
@@ -161,8 +169,16 @@ parse_hunk_header(const char *header, sv
* but we ignore that. */
/* Try to parse the second range. */
- if (! parse_range(&hunk->modified_start, &hunk->modified_length, range->data))
- return FALSE;
+ if (reverse)
+ {
+ if (! parse_range(&hunk->original_start, &hunk->original_length, range->data))
+ return FALSE;
+ }
+ else
+ {
+ if (! parse_range(&hunk->modified_start, &hunk->modified_length, range->data))
+ return FALSE;
+ }
/* Hunk header is good. */
return TRUE;
@@ -204,19 +220,60 @@ remove_leading_char_transformer(svn_stri
return SVN_NO_ERROR;
}
+/** line-transformer callback to reverse a diff text. */
+static svn_error_t *
+reverse_diff_transformer(svn_stringbuf_t **buf,
+ const char *line,
+ void *baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_hunk_t hunk;
+
+ /* ### 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))
+ {
+ *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);
+ (*buf)->data[0] = '-';
+ }
+ else if (line[0] == '-')
+ {
+ *buf = svn_stringbuf_create(line, result_pool);
+ (*buf)->data[0] = '+';
+ }
+ else
+ *buf = svn_stringbuf_create(line, result_pool);
+
+ 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.
* Allocate results in RESULT_POOL.
* Use SCRATCH_POOL for all other allocations. */
static svn_error_t *
parse_next_hunk(svn_hunk_t **hunk,
svn_patch_t *patch,
svn_stream_t *stream,
+ svn_boolean_t reverse,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
static const char * const minus = "--- ";
static const char * const atat = "@@";
+ svn_stringbuf_t *line;
svn_boolean_t eof, in_hunk, hunk_seen;
apr_off_t pos, last_line;
apr_off_t start, end;
@@ -224,6 +281,9 @@ parse_next_hunk(svn_hunk_t **hunk,
svn_stream_t *original_text;
svn_stream_t *modified_text;
svn_linenum_t original_lines;
+ svn_linenum_t leading_context;
+ svn_linenum_t trailing_context;
+ svn_boolean_t changed_line_seen;
apr_pool_t *iterpool;
if (apr_file_eof(patch->patch_file) == APR_EOF)
@@ -235,6 +295,9 @@ parse_next_hunk(svn_hunk_t **hunk,
in_hunk = FALSE;
hunk_seen = FALSE;
+ leading_context = 0;
+ trailing_context = 0;
+ changed_line_seen = FALSE;
*hunk = apr_pcalloc(result_pool, sizeof(**hunk));
/* Get current seek position -- APR has no ftell() :( */
@@ -244,7 +307,6 @@ parse_next_hunk(svn_hunk_t **hunk,
iterpool = svn_pool_create(scratch_pool);
do
{
- svn_stringbuf_t *line;
svn_pool_clear(iterpool);
@@ -269,6 +331,19 @@ parse_next_hunk(svn_hunk_t **hunk,
if (in_hunk)
{
char c;
+ char add;
+ char del;
+
+ if (reverse)
+ {
+ add = '-';
+ del = '+';
+ }
+ else
+ {
+ add = '+';
+ del = '-';
+ }
if (! hunk_seen)
{
@@ -278,20 +353,28 @@ parse_next_hunk(svn_hunk_t **hunk,
}
c = line->data[0];
- if (original_lines > 0 && (c == ' ' || c == '-'))
+ /* Tolerate chopped leading spaces on empty lines. */
+ if (original_lines > 0 && (c == ' ' || (! eof && line->len == 0)))
{
hunk_seen = TRUE;
original_lines--;
+ if (changed_line_seen)
+ trailing_context++;
+ else
+ leading_context++;
}
- else if (c == '+')
+ else if (c == add || c == del)
{
hunk_seen = TRUE;
- }
- /* Tolerate chopped leading spaces on empty lines. */
- else if (original_lines > 0 && ! eof && line->len == 0)
- {
- hunk_seen = TRUE;
- original_lines--;
+ changed_line_seen = TRUE;
+
+ /* A hunk may have context in the middle. We only want the
+ last lines of context. */
+ if (trailing_context > 0)
+ trailing_context = 0;
+
+ if (original_lines > 0 && c == del)
+ original_lines--;
}
else
{
@@ -308,8 +391,9 @@ parse_next_hunk(svn_hunk_t **hunk,
{
if (starts_with(line->data, atat))
{
- /* Looks like we have a hunk header, let's try to rip it apart. */
- in_hunk = parse_hunk_header(line->data, *hunk, iterpool);
+ /* Looks like we have a hunk header, try to rip it apart. */
+ in_hunk = parse_hunk_header(line->data, *hunk, reverse,
+ iterpool);
if (in_hunk)
original_lines = (*hunk)->original_length;
}
@@ -318,12 +402,14 @@ parse_next_hunk(svn_hunk_t **hunk,
break;
}
}
- while (! eof);
+ /* Check for the line length since a file may not have a newline at the
+ * end and we depend upon the last line to be an empty one. */
+ while (! eof || line->len > 0);
svn_pool_destroy(iterpool);
if (! eof)
/* Rewind to the start of the line just read, so subsequent calls
- * to this function or svn_diff__parse_next_patch() don't end
+ * to this function or svn_diff_parse_next_patch() don't end
* up skipping the line -- it may contain a patch or hunk header. */
SVN_ERR(svn_io_file_seek(patch->patch_file, APR_SET, &last_line,
scratch_pool));
@@ -361,8 +447,20 @@ parse_next_hunk(svn_hunk_t **hunk,
remove_leading_char_transformer);
/* Set the hunk's texts. */
(*hunk)->diff_text = diff_text;
- (*hunk)->original_text = original_text;
- (*hunk)->modified_text = modified_text;
+ if (reverse)
+ {
+ svn_stream_set_line_transformer_callback(diff_text,
+ reverse_diff_transformer);
+ (*hunk)->original_text = modified_text;
+ (*hunk)->modified_text = original_text;
+ }
+ else
+ {
+ (*hunk)->original_text = original_text;
+ (*hunk)->modified_text = modified_text;
+ }
+ (*hunk)->leading_context = leading_context;
+ (*hunk)->trailing_context = trailing_context;
}
else
/* Something went wrong, just discard the result. */
@@ -390,7 +488,7 @@ compare_hunks(const void *a, const void
* Ensure that all streams which were opened for HUNK are closed.
*/
static svn_error_t *
-close_hunk(svn_hunk_t *hunk)
+close_hunk(const svn_hunk_t *hunk)
{
SVN_ERR(svn_stream_close(hunk->original_text));
SVN_ERR(svn_stream_close(hunk->modified_text));
@@ -399,10 +497,11 @@ close_hunk(svn_hunk_t *hunk)
}
svn_error_t *
-svn_diff__parse_next_patch(svn_patch_t **patch,
- apr_file_t *patch_file,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+svn_diff_parse_next_patch(svn_patch_t **patch,
+ apr_file_t *patch_file,
+ svn_boolean_t reverse,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
static const char * const minus = "--- ";
static const char * const plus = "+++ ";
@@ -471,14 +570,20 @@ svn_diff__parse_next_patch(svn_patch_t *
if ((! in_header) && strcmp(indicator, minus) == 0)
{
/* First line of header contains old filename. */
- (*patch)->old_filename = apr_pstrdup(result_pool, canon_path);
+ 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. */
- (*patch)->new_filename = apr_pstrdup(result_pool, canon_path);
+ 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! */
}
@@ -501,8 +606,8 @@ svn_diff__parse_next_patch(svn_patch_t *
{
svn_pool_clear(iterpool);
- SVN_ERR(parse_next_hunk(&hunk, *patch, stream, result_pool,
- iterpool));
+ SVN_ERR(parse_next_hunk(&hunk, *patch, stream, reverse,
+ result_pool, iterpool));
if (hunk)
APR_ARRAY_PUSH((*patch)->hunks, svn_hunk_t *) = hunk;
}
@@ -526,13 +631,13 @@ svn_diff__parse_next_patch(svn_patch_t *
}
svn_error_t *
-svn_diff__close_patch(svn_patch_t *patch)
+svn_diff_close_patch(const svn_patch_t *patch)
{
int i;
for (i = 0; i < patch->hunks->nelts; i++)
{
- svn_hunk_t *hunk = APR_ARRAY_IDX(patch->hunks, i, svn_hunk_t *);
+ const svn_hunk_t *hunk = APR_ARRAY_IDX(patch->hunks, i, svn_hunk_t *);
SVN_ERR(close_hunk(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=984153&r1=984152&r2=984153&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 18:06:17 2010
@@ -760,7 +760,7 @@ svn_fs_change_txn_prop(svn_fs_txn_t *txn
}
svn_error_t *
-svn_fs_change_txn_props(svn_fs_txn_t *txn, apr_array_header_t *props,
+svn_fs_change_txn_props(svn_fs_txn_t *txn, const apr_array_header_t *props,
apr_pool_t *pool)
{
return txn->vtable->change_props(txn, props, pool);
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=984153&r1=984152&r2=984153&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 18:06:17 2010
@@ -214,7 +214,7 @@ typedef struct txn_vtable_t
const svn_string_t *value, apr_pool_t *pool);
svn_error_t *(*root)(svn_fs_root_t **root_p, svn_fs_txn_t *txn,
apr_pool_t *pool);
- svn_error_t *(*change_props)(svn_fs_txn_t *txn, apr_array_header_t *props,
+ svn_error_t *(*change_props)(svn_fs_txn_t *txn, const apr_array_header_t *props,
apr_pool_t *pool);
} txn_vtable_t;
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/changes-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/changes-table.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/changes-table.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/changes-table.c Tue Aug 10 18:06:17 2010
@@ -168,6 +168,15 @@ fold_change(apr_hash_t *changes,
(SVN_ERR_FS_CORRUPT, NULL,
_("Invalid change ordering: non-add change on deleted path"));
+ /* Sanity check: an add can't follow anything except
+ a delete or reset. */
+ if ((change->kind == svn_fs_path_change_add)
+ && (old_change->change_kind != svn_fs_path_change_delete)
+ && (old_change->change_kind != svn_fs_path_change_reset))
+ return svn_error_create
+ (SVN_ERR_FS_CORRUPT, NULL,
+ _("Invalid change ordering: add change on preexisting path"));
+
/* Now, merge that change in. */
switch (change->kind)
{
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=984153&r1=984152&r2=984153&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 18:06:17 2010
@@ -281,7 +281,7 @@ get_dir_entries(apr_hash_t **entries_p,
trail_t *trail,
apr_pool_t *pool)
{
- apr_hash_t *entries = apr_hash_make(pool);
+ apr_hash_t *entries = NULL;
apr_hash_index_t *hi;
svn_string_t entries_raw;
svn_skel_t *entries_skel;
@@ -290,7 +290,7 @@ get_dir_entries(apr_hash_t **entries_p,
if (noderev->kind != svn_node_dir)
return svn_error_create
(SVN_ERR_FS_NOT_DIRECTORY, NULL,
- _("Attempted to create entry in non-directory parent"));
+ _("Attempted to get entries of a non-directory node"));
/* If there's a DATA-KEY, there might be entries to fetch. */
if (noderev->data_key)
@@ -836,13 +836,6 @@ svn_fs_base__dag_clone_root(dag_node_t *
}
-/* Delete the directory entry named NAME from PARENT, as part of
- TRAIL. PARENT must be mutable. NAME must be a single path
- component. If REQUIRE_EMPTY is true and the node being deleted is
- a directory, it must be empty.
-
- If return SVN_ERR_FS_NO_SUCH_ENTRY, then there is no entry NAME in
- PARENT. */
svn_error_t *
svn_fs_base__dag_delete(dag_node_t *parent,
const char *name,
@@ -1043,8 +1036,8 @@ svn_fs_base__dag_delete_if_mutable(svn_f
}
}
- /* ... then delete the node itself, after deleting any mutable
- representations and strings it points to. */
+ /* ... then delete the node itself, any mutable representations and
+ strings it points to, and possibly its node-origins record. */
return svn_fs_base__dag_remove_node(fs, id, txn_id, trail, pool);
}
@@ -1342,8 +1335,8 @@ svn_fs_base__dag_finalize_edits(dag_node
SVN_ERR(svn_fs_base__delete_rep_if_mutable(fs, old_data_key, txn_id,
trail, pool));
- /* If we've got a discardable rep (probably because we ended us
- re-using a preexisting one). Throw out the discardable rep. */
+ /* If we've got a discardable rep (probably because we ended up
+ re-using a preexisting one), throw out the discardable rep. */
if (useless_data_key)
SVN_ERR(svn_fs_base__delete_rep_if_mutable(fs, useless_data_key,
txn_id, trail, pool));
@@ -1537,6 +1530,33 @@ svn_fs_base__dag_deltify(dag_node_t *tar
}
+svn_error_t *
+svn_fs_base__dag_obliterate_rep(dag_node_t *node,
+ dag_node_t *pred_node,
+ trail_t *trail,
+ apr_pool_t *pool)
+{
+ node_revision_t *node_rev, *pred_node_rev;
+ svn_fs_t *fs = svn_fs_base__dag_get_fs(node);
+ const char *pred_key;
+
+ SVN_ERR(svn_fs_bdb__get_node_revision(&node_rev, fs, node->id, trail, pool));
+ if (pred_node)
+ {
+ SVN_ERR(svn_fs_bdb__get_node_revision(&pred_node_rev, fs, pred_node->id,
+ trail, pool));
+ pred_key = pred_node_rev->data_key;
+ }
+ else
+ {
+ pred_key = NULL;
+ }
+
+ return svn_fs_base__rep_obliterate(trail->fs, node_rev->data_key, pred_key,
+ trail, pool);
+}
+
+
/* Maybe store a `checksum-reps' index record for the representation whose
key is REP. (If there's already a rep for this checksum, we don't
bother overwriting it.) */
@@ -1643,7 +1663,8 @@ node_origins_update(const char *new_txn_
/* To find the nodes that originate in the old txn, we'll look in the
* "changes" table. Any change that added a node could have created a new
- * node id. */
+ * node id, but that change may have been superceded by a later change that
+ * deleted that node id and its corresponding 'node-origins' record. */
SVN_ERR(svn_fs_bdb__changes_fetch_raw(&changes, trail->fs, old_txn_id, trail,
scratch_pool));
for (i = 0; i < changes->nelts; i++)
@@ -1657,13 +1678,21 @@ node_origins_update(const char *new_txn_
{
const svn_fs_id_t *origin_id;
const char *node_id, *id_copy_id, *id_txn_id;
+ svn_error_t *err;
/* Find the destination node id of this change */
node_id = svn_fs_base__id_node_id(change->noderev_id);
/* Fetch the old node-origin */
- SVN_ERR(svn_fs_bdb__get_node_origin(&origin_id, trail->fs, node_id,
+ err = (svn_fs_bdb__get_node_origin(&origin_id, trail->fs, node_id,
trail, iterpool));
+ if (err && err->apr_err == SVN_ERR_FS_NO_SUCH_NODE_ORIGIN)
+ {
+ svn_error_clear(err);
+ continue;
+ }
+ SVN_ERR(err);
+
id_copy_id = svn_fs_base__id_copy_id(origin_id);
id_txn_id = svn_fs_base__id_txn_id(origin_id);
@@ -1689,6 +1718,9 @@ node_origins_update(const char *new_txn_
/* Modify each row in the "copies" table that is keyed by a (const char *)
* copy-id listed in COPY_IDS, changing the txn-id component of its
* "dst_noderev_id" field from OLD_TXN_ID to NEW_TXN_ID.
+ * If the dst_noderev_id then references a node-revision that does not exist,
+ * it must have been obliterated, so remove each such copy-id from COPY_IDS
+ * and from the "copies" table.
* Each entry in COPY_IDS must match exactly one row in the "copies" table.
*
* Work within TRAIL. */
@@ -1699,14 +1731,18 @@ copies_update(const char *new_txn_id,
trail_t *trail,
apr_pool_t *scratch_pool)
{
- int i;
+ int i, i_out;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ /* Loop over COPY_IDS, reading from index I, writing to index I_OUT.
+ * At the end, if I_OUT < I then some elements have been deleted. */
+ i_out = 0;
for (i = 0; i < copy_ids->nelts; i++)
{
const char *copy_id = APR_ARRAY_IDX(copy_ids, i, const char *);
copy_t *copy;
const char *id_node_id, *id_copy_id, *id_txn_id;
+ svn_error_t *err;
svn_pool_clear(iterpool);
@@ -1723,14 +1759,31 @@ copies_update(const char *new_txn_id,
copy->dst_noderev_id = svn_fs_base__id_create(id_node_id, id_copy_id,
new_txn_id, iterpool);
- /* Write the new "copy" row back under the same key (copy_id) */
- SVN_ERR(svn_fs_bdb__create_copy(trail->fs, copy_id,
- copy->src_path, copy->src_txn_id,
- copy->dst_noderev_id, copy->kind,
- trail, iterpool));
- }
+ /* Depending on whether the new node-revision exists ... */
+ err = svn_fs_bdb__get_node_revision(NULL, trail->fs,
+ copy->dst_noderev_id, trail,
+ iterpool);
+ if (err == NULL)
+ {
+ /* Write the new "copy" row back under the same key (copy_id) */
+ SVN_ERR(svn_fs_bdb__create_copy(trail->fs, copy_id,
+ copy->src_path, copy->src_txn_id,
+ copy->dst_noderev_id, copy->kind,
+ trail, iterpool));
+ APR_ARRAY_IDX(copy_ids, i_out++, const char *) = copy_id;
+ }
+ else
+ {
+ svn_error_clear(err);
+ /* Delete the copy id from COPY_IDS, and delete the copy row from
+ * the "copies" table. */
+ SVN_ERR(svn_fs_bdb__delete_copy(trail->fs, copy_id, trail, iterpool));
+ }
+ }
+ copy_ids->nelts = i_out;
svn_pool_destroy(iterpool);
+
return SVN_NO_ERROR;
}
@@ -1766,6 +1819,10 @@ svn_fs_base__dag_commit_obliteration_txn
SVN_ERR(copies_update(txn->id, old_txn_id, txn_obj->copies, trail,
scratch_pool));
+ /* Write back the new txn in case we changed its "copies" list */
+ SVN_ERR(svn_fs_bdb__put_txn(trail->fs, txn_obj, txn->id, trail,
+ scratch_pool));
+
/* Replace the revision entry in the `revisions' table. */
revision.txn_id = txn->id;
SVN_ERR(svn_fs_bdb__put_rev(&replacing_rev, txn->fs, &revision, trail,
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/dag.h
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/dag.h?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/dag.h (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/dag.h Tue Aug 10 18:06:17 2010
@@ -365,9 +365,12 @@ svn_error_t *svn_fs_base__dag_clone_chil
/* Delete the directory entry named NAME from PARENT, as part of
TRAIL. PARENT must be mutable. NAME must be a single path
component; it cannot be a slash-separated directory path. If the
- node being deleted is a mutable directory, remove all mutable nodes
- reachable from it. TXN_ID is the Subversion transaction under
- which this occurs.
+ entry being deleted points to a mutable node revision, also remove
+ that node revision and (if it is a directory) all mutable node
+ revisions reachable from it. Also delete the node-origins record
+ for each deleted node revision that had no predecessor.
+
+ TXN_ID is the Subversion transaction under which this occurs.
If return SVN_ERR_FS_NO_SUCH_ENTRY, then there is no entry NAME in
PARENT. */
@@ -380,9 +383,12 @@ svn_error_t *svn_fs_base__dag_delete(dag
/* Delete the node revision assigned to node ID from FS's `nodes'
table, as part of TRAIL. Also delete any mutable representations
- and strings associated with that node revision. ID may refer to a
- file or directory, which must be mutable. TXN_ID is the Subversion
- transaction under which this occurs.
+ and strings associated with that node revision. Also delete the
+ node-origins record for this node revision's node id, if this node
+ revision had no predecessor.
+
+ ID may refer to a file or directory, which must be mutable. TXN_ID
+ is the Subversion transaction under which this occurs.
NOTE: If ID represents a directory, and that directory has mutable
children, you risk orphaning those children by leaving them
@@ -398,9 +404,12 @@ svn_error_t *svn_fs_base__dag_remove_nod
/* Delete all mutable node revisions reachable from node ID, including
ID itself, from FS's `nodes' table, as part of TRAIL. Also delete
any mutable representations and strings associated with that node
- revision. ID may refer to a file or directory, which may be
- mutable or immutable. TXN_ID is the Subversion transaction under
- which this occurs. */
+ revision. Also delete the node-origins record for each deleted
+ node revision that had no predecessor.
+
+ ID may refer to a file or directory, which may be mutable or
+ immutable. TXN_ID is the Subversion transaction under which this
+ occurs. */
svn_error_t *svn_fs_base__dag_delete_if_mutable(svn_fs_t *fs,
const svn_fs_id_t *id,
const char *txn_id,
@@ -549,6 +558,15 @@ svn_error_t *svn_fs_base__dag_deltify(da
trail_t *trail,
apr_pool_t *pool);
+/* Obliterate NODE's data by constructing a new representation that
+ consists of a no-change delta from PRED_NODE, and changing NODE to
+ use that new rep, and leaving the old rep alone in case it is used
+ by other nodes. If PRED_NODE is null
+ then construct a representation with an empty fulltext instead. */
+svn_error_t *svn_fs_base__dag_obliterate_rep(dag_node_t *node,
+ dag_node_t *pred_node,
+ trail_t *trail,
+ apr_pool_t *pool);
/* Index NODE's backing data representations by their checksum. Do
this as part of TRAIL. Use POOL for allocations. */
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/node-rev.h
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/node-rev.h?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/node-rev.h (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/node-rev.h Tue Aug 10 18:06:17 2010
@@ -82,7 +82,7 @@ svn_error_t *svn_fs_base__create_success
/* Delete node revision ID from FS's `nodes' table, as part of TRAIL.
If ORIGIN_ALSO is set, also delete the record for this ID's node ID
from the `node-origins' index table (which is typically only done
- if the caller things that ID points to the only node revision ID in
+ if the caller thinks that ID points to the only node revision ID in
its line of history).
WARNING: This does not check that the node revision is mutable!
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/obliterate.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/obliterate.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/obliterate.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/obliterate.c Tue Aug 10 18:06:17 2010
@@ -161,8 +161,8 @@ svn_fs_base__node_rev_dup(const svn_fs_i
for (hi = apr_hash_first(scratch_pool, entries); hi;
hi = apr_hash_next(hi))
{
- const char *child_name = svn_apr_hash_index_key(hi);
- svn_fs_dirent_t *child_entry = svn_apr_hash_index_val(hi);
+ const char *child_name = svn__apr_hash_index_key(hi);
+ svn_fs_dirent_t *child_entry = svn__apr_hash_index_val(hi);
const svn_fs_id_t *new_child_id;
svn_pool_clear(iterpool);
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/reps-strings.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/reps-strings.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/reps-strings.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/reps-strings.c Tue Aug 10 18:06:17 2010
@@ -132,7 +132,7 @@ delta_string_keys(apr_array_header_t **k
/* Delete the strings associated with array KEYS in FS as part of TRAIL. */
static svn_error_t *
-delete_strings(apr_array_header_t *keys,
+delete_strings(const apr_array_header_t *keys,
svn_fs_t *fs,
trail_t *trail,
apr_pool_t *pool)
@@ -323,7 +323,7 @@ get_one_window(struct compose_handler_ba
static svn_error_t *
rep_undeltify_range(svn_fs_t *fs,
- apr_array_header_t *deltas,
+ const apr_array_header_t *deltas,
representation_t *fulltext,
int cur_chunk,
char *buf,
@@ -1621,3 +1621,132 @@ svn_fs_base__rep_deltify(svn_fs_t *fs,
return SVN_NO_ERROR;
}
+
+svn_error_t *svn_fs_base__rep_obliterate(svn_fs_t *fs,
+ const char *key,
+ const char *pred_key,
+ trail_t *trail,
+ apr_pool_t *pool)
+{
+ const char *new_str = NULL;
+ representation_t *empty;
+ svn_stream_t *new_stream;
+ struct write_svndiff_strings_baton new_baton;
+ svn_stream_t *pred_stream1, *pred_stream2;
+ svn_txdelta_stream_t *txdelta_stream;
+ base_fs_data_t *bfd = fs->fsap_data;
+ svn_txdelta_window_handler_t new_handler;
+ void *new_handler_baton;
+ apr_pool_t *wpool;
+ apr_array_header_t *windows;
+ window_write_t *ww;
+ svn_txdelta_window_t *window;
+ svn_filesize_t tview_off = 0;
+ svn_filesize_t diffsize = 0;
+ const unsigned char *digest;
+ representation_t *pred_rep;
+ representation_t new_rep;
+ rep_delta_chunk_t *chunk;
+ apr_array_header_t *chunks;
+ int i;
+
+ if (!pred_key)
+ {
+ /* No predecessor so just write a new empty rep */
+ SVN_ERR(svn_fs_bdb__string_append(fs, &new_str, 0, NULL, trail, pool));
+ empty = make_fulltext_rep(new_str, NULL,
+ svn_checksum_empty_checksum(svn_checksum_md5,
+ pool),
+ svn_checksum_empty_checksum(svn_checksum_sha1,
+ pool),
+ pool);
+ SVN_ERR(svn_fs_bdb__write_rep(fs, key, empty, trail, pool));
+
+ return SVN_NO_ERROR;
+ }
+
+ if (!strcmp(key, pred_key))
+ return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+ _("Attempt to obliterate '%s' using itself "),
+ key);
+
+ new_baton.fs = fs;
+ new_baton.trail = trail;
+ new_baton.header_read = FALSE;
+ new_stream = svn_stream_create(&new_baton, pool);
+ svn_stream_set_write(new_stream, write_svndiff_strings);
+
+ /* ### Is there a simpler way to write a no-change delta? */
+ SVN_ERR(svn_fs_base__rep_contents_read_stream(&pred_stream1, fs, pred_key,
+ TRUE, trail, pool));
+ SVN_ERR(svn_fs_base__rep_contents_read_stream(&pred_stream2, fs, pred_key,
+ TRUE, trail, pool));
+ svn_txdelta(&txdelta_stream, pred_stream1, pred_stream2, pool);
+
+ if (bfd->format >= SVN_FS_BASE__MIN_SVNDIFF1_FORMAT)
+ svn_txdelta_to_svndiff2(&new_handler, &new_handler_baton,
+ new_stream, 1, pool);
+ else
+ svn_txdelta_to_svndiff2(&new_handler, &new_handler_baton,
+ new_stream, 0, pool);
+
+ wpool = svn_pool_create(pool);
+ windows = apr_array_make(pool, 1, sizeof(ww));
+ do
+ {
+ new_baton.size = 0;
+ new_baton.key = NULL;
+ svn_pool_clear(wpool);
+
+ SVN_ERR(svn_txdelta_next_window(&window, txdelta_stream, wpool));
+ SVN_ERR(new_handler(window, new_handler_baton));
+ if (window)
+ {
+ ww = apr_pcalloc(pool, sizeof(*ww));
+ ww->key = new_baton.key;
+ ww->svndiff_len = new_baton.size;
+ ww->text_off = tview_off;
+ ww->text_len = window->tview_len;
+ APR_ARRAY_PUSH(windows, window_write_t *) = ww;
+ tview_off += window->tview_len;
+ diffsize += ww->svndiff_len;
+ }
+ } while (window);
+
+ svn_pool_destroy(wpool);
+
+ digest = svn_txdelta_md5_digest(txdelta_stream);
+ if (!digest)
+ return svn_error_createf(SVN_ERR_DELTA_MD5_CHECKSUM_ABSENT, NULL,
+ _("Failed to calculate MD5 digest for '%s'"),
+ pred_key);
+ /* ### Check the digest against something? pred_rep->md5_checksum? */
+
+ SVN_ERR(svn_fs_bdb__read_rep(&pred_rep, fs, pred_key, trail, pool));
+ new_rep.md5_checksum = svn_checksum_dup(pred_rep->md5_checksum, pool);
+ new_rep.sha1_checksum = svn_checksum_dup(pred_rep->sha1_checksum, pool);
+ new_rep.kind = rep_kind_delta;
+ new_rep.txn_id = NULL;
+
+ chunks = apr_array_make(pool, windows->nelts, sizeof(chunk));
+
+ for (i = 0; i < windows->nelts; i++)
+ {
+ ww = APR_ARRAY_IDX(windows, i, window_write_t *);
+
+ chunk = apr_palloc(pool, sizeof(*chunk));
+ chunk->offset = ww->text_off;
+
+ chunk->version = new_baton.version;
+ chunk->string_key = ww->key;
+ chunk->size = ww->text_len;
+ chunk->rep_key = pred_key;
+
+ APR_ARRAY_PUSH(chunks, rep_delta_chunk_t *) = chunk;
+ }
+
+ new_rep.contents.delta.chunks = chunks;
+ SVN_ERR(svn_fs_bdb__write_rep(fs, key, &new_rep, trail, pool));
+
+ return SVN_NO_ERROR;
+}
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/reps-strings.h
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/reps-strings.h?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/reps-strings.h (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/reps-strings.h Tue Aug 10 18:06:17 2010
@@ -38,14 +38,14 @@ extern "C" {
-/* Get or create a mutable representation in FS, store the new rep's
- key in *NEW_REP_KEY.
+/* Get or create a mutable representation in FS, and set *NEW_REP_KEY to its
+ key.
TXN_ID is the id of the Subversion transaction under which this occurs.
- If REP_KEY is already a mutable representation, set *NEW_REP_KEY to
- REP_KEY, else set *NEW_REP_KEY to a brand new rep key allocated in
- POOL. */
+ If REP_KEY is not null and is already a mutable representation, set
+ *NEW_REP_KEY to REP_KEY, else create a brand new rep and set *NEW_REP_KEY
+ to its key, allocated in POOL. */
svn_error_t *svn_fs_base__get_mutable_rep(const char **new_rep_key,
const char *rep_key,
svn_fs_t *fs,
@@ -168,6 +168,18 @@ svn_error_t *svn_fs_base__rep_deltify(sv
trail_t *trail,
apr_pool_t *pool);
+/* Obliterate KEY's data by creating a new rep that consists of a
+ no-change delta from PRED_KEY's data. If PRED_KEY is null then
+ construct an empty fulltext instead of a delta. KEY's old data
+ remains in the database in case some other key's data is derived
+ from it. */
+/* ### TODO: clarify. What kind of objects are KEY and PRED_KEY, and what
+ does it do with the new rep? */
+svn_error_t *svn_fs_base__rep_obliterate(svn_fs_t *fs,
+ const char *key,
+ const char *pred_key,
+ trail_t *trail,
+ apr_pool_t *pool);
#ifdef __cplusplus
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=984153&r1=984152&r2=984153&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 18:06:17 2010
@@ -56,8 +56,8 @@
/* Set *txn_p to a transaction object allocated in POOL for the
transaction in FS whose id is TXN_ID. If EXPECT_DEAD is set, this
transaction must be a dead one, else an error is returned. If
- EXPECT_DEAD is not set, an error is thrown if the transaction is
- *not* dead. */
+ EXPECT_DEAD is not set, the transaction must *not* be a dead one,
+ else an error is returned. */
static svn_error_t *
get_txn(transaction_t **txn_p,
svn_fs_t *fs,
@@ -437,9 +437,10 @@ svn_fs_base__add_txn_copy(svn_fs_t *fs,
/* Duplicate all entries in the "changes" table that are keyed by OLD_TXN_ID,
* creating new entries that are keyed by NEW_TXN_ID.
*
- * Each new "change" has the same content as the old one, except that if the
+ * Give each new "change" the same content as the old one, except that if the
* txn-id component of its noderev-id is OLD_TXN_ID (which is the case for
- * all changes except deletes) then that is changed to NEW_TXN_ID.
+ * all changes except deletes, and for some deletes, it seems) then change
+ * that to NEW_TXN_ID.
*
* Work within TRAIL. */
static svn_error_t *
@@ -456,17 +457,15 @@ changes_dup(const char *new_txn_id,
for (i = 0; i < changes->nelts; i++)
{
change_t *change = APR_ARRAY_IDX(changes, i, change_t *);
-
- if (change->kind != svn_fs_path_change_delete
- && change->kind != svn_fs_path_change_reset)
+ const char *node_id = svn_fs_base__id_node_id(change->noderev_id);
+ const char *copy_id = svn_fs_base__id_copy_id(change->noderev_id);
+ const char *txn_id = svn_fs_base__id_txn_id(change->noderev_id);
+
+ /* if (change->kind != svn_fs_path_change_delete
+ * && change->kind != svn_fs_path_change_reset) */
+ if (svn_fs_base__key_compare(txn_id, old_txn_id) == 0)
{
- const char *node_id, *copy_id;
-
/* Modify the "change": change noderev_id's txn_id to NEW_TXN_ID */
- node_id = svn_fs_base__id_node_id(change->noderev_id);
- copy_id = svn_fs_base__id_copy_id(change->noderev_id);
- SVN_ERR_ASSERT(svn_fs_base__key_compare(
- svn_fs_base__id_txn_id(change->noderev_id), old_txn_id) == 0);
change->noderev_id = svn_fs_base__id_create(node_id, copy_id,
new_txn_id,
scratch_pool);
@@ -638,7 +637,7 @@ svn_fs_base__change_txn_prop(svn_fs_txn_
svn_error_t *
svn_fs_base__change_txn_props(svn_fs_txn_t *txn,
- apr_array_header_t *props,
+ const apr_array_header_t *props,
apr_pool_t *pool)
{
apr_pool_t *iterpool = svn_pool_create(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=984153&r1=984152&r2=984153&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 18:06:17 2010
@@ -226,7 +226,7 @@ svn_error_t *svn_fs_base__change_txn_pro
apr_pool_t *pool);
svn_error_t *svn_fs_base__change_txn_props(svn_fs_txn_t *txn,
- apr_array_header_t *props,
+ const apr_array_header_t *props,
apr_pool_t *pool);
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/tree.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/tree.c Tue Aug 10 18:06:17 2010
@@ -2796,6 +2796,7 @@ svn_fs_base__commit_obliteration_txn(svn
{
struct commit_args commit_args;
+ /* Commit the replacement transaction. */
/* We do not need a re-try loop like the (catch up to head, try to
* commit) loop that svn_fs_base__commit_txn() uses, because the only
* concurrent changes that can affect this old revision are other
@@ -2806,7 +2807,9 @@ svn_fs_base__commit_obliteration_txn(svn
SVN_ERR(svn_fs_base__retry_txn(txn->fs, txn_body_commit_obliteration,
&commit_args, FALSE, pool));
- /* return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL); */
+ /* Remove the old txn and any unreferenced data attached to it. */
+ /* ### ... */
+
return SVN_NO_ERROR;
}
@@ -2937,6 +2940,94 @@ svn_fs_base__deltify(svn_fs_t *fs,
}
+struct txn_obliterate_rep_args
+{
+ const svn_fs_id_t *id;
+ svn_boolean_t has_pred;
+ const svn_fs_id_t *pred_id;
+};
+
+static svn_error_t *
+txn_body_obliterate_rep(void *baton, trail_t *trail)
+{
+ struct txn_obliterate_rep_args *args = baton;
+ dag_node_t *node, *pred_node;
+
+ SVN_ERR(svn_fs_base__dag_get_node(&node, trail->fs, args->id,
+ trail, trail->pool));
+ if (args->has_pred)
+ {
+ SVN_ERR(svn_fs_base__dag_get_node(&pred_node, trail->fs, args->pred_id,
+ trail, trail->pool));
+ }
+ else
+ {
+ pred_node = NULL;
+ }
+
+ SVN_ERR(svn_fs_base__dag_obliterate_rep(node, pred_node, trail, trail->pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_base__obliterate_rep(svn_fs_t *fs,
+ const char *path,
+ svn_revnum_t revision,
+ apr_pool_t *pool)
+{
+ svn_fs_root_t *root;
+ const char *txn_id;
+ struct rev_get_txn_id_args get_txn_args;
+ const svn_fs_id_t *id;
+ svn_node_kind_t kind;
+ struct txn_pred_count_args pred_count_args;
+ struct txn_obliterate_rep_args oblit_args;
+
+ SVN_ERR(svn_fs_base__revision_root(&root, fs, revision, pool));
+ get_txn_args.txn_id = &txn_id;
+ get_txn_args.revision = revision;
+ SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_rev_get_txn_id, &get_txn_args,
+ FALSE, pool));
+
+ SVN_ERR(base_node_id(&id, root, path, pool));
+ if (strcmp(svn_fs_base__id_txn_id(id), txn_id))
+ return svn_error_createf(SVN_ERR_FS_NOT_MUTABLE, NULL,
+ _("Unexpected immutable node at '%s'"), path);
+
+ SVN_ERR(base_check_path(&kind, root, path, pool));
+ if (kind != svn_node_file)
+ return svn_error_createf(SVN_ERR_FS_NOT_FILE, NULL,
+ _("Cannot obliterate '%s' as it is not a file"),
+ path);
+
+ pred_count_args.id = id;
+ SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_pred_count, &pred_count_args,
+ FALSE, pool));
+
+ if (pred_count_args.pred_count > 0)
+ {
+ struct txn_pred_id_args pred_id_args;
+
+ pred_id_args.id = id;
+ pred_id_args.pool = pool;
+ SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_pred_id, &pred_id_args,
+ FALSE, pool));
+
+ oblit_args.has_pred = TRUE;
+ oblit_args.pred_id = pred_id_args.pred_id;
+ }
+ else
+ {
+ oblit_args.has_pred = FALSE;
+ }
+ oblit_args.id = id;
+
+ return svn_fs_base__retry_txn(fs, txn_body_obliterate_rep, &oblit_args,
+ TRUE, pool);
+}
+
+
/* Modifying directories */
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/tree.h
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/tree.h?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/tree.h (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/tree.h Tue Aug 10 18:06:17 2010
@@ -95,6 +95,13 @@ svn_error_t *svn_fs_base__get_path_creat
trail_t *trail,
apr_pool_t *pool);
+/* ### Experimental obliterate-like-deltify - see implementation. */
+svn_error_t *
+svn_fs_base__obliterate_rep(svn_fs_t *fs,
+ const char *path,
+ svn_revnum_t revision,
+ apr_pool_t *pool);
+
#ifdef __cplusplus
}
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/util/fs_skels.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/util/fs_skels.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/util/fs_skels.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/util/fs_skels.c Tue Aug 10 18:06:17 2010
@@ -433,8 +433,9 @@ svn_fs_base__parse_transaction_skel(tran
{
/* Committed transactions have a revision number... */
transaction->base_id = NULL;
- transaction->revision = atoi(apr_pstrmemdup(pool, base_id_or_rev->data,
- base_id_or_rev->len));
+ transaction->revision =
+ SVN_STR_TO_REV(apr_pstrmemdup(pool, base_id_or_rev->data,
+ base_id_or_rev->len));
if (! SVN_IS_VALID_REVNUM(transaction->revision))
return skel_err("transaction");