The attached patch is an attempt to close the gap between "transmit text
deltas" and commit post-processing, by passing the temporary new text
base file paths around. It succeeds in that, at least it looks right
and passes the test suite.
The part of this patch that I haven't finished is with back-compat of
svn_wc__process_committed_internal(), and what is the difference between
its 'queue' parameter and its checksum/recurse/no_unlock/etc.
parameters, being values which are alternatively available in the queue.
svn_wc__process_committed_internal() is called by
svn_wc_process_committed_queue2() which passes the 'queue' param, and
also by the deprecated svn_wc_process_committed4() with QUEUE=NULL. I
had been assuming that if QUEUE==NULL then all the parameters that are
available in the queue (checksum for one) are not available, but that's
not how the back-compat wrapper wants to work. I'll need to fix that.
I think the right thing to do is to re-write the wrapper
(svn_wc_process_committed4()) to construct a new queue with one item and
pass that, and stop having the other parameters (checksum etc.) passed
as separate parameters. I'll look at that tomorrow. I may already have
committed changes that break that back-compat; I'll check.
The internal recursion of svn_wc__process_committed_internal() is
confusing me: it passes NO_UNLOCK=TRUE to itself when recursing,
regardless of what no_unlock value was passed in or what is in the queue
item. Yet it passes the received value of KEEP_CHANGELIST. For the
NEW_DAV_CACHE and CHECKSUM arguments it passes NULL, which is half
explained by them only having meaning in connection with a single node:
the same ones cannot be applicable to a child node.
Comments?
- Julian
### This version of the patch carries the text base path through the client
### 'tempfiles' hash and adds it into the WC commit-items struct.
In a commit, pass the temporary paths of the new text base files through
from the pre-commit to the post-commit stage, instead of re-deriving them.
This completes the data flow of these paths so that they no longer need to
be deterministically derivable.
* subversion/include/svn_wc.h
(svn_wc_queue_committed3): Add a new parameter 'new_text_base_abspath'.
### Also doc that CHECKSUM must be given when applicable, but that should be a separate change.
(svn_wc_queue_committed2): Adjust doc string accordingly.
* subversion/libsvn_client/commit.c
(post_commit_baton, post_process_commit_item, svn_client_commit4): Pass the
new text base abspaths down, through the post_commit_baton, to
svn_wc_queue_committed3().
* subversion/libsvn_wc/adm_crawler.c
(svn_wc_transmit_text_deltas3):
### Brute-force verification of these changes. Not to be committed.
* subversion/libsvn_wc/adm_ops.c
(committed_queue_item_t): Add a new member 'new_text_base_abspath'.
(process_committed_leaf): Take 'new_text_base_abspath' as a parameter
instead of deriving it.
(svn_wc__process_committed_internal): Find 'new_text_base_abspath' and
'checksum' in the Committed Queue Item and pass them to
process_committed_leaf(). Don't take 'checksum' as a param.
(svn_wc_queue_committed3): Take 'new_text_base_abspath' as a parameter and
store it in the queue.
(svn_wc_process_committed_queue2): Adjust the call to
svn_wc__process_committed_internal().
* subversion/libsvn_wc/deprecated.c
(svn_wc_process_committed4): Adjust the call to
svn_wc__process_committed_internal().
(svn_wc_queue_committed2): Implement the old behaviour, looking for a file
at a deterministic temporary text base path, and passing that to
svn_wc_queue_committed3().
* subversion/libsvn_wc/wc.h
(svn_wc__process_committed_internal): Remove the 'checksum' parameter, as it
is now passed via the 'queue' parameter.
* notes/wc-ng/use-of-tmp-text-base-path
Update accordingly.
--This line, and those below, will be ignored--
Index: notes/wc-ng/use-of-tmp-text-base-path
===================================================================
--- notes/wc-ng/use-of-tmp-text-base-path (revision 928789)
+++ notes/wc-ng/use-of-tmp-text-base-path (working copy)
@@ -1,5 +1,5 @@
-Call graphs of the use of the WC-1 temporary text base path, as of r927056.
+Call graphs of the use of the WC-1 temporary text base path.
This is to help us eliminate the use of this path and replace it with a more
encapsulated way of referring to the new text base, as part of migration to a
@@ -14,46 +14,46 @@ path is obtained, and the extent to whic
svn_client_commit4()
- |^[T] | [T] Terminates here
- wc_to_repos_copy() |^[M] |
- | |^ | [M] Multiple files
- svn_client__do_commit() |
- [N] |^ | [N] Not when caller is
- |^ | wc_to_repos_copy()
- |^ |
- LIBSVN_CLIENT |^ |
+ |^ |v [T] Terminates here
+ wc_to_repos_copy() |^[M] |v[M]
+ | |^ |v [M] Multiple files
+ svn_client__do_commit() |v
+ [N] |^ |v [N] Not when caller is
+ |^ |v wc_to_repos_copy()
+ |^ |v
+ LIBSVN_CLIENT |^ |v
..........................................................................
- LIBSVN_WC |^ |
- |^ |
+ LIBSVN_WC |^ |v
+ |^ |v
|^ +---+
- |^ |
- svn_wc_transmit_text_deltas3() |
- [N] |^ |
- svn_wc__internal_transmit_text_deltas() |
- [N] |^ |
- |^ |
+ |^ |v
+ svn_wc_transmit_text_deltas3() |v
+ [N] |^ |v
+ svn_wc__internal_transmit_text_deltas() |v
+ [N] |^ |v
+ |^ |v
|^ { svn_wc_process_committed_queue2() }
|^ { svn_wc_process_committed4() }
- |^ |
+ |^ |v
|^ svn_wc__process_committed_internal()
- |^ |
+ |^ |v
|^ process_committed_leaf()
- |^ |^ |v
- |^ |^ svn_wc__wq_add_postcommit()
- |^ |^ *v
- |^ |^ *v
- |^ |^ *v
- |^ |^ WQ:OP_POSTCOMMIT
- |^ |^ *v
- |^ |^ *v
- |^ |^ *v
- |^ |^ run_postcommit()
- |^ |^ |v
- |^ |^ log_do_committed()
- |^ |^ |v
- |^ |^ install_committed_file()
- |^ |^ |v
- |^ |^ |v
+ |^ | |v
+ |^ | svn_wc__wq_add_postcommit()
+ |^ | *v
+ |^ | *v
+ |^ | *v
+ |^ | WQ:OP_POSTCOMMIT
+ |^ | *v
+ |^ | *v
+ |^ | *v
+ |^ | run_postcommit()
+ |^ | |v
+ |^ | log_do_committed()
+ |^ | |v
+ |^ | install_committed_file()
+ |^ | |v
+ |^ | |v
svn_wc__text_base_path(tmp=TRUE) svn_wc__sync_text_base()
|^ |v
|^ [initialization] svn_io_rename()
Index: subversion/include/svn_wc.h
===================================================================
--- subversion/include/svn_wc.h (revision 928789)
+++ subversion/include/svn_wc.h (working copy)
@@ -4746,8 +4746,9 @@ svn_wc_committed_queue_create(apr_pool_t
* svn_wc_process_committed_queue2().
*
* All pointer data passed to this function (@a local_abspath,
- * @a wcprop_changes * and @a checksum) should remain valid until the
- * queue has been processed by svn_wc_process_committed_queue2().
+ * @a wcprop_changes, @a checksum and @a new_text_base_abspath) should
+ * remain valid until the queue has been processed by
+ * svn_wc_process_committed_queue2().
*
* Record in @a queue that @a local_abspath will need to be bumped
* after a commit succeeds.
@@ -4765,11 +4766,9 @@ svn_wc_committed_queue_create(apr_pool_t
* If @a remove_changelist is @c TRUE, any association with a
* changelist will be removed.
*
- * If @a local_abspath is a file and @a checksum is non-NULL, use @a checksum
- * as the checksum for the new text base. Otherwise, calculate the checksum
- * if needed.
- * ### [JAF] No, it doesn't calculate the checksum, it stores null in wc.db:
- * ### see svn_wc__process_committed_internal().
+ * If there is a new text base file to be installed, @a new_text_base_abspath
+ * must be its path and @a checksum must be its MD5 checksum. Otherwise,
+ * @a new_text_base_abspath and @a checksum must be NULL.
*
* If @a recurse is TRUE and @a local_abspath is a directory, then bump every
* versioned object at or under @a path. This is usually done for
@@ -4791,11 +4790,15 @@ svn_wc_queue_committed3(svn_wc_committed
const apr_array_header_t *wcprop_changes,
svn_boolean_t remove_lock,
svn_boolean_t remove_changelist,
+ const char *new_text_base_abspath,
const svn_checksum_t *checksum,
apr_pool_t *scratch_pool);
/** Same as svn_wc_queue_committed3() except @a path doesn't have to be an
- * abspath and @a adm_access is unused.
+ * abspath, @a adm_access is unused and the new text base file (if there is
+ * one) is found automatically.
+ * ### and the docs previously implied @a checksum was optional, but it
+ * ### doesn't seem so: see svn_wc__process_committed_internal().
*
* @since New in 1.6.
*
Index: subversion/libsvn_client/commit.c
===================================================================
--- subversion/libsvn_client/commit.c (revision 928789)
+++ subversion/libsvn_client/commit.c (working copy)
@@ -941,6 +941,7 @@ struct post_commit_baton
svn_wc_context_t *wc_ctx;
svn_boolean_t keep_changelists;
svn_boolean_t keep_locks;
+ apr_hash_t *new_text_base_abspaths;
apr_hash_t *checksums;
};
@@ -984,6 +985,9 @@ post_process_commit_item(void *baton, vo
return svn_wc_queue_committed3(btn->queue, item->path,
loop_recurse, item->incoming_prop_changes,
remove_lock, !btn->keep_changelists,
+ apr_hash_get(btn->new_text_base_abspaths,
+ item->path,
+ APR_HASH_KEY_STRING),
apr_hash_get(btn->checksums,
item->path,
APR_HASH_KEY_STRING),
@@ -1098,7 +1102,7 @@ svn_client_commit4(svn_commit_info_t **c
apr_array_header_t *rel_targets;
apr_hash_t *committables;
apr_hash_t *lock_tokens;
- apr_hash_t *tempfiles = NULL;
+ apr_hash_t *new_text_base_abspaths = NULL;
apr_hash_t *checksums;
apr_array_header_t *commit_items;
svn_error_t *cmt_err = SVN_NO_ERROR, *unlock_err = SVN_NO_ERROR;
@@ -1256,8 +1260,8 @@ svn_client_commit4(svn_commit_info_t **c
/* Perform the commit. */
cmt_err = svn_client__do_commit(base_url, commit_items, editor, edit_baton,
- notify_prefix, &tempfiles, &checksums, ctx,
- pool);
+ notify_prefix, &new_text_base_abspaths,
+ &checksums, ctx, pool);
/* Handle a successful commit. */
if ((! cmt_err)
@@ -1271,6 +1275,7 @@ svn_client_commit4(svn_commit_info_t **c
btn.wc_ctx = ctx->wc_ctx;
btn.keep_changelists = keep_changelists;
btn.keep_locks = keep_locks;
+ btn.new_text_base_abspaths = new_text_base_abspaths;
btn.checksums = checksums;
/* Make a note that our commit is finished. */
@@ -1309,7 +1314,7 @@ svn_client_commit4(svn_commit_info_t **c
unlock_err = svn_wc__release_write_lock(ctx->wc_ctx, base_dir, pool);
if (! unlock_err)
- cleanup_err = remove_tmpfiles(tempfiles, pool);
+ cleanup_err = remove_tmpfiles(new_text_base_abspaths, pool);
}
/* As per our promise, if *commit_info_p isn't set, provide a default where
Index: subversion/libsvn_wc/adm_crawler.c
===================================================================
--- subversion/libsvn_wc/adm_crawler.c (revision 928789)
+++ subversion/libsvn_wc/adm_crawler.c (working copy)
@@ -1330,10 +1330,36 @@ svn_wc_transmit_text_deltas3(const char
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- return svn_wc__internal_transmit_text_deltas(tempfile, digest, wc_ctx->db,
- local_abspath, fulltext, editor,
- file_baton, result_pool,
- scratch_pool);
+ const char *tempfile_1;
+ const char *new_text_base_abspath;
+ svn_node_kind_t new_text_base_kind;
+
+ SVN_ERR(svn_wc__internal_transmit_text_deltas(&tempfile_1, digest, wc_ctx->db,
+ local_abspath, fulltext, editor,
+ file_baton, result_pool,
+ scratch_pool));
+ if (tempfile)
+ *tempfile = tempfile_1;
+
+ /* For transition, verify that TEMPFILE_1 is non-null iff a file exists
+ * at the WC-1 deterministic tmp text base path. */
+
+ SVN_ERR(svn_wc__text_base_path(&new_text_base_abspath, wc_ctx->db,
+ local_abspath, TRUE, scratch_pool));
+ SVN_ERR(svn_io_check_path(new_text_base_abspath, &new_text_base_kind,
+ scratch_pool));
+ if (new_text_base_kind != svn_node_file)
+ new_text_base_abspath = NULL;
+
+ if (!tempfile_1 != !new_text_base_abspath
+ || (tempfile_1 && strcmp(tempfile_1, new_text_base_abspath) != 0))
+ {
+ printf("## tempfile_1='%s',\n## but new_t='%s' and kind=%d\n",
+ tempfile_1, new_text_base_abspath, new_text_base_kind);
+ abort();
+ }
+
+ return SVN_NO_ERROR;
}
svn_error_t *
Index: subversion/libsvn_wc/adm_ops.c
===================================================================
--- subversion/libsvn_wc/adm_ops.c (revision 928789)
+++ subversion/libsvn_wc/adm_ops.c (working copy)
@@ -83,6 +83,7 @@ typedef struct
svn_boolean_t recurse;
svn_boolean_t no_unlock;
svn_boolean_t keep_changelist;
+ const char *new_text_base_abspath;
const svn_checksum_t *checksum;
apr_hash_t *new_dav_cache;
} committed_queue_item_t;
@@ -345,8 +346,8 @@ process_deletion_postcommit(svn_wc__db_t
}
-/* CHECKSUM is the checksum of the new text base for LOCAL_ABSPATH, and must
- * be provided if there is one, else NULL. */
+/* If there is a new text base file for LOCAL_ABSPATH, CHECKSUM must be its
+ * checksum and NEW_TEXT_BASE_ABSPATH must be its path. */
static svn_error_t *
process_committed_leaf(svn_wc__db_t *db,
const char *local_abspath,
@@ -356,6 +357,7 @@ process_committed_leaf(svn_wc__db_t *db,
apr_hash_t *new_dav_cache,
svn_boolean_t no_unlock,
svn_boolean_t keep_changelist,
+ const char *new_text_base_abspath,
const svn_checksum_t *checksum,
apr_pool_t *scratch_pool)
{
@@ -363,7 +365,6 @@ process_committed_leaf(svn_wc__db_t *db,
svn_wc__db_kind_t kind;
const svn_checksum_t *copied_checksum;
const char *adm_abspath;
- const char *tmp_text_base_abspath;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
@@ -431,19 +432,7 @@ process_committed_leaf(svn_wc__db_t *db,
SVN_ERR(svn_wc__loggy_delete_lock(db, adm_abspath,
local_abspath, scratch_pool));
- /* Set TMP_TEXT_BASE_ABSPATH to the new text base to be installed, if any. */
- {
- svn_node_kind_t new_base_kind;
-
- SVN_ERR(svn_wc__text_base_path(&tmp_text_base_abspath, db, local_abspath,
- TRUE, scratch_pool));
- SVN_ERR(svn_io_check_path(tmp_text_base_abspath, &new_base_kind,
- scratch_pool));
- if (new_base_kind != svn_node_file)
- tmp_text_base_abspath = NULL;
- }
-
- SVN_ERR(svn_wc__wq_add_postcommit(db, local_abspath, tmp_text_base_abspath,
+ SVN_ERR(svn_wc__wq_add_postcommit(db, local_abspath, new_text_base_abspath,
new_revnum,
new_date, rev_author, checksum,
new_dav_cache, keep_changelist,
@@ -463,19 +452,24 @@ svn_wc__process_committed_internal(svn_w
apr_hash_t *new_dav_cache,
svn_boolean_t no_unlock,
svn_boolean_t keep_changelist,
- const svn_checksum_t *checksum,
const svn_wc_committed_queue_t *queue,
apr_pool_t *scratch_pool)
{
+ const committed_queue_item_t *cqi;
svn_wc__db_kind_t kind;
+ cqi = queue ? apr_hash_get(queue->queue, local_abspath, APR_HASH_KEY_STRING)
+ : NULL;
+
SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath, TRUE, scratch_pool));
SVN_ERR(process_committed_leaf(db, local_abspath,
new_revnum, new_date, rev_author,
new_dav_cache,
no_unlock, keep_changelist,
- checksum, scratch_pool));
+ cqi ? cqi->new_text_base_abspath : NULL,
+ cqi ? cqi->checksum : NULL,
+ scratch_pool));
if (recurse && kind == svn_wc__db_kind_dir)
{
@@ -533,12 +527,15 @@ svn_wc__process_committed_internal(svn_w
rev_author,
NULL,
TRUE /* no_unlock */,
- keep_changelist, NULL,
+ keep_changelist,
queue, iterpool));
SVN_ERR(svn_wc__wq_run(db, this_abspath, NULL, NULL, iterpool));
}
else
{
+ cqi = queue ? apr_hash_get(queue->queue, this_abspath,
+ APR_HASH_KEY_STRING) : NULL;
+
/* Suppress log creation for deleted entries in a replaced
directory. By the time any log we create here is run,
those entries will already have been removed (as a result
@@ -556,23 +553,15 @@ svn_wc__process_committed_internal(svn_w
continue;
}
- checksum = NULL;
- if (queue != NULL)
- {
- const committed_queue_item_t *cqi
- = apr_hash_get(queue->queue, this_abspath,
- APR_HASH_KEY_STRING);
-
- if (cqi != NULL)
- checksum = cqi->checksum;
- }
-
SVN_ERR(process_committed_leaf(db, this_abspath,
new_revnum,
new_date, rev_author, NULL,
TRUE /* no_unlock */,
keep_changelist,
- checksum, iterpool));
+ cqi ? cqi->new_text_base_abspath
+ : NULL,
+ cqi ? cqi->checksum : NULL,
+ iterpool));
}
}
@@ -626,6 +615,7 @@ svn_wc_queue_committed3(svn_wc_committed
const apr_array_header_t *wcprop_changes,
svn_boolean_t remove_lock,
svn_boolean_t remove_changelist,
+ const char *new_text_base_abspath,
const svn_checksum_t *checksum,
apr_pool_t *scratch_pool)
{
@@ -645,6 +635,7 @@ svn_wc_queue_committed3(svn_wc_committed
cqi->recurse = recurse;
cqi->no_unlock = !remove_lock;
cqi->keep_changelist = !remove_changelist;
+ cqi->new_text_base_abspath = new_text_base_abspath;
cqi->checksum = checksum;
cqi->new_dav_cache = svn_wc__prop_array_to_hash(wcprop_changes, queue->pool);
@@ -725,8 +716,7 @@ svn_wc_process_committed_queue2(svn_wc_c
cqi->new_dav_cache,
cqi->no_unlock,
cqi->keep_changelist,
- cqi->checksum, queue,
- iterpool));
+ queue, iterpool));
SVN_ERR(svn_wc__wq_run(wc_ctx->db, cqi->local_abspath, NULL, NULL,
iterpool));
Index: subversion/libsvn_wc/deprecated.c
===================================================================
--- subversion/libsvn_wc/deprecated.c (revision 928789)
+++ subversion/libsvn_wc/deprecated.c (working copy)
@@ -39,6 +39,7 @@
#include "lock.h"
#include "props.h"
#include "workqueue.h"
+#include "adm_files.h"
#include "svn_private_config.h"
@@ -584,7 +585,7 @@ svn_wc_process_committed4(const char *pa
new_revnum, new_date, rev_author,
wcprop_changes_hash,
!remove_lock, !remove_changelist,
- checksum, NULL, pool));
+ NULL, pool));
/* Run the log file(s) we just created. */
return svn_error_return(svn_wc__wq_run(db, local_abspath, NULL, NULL, pool));
@@ -3714,10 +3715,26 @@ svn_wc_queue_committed2(svn_wc_committed
apr_pool_t *scratch_pool)
{
const char *local_abspath;
+ const char *new_text_base_abspath;
SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
+
+ /* Set TMP_TEXT_BASE_ABSPATH to the new text base to be installed, if any. */
+ {
+ svn_wc__db_t *db = svn_wc__adm_get_db(adm_access);
+ svn_node_kind_t new_base_kind;
+
+ SVN_ERR(svn_wc__text_base_path(&new_text_base_abspath, db, local_abspath,
+ TRUE, scratch_pool));
+ SVN_ERR(svn_io_check_path(new_text_base_abspath, &new_base_kind,
+ scratch_pool));
+ if (new_base_kind != svn_node_file)
+ new_text_base_abspath = NULL;
+ }
+
return svn_wc_queue_committed3(queue, local_abspath, recurse, wcprop_changes,
- remove_lock, remove_changelist, checksum,
+ remove_lock, remove_changelist,
+ new_text_base_abspath, checksum,
scratch_pool);
}
Index: subversion/libsvn_wc/wc.h
===================================================================
--- subversion/libsvn_wc/wc.h (revision 928789)
+++ subversion/libsvn_wc/wc.h (working copy)
@@ -212,11 +212,6 @@ svn_wc__get_committed_queue_pool(const s
*
* If @keep_changelist is set, don't remove any changeset assignments
* from @a local_abspath; otherwise, clear it of such assignments.
- *
- * If @a local_abspath is a file and @a checksum is non-NULL, use @a checksum
- * as the checksum for the new text base. Otherwise, calculate the checksum
- * if needed.
- * ### [JAF] No, it doesn't calculate the checksum, it stores null in wc.db.
*/
svn_error_t *
svn_wc__process_committed_internal(svn_wc__db_t *db,
@@ -228,7 +223,6 @@ svn_wc__process_committed_internal(svn_w
apr_hash_t *new_dav_cache,
svn_boolean_t no_unlock,
svn_boolean_t keep_changelist,
- const svn_checksum_t *checksum,
const svn_wc_committed_queue_t *queue,
apr_pool_t *scratch_pool);