Return-Path: X-Original-To: apmail-subversion-commits-archive@minotaur.apache.org Delivered-To: apmail-subversion-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id C420F995C for ; Thu, 15 Mar 2012 21:40:58 +0000 (UTC) Received: (qmail 21460 invoked by uid 500); 15 Mar 2012 21:40:58 -0000 Delivered-To: apmail-subversion-commits-archive@subversion.apache.org Received: (qmail 21437 invoked by uid 500); 15 Mar 2012 21:40:58 -0000 Mailing-List: contact commits-help@subversion.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@subversion.apache.org Delivered-To: mailing list commits@subversion.apache.org Received: (qmail 21429 invoked by uid 99); 15 Mar 2012 21:40:58 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 15 Mar 2012 21:40:58 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 15 Mar 2012 21:40:43 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 0EB8F23889E1; Thu, 15 Mar 2012 21:40:21 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1301216 [2/4] - in /subversion/branches/inheritable-props: ./ notes/ notes/directory-index/ subversion/bindings/javahl/ subversion/bindings/swig/ruby/test/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversio... Date: Thu, 15 Mar 2012 21:40:17 -0000 To: commits@subversion.apache.org From: pburba@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120315214021.0EB8F23889E1@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Modified: subversion/branches/inheritable-props/subversion/libsvn_wc/wc-queries.sql URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_wc/wc-queries.sql?rev=1301216&r1=1301215&r2=1301216&view=diff ============================================================================== --- subversion/branches/inheritable-props/subversion/libsvn_wc/wc-queries.sql (original) +++ subversion/branches/inheritable-props/subversion/libsvn_wc/wc-queries.sql Thu Mar 15 21:40:15 2012 @@ -51,8 +51,7 @@ ORDER BY op_depth DESC -- STMT_SELECT_BASE_NODE SELECT repos_id, repos_path, presence, kind, revision, checksum, translated_size, changed_revision, changed_date, changed_author, depth, - symlink_target, last_mod_time, properties, file_external IS NOT NULL, - moved_to + symlink_target, last_mod_time, properties, file_external IS NOT NULL FROM nodes WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0 @@ -60,7 +59,6 @@ WHERE wc_id = ?1 AND local_relpath = ?2 SELECT nodes.repos_id, nodes.repos_path, presence, kind, revision, checksum, translated_size, changed_revision, changed_date, changed_author, depth, symlink_target, last_mod_time, properties, file_external IS NOT NULL, - moved_to, /* All the columns until now must match those returned by STMT_SELECT_BASE_NODE. The implementation of svn_wc__db_base_get_info() assumes that these columns are followed by the lock information) */ @@ -283,13 +281,18 @@ WHERE wc_id = ?1 AND local_relpath = ?2 SELECT dav_cache FROM nodes WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0 +/* ### FIXME. modes_move.moved_to IS NOT NULL works when there is + only one move but we need something else when there are several. */ -- STMT_SELECT_DELETION_INFO -SELECT nodes_base.presence, nodes_work.presence, nodes_base.moved_to, +SELECT nodes_base.presence, nodes_work.presence, nodes_move.moved_to, nodes_work.op_depth FROM nodes AS nodes_work +LEFT OUTER JOIN nodes nodes_move ON nodes_move.wc_id = nodes_work.wc_id + AND nodes_move.local_relpath = nodes_work.local_relpath + AND nodes_move.moved_to IS NOT NULL LEFT OUTER JOIN nodes nodes_base ON nodes_base.wc_id = nodes_work.wc_id - AND nodes_base.local_relpath = nodes_work.local_relpath - AND nodes_base.op_depth = 0 + AND nodes_base.local_relpath = nodes_work.local_relpath + AND nodes_base.op_depth = 0 WHERE nodes_work.wc_id = ?1 AND nodes_work.local_relpath = ?2 AND nodes_work.op_depth = (SELECT MAX(op_depth) FROM nodes WHERE wc_id = ?1 AND local_relpath = ?2 @@ -884,28 +887,32 @@ INSERT OR REPLACE INTO nodes ( wc_id, local_relpath, op_depth, parent_relpath, repos_id, repos_path, revision, presence, depth, moved_here, kind, changed_revision, changed_date, changed_author, checksum, properties, translated_size, - last_mod_time, symlink_target ) -SELECT wc_id, ?3 /*local_relpath*/, ?4 /*op_depth*/, ?5 /*parent_relpath*/, - repos_id, repos_path, revision, ?6 /*presence*/, depth, ?7/*moved_here*/, - kind, changed_revision, changed_date, changed_author, checksum, properties, - translated_size, last_mod_time, symlink_target -FROM nodes -WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0 + last_mod_time, symlink_target, moved_to ) +SELECT src.wc_id, ?3 /*local_relpath*/, ?4 /*op_depth*/, ?5 /*parent_relpath*/, + src.repos_id, src.repos_path, src.revision, ?6 /*presence*/, src.depth, + ?7/*moved_here*/, src.kind, src.changed_revision, src.changed_date, + src.changed_author, src.checksum, src.properties, src.translated_size, + src.last_mod_time, src.symlink_target, dst.moved_to +FROM nodes AS src +LEFT OUTER JOIN nodes_current dst ON dst.wc_id = src.wc_id + AND dst.local_relpath = ?3 AND dst.op_depth = ?4 +WHERE src.wc_id = ?1 AND src.local_relpath = ?2 AND src.op_depth = 0 -- STMT_INSERT_WORKING_NODE_COPY_FROM_WORKING INSERT OR REPLACE INTO nodes ( - wc_id, local_relpath, op_depth, parent_relpath, repos_id, repos_path, - revision, presence, depth, moved_here, kind, changed_revision, changed_date, - changed_author, checksum, properties, translated_size, last_mod_time, - symlink_target ) -SELECT wc_id, ?3 /*local_relpath*/, ?4 /*op_depth*/, ?5 /*parent_relpath*/, - repos_id, repos_path, revision, ?6 /*presence*/, depth, ?7 /*moved_here*/, - kind, changed_revision, changed_date, changed_author, checksum, properties, - translated_size, last_mod_time, symlink_target -FROM nodes -WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth > 0 -ORDER BY op_depth DESC -LIMIT 1 + wc_id, local_relpath, op_depth, parent_relpath, repos_id, + repos_path, revision, presence, depth, moved_here, kind, changed_revision, + changed_date, changed_author, checksum, properties, translated_size, + last_mod_time, symlink_target, moved_to ) +SELECT src.wc_id, ?3 /*local_relpath*/, ?4 /*op_depth*/, ?5 /*parent_relpath*/, + src.repos_id, src.repos_path, src.revision, ?6 /*presence*/, src.depth, + ?7 /*moved_here*/, src.kind, src.changed_revision, src.changed_date, + src.changed_author, src.checksum, src.properties, src.translated_size, + src.last_mod_time, src.symlink_target, dst.moved_to +FROM nodes_current AS src +LEFT OUTER JOIN nodes_current dst ON dst.wc_id = src.wc_id + AND dst.local_relpath = ?3 AND dst.op_depth = ?4 +WHERE src.wc_id = ?1 AND src.local_relpath = ?2 AND src.op_depth > 0 -- STMT_INSERT_WORKING_NODE_COPY_FROM_DEPTH INSERT OR REPLACE INTO nodes ( @@ -1373,34 +1380,48 @@ WHERE wc_id = ?1 AND presence='normal' AND file_external IS NULL +/* ### FIXME: op-depth? What about multiple moves? */ -- STMT_SELECT_MOVED_FROM_RELPATH -SELECT local_relpath FROM nodes -WHERE wc_id = ?1 AND moved_to = ?2 AND op_depth = 0 +SELECT local_relpath, op_depth FROM nodes +WHERE wc_id = ?1 AND moved_to = ?2 AND op_depth > 0 -- STMT_UPDATE_MOVED_TO_RELPATH -UPDATE nodes SET moved_to = ?3 -WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0 +UPDATE nodes SET moved_to = ?4 +WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3 +/* ### FIXME: op-depth? What about multiple moves? */ -- STMT_CLEAR_MOVED_TO_RELPATH UPDATE nodes SET moved_to = NULL -WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0 - --- STMT_CLEAR_MOVED_TO_RELPATH_RECURSIVE -UPDATE nodes SET moved_to = NULL -WHERE wc_id = ?1 - AND (?2 = '' - OR local_relpath = ?2 - OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2)) - AND op_depth = 0 +WHERE wc_id = ?1 AND local_relpath = ?2 /* This statement returns pairs of move-roots below the path ?2 in WC_ID ?1. * Each row returns a moved-here path (always a child of ?2) in the first * column, and its matching moved-away (deleted) path in the second column. */ -- STMT_SELECT_MOVED_HERE_CHILDREN SELECT moved_to, local_relpath FROM nodes -WHERE wc_id = ?1 AND op_depth = 0 +WHERE wc_id = ?1 AND op_depth > 0 AND IS_STRICT_DESCENDANT_OF(moved_to, ?2) +/* This statement returns pairs of paths that define a move where the + destination of the move is within the subtree rooted at path ?2 in + WC_ID ?1. */ +-- STMT_SELECT_MOVED_PAIR +SELECT local_relpath, moved_to, op_depth FROM nodes_current +WHERE wc_id = ?1 + AND (IS_STRICT_DESCENDANT_OF(moved_to, ?2) + OR (IS_STRICT_DESCENDANT_OF(local_relpath, ?2) + AND moved_to IS NOT NULL)) + +/* This statement returns pairs of move-roots below the path ?2 in WC_ID ?1, + * where the source of the move is within the subtree rooted at path ?2, and + * the destination of the move is outside the subtree rooted at path ?2. */ +-- STMT_SELECT_MOVED_PAIR2 +SELECT local_relpath, moved_to FROM nodes_current +WHERE wc_id = ?1 + AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2) + AND moved_to IS NOT NULL + AND NOT IS_STRICT_DESCENDANT_OF(moved_to, ?2) + /* ------------------------------------------------------------------------- */ /* Queries for verification. */ Modified: subversion/branches/inheritable-props/subversion/libsvn_wc/wc_db.c URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_wc/wc_db.c?rev=1301216&r1=1301215&r2=1301216&view=diff ============================================================================== --- subversion/branches/inheritable-props/subversion/libsvn_wc/wc_db.c (original) +++ subversion/branches/inheritable-props/subversion/libsvn_wc/wc_db.c Thu Mar 15 21:40:15 2012 @@ -368,6 +368,7 @@ scan_addition(svn_wc__db_status_t *statu svn_revnum_t *original_revision, const char **moved_from_relpath, const char **moved_from_op_root_relpath, + apr_int64_t *moved_from_op_depth, svn_wc__db_wcroot_t *wcroot, const char *local_relpath, apr_pool_t *result_pool, @@ -781,7 +782,6 @@ insert_base_node(void *baton, svn_sqlite__stmt_t *stmt; svn_filesize_t recorded_size = SVN_INVALID_FILESIZE; apr_int64_t recorded_mod_time; - const char *moved_to_relpath = NULL; svn_boolean_t have_row; /* The directory at the WCROOT has a NULL parent_relpath. Otherwise, @@ -813,15 +813,13 @@ insert_base_node(void *baton, recorded_size = get_recorded_size(stmt, 6); recorded_mod_time = svn_sqlite__column_int64(stmt, 12); } - /* Always preserve moved-to info. */ - moved_to_relpath = svn_sqlite__column_text(stmt, 15, scratch_pool); } SVN_ERR(svn_sqlite__reset(stmt)); SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_INSERT_NODE)); SVN_ERR(svn_sqlite__bindf(stmt, "isisisr" "tstr" /* 8 - 11 */ - "isnnnnnsss", /* 12 - 21 */ + "isnnnnns", /* 12 - 19 */ wcroot->wc_id, /* 1 */ local_relpath, /* 2 */ (apr_int64_t)0, /* op_depth is 0 for base */ @@ -837,9 +835,7 @@ insert_base_node(void *baton, pibb->changed_date, /* 12 */ pibb->changed_author, /* 13 */ (pibb->kind == svn_kind_symlink) ? - pibb->target : NULL, /* 19 */ - NULL /* 20 */, - moved_to_relpath /* 21 */)); + pibb->target : NULL)); /* 19 */ if (pibb->kind == svn_kind_file) { if (!pibb->checksum @@ -971,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) + { + 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__get_statement(&stmt, sdb, + STMT_SELECT_WORKING_NODE)); + 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; } @@ -2039,7 +2069,7 @@ base_get_info(svn_wc__db_status_t *statu SVN_ERR_ASSERT(!repos_relpath || *repos_relpath); if (lock) { - *lock = lock_from_columns(stmt, 16, 17, 18, 19, result_pool); + *lock = lock_from_columns(stmt, 15, 16, 17, 18, result_pool); } if (changed_rev) { @@ -3421,7 +3451,7 @@ get_info_for_copy(apr_int64_t *copyfrom_ SVN_ERR(scan_addition(NULL, &op_root_relpath, NULL, NULL, /* repos_* */ copyfrom_relpath, copyfrom_id, copyfrom_rev, - NULL, NULL, wcroot, local_relpath, + NULL, NULL, NULL, wcroot, local_relpath, scratch_pool, scratch_pool)); if (*copyfrom_relpath) { @@ -3450,7 +3480,7 @@ get_info_for_copy(apr_int64_t *copyfrom_ SVN_ERR(scan_addition(NULL, &op_root_relpath, NULL, NULL, /* repos_* */ copyfrom_relpath, copyfrom_id, copyfrom_rev, - NULL, NULL, wcroot, parent_del_relpath, + NULL, NULL, NULL, wcroot, parent_del_relpath, scratch_pool, scratch_pool)); *copyfrom_relpath = svn_relpath_join(*copyfrom_relpath, @@ -3626,13 +3656,14 @@ db_op_copy(svn_wc__db_wcroot_t *src_wcro SVN_ERR(svn_sqlite__get_statement(&stmt, src_wcroot->sdb, STMT_INSERT_WORKING_NODE_COPY_FROM_BASE)); - SVN_ERR(svn_sqlite__bindf(stmt, "issisti", + SVN_ERR(svn_sqlite__bindf(stmt, "issist", src_wcroot->wc_id, src_relpath, dst_relpath, dst_op_depth, dst_parent_relpath, - presence_map, dst_presence, - (apr_int64_t)(is_move ? 1 : 0))); + presence_map, dst_presence)); + if (is_move) + SVN_ERR(svn_sqlite__bind_int64(stmt, 7, 1)); SVN_ERR(svn_sqlite__step_done(stmt)); @@ -5373,14 +5404,9 @@ op_revert_txn(void *baton, SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath)); SVN_ERR(svn_sqlite__step_done(stmt)); + /* If this node was moved-here, clear moved-to at the move source. */ if (moved_here) SVN_ERR(clear_moved_to(local_relpath, wcroot, scratch_pool)); - - /* Clear the moved-to path of the BASE node. */ - SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, - STMT_CLEAR_MOVED_TO_RELPATH)); - SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath)); - SVN_ERR(svn_sqlite__step_done(stmt)); } SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, @@ -5512,12 +5538,6 @@ op_revert_recursive_txn(void *baton, && moved_here) SVN_ERR(clear_moved_to(local_relpath, wcroot, scratch_pool)); - /* Clear any moved-to paths of potentially 'moved-away' nodes. */ - SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, - STMT_CLEAR_MOVED_TO_RELPATH_RECURSIVE)); - SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath)); - SVN_ERR(svn_sqlite__step_done(stmt)); - return SVN_NO_ERROR; } @@ -6274,6 +6294,7 @@ info_below_working(svn_boolean_t *have_b static svn_error_t * delete_update_movedto(svn_wc__db_wcroot_t *wcroot, const char *child_moved_from_relpath, + apr_int64_t op_depth, const char *new_moved_to_relpath, apr_pool_t *scratch_pool) { @@ -6282,9 +6303,10 @@ delete_update_movedto(svn_wc__db_wcroot_ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_UPDATE_MOVED_TO_RELPATH)); - SVN_ERR(svn_sqlite__bindf(stmt, "iss", + SVN_ERR(svn_sqlite__bindf(stmt, "isis", wcroot->wc_id, child_moved_from_relpath, + op_depth, new_moved_to_relpath)); SVN_ERR(svn_sqlite__step_done(stmt)); @@ -6297,6 +6319,37 @@ struct op_delete_baton_t { const char *moved_to_relpath; /* NULL if delete is not part of a move */ }; +/* This structure is used while rewriting move information for nodes. + * + * The most simple case of rewriting move information happens when + * a moved-away subtree is moved again: mv A B; mv B C + * The second move requires rewriting moved-to info at or within A. + * + * Another example is a move of a subtree which had nodes moved into it: + * mv A B/F; mv B G + * This requires rewriting such that A/F is marked has having moved to G/F. + * + * Another case is where a node becomes a nested moved node. + * A nested move happens when a subtree child is moved before or after + * the subtree itself is moved. For example: + * mv A/F A/G; mv A B + * In this case, the move A/F -> A/G is rewritten to B/F -> B/G. + * Note that the following sequence results in the same DB state: + * mv A B; mv B/F B/G + * We do not care about the order the moves were performed in. + * For details, see http://wiki.apache.org/subversion/MultiLayerMoves + */ +struct moved_node_t { + /* The source of the move. */ + const char *local_relpath; + + /* The move destination. */ + const char *moved_to_relpath; + + /* The op-depth of the deleted node at the source of the move. */ + apr_int64_t op_depth; +}; + static svn_error_t * delete_node(void *baton, svn_wc__db_wcroot_t *wcroot, @@ -6311,6 +6364,7 @@ delete_node(void *baton, apr_int64_t select_depth; /* Depth of what is to be deleted */ svn_boolean_t refetch_depth = FALSE; svn_kind_t kind; + apr_array_header_t *moved_nodes = NULL; SVN_ERR(read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -6345,116 +6399,129 @@ delete_node(void *baton, if (b->moved_to_relpath) { - const char *moved_from_relpath = NULL; - - /* ### call scan_addition_txn() directly? */ + const char *moved_from_op_root_relpath; + struct moved_node_t *moved_node + = apr_palloc(scratch_pool, sizeof(struct moved_node_t)); + + /* The node is being moved-away. + * Figure out if the node was moved-here before, or whether this + * is the first time the node is moved. */ if (status == svn_wc__db_status_added) - SVN_ERR(scan_addition(&status, NULL, NULL, NULL, - NULL, NULL, NULL, - &moved_from_relpath, NULL, + SVN_ERR(scan_addition(&status, NULL, NULL, NULL, NULL, NULL, NULL, + &moved_node->local_relpath, + &moved_from_op_root_relpath, + &moved_node->op_depth, wcroot, local_relpath, scratch_pool, scratch_pool)); - if (status == svn_wc__db_status_moved_here) + if (status != svn_wc__db_status_moved_here || + strcmp(moved_from_op_root_relpath, moved_node->local_relpath) != 0) { - /* The node has already been moved, possibly along with a parent, - * and is being moved again. Update the existing moved_to path - * in the BASE node. */ - SVN_ERR(delete_update_movedto(wcroot, moved_from_relpath, - b->moved_to_relpath, scratch_pool)); - } + /* The node is becoming a move-root for the first time, + * possibly because of a nested move operation. */ + moved_node->local_relpath = local_relpath; + moved_node->op_depth = b->delete_depth; + } + moved_node->moved_to_relpath = b->moved_to_relpath; + + /* ### Use array of struct rather than pointers? */ + moved_nodes = apr_array_make(scratch_pool, 1, + sizeof(struct moved_node_t *)); + APR_ARRAY_PUSH(moved_nodes, const struct moved_node_t *) = moved_node; /* If a subtree is being moved-away, we need to update moved-to - * information in BASE for all children that were moved into this - * subtree. */ + * information for all children that were moved into, or within, + * this subtree. */ if (kind == svn_kind_dir) { - apr_pool_t *iterpool; - SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, - STMT_SELECT_MOVED_HERE_CHILDREN)); + STMT_SELECT_MOVED_PAIR)); SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath)); - SVN_ERR(svn_sqlite__step(&have_row, stmt)); - iterpool = svn_pool_create(scratch_pool); while (have_row) { - svn_wc__db_status_t child_status; - const char *child_moved_from_relpath = NULL; - const char *child_delete_op_root_relpath = NULL; - const char *moved_here_child_relpath = - svn_sqlite__column_text(stmt, 0, scratch_pool); - svn_error_t *err; - - svn_pool_clear(iterpool); - - /* The moved-here-children query returns info based on the - * delete-half of the move. Check if that the copied-half of - * the move matches this information. */ - err = read_info(&child_status, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, - wcroot, moved_here_child_relpath, - iterpool, iterpool); - if (err) - return svn_error_compose_create(err, svn_sqlite__reset(stmt)); + const char *move_relpath + = svn_sqlite__column_text(stmt, 0, NULL); + const char *move_subtree_relpath + = svn_relpath_skip_ancestor(local_relpath, move_relpath); + const char *child_moved_to + = svn_sqlite__column_text(stmt, 1, NULL); + const char *child_moved_to_subtree_relpath + = svn_relpath_skip_ancestor(local_relpath, child_moved_to); + apr_int64_t child_op_depth = svn_sqlite__column_int64(stmt, 2); + + moved_node = apr_palloc(scratch_pool, + sizeof(struct moved_node_t)); + if (move_subtree_relpath) + moved_node->local_relpath + = svn_relpath_join(b->moved_to_relpath, + move_subtree_relpath, scratch_pool); + else + moved_node->local_relpath + = apr_pstrdup(scratch_pool, move_relpath); - if (child_status == svn_wc__db_status_added) - { - err = scan_addition(&child_status, NULL, NULL, NULL, - NULL, NULL, NULL, - &child_moved_from_relpath, - &child_delete_op_root_relpath, - wcroot, moved_here_child_relpath, - iterpool, iterpool); - if (err) - return svn_error_compose_create(err, - svn_sqlite__reset(stmt)); - } -#ifdef SVN_DEBUG - /* This catches incorrectly recorded moves. - * It is possible to hit this during normal operation - * if a move was interrupted mid-way so only perform - * this check in debug mode. */ - SVN_ERR_ASSERT(child_moved_from_relpath && - !strcmp(child_moved_from_relpath, - svn_sqlite__column_text(stmt, 1, NULL))); -#endif - if (child_status == svn_wc__db_status_moved_here) - { - const char *child_subtree_relpath; - const char *new_moved_to_relpath; + if (child_moved_to_subtree_relpath) + moved_node->moved_to_relpath + = svn_relpath_join(b->moved_to_relpath, + child_moved_to_subtree_relpath, + scratch_pool); + else + moved_node->moved_to_relpath + = apr_pstrdup(scratch_pool, child_moved_to); - /* Compute the new moved-to path for this child... */ - child_subtree_relpath = - svn_relpath_skip_ancestor(local_relpath, - moved_here_child_relpath); - SVN_ERR_ASSERT(child_subtree_relpath); - - new_moved_to_relpath = - svn_relpath_join(b->moved_to_relpath, - child_subtree_relpath, iterpool); - /* ... and update the BASE moved-to record. */ - err = delete_update_movedto(wcroot, child_moved_from_relpath, - new_moved_to_relpath, - scratch_pool); + if (child_op_depth > b->delete_depth + && svn_relpath_skip_ancestor(local_relpath, + moved_node->local_relpath)) + moved_node->op_depth = b->delete_depth; + else + moved_node->op_depth = child_op_depth; - if (err) - return svn_error_trace(svn_error_compose_create( - err, - svn_sqlite__reset(stmt))); - } + APR_ARRAY_PUSH(moved_nodes, const struct moved_node_t *) + = moved_node; SVN_ERR(svn_sqlite__step(&have_row, stmt)); } - svn_pool_destroy(iterpool); - SVN_ERR(svn_sqlite__reset(stmt)); } } + /* Find children that were moved out of the subtree rooted at this node. + * We'll need to update their op-depth columns because their deletion + * is now implied by the deletion of their parent (i.e. this node). */ + if (kind == svn_kind_dir && !b->moved_to_relpath) + { + apr_pool_t *iterpool; + + SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, + STMT_SELECT_MOVED_PAIR2)); + SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath)); + + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + + iterpool = svn_pool_create(scratch_pool); + while (have_row) + { + struct moved_node_t *moved_node + = apr_palloc(scratch_pool, sizeof(struct moved_node_t)); + + moved_node->local_relpath + = svn_sqlite__column_text(stmt, 0, scratch_pool); + moved_node->moved_to_relpath + = svn_sqlite__column_text(stmt, 1, scratch_pool); + moved_node->op_depth = b->delete_depth; + + if (!moved_nodes) + moved_nodes = apr_array_make(scratch_pool, 1, + sizeof(struct moved_node_t *)); + APR_ARRAY_PUSH(moved_nodes, const struct moved_node_t *) = moved_node; + + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + } + svn_pool_destroy(iterpool); + SVN_ERR(svn_sqlite__reset(stmt)); + } + if (op_root) { svn_boolean_t below_base; @@ -6487,7 +6554,7 @@ delete_node(void *baton, SVN_ERR(scan_addition(&status, NULL, NULL, NULL, NULL, NULL, NULL, &moved_from_relpath, - &moved_from_op_root_relpath, + &moved_from_op_root_relpath, NULL, wcroot, local_relpath, scratch_pool, scratch_pool)); if (status == svn_wc__db_status_moved_here && @@ -6547,12 +6614,6 @@ delete_node(void *baton, if (add_work) { /* Delete the node at LOCAL_RELPATH, and possibly mark it as moved. */ - if (b->moved_to_relpath) - { - /* Record moved-to relpath in BASE. */ - SVN_ERR(delete_update_movedto(wcroot, local_relpath, - b->moved_to_relpath, scratch_pool)); - } /* Delete the node and possible descendants. */ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, @@ -6563,6 +6624,23 @@ delete_node(void *baton, SVN_ERR(svn_sqlite__step_done(stmt)); } + if (moved_nodes) + { + int i; + + for (i = 0; i < moved_nodes->nelts; ++i) + { + const struct moved_node_t *moved_node + = APR_ARRAY_IDX(moved_nodes, i, void *); + + SVN_ERR(delete_update_movedto(wcroot, + moved_node->local_relpath, + moved_node->op_depth, + moved_node->moved_to_relpath, + scratch_pool)); + } + } + return SVN_NO_ERROR; } @@ -7356,13 +7434,16 @@ read_children_info(void *baton, /* Assume working copy is all one repos_id so that a single cached value is sufficient. */ if (repos_id != last_repos_id) - return svn_error_createf( + { + err= svn_error_createf( SVN_ERR_WC_DB_ERROR, NULL, _("The node '%s' comes from unexpected repository " "'%s', expected '%s'; if this node is a file " "external using the correct URL in the external " "definition can fix the problem, see issue #4087"), child_relpath, repos_root_url, last_repos_root_url); + return svn_error_compose_create(err, svn_sqlite__reset(stmt)); + } child->repos_root_url = repos_root_url; child->repos_uuid = repos_uuid; } @@ -7419,29 +7500,29 @@ read_children_info(void *baton, if (op_depth == 0) { - const char *moved_to_relpath; - child_item->info.have_base = TRUE; /* Get the lock info, available only at op_depth 0. */ child_item->info.lock = lock_from_columns(stmt, 15, 16, 17, 18, result_pool); - /* Moved-to is only stored at op_depth 0. */ - moved_to_relpath = svn_sqlite__column_text(stmt, 21, NULL); - if (moved_to_relpath) - child_item->info.moved_to_abspath = - svn_dirent_join(wcroot->abspath, moved_to_relpath, result_pool); - /* FILE_EXTERNAL flag only on op_depth 0. */ child_item->info.file_external = svn_sqlite__column_boolean(stmt, 22); } else { + const char *moved_to_relpath; + child_item->nr_layers++; child_item->info.have_more_work = (child_item->nr_layers > 1); + /* Moved-to can only exist at op_depth > 0. */ + moved_to_relpath = svn_sqlite__column_text(stmt, 21, NULL); + if (moved_to_relpath) + child_item->info.moved_to_abspath = + svn_dirent_join(wcroot->abspath, moved_to_relpath, result_pool); + /* Moved-here can only exist at op_depth > 0. */ child_item->info.moved_here = svn_sqlite__column_boolean(stmt, 20); } @@ -7848,7 +7929,8 @@ read_url_txn(void *baton, if (status == svn_wc__db_status_added) { SVN_ERR(scan_addition(NULL, NULL, &repos_relpath, &repos_id, NULL, - NULL, NULL, NULL, NULL, wcroot, local_relpath, + NULL, NULL, NULL, NULL, NULL, + wcroot, local_relpath, scratch_pool, scratch_pool)); } else if (status == svn_wc__db_status_deleted) @@ -7881,7 +7963,7 @@ read_url_txn(void *baton, scratch_pool); SVN_ERR(scan_addition(NULL, NULL, &repos_relpath, &repos_id, - NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, wcroot, work_relpath, scratch_pool, scratch_pool)); @@ -8630,7 +8712,7 @@ svn_wc__db_global_relocate(svn_wc__db_t if (status == svn_wc__db_status_added) { SVN_ERR(scan_addition(NULL, NULL, NULL, &rb.old_repos_id, - NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, wcroot, local_dir_relpath, scratch_pool, scratch_pool)); } @@ -9564,6 +9646,7 @@ get_moved_from_info(svn_wc__db_status_t const char **moved_from_relpath, const char **moved_from_op_root_relpath, const char *moved_to_op_root_relpath, + apr_int64_t *op_depth, svn_wc__db_wcroot_t *wcroot, const char *local_relpath, apr_pool_t *result_pool, @@ -9599,6 +9682,9 @@ get_moved_from_info(svn_wc__db_status_t if (status) *status = svn_wc__db_status_moved_here; + if (op_depth) + *op_depth = svn_sqlite__column_int64(stmt, 1); + if (moved_from_relpath || moved_from_op_root_relpath) { const char *db_delete_op_root_relpath; @@ -9660,6 +9746,7 @@ struct scan_addition_baton_t svn_revnum_t *original_revision; const char **moved_from_relpath; const char **moved_from_op_root_relpath; + apr_int64_t *moved_from_op_depth; apr_pool_t *result_pool; }; @@ -9689,6 +9776,8 @@ scan_addition_txn(void *baton, *sab->moved_from_relpath = NULL; if (sab->moved_from_op_root_relpath) *sab->moved_from_op_root_relpath = NULL; + if (sab->moved_from_op_depth) + *sab->moved_from_op_depth = 0; { svn_sqlite__stmt_t *stmt; @@ -9819,8 +9908,9 @@ scan_addition_txn(void *baton, SVN_ERR(get_moved_from_info(sab->status, sab->moved_from_relpath, sab->moved_from_op_root_relpath, - op_root_relpath, wcroot, - local_relpath, + op_root_relpath, + sab->moved_from_op_depth, + wcroot, local_relpath, sab->result_pool, scratch_pool)); else if (sab->status) @@ -9941,6 +10031,7 @@ scan_addition(svn_wc__db_status_t *statu svn_revnum_t *original_revision, const char **moved_from_relpath, const char **moved_from_op_root_relpath, + apr_int64_t *moved_from_op_depth, svn_wc__db_wcroot_t *wcroot, const char *local_relpath, apr_pool_t *result_pool, @@ -9957,6 +10048,7 @@ scan_addition(svn_wc__db_status_t *statu sab.original_revision = original_revision; sab.moved_from_relpath = moved_from_relpath; sab.moved_from_op_root_relpath = moved_from_op_root_relpath; + sab.moved_from_op_depth = moved_from_op_depth; sab.result_pool = result_pool; return svn_error_trace(svn_wc__db_with_txn(wcroot, local_relpath, @@ -10003,8 +10095,8 @@ svn_wc__db_scan_addition(svn_wc__db_stat SVN_ERR(scan_addition(status, &op_root_relpath, repos_relpath, repos_id_p, original_repos_relpath, original_repos_id_p, original_revision, &moved_from_relpath, - &moved_from_op_root_relpath, wcroot, local_relpath, - result_pool, scratch_pool)); + &moved_from_op_root_relpath, NULL, + wcroot, local_relpath, result_pool, scratch_pool)); if (op_root_abspath) *op_root_abspath = svn_dirent_join(wcroot->abspath, op_root_relpath, Modified: subversion/branches/inheritable-props/subversion/mod_dav_svn/version.c URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/mod_dav_svn/version.c?rev=1301216&r1=1301215&r2=1301216&view=diff ============================================================================== --- subversion/branches/inheritable-props/subversion/mod_dav_svn/version.c (original) +++ subversion/branches/inheritable-props/subversion/mod_dav_svn/version.c Thu Mar 15 21:40:15 2012 @@ -1382,6 +1382,15 @@ merge(dav_resource *target, SVN_DAV_ERROR_NAMESPACE, SVN_DAV_ERROR_TAG); } + if (! source->exists) + { + return dav_svn__new_error_tag(pool, HTTP_METHOD_NOT_ALLOWED, + SVN_ERR_INCORRECT_PARAMS, + "MERGE activity or transaction resource " + "does not exist.", + SVN_DAV_ERROR_NAMESPACE, + SVN_DAV_ERROR_TAG); + } /* Before attempting the final commit, we need to push any incoming lock-tokens into the filesystem's access_t. Normally they come Modified: subversion/branches/inheritable-props/subversion/svn/log-cmd.c URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/svn/log-cmd.c?rev=1301216&r1=1301215&r2=1301216&view=diff ============================================================================== --- subversion/branches/inheritable-props/subversion/svn/log-cmd.c (original) +++ subversion/branches/inheritable-props/subversion/svn/log-cmd.c Thu Mar 15 21:40:15 2012 @@ -423,18 +423,23 @@ log_entry_receiver_xml(void *baton, if (log_entry->changed_paths2) { - apr_hash_index_t *hi; + apr_array_header_t *sorted_paths; + int i; /* */ svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "paths", NULL); - for (hi = apr_hash_first(pool, log_entry->changed_paths2); - hi != NULL; - hi = apr_hash_next(hi)) + /* Get an array of sorted hash keys. */ + sorted_paths = svn_sort__hash(log_entry->changed_paths2, + svn_sort_compare_items_as_paths, pool); + + for (i = 0; i < sorted_paths->nelts; i++) { - const char *path = svn__apr_hash_index_key(hi); - svn_log_changed_path2_t *log_item = svn__apr_hash_index_val(hi); + svn_sort__item_t *item = &(APR_ARRAY_IDX(sorted_paths, i, + svn_sort__item_t)); + const char *path = item->key; + svn_log_changed_path2_t *log_item = item->value; char action[2]; action[0] = log_item->action; Modified: subversion/branches/inheritable-props/subversion/tests/cmdline/authz_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/tests/cmdline/authz_tests.py?rev=1301216&r1=1301215&r2=1301216&view=diff ============================================================================== --- subversion/branches/inheritable-props/subversion/tests/cmdline/authz_tests.py (original) +++ subversion/branches/inheritable-props/subversion/tests/cmdline/authz_tests.py Thu Mar 15 21:40:15 2012 @@ -1290,7 +1290,8 @@ def wc_commit_error_handling(sbox): # Allow the informative error for dav and the ra_svn specific one that is # returned on editor->edit_close(). expected_err = "(svn: E195023: Changing directory '.*Z' is forbidden)|" + \ - "(svn: E220004: Access denied)" + "(svn: E220004: Access denied)|" + \ + "(svn: E175013: Access to '.*Z' forbidden)" svntest.actions.run_and_verify_svn(None, None, expected_err, 'ci', wc_dir, '-m', '') @@ -1302,7 +1303,8 @@ def wc_commit_error_handling(sbox): # Allow the informative error for dav and the ra_svn specific one that is # returned on editor->edit_close(). expected_err = "(svn: E195023: Changing file '.*zeta' is forbidden)|" + \ - "(svn: E220004: Access denied)" + "(svn: E220004: Access denied)|" + \ + "(svn: E175013: Access to '.*zeta' forbidden)" svntest.actions.run_and_verify_svn(None, None, expected_err, 'ci', wc_dir, '-m', '') sbox.simple_revert('A/zeta') @@ -1323,7 +1325,8 @@ def wc_commit_error_handling(sbox): # Allow the informative error for dav and the ra_svn specific one that is # returned on editor->edit_close(). expected_err = "(svn: E195023: Changing file '.*lambda' is forbidden.*)|" + \ - "(svn: E220004: Access denied)" + "(svn: E220004: Access denied)|" + \ + "(svn: E175013: Access to '.*lambda' forbidden)" svntest.actions.run_and_verify_svn(None, None, expected_err, 'ci', wc_dir, '-m', '') @@ -1333,7 +1336,8 @@ def wc_commit_error_handling(sbox): # Allow the informative error for dav and the ra_svn specific one that is # returned on editor->edit_close(). expected_err = "(svn: E195023: Changing file '.*lambda' is forbidden.*)|" + \ - "(svn: E220004: Access denied)" + "(svn: E220004: Access denied)|" + \ + "(svn: E175013: Access to '.*lambda' forbidden)" svntest.actions.run_and_verify_svn(None, None, expected_err, 'ci', wc_dir, '-m', '') @@ -1343,7 +1347,8 @@ def wc_commit_error_handling(sbox): # Allow the informative error for dav and the ra_svn specific one that is # returned on editor->edit_close(). expected_err = "(svn: E195023: Changing directory '.*F' is forbidden.*)|" + \ - "(svn: E220004: Access denied)" + "(svn: E220004: Access denied)|" + \ + "(svn: E175013: Access to '.*F' forbidden)" svntest.actions.run_and_verify_svn(None, None, expected_err, 'ci', wc_dir, '-m', '') sbox.simple_revert('A/B/F') @@ -1352,7 +1357,8 @@ def wc_commit_error_handling(sbox): # Allow the informative error for dav and the ra_svn specific one that is # returned on editor->edit_close(). expected_err = "(svn: E195023: Changing file '.*mu' is forbidden.*)|" + \ - "(svn: E220004: Access denied)" + "(svn: E220004: Access denied)|" + \ + "(svn: E175013: Access to '.*mu' forbidden)" svntest.actions.run_and_verify_svn(None, None, expected_err, 'ci', wc_dir, '-m', '') Modified: subversion/branches/inheritable-props/subversion/tests/cmdline/checkout_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/tests/cmdline/checkout_tests.py?rev=1301216&r1=1301215&r2=1301216&view=diff ============================================================================== --- subversion/branches/inheritable-props/subversion/tests/cmdline/checkout_tests.py (original) +++ subversion/branches/inheritable-props/subversion/tests/cmdline/checkout_tests.py Thu Mar 15 21:40:15 2012 @@ -31,6 +31,7 @@ import sys, re, os, time, subprocess # Our testing module import svntest from svntest import wc, actions +import logging # (abbreviation) Skip = svntest.testcase.Skip_deco @@ -41,6 +42,8 @@ Issue = svntest.testcase.Issue_deco Wimp = svntest.testcase.Wimp_deco Item = wc.StateItem +logger = logging.getLogger() + #---------------------------------------------------------------------- # Helper function for testing stderr from co. # If none of the strings in STDERR list matches the regular expression @@ -50,10 +53,9 @@ def test_stderr(re_string, stderr): for line in stderr: if exp_err_re.search(line): return - if svntest.main.options.verbose: - for x in stderr: - sys.stdout.write(x) - print("Expected stderr reg-ex: '" + re_string + "'") + for x in stderr: + logger.debug(x[:-1]) + logger.info("Expected stderr reg-ex: '" + re_string + "'") raise svntest.Failure("Checkout failed but not in the expected way") #---------------------------------------------------------------------- Modified: subversion/branches/inheritable-props/subversion/tests/cmdline/depth_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/tests/cmdline/depth_tests.py?rev=1301216&r1=1301215&r2=1301216&view=diff ============================================================================== --- subversion/branches/inheritable-props/subversion/tests/cmdline/depth_tests.py (original) +++ subversion/branches/inheritable-props/subversion/tests/cmdline/depth_tests.py Thu Mar 15 21:40:15 2012 @@ -2843,7 +2843,6 @@ def update_below_depth_empty(sbox): None, None) # Test for issue #4136. -@XFail() @Issue(4136) def commit_then_immediates_update(sbox): "deep commit followed by update --depth immediates" Modified: subversion/branches/inheritable-props/subversion/tests/cmdline/merge_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/tests/cmdline/merge_tests.py?rev=1301216&r1=1301215&r2=1301216&view=diff ============================================================================== --- subversion/branches/inheritable-props/subversion/tests/cmdline/merge_tests.py (original) +++ subversion/branches/inheritable-props/subversion/tests/cmdline/merge_tests.py Thu Mar 15 21:40:15 2012 @@ -17405,6 +17405,67 @@ def svnmucc_abuse_1(sbox): svntest.main.run_svn(None, 'merge', '-c', 'r5', '^/A@r5', sbox.ospath('A_COPY')) +#---------------------------------------------------------------------- +# Test for issue #4138 'replacement in merge source not notified correctly'. +@SkipUnless(server_has_mergeinfo) +@XFail() +@Issue(4138) +def merge_source_with_replacement(sbox): + "replacement in merge source not notified correctly" + + sbox.build() + wc_dir = sbox.wc_dir + + # Some paths we'll care about. + A_path = os.path.join(sbox.wc_dir, 'A') + omega_path = os.path.join(sbox.wc_dir, 'A', 'D', 'H', 'omega') + A_COPY_path = os.path.join(sbox.wc_dir, 'A_COPY') + beta_COPY_path = os.path.join(sbox.wc_dir, 'A_COPY', 'B', 'E', 'beta') + psi_COPY_path = os.path.join(sbox.wc_dir, 'A_COPY', 'D', 'H', 'psi') + rho_COPY_path = os.path.join(sbox.wc_dir, 'A_COPY', 'D', 'G', 'rho') + omega_COPY_path = os.path.join(sbox.wc_dir, 'A_COPY', 'D', 'H', 'omega') + + # branch A@1 to A_COPY in r2, then make a few edits under A in r3-6: + wc_disk, wc_status = set_up_branch(sbox) + + # r7 Delete A, replace it with A@5, effectively reverting the change + # made to A/D/H/omega in r6: + svntest.main.run_svn(None, 'up', wc_dir) + svntest.main.run_svn(None, 'del', A_path) + svntest.main.run_svn(None, 'copy', sbox.repo_url + '/A@5', A_path) + svntest.main.run_svn(None, 'ci', '-m', + 'Replace A with older version of itself', wc_dir) + + # r8: Make an edit to A/D/H/omega: + svntest.main.file_write(omega_path, "New content for 'omega'.\n") + svntest.main.run_svn(None, 'ci', '-m', 'file edit', wc_dir) + + # Update and sync merge ^/A to A_COPY. + svntest.main.run_svn(None, 'up', wc_dir) + # This currently fails because the merge notifications make it look like + # r6 from ^/A was merged and recorded: + # + # >svn merge ^^/A A_COPY + # --- Merging r2 through r5 into 'A_COPY': + # U A_COPY\B\E\beta + # U A_COPY\D\G\rho + # U A_COPY\D\H\psi + # --- Recording mergeinfo for merge of r2 through r5 into 'A_COPY': + # U A_COPY + # --- Merging r6 through r8 into 'A_COPY': + # U A_COPY\D\H\omega + # --- Recording mergeinfo for merge of r6 through r8 into 'A_COPY': + # G A_COPY + expected_output = expected_merge_output([[2,5],[7,8]], + ['U ' + beta_COPY_path + '\n', + 'U ' + rho_COPY_path + '\n', + 'U ' + omega_COPY_path + '\n', + 'U ' + psi_COPY_path + '\n', + ' U ' + A_COPY_path + '\n', + ' G ' + A_COPY_path + '\n',]) + svntest.actions.run_and_verify_svn(None, expected_output, [], + 'merge', sbox.repo_url + '/A', + A_COPY_path) ######################################################################## # Run the tests @@ -17537,6 +17598,7 @@ test_list = [ None, unnecessary_noninheritable_mergeinfo_missing_subtrees, unnecessary_noninheritable_mergeinfo_shallow_merge, svnmucc_abuse_1, + merge_source_with_replacement, ] if __name__ == '__main__': Modified: subversion/branches/inheritable-props/subversion/tests/cmdline/svnsync_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/tests/cmdline/svnsync_tests.py?rev=1301216&r1=1301215&r2=1301216&view=diff ============================================================================== --- subversion/branches/inheritable-props/subversion/tests/cmdline/svnsync_tests.py (original) +++ subversion/branches/inheritable-props/subversion/tests/cmdline/svnsync_tests.py Thu Mar 15 21:40:15 2012 @@ -28,7 +28,7 @@ import sys, os # Test suite-specific modules -import locale, re +import locale, re, urllib # Our testing module import svntest @@ -191,14 +191,16 @@ def setup_and_sync(sbox, dump_file_conte repo_url = sbox.repo_url cwd = os.getcwd() if is_src_ra_local: - repo_url = svntest.main.file_scheme_prefix + svntest.main.pathname2url(os.path.join(cwd, sbox.repo_dir)) + repo_url = svntest.main.file_scheme_prefix + \ + urllib.pathname2url(os.path.join(cwd, sbox.repo_dir)) if subdir: repo_url = repo_url + subdir dest_repo_url = dest_sbox.repo_url if is_dest_ra_local: - dest_repo_url = svntest.main.file_scheme_prefix + svntest.main.pathname2url(os.path.join(cwd, dest_sbox.repo_dir)) + dest_repo_url = svntest.main.file_scheme_prefix + \ + urllib.pathname2url(os.path.join(cwd, dest_sbox.repo_dir)) run_init(dest_repo_url, repo_url, source_prop_encoding) run_sync(dest_repo_url, repo_url, @@ -1029,7 +1031,7 @@ def copy_delete_unreadable_child(sbox): % (authz, authz)) dest_url = svntest.main.file_scheme_prefix \ - + svntest.main.pathname2url(os.path.abspath(dest_sbox.repo_dir)) + + urllib.pathname2url(os.path.abspath(dest_sbox.repo_dir)) run_init(dest_url, sbox.repo_url) run_sync(dest_url) Modified: subversion/branches/inheritable-props/subversion/tests/cmdline/svntest/actions.py URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/tests/cmdline/svntest/actions.py?rev=1301216&r1=1301215&r2=1301216&view=diff ============================================================================== --- subversion/branches/inheritable-props/subversion/tests/cmdline/svntest/actions.py (original) +++ subversion/branches/inheritable-props/subversion/tests/cmdline/svntest/actions.py Thu Mar 15 21:40:15 2012 @@ -24,14 +24,31 @@ ###################################################################### import os, shutil, re, sys, errno -import difflib, pprint +import difflib, pprint, logging import xml.parsers.expat from xml.dom.minidom import parseString +if sys.version_info[0] >= 3: + # Python >=3.0 + from io import StringIO +else: + # Python <3.0 + from cStringIO import StringIO import svntest from svntest import main, verify, tree, wc from svntest import Failure +logger = logging.getLogger() + +def _log_tree_state(msg, actual, subtree=""): + if subtree: + subtree += os.sep + o = StringIO() + o.write(msg + '\n') + tree.dump_tree_script(actual, subtree, stream=o) + logger.warn(o.getvalue()) + o.close() + def no_sleep_for_timestamps(): os.environ['SVN_I_LOVE_CORRUPTED_WORKING_COPIES_SO_DISABLE_SLEEP_FOR_TIMESTAMPS'] = 'yes' @@ -84,9 +101,9 @@ def setup_pristine_greek_repository(): lastline = output.pop().strip() match = re.search("(Committed|Imported) revision [0-9]+.", lastline) if not match: - print("ERROR: import did not succeed, while creating greek repos.") - print("The final line from 'svn import' was:") - print(lastline) + logger.error("import did not succeed, while creating greek repos.") + logger.error("The final line from 'svn import' was:") + logger.error(lastline) sys.exit(1) output_tree = wc.State.from_commit(output) @@ -117,7 +134,7 @@ def guarantee_empty_repository(path): nothing.""" if path == main.pristine_greek_repos_dir: - print("ERROR: attempt to overwrite the pristine repos! Aborting.") + logger.error("attempt to overwrite the pristine repos! Aborting.") sys.exit(1) # create an empty repository at PATH. @@ -134,13 +151,13 @@ def guarantee_greek_repository(path, min nothing but the greek-tree at revision 1.""" if path == main.pristine_greek_repos_dir: - print("ERROR: attempt to overwrite the pristine repos! Aborting.") + logger.error("attempt to overwrite the pristine repos! Aborting.") sys.exit(1) # copy the pristine repository to PATH. main.safe_rmtree(path) if main.copy_repos(main.pristine_greek_repos_dir, path, 1, 1, minor_version): - print("ERROR: copying repository failed.") + logger.error("copying repository failed.") sys.exit(1) # make the repos world-writeable, for mod_dav_svn's sake. @@ -458,8 +475,7 @@ def run_and_verify_checkout2(do_remove, try: tree.compare_trees("output", actual, output_tree) except tree.SVNTreeUnequal: - print("ACTUAL OUTPUT TREE:") - tree.dump_tree_script(actual, wc_dir_name + os.sep) + _log_tree_state("ACTUAL OUTPUT TREE:", actual, wc_dir_name) raise # Create a tree by scanning the working copy @@ -471,8 +487,7 @@ def run_and_verify_checkout2(do_remove, singleton_handler_a, a_baton, singleton_handler_b, b_baton) except tree.SVNTreeUnequal: - print("ACTUAL DISK TREE:") - tree.dump_tree_script(actual, wc_dir_name + os.sep) + _log_tree_state("ACTUAL DISK TREE:", actual, wc_dir_name) raise def run_and_verify_checkout(URL, wc_dir_name, output_tree, disk_tree, @@ -523,8 +538,7 @@ def run_and_verify_export(URL, export_di try: tree.compare_trees("output", actual, output_tree) except tree.SVNTreeUnequal: - print("ACTUAL OUTPUT TREE:") - tree.dump_tree_script(actual, export_dir_name + os.sep) + _log_tree_state("ACTUAL OUTPUT TREE:", actual, export_dir_name) raise # Create a tree by scanning the working copy. Don't ignore @@ -536,8 +550,7 @@ def run_and_verify_export(URL, export_di try: tree.compare_trees("disk", actual, disk_tree) except tree.SVNTreeUnequal: - print("ACTUAL DISK TREE:") - tree.dump_tree_script(actual, export_dir_name + os.sep) + _log_tree_state("ACTUAL DISK TREE:", actual, export_dir_name) raise @@ -756,8 +769,7 @@ def verify_update(actual_output, try: tree.compare_trees("output", actual_output, output_tree) except tree.SVNTreeUnequal: - print("ACTUAL OUTPUT TREE:") - tree.dump_tree_script(actual_output, wc_dir_name + os.sep) + _log_tree_state("ACTUAL OUTPUT TREE:", actual_output, wc_dir_name) raise # Verify actual mergeinfo recording output against expected output. @@ -766,9 +778,8 @@ def verify_update(actual_output, tree.compare_trees("mergeinfo_output", actual_mergeinfo_output, mergeinfo_output_tree) except tree.SVNTreeUnequal: - print("ACTUAL MERGEINFO OUTPUT TREE:") - tree.dump_tree_script(actual_mergeinfo_output, - wc_dir_name + os.sep) + _log_tree_state("ACTUAL MERGEINFO OUTPUT TREE:", actual_mergeinfo_output, + wc_dir_name) raise # Verify actual mergeinfo elision output against expected output. @@ -777,9 +788,8 @@ def verify_update(actual_output, tree.compare_trees("elision_output", actual_elision_output, elision_output_tree) except tree.SVNTreeUnequal: - print("ACTUAL ELISION OUTPUT TREE:") - tree.dump_tree_script(actual_elision_output, - wc_dir_name + os.sep) + _log_tree_state("ACTUAL ELISION OUTPUT TREE:", actual_elision_output, + wc_dir_name) raise # Create a tree by scanning the working copy, and verify it @@ -790,10 +800,8 @@ def verify_update(actual_output, singleton_handler_a, a_baton, singleton_handler_b, b_baton) except tree.SVNTreeUnequal: - print("EXPECTED DISK TREE:") - tree.dump_tree_script(disk_tree) - print("ACTUAL DISK TREE:") - tree.dump_tree_script(actual_disk) + _log_tree_state("EXPECTED DISK TREE:", disk_tree) + _log_tree_state("ACTUAL DISK TREE:", actual_disk) raise # Verify via 'status' command too, if possible. @@ -1041,9 +1049,9 @@ def run_and_verify_merge(dir, rev1, rev2 try: tree.compare_trees("disk", post_disk, pre_disk) except tree.SVNTreeError: - print("=============================================================") - print("Dry-run merge altered working copy") - print("=============================================================") + logger.warn("=============================================================") + logger.warn("Dry-run merge altered working copy") + logger.warn("=============================================================") raise @@ -1107,26 +1115,26 @@ def run_and_verify_merge(dir, rev1, rev2 out_dry_copy = set(out_dry[:]) if out_copy != out_dry_copy: - print("=============================================================") - print("Merge outputs differ") - print("The dry-run merge output:") + logger.warn("=============================================================") + logger.warn("Merge outputs differ") + logger.warn("The dry-run merge output:") for x in out_dry: - sys.stdout.write(x) - print("The full merge output:") + logger.warn(x) + logger.warn("The full merge output:") for x in out: - sys.stdout.write(x) - print("=============================================================") + logger.warn(x) + logger.warn("=============================================================") raise main.SVNUnmatchedError def missing_skip(a, b): - print("=============================================================") - print("Merge failed to skip: " + a.path) - print("=============================================================") + logger.warn("=============================================================") + logger.warn("Merge failed to skip: %s", a.path) + logger.warn("=============================================================") raise Failure def extra_skip(a, b): - print("=============================================================") - print("Merge unexpectedly skipped: " + a.path) - print("=============================================================") + logger.warn("=============================================================") + logger.warn("Merge unexpectedly skipped: %s", a.path) + logger.warn("=============================================================") raise Failure myskiptree = tree.build_tree_from_skipped(out) @@ -1136,8 +1144,7 @@ def run_and_verify_merge(dir, rev1, rev2 tree.compare_trees("skip", myskiptree, skip_tree, extra_skip, None, missing_skip, None) except tree.SVNTreeUnequal: - print("ACTUAL SKIP TREE:") - tree.dump_tree_script(myskiptree, dir + os.sep) + _log_tree_state("ACTUAL SKIP TREE:", myskiptree, dir) raise actual_diff = svntest.wc.State.from_checkout(merge_diff_out, False) @@ -1193,9 +1200,9 @@ def run_and_verify_patch(dir, patch_path try: tree.compare_trees("disk", post_disk, pre_disk) except tree.SVNTreeError: - print("=============================================================") - print("'svn patch --dry-run' altered working copy") - print("=============================================================") + logger.warn("=============================================================") + logger.warn("'svn patch --dry-run' altered working copy") + logger.warn("=============================================================") raise # Update and make a tree of the output. @@ -1212,9 +1219,9 @@ def run_and_verify_patch(dir, patch_path if not match: raise main.SVNUnmatchedError elif err: - print("UNEXPECTED STDERR:") + logger.warn("UNEXPECTED STDERR:") for x in err: - sys.stdout.write(x) + logger.warn(x) raise verify.SVNUnexpectedStderr if dry_run and out != out_dry: @@ -1225,14 +1232,14 @@ def run_and_verify_patch(dir, patch_path '', out_dry_expected, out_dry) def missing_skip(a, b): - print("=============================================================") - print("'svn patch' failed to skip: " + a.path) - print("=============================================================") + logger.warn("=============================================================") + logger.warn("'svn patch' failed to skip: %s", a.path) + logger.warn("=============================================================") raise Failure def extra_skip(a, b): - print("=============================================================") - print("'svn patch' unexpectedly skipped: " + a.path) - print("=============================================================") + logger.warn("=============================================================") + logger.warn("'svn patch' unexpectedly skipped: %s", a.path) + logger.warn("=============================================================") raise Failure myskiptree = tree.build_tree_from_skipped(out) @@ -1366,9 +1373,9 @@ def process_output_for_commit(output): cm = re.compile("(Committed|Imported) revision [0-9]+.") match = cm.search(lastline) if not match: - print("ERROR: commit did not succeed.") - print("The final line from 'svn ci' was:") - print(lastline) + logger.warn("ERROR: commit did not succeed.") + logger.warn("The final line from 'svn ci' was:") + logger.warn(lastline) raise main.SVNCommitFailure # The new 'final' line in the output is either a regular line that @@ -1438,8 +1445,7 @@ def run_and_verify_commit(wc_dir_name, o except tree.SVNTreeError: verify.display_trees("Output of commit is unexpected", "OUTPUT TREE", output_tree, actual) - print("ACTUAL OUTPUT TREE:") - tree.dump_tree_script(actual, wc_dir_name + os.sep) + _log_tree_state("ACTUAL OUTPUT TREE:", actual, wc_dir_name) raise # Verify via 'status' command too, if possible. @@ -1478,8 +1484,7 @@ def run_and_verify_status(wc_dir_name, o singleton_handler_b, b_baton) except tree.SVNTreeError: verify.display_trees(None, 'STATUS OUTPUT TREE', output_tree, actual) - print("ACTUAL STATUS TREE:") - tree.dump_tree_script(actual, wc_dir_name + os.sep) + _log_tree_state("ACTUAL STATUS TREE:", actual, wc_dir_name) raise # if we have an output State, and we can/are-allowed to create an @@ -1515,8 +1520,7 @@ def run_and_verify_unquiet_status(wc_dir try: tree.compare_trees("UNQUIET STATUS", actual, status_tree) except tree.SVNTreeError: - print("ACTUAL UNQUIET STATUS TREE:") - tree.dump_tree_script(actual, wc_dir_name + os.sep) + _log_tree_state("ACTUAL UNQUIET STATUS TREE:", actual, wc_dir_name) raise def run_and_verify_status_xml(expected_entries = [], @@ -1621,7 +1625,7 @@ def run_and_verify_diff_summarize_xml(er modified_path = modified_path.replace(os.sep, "/") if modified_path not in expected_paths: - print("ERROR: %s not expected in the changed paths." % modified_path) + logger.warn("ERROR: %s not expected in the changed paths.", modified_path) raise Failure index = expected_paths.index(modified_path) @@ -1633,15 +1637,15 @@ def run_and_verify_diff_summarize_xml(er actual_prop = path.getAttribute('props') if expected_item != actual_item: - print("ERROR: expected: %s actual: %s" % (expected_item, actual_item)) + logger.warn("ERROR: expected: %s actual: %s", expected_item, actual_item) raise Failure if expected_kind != actual_kind: - print("ERROR: expected: %s actual: %s" % (expected_kind, actual_kind)) + logger.warn("ERROR: expected: %s actual: %s", expected_kind, actual_kind) raise Failure if expected_prop != actual_prop: - print("ERROR: expected: %s actual: %s" % (expected_prop, actual_prop)) + logger.warn("ERROR: expected: %s actual: %s", expected_prop, actual_prop) raise Failure def run_and_verify_diff_summarize(output_tree, *args): @@ -1664,8 +1668,7 @@ def run_and_verify_diff_summarize(output tree.compare_trees("output", actual, output_tree) except tree.SVNTreeError: verify.display_trees(None, 'DIFF OUTPUT TREE', output_tree, actual) - print("ACTUAL DIFF OUTPUT TREE:") - tree.dump_tree_script(actual) + _log_tree_state("ACTUAL DIFF OUTPUT TREE:", actual) raise def run_and_validate_lock(path, username): @@ -1929,9 +1932,9 @@ def check_prop(name, path, exp_out, revp '--password', main.wc_passwd, *revprop_options) if out != exp_out: - print("svn pg --strict %s output does not match expected." % name) - print("Expected standard output: %s\n" % exp_out) - print("Actual standard output: %s\n" % out) + logger.warn("svn pg --strict %s output does not match expected.", name) + logger.warn("Expected standard output: %s\n", exp_out) + logger.warn("Actual standard output: %s\n", out) raise Failure def fill_file_with_lines(wc_path, line_nbr, line_descrip=None, @@ -2525,8 +2528,8 @@ def deep_trees_run_tests_scheme_for_upda try: add_deep_trees(sbox, test_case.name) except: - print("ERROR IN: Tests scheme for update: " - + "while setting up deep trees in '%s'" % test_case.name) + logger.warn("ERROR IN: Tests scheme for update: " + + "while setting up deep trees in '%s'", test_case.name) raise @@ -2541,8 +2544,8 @@ def deep_trees_run_tests_scheme_for_upda try: test_case.incoming_action(j(sbox.wc_dir, test_case.name)) except: - print("ERROR IN: Tests scheme for update: " - + "while performing incoming action in '%s'" % test_case.name) + logger.warn("ERROR IN: Tests scheme for update: " + + "while performing incoming action in '%s'", test_case.name) raise @@ -2562,8 +2565,8 @@ def deep_trees_run_tests_scheme_for_upda try: test_case.local_action(j(wc_dir, test_case.name)) except: - print("ERROR IN: Tests scheme for update: " - + "while performing local action in '%s'" % test_case.name) + logger.warn("ERROR IN: Tests scheme for update: " + + "while performing local action in '%s'", test_case.name) raise @@ -2597,8 +2600,8 @@ def deep_trees_run_tests_scheme_for_upda run_and_verify_info([x_info[path]], j(base, path)) except: - print("ERROR IN: Tests scheme for update: " - + "while verifying in '%s'" % test_case.name) + logger.warn("ERROR IN: Tests scheme for update: " + + "while verifying in '%s'", test_case.name) raise @@ -2617,8 +2620,8 @@ def deep_trees_run_tests_scheme_for_upda test_case.commit_block_string, base) except: - print("ERROR IN: Tests scheme for update: " - + "while checking commit-blocking in '%s'" % test_case.name) + logger.warn("ERROR IN: Tests scheme for update: " + + "while checking commit-blocking in '%s'", test_case.name) raise @@ -2776,8 +2779,8 @@ def deep_trees_run_tests_scheme_for_swit make_deep_trees(j(base, "incoming")) main.run_svn(None, 'add', base) except: - print("ERROR IN: Tests scheme for switch: " - + "while setting up deep trees in '%s'" % test_case.name) + logger.warn("ERROR IN: Tests scheme for switch: " + + "while setting up deep trees in '%s'", test_case.name) raise @@ -2792,8 +2795,8 @@ def deep_trees_run_tests_scheme_for_swit try: test_case.incoming_action(j(sbox.wc_dir, test_case.name, "incoming")) except: - print("ERROR IN: Tests scheme for switch: " - + "while performing incoming action in '%s'" % test_case.name) + logger.warn("ERROR IN: Tests scheme for switch: " + + "while performing incoming action in '%s'", test_case.name) raise @@ -2808,8 +2811,8 @@ def deep_trees_run_tests_scheme_for_swit try: test_case.local_action(j(sbox.wc_dir, test_case.name, "local")) except: - print("ERROR IN: Tests scheme for switch: " - + "while performing local action in '%s'" % test_case.name) + logger.warn("ERROR IN: Tests scheme for switch: " + + "while performing local action in '%s'", test_case.name) raise @@ -2843,8 +2846,8 @@ def deep_trees_run_tests_scheme_for_swit for path in x_info: run_and_verify_info([x_info[path]], j(local, path)) except: - print("ERROR IN: Tests scheme for switch: " - + "while verifying in '%s'" % test_case.name) + logger.warn("ERROR IN: Tests scheme for switch: " + + "while verifying in '%s'", test_case.name) raise @@ -2863,8 +2866,8 @@ def deep_trees_run_tests_scheme_for_swit test_case.commit_block_string, local) except: - print("ERROR IN: Tests scheme for switch: " - + "while checking commit-blocking in '%s'" % test_case.name) + logger.warn("ERROR IN: Tests scheme for switch: " + + "while checking commit-blocking in '%s'", test_case.name) raise @@ -2938,8 +2941,8 @@ def deep_trees_run_tests_scheme_for_merg make_deep_trees(j(base, "incoming")) main.run_svn(None, 'add', base) except: - print("ERROR IN: Tests scheme for merge: " - + "while setting up deep trees in '%s'" % test_case.name) + logger.warn("ERROR IN: Tests scheme for merge: " + + "while setting up deep trees in '%s'", test_case.name) raise @@ -2958,8 +2961,8 @@ def deep_trees_run_tests_scheme_for_merg main.run_svn(None, 'cp', incoming_url, local_url, '-m', 'copy incoming to local') except: - print("ERROR IN: Tests scheme for merge: " - + "while copying deep trees in '%s'" % test_case.name) + logger.warn("ERROR IN: Tests scheme for merge: " + + "while copying deep trees in '%s'", test_case.name) raise # 4) Update to load all of the "/local" subdirs into the working copies. @@ -2967,7 +2970,7 @@ def deep_trees_run_tests_scheme_for_merg try: main.run_svn(None, 'up', sbox.wc_dir) except: - print("ERROR IN: Tests scheme for merge: " + logger.warn("ERROR IN: Tests scheme for merge: " + "while updating local subdirs") raise @@ -2978,8 +2981,8 @@ def deep_trees_run_tests_scheme_for_merg try: test_case.incoming_action(j(sbox.wc_dir, test_case.name, "incoming")) except: - print("ERROR IN: Tests scheme for merge: " - + "while performing incoming action in '%s'" % test_case.name) + logger.warn("ERROR IN: Tests scheme for merge: " + + "while performing incoming action in '%s'", test_case.name) raise @@ -2990,7 +2993,7 @@ def deep_trees_run_tests_scheme_for_merg main.run_svn(None, 'ci', '-m', 'Committing incoming actions', sbox.wc_dir) except: - print("ERROR IN: Tests scheme for merge: " + logger.warn("ERROR IN: Tests scheme for merge: " + "while committing incoming actions") raise @@ -3001,8 +3004,8 @@ def deep_trees_run_tests_scheme_for_merg try: test_case.local_action(j(sbox.wc_dir, test_case.name, "local")) except: - print("ERROR IN: Tests scheme for merge: " - + "while performing local action in '%s'" % test_case.name) + logger.warn("ERROR IN: Tests scheme for merge: " + + "while performing local action in '%s'", test_case.name) raise @@ -3013,7 +3016,7 @@ def deep_trees_run_tests_scheme_for_merg main.run_svn(None, 'ci', '-m', 'Committing incoming and local actions', sbox.wc_dir) except: - print("ERROR IN: Tests scheme for merge: " + logger.warn("ERROR IN: Tests scheme for merge: " + "while committing incoming and local actions") raise @@ -3055,8 +3058,8 @@ def deep_trees_run_tests_scheme_for_merg False, False, *varargs) run_and_verify_unquiet_status(local, x_status) except: - print("ERROR IN: Tests scheme for merge: " - + "while verifying in '%s'" % test_case.name) + logger.warn("ERROR IN: Tests scheme for merge: " + + "while verifying in '%s'", test_case.name) raise @@ -3076,8 +3079,8 @@ def deep_trees_run_tests_scheme_for_merg test_case.commit_block_string, local) except: - print("ERROR IN: Tests scheme for merge: " - + "while checking commit-blocking in '%s'" % test_case.name) + logger.warn("ERROR IN: Tests scheme for merge: " + + "while checking commit-blocking in '%s'", test_case.name) raise Modified: subversion/branches/inheritable-props/subversion/tests/cmdline/svntest/factory.py URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/tests/cmdline/svntest/factory.py?rev=1301216&r1=1301215&r2=1301216&view=diff ============================================================================== --- subversion/branches/inheritable-props/subversion/tests/cmdline/svntest/factory.py (original) +++ subversion/branches/inheritable-props/subversion/tests/cmdline/svntest/factory.py Thu Mar 15 21:40:15 2012 @@ -255,7 +255,7 @@ if sys.version_info[0] >= 3: from io import StringIO else: # Python <3.0 - from StringIO import StringIO + from cStringIO import StringIO def make(wc_dir, commands, prev_status=None, prev_disk=None, verbose=True): """The Factory Invocation Function. This is typically the only one