Author: stsp Date: Mon Mar 12 20:06:40 2012 New Revision: 1299817 URL: http://svn.apache.org/viewvc?rev=1299817&view=rev Log: On the multi-layer-moves branch, retain move information during replace.
Before this change, replacing a moved-away node with a copy deleted the moved-to relpath of the node from the DB row. So given a node such as 2|A/B/C/D|base-deleted|X| the result of replacing A/B with a copy that includes a C/D was this: 2|A/B/C/D|normal|| With this change, the moved-to relpath is retained: 2|A/B/C/D|normal|X| See http://wiki.apache.org/subversion/MultiLayerMoves for details. Note that, after the replacement, 'svn status' still doesn't show A/B/C/D as having moved to X. This is probably because status only shows move information for op-roots. This might need to be revisited... *grumble* Though maybe this is fine as is? * subversion/libsvn_wc/wc_db.c (insert_incomplete_children): Preserve the moved-to path while replacing working nodes. While here, introduce an iterpool. Modified: subversion/branches/multi-layer-moves/subversion/libsvn_wc/wc_db.c Modified: subversion/branches/multi-layer-moves/subversion/libsvn_wc/wc_db.c URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_wc/wc_db.c?rev=1299817&r1=1299816&r2=1299817&view=diff ============================================================================== --- subversion/branches/multi-layer-moves/subversion/libsvn_wc/wc_db.c (original) +++ subversion/branches/multi-layer-moves/subversion/libsvn_wc/wc_db.c Mon Mar 12 20:06:40 2012 @@ -967,38 +967,72 @@ insert_incomplete_children(svn_sqlite__d { svn_sqlite__stmt_t *stmt; int i; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + apr_hash_t *moved_to_relpaths = apr_hash_make(scratch_pool); SVN_ERR_ASSERT(repos_path != NULL || op_depth > 0); SVN_ERR_ASSERT((repos_id != INVALID_REPOS_ID) == (repos_path != NULL)); + /* If we're inserting WORKING nodes, we might be replacing existing + * nodes which were moved-away. We need to retain the moved-to relpath of + * such nodes in order not to lose move information during replace. */ + if (op_depth > 0) + { + SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_WORKING_NODE)); + + for (i = children->nelts; i--; ) + { + const char *name = APR_ARRAY_IDX(children, i, const char *); + svn_boolean_t have_row; + + svn_pool_clear(iterpool); + + SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, + svn_relpath_join(local_relpath, name, + iterpool))); + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + if (have_row && !svn_sqlite__column_is_null(stmt, 14)) + apr_hash_set(moved_to_relpaths, name, APR_HASH_KEY_STRING, + svn_sqlite__column_text(stmt, 14, scratch_pool)); + } + + SVN_ERR(svn_sqlite__reset(stmt)); + } + SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_NODE)); for (i = children->nelts; i--; ) { const char *name = APR_ARRAY_IDX(children, i, const char *); - SVN_ERR(svn_sqlite__bindf(stmt, "isisnnrsns", + svn_pool_clear(iterpool); + + SVN_ERR(svn_sqlite__bindf(stmt, "isisnnrsnsnnnnnnnnnnsn", wc_id, svn_relpath_join(local_relpath, name, - scratch_pool), + iterpool), op_depth, local_relpath, revision, "incomplete", /* 8, presence */ - "unknown")); /* 10, kind */ - + "unknown", /* 10, kind */ + /* 21, moved_to */ + apr_hash_get(moved_to_relpaths, name, + APR_HASH_KEY_STRING))); if (repos_id != INVALID_REPOS_ID) { SVN_ERR(svn_sqlite__bind_int64(stmt, 5, repos_id)); SVN_ERR(svn_sqlite__bind_text(stmt, 6, svn_relpath_join(repos_path, name, - scratch_pool))); + iterpool))); } SVN_ERR(svn_sqlite__insert(NULL, stmt)); } + svn_pool_destroy(iterpool); + return SVN_NO_ERROR; }
