Modified: subversion/branches/ev2-export/subversion/tests/libsvn_wc/db-test.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/libsvn_wc/db-test.c?rev=1421507&r1=1421506&r2=1421507&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/tests/libsvn_wc/db-test.c (original) +++ subversion/branches/ev2-export/subversion/tests/libsvn_wc/db-test.c Thu Dec 13 20:39:17 2012 @@ -391,6 +391,7 @@ test_getting_info(apr_pool_t *pool) const svn_checksum_t *checksum; const char *target; svn_boolean_t had_props; + apr_hash_t *props; svn_boolean_t update_root; svn_wc__db_lock_t *lock; svn_wc__db_t *db; @@ -403,7 +404,7 @@ test_getting_info(apr_pool_t *pool) &status, &kind, &revision, &repos_relpath, &repos_root_url, &repos_uuid, &changed_rev, &changed_date, &changed_author,&depth, &checksum, - &target, &lock, &had_props, + &target, &lock, &had_props, &props, &update_root, db, local_abspath, pool, pool)); @@ -420,6 +421,9 @@ test_getting_info(apr_pool_t *pool) SVN_TEST_ASSERT(checksum == NULL); SVN_TEST_ASSERT(target == NULL); SVN_TEST_ASSERT(lock == NULL); + SVN_TEST_ASSERT(had_props == FALSE); + SVN_TEST_ASSERT(apr_hash_count(props) == 0); + /* SVN_TEST_ASSERT(update_root == ???); */ /* Test: file-specific values. */ SVN_ERR(svn_wc__db_base_get_info( @@ -427,7 +431,7 @@ test_getting_info(apr_pool_t *pool) &repos_relpath, &repos_root_url, &repos_uuid, NULL, NULL, NULL, NULL, &checksum, NULL, NULL, - NULL, NULL, + NULL, NULL, NULL, db, svn_dirent_join(local_abspath, "A", pool), pool, pool)); SVN_TEST_ASSERT(kind == svn_kind_file); @@ -442,7 +446,7 @@ test_getting_info(apr_pool_t *pool) &repos_relpath, &repos_root_url, &repos_uuid, &changed_rev, &changed_date, &changed_author, &depth, &checksum, &target, &lock, - NULL, NULL, + NULL, NULL, NULL, db, svn_dirent_join(local_abspath, "B", pool), pool, pool)); SVN_TEST_ASSERT(kind == svn_kind_symlink); @@ -465,7 +469,7 @@ test_getting_info(apr_pool_t *pool) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, db, svn_dirent_join(local_abspath, "C", pool), pool, pool)); SVN_TEST_ASSERT(kind == svn_kind_unknown); @@ -477,7 +481,7 @@ test_getting_info(apr_pool_t *pool) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, db, svn_dirent_join(local_abspath, "D", pool), pool, pool)); SVN_TEST_ASSERT(status == svn_wc__db_status_not_present); @@ -488,7 +492,7 @@ test_getting_info(apr_pool_t *pool) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, db, svn_dirent_join(local_abspath, "E", pool), pool, pool)); SVN_TEST_ASSERT(status == svn_wc__db_status_incomplete); @@ -499,7 +503,7 @@ test_getting_info(apr_pool_t *pool) NULL, NULL, NULL, NULL, NULL, NULL, NULL, &checksum, NULL, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, db, svn_dirent_join(local_abspath, "F", pool), pool, pool)); SVN_TEST_STRING_ASSERT(SHA1_1, @@ -511,7 +515,7 @@ test_getting_info(apr_pool_t *pool) &repos_relpath, &repos_root_url, &repos_uuid, &changed_rev, &changed_date, &changed_author, NULL, NULL, NULL, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, db, svn_dirent_join(local_abspath, "G", pool), pool, pool)); SVN_TEST_STRING_ASSERT(repos_relpath, "G-alt"); @@ -527,7 +531,7 @@ test_getting_info(apr_pool_t *pool) NULL, NULL, NULL, NULL, NULL, NULL, NULL, &checksum, &target, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, db, svn_dirent_join(local_abspath, "H", pool), pool, pool)); SVN_TEST_ASSERT(checksum == NULL); @@ -539,7 +543,7 @@ test_getting_info(apr_pool_t *pool) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, db, svn_dirent_join(local_abspath, "missing-file", pool), pool, pool); SVN_TEST_ASSERT(err != NULL && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND); @@ -568,14 +572,12 @@ validate_node(svn_wc__db_t *db, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, db, path, scratch_pool, scratch_pool)); SVN_TEST_ASSERT(kind == expected_kind); SVN_TEST_ASSERT(status == expected_status); - SVN_ERR(svn_wc__db_base_get_props(&props, db, path, - scratch_pool, scratch_pool)); switch (status) { case svn_wc__db_status_server_excluded: @@ -583,13 +585,18 @@ validate_node(svn_wc__db_t *db, case svn_wc__db_status_incomplete: case svn_wc__db_status_not_present: /* Our tests aren't setting properties on these node types, so - short-circuit examination of name/value pairs. */ + short-circuit examination of name/value pairs, to avoid having + to handle the error from svn_wc__db_base_get_props(). */ return SVN_NO_ERROR; - default: - SVN_TEST_ASSERT(props != NULL); + break; /* Fall through */ } + SVN_ERR(svn_wc__db_base_get_props(&props, db, path, + scratch_pool, scratch_pool)); + + SVN_TEST_ASSERT(props != NULL); + value = apr_hash_get(props, "p1", APR_HASH_KEY_STRING); SVN_TEST_STRING_ASSERT(value->data, "v1"); @@ -803,10 +810,10 @@ test_working_info(apr_pool_t *pool) svn_revnum_t changed_rev; apr_time_t changed_date; const char *changed_author; - apr_time_t last_mod_time; + apr_time_t recorded_time; svn_depth_t depth; const svn_checksum_t *checksum; - svn_filesize_t translated_size; + svn_filesize_t recorded_size; const char *target; const char *changelist; const char *original_repos_relpath; @@ -832,7 +839,7 @@ test_working_info(apr_pool_t *pool) &changed_rev, &changed_date, &changed_author, &depth, &checksum, &target, &original_repos_relpath, &original_root_url, &original_uuid, &original_revnum, - &lock, &translated_size, &last_mod_time, &changelist, + &lock, &recorded_size, &recorded_time, &changelist, &conflicted, &op_root, &had_props, &props_mod, &have_base, &have_more_work, &have_work, db, svn_dirent_join(local_abspath, "I", pool), @@ -848,18 +855,22 @@ test_working_info(apr_pool_t *pool) SVN_TEST_STRING_ASSERT(changed_author, AUTHOR_2); SVN_TEST_ASSERT(depth == svn_depth_immediates); SVN_TEST_ASSERT(checksum == NULL); - SVN_TEST_ASSERT(translated_size == SVN_INVALID_FILESIZE); + SVN_TEST_ASSERT(recorded_size == SVN_INVALID_FILESIZE); SVN_TEST_ASSERT(target == NULL); SVN_TEST_STRING_ASSERT(changelist, "changelist"); SVN_TEST_STRING_ASSERT(original_repos_relpath, "some/dir"); SVN_TEST_STRING_ASSERT(original_root_url, ROOT_TWO); SVN_TEST_STRING_ASSERT(original_uuid, UUID_TWO); SVN_TEST_ASSERT(original_revnum == 2); + SVN_TEST_ASSERT(had_props == FALSE); SVN_TEST_ASSERT(props_mod == FALSE); SVN_TEST_ASSERT(have_base == TRUE); + /* SVN_TEST_ASSERT(have_more_work...); */ SVN_TEST_ASSERT(have_work == TRUE); SVN_TEST_ASSERT(conflicted == FALSE); SVN_TEST_ASSERT(lock == NULL); + /* SVN_TEST_ASSERT(last_mod_time...); */ + /* SVN_TEST_ASSERT(op_root...); */ /* ### we need a hojillion more tests in here. I just want to get this
Modified: subversion/branches/ev2-export/subversion/tests/libsvn_wc/op-depth-test.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/libsvn_wc/op-depth-test.c?rev=1421507&r1=1421506&r2=1421507&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/tests/libsvn_wc/op-depth-test.c (original) +++ subversion/branches/ev2-export/subversion/tests/libsvn_wc/op-depth-test.c Thu Dec 13 20:39:17 2012 @@ -35,6 +35,7 @@ #include "svn_wc.h" #include "svn_client.h" #include "svn_hash.h" +#include "svn_sorts.h" #include "utils.h" @@ -98,19 +99,49 @@ typedef struct nodes_row_t { svn_boolean_t file_external; const char *moved_to; svn_boolean_t moved_here; + const char *props; /* comma-separated list of prop names */ } nodes_row_t; /* Macro for filling in the REPO_* fields of a non-base NODES_ROW_T * that has no copy-from info. */ #define NO_COPY_FROM SVN_INVALID_REVNUM, NULL, FALSE #define MOVED_HERE FALSE, NULL, TRUE +#define NOT_MOVED FALSE, NULL, FALSE + +/* Return a comma-separated list of the prop names in PROPS, in lexically + * ascending order, or NULL if PROPS is empty or NULL. (Here, we don't + * care about the difference between 'has no props' and 'can't have props', + * and we choose to represent both of those as NULL.) */ +static const char * +props_hash_to_text(apr_hash_t *props, apr_pool_t *pool) +{ + apr_array_header_t *props_sorted; + svn_stringbuf_t *str; + int i; + + if (! props) + return NULL; + + str = svn_stringbuf_create_empty(pool); + props_sorted = svn_sort__hash(props, svn_sort_compare_items_lexically, pool); + for (i = 0; i < props_sorted->nelts; i++) + { + const svn_sort__item_t *item + = &APR_ARRAY_IDX(props_sorted, i, svn_sort__item_t); + + if (str->len) + svn_stringbuf_appendbyte(str, ','); + svn_stringbuf_appendcstr(str, item->key); + } + return str->len ? str->data : NULL; +} /* Return a human-readable string representing ROW. */ static const char * print_row(const nodes_row_t *row, apr_pool_t *result_pool) { - const char *file_external_str, *moved_here_str, *moved_to_str; + const char *file_external_str, *moved_here_str, *moved_to_str, *props; if (row == NULL) return "(null)"; @@ -130,18 +161,23 @@ print_row(const nodes_row_t *row, else file_external_str = ""; + if (row->props) + props = apr_psprintf(result_pool, ", p=(%s)", row->props); + else + props = ""; + if (row->repo_revnum == SVN_INVALID_REVNUM) - return apr_psprintf(result_pool, "%d, %s, %s%s%s%s", + return apr_psprintf(result_pool, "%d, %s, %s%s%s%s%s", row->op_depth, row->local_relpath, row->presence, moved_here_str, moved_to_str, - file_external_str); + file_external_str, props); else - return apr_psprintf(result_pool, "%d, %s, %s, %s ^/%s@%d%s%s%s", + return apr_psprintf(result_pool, "%d, %s, %s, %s ^/%s@%d%s%s%s%s", row->op_depth, row->local_relpath, row->presence, row->op_depth == 0 ? "base" : "copyfrom", row->repo_relpath, (int)row->repo_revnum, moved_here_str, moved_to_str, - file_external_str); + file_external_str, props); } /* A baton to pass through svn_hash_diff() to compare_nodes_rows(). */ @@ -188,7 +224,9 @@ compare_nodes_rows(const void *key, apr_ || (expected->moved_to && !found->moved_to) || (!expected->moved_to && found->moved_to) || (expected->moved_to - && strcmp(expected->moved_to, found->moved_to))) + && strcmp(expected->moved_to, found->moved_to)) + || (expected->props != NULL + && strcmp_null(expected->props, found->props) != 0)) { b->errors = svn_error_createf( SVN_ERR_TEST_FAILED, b->errors, @@ -218,7 +256,8 @@ check_db_rows(svn_test__sandbox_t *b, svn_sqlite__stmt_t *stmt; static const char *const statements[] = { "SELECT op_depth, nodes.presence, nodes.local_relpath, revision," - " repos_path, file_external, def_local_relpath, moved_to, moved_here" + " repos_path, file_external, def_local_relpath, moved_to, moved_here," + " properties" " FROM nodes " " LEFT OUTER JOIN externals" " ON nodes.local_relpath = externals.local_relpath" @@ -248,6 +287,7 @@ check_db_rows(svn_test__sandbox_t *b, { const char *key; nodes_row_t *row = apr_palloc(b->pool, sizeof(*row)); + apr_hash_t *props_hash; row->op_depth = svn_sqlite__column_int(stmt, 0); row->presence = svn_sqlite__column_text(stmt, 1, b->pool); @@ -261,6 +301,9 @@ check_db_rows(svn_test__sandbox_t *b, "incomplete {%s}", print_row(row, b->pool)); row->moved_to = svn_sqlite__column_text(stmt, 7, b->pool); row->moved_here = svn_sqlite__column_boolean(stmt, 8); + SVN_ERR(svn_sqlite__column_properties(&props_hash, stmt, 9, + b->pool, b->pool)); + row->props = props_hash_to_text(props_hash, b->pool); key = apr_psprintf(b->pool, "%d %s", row->op_depth, row->local_relpath); apr_hash_set(found_hash, key, APR_HASH_KEY_STRING, row); @@ -4284,6 +4327,8 @@ move_added(const svn_test_opts_t *opts, return SVN_NO_ERROR; } +/* Test the result of 'update' when the incoming changes are inside a + * directory that is locally moved. */ static svn_error_t * move_update(const svn_test_opts_t *opts, apr_pool_t *pool) { @@ -4291,16 +4336,39 @@ move_update(const svn_test_opts_t *opts, SVN_ERR(svn_test__sandbox_create(&b, "move_update", opts, pool)); + /* r1: Create files 'f', 'h' */ SVN_ERR(sbox_wc_mkdir(&b, "A")); SVN_ERR(sbox_wc_mkdir(&b, "A/B")); sbox_file_write(&b, "A/B/f", "r1 content\n"); + sbox_file_write(&b, "A/B/h", "r1 content\n"); SVN_ERR(sbox_wc_add(&b, "A/B/f")); + SVN_ERR(sbox_wc_add(&b, "A/B/h")); SVN_ERR(sbox_wc_commit(&b, "")); + + /* r2: Modify 'f' */ sbox_file_write(&b, "A/B/f", "r1 content\nr2 content\n"); SVN_ERR(sbox_wc_commit(&b, "")); + + /* r3: Delete 'h', add 'g' */ sbox_file_write(&b, "A/B/g", "r3 content\n"); SVN_ERR(sbox_wc_add(&b, "A/B/g")); + SVN_ERR(sbox_wc_delete(&b, "A/B/h")); SVN_ERR(sbox_wc_commit(&b, "")); + + /* r4: Add a new subtree 'X' */ + SVN_ERR(sbox_wc_mkdir(&b, "X")); + sbox_file_write(&b, "X/f", "r4 content\n"); + sbox_file_write(&b, "X/g", "r4 content\n"); + sbox_file_write(&b, "X/h", "r4 content\n"); + SVN_ERR(sbox_wc_add(&b, "X/f")); + SVN_ERR(sbox_wc_add(&b, "X/g")); + SVN_ERR(sbox_wc_add(&b, "X/h")); + SVN_ERR(sbox_wc_commit(&b, "")); + + /* r5: Add a subtree 'A/B/C' */ + SVN_ERR(sbox_wc_mkdir(&b, "A/B/C")); + SVN_ERR(sbox_wc_commit(&b, "")); + SVN_ERR(sbox_wc_update(&b, "", 1)); /* A is single-revision so A2 is a single-revision copy */ @@ -4311,12 +4379,15 @@ move_update(const svn_test_opts_t *opts, {0, "A", "normal", 1, "A"}, {0, "A/B", "normal", 1, "A/B"}, {0, "A/B/f", "normal", 1, "A/B/f"}, + {0, "A/B/h", "normal", 1, "A/B/h"}, {1, "A", "base-deleted", NO_COPY_FROM, "A2"}, {1, "A/B", "base-deleted", NO_COPY_FROM}, {1, "A/B/f", "base-deleted", NO_COPY_FROM}, + {1, "A/B/h", "base-deleted", NO_COPY_FROM}, {1, "A2", "normal", 1, "A", MOVED_HERE}, {1, "A2/B", "normal", 1, "A/B", MOVED_HERE}, {1, "A2/B/f", "normal", 1, "A/B/f", MOVED_HERE}, + {1, "A2/B/h", "normal", 1, "A/B/h", MOVED_HERE}, {0} }; SVN_ERR(check_db_rows(&b, "", nodes)); @@ -4330,31 +4401,37 @@ move_update(const svn_test_opts_t *opts, {0, "A", "normal", 2, "A"}, {0, "A/B", "normal", 2, "A/B"}, {0, "A/B/f", "normal", 2, "A/B/f"}, + {0, "A/B/h", "normal", 2, "A/B/h"}, {1, "A", "base-deleted", NO_COPY_FROM, "A2"}, {1, "A/B", "base-deleted", NO_COPY_FROM}, {1, "A/B/f", "base-deleted", NO_COPY_FROM}, + {1, "A/B/h", "base-deleted", NO_COPY_FROM}, {1, "A2", "normal", 1, "A", MOVED_HERE}, {1, "A2/B", "normal", 1, "A/B", MOVED_HERE}, {1, "A2/B/f", "normal", 1, "A/B/f", MOVED_HERE}, + {1, "A2/B/h", "normal", 1, "A/B/h", MOVED_HERE}, {0} }; SVN_ERR(check_db_rows(&b, "", nodes)); } /* Resolve should update the move. */ - SVN_ERR(sbox_wc_resolve(&b, "A")); + SVN_ERR(sbox_wc_resolve(&b, "A", svn_wc_conflict_choose_mine_conflict)); { nodes_row_t nodes[] = { {0, "", "normal", 2, ""}, {0, "A", "normal", 2, "A"}, {0, "A/B", "normal", 2, "A/B"}, {0, "A/B/f", "normal", 2, "A/B/f"}, + {0, "A/B/h", "normal", 2, "A/B/h"}, {1, "A", "base-deleted", NO_COPY_FROM, "A2"}, {1, "A/B", "base-deleted", NO_COPY_FROM}, {1, "A/B/f", "base-deleted", NO_COPY_FROM}, + {1, "A/B/h", "base-deleted", NO_COPY_FROM}, {1, "A2", "normal", 2, "A", MOVED_HERE}, {1, "A2/B", "normal", 2, "A/B", MOVED_HERE}, {1, "A2/B/f", "normal", 2, "A/B/f", MOVED_HERE}, + {1, "A2/B/h", "normal", 2, "A/B/h", MOVED_HERE}, {0} }; SVN_ERR(check_db_rows(&b, "", nodes)); @@ -4376,13 +4453,13 @@ move_update(const svn_test_opts_t *opts, {1, "A2", "normal", 2, "A", MOVED_HERE}, {1, "A2/B", "normal", 2, "A/B", MOVED_HERE}, {1, "A2/B/f", "normal", 2, "A/B/f", MOVED_HERE}, + {1, "A2/B/h", "normal", 2, "A/B/h", MOVED_HERE}, {0} }; SVN_ERR(check_db_rows(&b, "", nodes)); } - /* Are we going to handle this case? */ - SVN_ERR(sbox_wc_resolve(&b, "A")); + SVN_ERR(sbox_wc_resolve(&b, "A", svn_wc_conflict_choose_mine_conflict)); { nodes_row_t nodes[] = { {0, "", "normal", 3, ""}, @@ -4403,6 +4480,150 @@ move_update(const svn_test_opts_t *opts, SVN_ERR(check_db_rows(&b, "", nodes)); } + SVN_ERR(sbox_wc_delete(&b, "A2/B")); + { + nodes_row_t nodes[] = { + {0, "", "normal", 3, ""}, + {0, "A", "normal", 3, "A"}, + {0, "A/B", "normal", 3, "A/B"}, + {0, "A/B/f", "normal", 3, "A/B/f"}, + {0, "A/B/g", "normal", 3, "A/B/g"}, + {1, "A", "base-deleted", NO_COPY_FROM, "A2"}, + {1, "A/B", "base-deleted", NO_COPY_FROM}, + {1, "A/B/f", "base-deleted", NO_COPY_FROM}, + {1, "A/B/g", "base-deleted", NO_COPY_FROM}, + {1, "A2", "normal", 3, "A", MOVED_HERE}, + {1, "A2/B", "normal", 3, "A/B", MOVED_HERE}, + {1, "A2/B/f", "normal", 3, "A/B/f", MOVED_HERE}, + {1, "A2/B/g", "normal", 3, "A/B/g", MOVED_HERE}, + {2, "A2/B", "base-deleted", NO_COPY_FROM}, + {2, "A2/B/f", "base-deleted", NO_COPY_FROM}, + {2, "A2/B/g", "base-deleted", NO_COPY_FROM}, + {0} + }; + SVN_ERR(check_db_rows(&b, "", nodes)); + } + + SVN_ERR(sbox_wc_update(&b, "", 2)); + SVN_ERR(sbox_wc_resolve(&b, "A", svn_wc_conflict_choose_mine_conflict)); + { + nodes_row_t nodes[] = { + {0, "", "normal", 2, ""}, + {0, "A", "normal", 2, "A"}, + {0, "A/B", "normal", 2, "A/B"}, + {0, "A/B/f", "normal", 2, "A/B/f"}, + {0, "A/B/h", "normal", 2, "A/B/h"}, + {1, "A", "base-deleted", NO_COPY_FROM, "A2"}, + {1, "A/B", "base-deleted", NO_COPY_FROM}, + {1, "A/B/f", "base-deleted", NO_COPY_FROM}, + {1, "A/B/h", "base-deleted", NO_COPY_FROM}, + {1, "A2", "normal", 2, "A", MOVED_HERE}, + {1, "A2/B", "normal", 2, "A/B", MOVED_HERE}, + {1, "A2/B/f", "normal", 2, "A/B/f", MOVED_HERE}, + {1, "A2/B/h", "normal", 2, "A/B/h", MOVED_HERE}, + {2, "A2/B", "base-deleted", NO_COPY_FROM}, + {2, "A2/B/f", "base-deleted", NO_COPY_FROM}, + {2, "A2/B/h", "base-deleted", NO_COPY_FROM}, + {0} + }; + SVN_ERR(check_db_rows(&b, "", nodes)); + } + + SVN_ERR(sbox_wc_update(&b, "X", 4)); + SVN_ERR(sbox_wc_copy(&b, "X", "A2/B")); + { + nodes_row_t nodes[] = { + {0, "", "normal", 2, ""}, + {0, "A", "normal", 2, "A"}, + {0, "A/B", "normal", 2, "A/B"}, + {0, "A/B/f", "normal", 2, "A/B/f"}, + {0, "A/B/h", "normal", 2, "A/B/h"}, + {0, "X", "normal", 4, "X"}, + {0, "X/f", "normal", 4, "X/f"}, + {0, "X/g", "normal", 4, "X/g"}, + {0, "X/h", "normal", 4, "X/h"}, + {1, "A", "base-deleted", NO_COPY_FROM, "A2"}, + {1, "A/B", "base-deleted", NO_COPY_FROM}, + {1, "A/B/f", "base-deleted", NO_COPY_FROM}, + {1, "A/B/h", "base-deleted", NO_COPY_FROM}, + {1, "A2", "normal", 2, "A", MOVED_HERE}, + {1, "A2/B", "normal", 2, "A/B", MOVED_HERE}, + {1, "A2/B/f", "normal", 2, "A/B/f", MOVED_HERE}, + {1, "A2/B/h", "normal", 2, "A/B/h", MOVED_HERE}, + {2, "A2/B", "normal", 4, "X"}, + {2, "A2/B/f", "normal", 4, "X/f"}, + {2, "A2/B/g", "normal", 4, "X/g"}, + {2, "A2/B/h", "normal", 4, "X/h"}, + {0} + }; + SVN_ERR(check_db_rows(&b, "", nodes)); + } + + SVN_ERR(sbox_wc_update(&b, "", 4)); + SVN_ERR(sbox_wc_resolve(&b, "A", svn_wc_conflict_choose_mine_conflict)); + { + nodes_row_t nodes[] = { + {0, "", "normal", 4, ""}, + {0, "A", "normal", 4, "A"}, + {0, "A/B", "normal", 4, "A/B"}, + {0, "A/B/f", "normal", 4, "A/B/f"}, + {0, "A/B/g", "normal", 4, "A/B/g"}, + {0, "X", "normal", 4, "X"}, + {0, "X/f", "normal", 4, "X/f"}, + {0, "X/g", "normal", 4, "X/g"}, + {0, "X/h", "normal", 4, "X/h"}, + {1, "A", "base-deleted", NO_COPY_FROM, "A2"}, + {1, "A/B", "base-deleted", NO_COPY_FROM}, + {1, "A/B/f", "base-deleted", NO_COPY_FROM}, + {1, "A/B/g", "base-deleted", NO_COPY_FROM}, + {1, "A2", "normal", 4, "A", MOVED_HERE}, + {1, "A2/B", "normal", 4, "A/B", MOVED_HERE}, + {1, "A2/B/f", "normal", 4, "A/B/f", MOVED_HERE}, + {1, "A2/B/g", "normal", 4, "A/B/g", MOVED_HERE}, + {2, "A2/B", "normal", 4, "X"}, + {2, "A2/B/f", "normal", 4, "X/f"}, + {2, "A2/B/g", "normal", 4, "X/g"}, + {2, "A2/B/h", "normal", 4, "X/h"}, + {0} + }; + SVN_ERR(check_db_rows(&b, "", nodes)); + } + + SVN_ERR(sbox_wc_update(&b, "", 5)); + SVN_ERR(sbox_wc_resolve(&b, "A", svn_wc_conflict_choose_mine_conflict)); + { + nodes_row_t nodes[] = { + {0, "", "normal", 5, ""}, + {0, "A", "normal", 5, "A"}, + {0, "A/B", "normal", 5, "A/B"}, + {0, "A/B/f", "normal", 5, "A/B/f"}, + {0, "A/B/g", "normal", 5, "A/B/g"}, + {0, "A/B/C", "normal", 5, "A/B/C"}, + {0, "X", "normal", 5, "X"}, + {0, "X/f", "normal", 5, "X/f"}, + {0, "X/g", "normal", 5, "X/g"}, + {0, "X/h", "normal", 5, "X/h"}, + {1, "A", "base-deleted", NO_COPY_FROM, "A2"}, + {1, "A/B", "base-deleted", NO_COPY_FROM}, + {1, "A/B/f", "base-deleted", NO_COPY_FROM}, + {1, "A/B/g", "base-deleted", NO_COPY_FROM}, + {1, "A/B/C", "base-deleted", NO_COPY_FROM}, + {1, "A2", "normal", 5, "A", MOVED_HERE}, + {1, "A2/B", "normal", 5, "A/B", MOVED_HERE}, + {1, "A2/B/f", "normal", 5, "A/B/f", MOVED_HERE}, + {1, "A2/B/g", "normal", 5, "A/B/g", MOVED_HERE}, + {1, "A2/B/C", "normal", 5, "A/B/C", MOVED_HERE}, + {2, "A2/B", "normal", 4, "X"}, + {2, "A2/B/f", "normal", 4, "X/f"}, + {2, "A2/B/g", "normal", 4, "X/g"}, + {2, "A2/B/h", "normal", 4, "X/h"}, + {2, "A2/B/C", "base-deleted", NO_COPY_FROM}, + {0} + }; + SVN_ERR(check_db_rows(&b, "", nodes)); + } + + return SVN_NO_ERROR; } @@ -4805,6 +5026,206 @@ mixed_rev_move(const svn_test_opts_t *op return SVN_NO_ERROR; } +/* Test the result of 'update' when the incoming changes are inside a + * directory that is locally moved. */ +static svn_error_t * +update_prop_mod_into_moved(const svn_test_opts_t *opts, apr_pool_t *pool) +{ + svn_test__sandbox_t b; + + SVN_ERR(svn_test__sandbox_create(&b, "update_prop_mod_into_moved", opts, pool)); + + /* r1: Create files 'f', 'h' */ + SVN_ERR(sbox_wc_mkdir(&b, "A")); + SVN_ERR(sbox_wc_mkdir(&b, "A/B")); + sbox_file_write(&b, "A/B/f", "r1 content\n"); + sbox_file_write(&b, "A/B/h", "r1 content\n"); + SVN_ERR(sbox_wc_add(&b, "A/B/f")); + SVN_ERR(sbox_wc_add(&b, "A/B/h")); + SVN_ERR(sbox_wc_propset(&b, "pd", "f1", "A/B/f")); + SVN_ERR(sbox_wc_propset(&b, "pn", "f1", "A/B/f")); + SVN_ERR(sbox_wc_propset(&b, "pm", "f1", "A/B/f")); + SVN_ERR(sbox_wc_propset(&b, "p", "h1", "A/B/h")); + SVN_ERR(sbox_wc_commit(&b, "")); + + /* r2: Modify 'f'. Delete prop 'pd', modify prop 'pm', add prop 'pa', + * leave prop 'pn' unchanged. */ + sbox_file_write(&b, "A/B/f", "r1 content\nr2 content\n"); + SVN_ERR(sbox_wc_propset(&b, "pd", NULL, "A/B/f")); + SVN_ERR(sbox_wc_propset(&b, "pm", "f2", "A/B/f")); + SVN_ERR(sbox_wc_propset(&b, "pa", "f2", "A/B/f")); + SVN_ERR(sbox_wc_commit(&b, "")); + + /* r3: Delete 'h', add 'g' */ + sbox_file_write(&b, "A/B/g", "r3 content\n"); + SVN_ERR(sbox_wc_add(&b, "A/B/g")); + SVN_ERR(sbox_wc_propset(&b, "p", "g3", "A/B/g")); + SVN_ERR(sbox_wc_delete(&b, "A/B/h")); + SVN_ERR(sbox_wc_commit(&b, "")); + + SVN_ERR(sbox_wc_update(&b, "", 1)); + { + nodes_row_t nodes[] = { + {0, "", "normal", 1, ""}, + {0, "A", "normal", 1, "A"}, + {0, "A/B", "normal", 1, "A/B"}, + {0, "A/B/f", "normal", 1, "A/B/f", NOT_MOVED, "pd,pm,pn"}, + {0, "A/B/h", "normal", 1, "A/B/h", NOT_MOVED, "p"}, + {0} + }; + SVN_ERR(check_db_rows(&b, "", nodes)); + } + + /* A is single-revision so A2 is a single-revision copy */ + SVN_ERR(sbox_wc_move(&b, "A", "A2")); + { + nodes_row_t nodes[] = { + {0, "", "normal", 1, ""}, + {0, "A", "normal", 1, "A"}, + {0, "A/B", "normal", 1, "A/B"}, + {0, "A/B/f", "normal", 1, "A/B/f", NOT_MOVED, "pd,pm,pn"}, + {0, "A/B/h", "normal", 1, "A/B/h", NOT_MOVED, "p"}, + {1, "A", "base-deleted", NO_COPY_FROM, "A2"}, + {1, "A/B", "base-deleted", NO_COPY_FROM}, + {1, "A/B/f", "base-deleted", NO_COPY_FROM}, + {1, "A/B/h", "base-deleted", NO_COPY_FROM}, + {1, "A2", "normal", 1, "A", MOVED_HERE}, + {1, "A2/B", "normal", 1, "A/B", MOVED_HERE}, + {1, "A2/B/f", "normal", 1, "A/B/f", MOVED_HERE, "pd,pm,pn"}, + {1, "A2/B/h", "normal", 1, "A/B/h", MOVED_HERE, "p"}, + {0} + }; + SVN_ERR(check_db_rows(&b, "", nodes)); + } + + /* Update causes a tree-conflict on A due to incoming text-change. */ + SVN_ERR(sbox_wc_update(&b, "", 2)); + { + nodes_row_t nodes[] = { + {0, "", "normal", 2, ""}, + {0, "A", "normal", 2, "A"}, + {0, "A/B", "normal", 2, "A/B"}, + {0, "A/B/f", "normal", 2, "A/B/f", NOT_MOVED, "pa,pm,pn"}, + {0, "A/B/h", "normal", 2, "A/B/h", NOT_MOVED, "p"}, + {1, "A", "base-deleted", NO_COPY_FROM, "A2"}, + {1, "A/B", "base-deleted", NO_COPY_FROM}, + {1, "A/B/f", "base-deleted", NO_COPY_FROM}, + {1, "A/B/h", "base-deleted", NO_COPY_FROM}, + {1, "A2", "normal", 1, "A", MOVED_HERE}, + {1, "A2/B", "normal", 1, "A/B", MOVED_HERE}, + {1, "A2/B/f", "normal", 1, "A/B/f", MOVED_HERE, "pd,pm,pn"}, + {1, "A2/B/h", "normal", 1, "A/B/h", MOVED_HERE, "p"}, + {0} + }; + SVN_ERR(check_db_rows(&b, "", nodes)); + } + + /* Resolve should update the move. */ + SVN_ERR(sbox_wc_resolve(&b, "A", svn_wc_conflict_choose_mine_conflict)); + { + nodes_row_t nodes[] = { + {0, "", "normal", 2, ""}, + {0, "A", "normal", 2, "A"}, + {0, "A/B", "normal", 2, "A/B"}, + {0, "A/B/f", "normal", 2, "A/B/f", NOT_MOVED, "pa,pm,pn"}, + {0, "A/B/h", "normal", 2, "A/B/h", NOT_MOVED, "p"}, + {1, "A", "base-deleted", NO_COPY_FROM, "A2"}, + {1, "A/B", "base-deleted", NO_COPY_FROM}, + {1, "A/B/f", "base-deleted", NO_COPY_FROM}, + {1, "A/B/h", "base-deleted", NO_COPY_FROM}, + {1, "A2", "normal", 2, "A", MOVED_HERE}, + {1, "A2/B", "normal", 2, "A/B", MOVED_HERE}, + {1, "A2/B/f", "normal", 2, "A/B/f", MOVED_HERE, "pa,pm,pn"}, + {1, "A2/B/h", "normal", 2, "A/B/h", MOVED_HERE, "p"}, + {0} + }; + SVN_ERR(check_db_rows(&b, "", nodes)); + } + + return SVN_NO_ERROR; +} + +static svn_error_t * +nested_move_update(const svn_test_opts_t *opts, apr_pool_t *pool) +{ + svn_test__sandbox_t b; + + SVN_ERR(svn_test__sandbox_create(&b, "nested_move_update", opts, pool)); + + /* r1: Create file 'f' */ + SVN_ERR(sbox_wc_mkdir(&b, "A")); + SVN_ERR(sbox_wc_mkdir(&b, "A/B")); + SVN_ERR(sbox_wc_mkdir(&b, "A/B/C")); + sbox_file_write(&b, "A/B/C/f", "r1 content\n"); + SVN_ERR(sbox_wc_add(&b, "A/B/C/f")); + SVN_ERR(sbox_wc_commit(&b, "")); + + /* r2: Modify 'f' */ + sbox_file_write(&b, "A/B/C/f", "r1 content\nr2 content\n"); + SVN_ERR(sbox_wc_commit(&b, "")); + + SVN_ERR(sbox_wc_update(&b, "", 1)); + + SVN_ERR(sbox_wc_move(&b, "A", "A2")); + SVN_ERR(sbox_wc_move(&b, "A2/B/C", "A2/B/C2")); + { + nodes_row_t nodes[] = { + {0, "", "normal", 1, ""}, + {0, "A", "normal", 1, "A"}, + {0, "A/B", "normal", 1, "A/B"}, + {0, "A/B/C", "normal", 1, "A/B/C"}, + {0, "A/B/C/f", "normal", 1, "A/B/C/f"}, + {1, "A", "base-deleted", NO_COPY_FROM, "A2"}, + {1, "A/B", "base-deleted", NO_COPY_FROM}, + {1, "A/B/C", "base-deleted", NO_COPY_FROM}, + {1, "A/B/C/f", "base-deleted", NO_COPY_FROM}, + {1, "A2", "normal", 1, "A", MOVED_HERE}, + {1, "A2/B", "normal", 1, "A/B", MOVED_HERE}, + {1, "A2/B/C", "normal", 1, "A/B/C", MOVED_HERE}, + {1, "A2/B/C/f", "normal", 1, "A/B/C/f", MOVED_HERE}, + {3, "A2/B/C", "base-deleted", NO_COPY_FROM, "A2/B/C2"}, + {3, "A2/B/C/f", "base-deleted", NO_COPY_FROM}, + {3, "A2/B/C2", "normal", 1, "A/B/C", MOVED_HERE}, + {3, "A2/B/C2/f", "normal", 1, "A/B/C/f", MOVED_HERE}, + {0} + }; + SVN_ERR(check_db_rows(&b, "", nodes)); + } + + SVN_ERR(sbox_wc_update(&b, "", 2)); + + /* Following the A->A2 move should raise a tree-conflict on A2/B/C, + resolving that may require an explicit resolve. */ + SVN_ERR(sbox_wc_resolve(&b, "A", svn_wc_conflict_choose_mine_conflict)); + SVN_ERR(sbox_wc_resolve(&b, "A2/B/C", svn_wc_conflict_choose_mine_conflict)); + { + nodes_row_t nodes[] = { + {0, "", "normal", 2, ""}, + {0, "A", "normal", 2, "A"}, + {0, "A/B", "normal", 2, "A/B"}, + {0, "A/B/C", "normal", 2, "A/B/C"}, + {0, "A/B/C/f", "normal", 2, "A/B/C/f"}, + {1, "A", "base-deleted", NO_COPY_FROM, "A2"}, + {1, "A/B", "base-deleted", NO_COPY_FROM}, + {1, "A/B/C", "base-deleted", NO_COPY_FROM}, + {1, "A/B/C/f", "base-deleted", NO_COPY_FROM}, + {1, "A2", "normal", 2, "A", MOVED_HERE}, + {1, "A2/B", "normal", 2, "A/B", MOVED_HERE}, + {1, "A2/B/C", "normal", 2, "A/B/C", MOVED_HERE}, + {1, "A2/B/C/f", "normal", 2, "A/B/C/f", MOVED_HERE}, + {3, "A2/B/C", "base-deleted", NO_COPY_FROM, "A2/B/C2"}, + {3, "A2/B/C/f", "base-deleted", NO_COPY_FROM}, + {3, "A2/B/C2", "normal", 2, "A/B/C", MOVED_HERE}, + {3, "A2/B/C2/f", "normal", 2, "A/B/C/f", MOVED_HERE}, + {0} + }; + SVN_ERR(check_db_rows(&b, "", nodes)); + } + + + return SVN_NO_ERROR; +} + /* ---------------------------------------------------------------------- */ /* The list of test functions */ @@ -4894,7 +5315,7 @@ struct svn_test_descriptor_t test_funcs[ "move_on_move2"), SVN_TEST_OPTS_PASS(move_added, "move_added"), - SVN_TEST_OPTS_XFAIL(move_update, + SVN_TEST_OPTS_PASS(move_update, "move_update"), SVN_TEST_OPTS_PASS(test_scan_delete, "scan_delete"), @@ -4902,5 +5323,9 @@ struct svn_test_descriptor_t test_funcs[ "follow_moved_to"), SVN_TEST_OPTS_PASS(mixed_rev_move, "mixed_rev_move"), + SVN_TEST_OPTS_PASS(update_prop_mod_into_moved, + "update_prop_mod_into_moved"), + SVN_TEST_OPTS_XFAIL(nested_move_update, + "nested_move_update"), SVN_TEST_NULL }; Modified: subversion/branches/ev2-export/subversion/tests/libsvn_wc/utils.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/libsvn_wc/utils.c?rev=1421507&r1=1421506&r2=1421507&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/tests/libsvn_wc/utils.c (original) +++ subversion/branches/ev2-export/subversion/tests/libsvn_wc/utils.c Thu Dec 13 20:39:17 2012 @@ -321,22 +321,24 @@ sbox_wc_update(svn_test__sandbox_t *b, c svn_error_t * sbox_wc_resolved(svn_test__sandbox_t *b, const char *path) { - svn_client_ctx_t *ctx; - - SVN_ERR(svn_client_create_context2(&ctx, NULL, b->pool)); - return svn_client_resolve(sbox_wc_path(b, path), svn_depth_infinity, - svn_wc_conflict_choose_merged, ctx, b->pool); + return sbox_wc_resolve(b, path, svn_wc_conflict_choose_merged); } svn_error_t * -sbox_wc_resolve(svn_test__sandbox_t *b, const char *path) +sbox_wc_resolve(svn_test__sandbox_t *b, const char *path, + svn_wc_conflict_choice_t conflict_choice) { - svn_client_ctx_t *ctx; - - SVN_ERR(svn_client_create_context2(&ctx, NULL, b->pool)); - return svn_client_resolve(sbox_wc_path(b, path), svn_depth_infinity, - svn_wc_conflict_choose_mine_conflict, - ctx, b->pool); + SVN_ERR(svn_wc__resolve_conflicts(b->wc_ctx, sbox_wc_path(b, path), + svn_depth_infinity, + TRUE /* resolve_text */, + "" /* resolve_prop (ALL props) */, + TRUE /* resolve_tree */, + conflict_choice, + NULL, NULL, /* conflict func */ + NULL, NULL, /* cancellation */ + NULL, NULL, /* notification */ + b->pool)); + return SVN_NO_ERROR; } svn_error_t * @@ -361,12 +363,13 @@ sbox_wc_propset(svn_test__sandbox_t *b, svn_client_ctx_t *ctx; apr_array_header_t *paths = apr_array_make(b->pool, 1, sizeof(const char *)); + svn_string_t *pval = value ? svn_string_create(value, b->pool) : NULL; SVN_ERR(svn_client_create_context2(&ctx, NULL, b->pool)); APR_ARRAY_PUSH(paths, const char *) = sbox_wc_path(b, path); - return svn_client_propset_local(name, svn_string_create(value, b->pool), - paths, svn_depth_empty, TRUE, NULL, ctx, - b->pool); + return svn_client_propset_local(name, pval, paths, svn_depth_empty, + TRUE /* skip_checks */, + NULL, ctx, b->pool); } svn_error_t * Modified: subversion/branches/ev2-export/subversion/tests/libsvn_wc/utils.h URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/libsvn_wc/utils.h?rev=1421507&r1=1421506&r2=1421507&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/tests/libsvn_wc/utils.h (original) +++ subversion/branches/ev2-export/subversion/tests/libsvn_wc/utils.h Thu Dec 13 20:39:17 2012 @@ -130,13 +130,14 @@ sbox_wc_resolved(svn_test__sandbox_t *b, /* */ svn_error_t * -sbox_wc_resolve(svn_test__sandbox_t *b, const char *path); +sbox_wc_resolve(svn_test__sandbox_t *b, const char *path, + svn_wc_conflict_choice_t conflict_choice); /* */ svn_error_t * sbox_wc_move(svn_test__sandbox_t *b, const char *src, const char *dst); -/* */ +/* Set property NAME to VALUE on PATH. If VALUE=NULL, delete the property. */ svn_error_t * sbox_wc_propset(svn_test__sandbox_t *b, const char *name, Modified: subversion/branches/ev2-export/subversion/tests/libsvn_wc/wc-queries-test.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/libsvn_wc/wc-queries-test.c?rev=1421507&r1=1421506&r2=1421507&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/tests/libsvn_wc/wc-queries-test.c (original) +++ subversion/branches/ev2-export/subversion/tests/libsvn_wc/wc-queries-test.c Thu Dec 13 20:39:17 2012 @@ -87,7 +87,6 @@ static const int slow_statements[] = /* Is there a record? ### Can we somehow check for LIMIT 1? */ STMT_LOOK_FOR_WORK, - STMT_HAS_WORKING_NODES, /* Full temporary table read */ STMT_INSERT_ACTUAL_EMPTIES, Modified: subversion/branches/ev2-export/tools/dev/contribulyze.py URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/tools/dev/contribulyze.py?rev=1421507&r1=1421506&r2=1421507&view=diff ============================================================================== --- subversion/branches/ev2-export/tools/dev/contribulyze.py (original) +++ subversion/branches/ev2-export/tools/dev/contribulyze.py Thu Dec 13 20:39:17 2012 @@ -511,8 +511,13 @@ class LogMessage(object): log_separator = '-' * 72 + '\n' log_header_re = re.compile\ ('^(r[0-9]+) \| ([^|]+) \| ([^|]+) \| ([0-9]+)[^0-9]') -field_re = re.compile('^(Patch|Review(ed)?|Suggested|Found|Inspired) by:\s*\S.*$') -field_aliases = { 'Reviewed' : 'Review' } +field_re = re.compile( + '^(Patch|Review(ed)?|Suggested|Found|Inspired|Tested|Reported) by:' + '\s*\S.*$') +field_aliases = { + 'Reviewed' : 'Review', + 'Reported' : 'Found', +} parenthetical_aside_re = re.compile('^\s*\(.*\)\s*$') def graze(input): Modified: subversion/branches/ev2-export/tools/dist/backport.pl URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/tools/dist/backport.pl?rev=1421507&r1=1421506&r2=1421507&view=diff ============================================================================== --- subversion/branches/ev2-export/tools/dist/backport.pl (original) +++ subversion/branches/ev2-export/tools/dist/backport.pl Thu Dec 13 20:39:17 2012 @@ -233,6 +233,9 @@ sub main { die "A vim with the +ex_extra feature is required" if `${VIM} --version` !~ /[+]ex_extra/; + # ### TODO: need to run 'revert' here + # ### TODO: both here and in merge(), unlink files that previous merges added + die "Local mods to STATUS file $STATUS" if `$SVN status -q $STATUS`; @ARGV = $STATUS; # Skip most of the file Modified: subversion/branches/ev2-export/tools/dist/release.py URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/tools/dist/release.py?rev=1421507&r1=1421506&r2=1421507&view=diff ============================================================================== --- subversion/branches/ev2-export/tools/dist/release.py (original) +++ subversion/branches/ev2-export/tools/dist/release.py Thu Dec 13 20:39:17 2012 @@ -34,6 +34,9 @@ # It'd be kind of nice to use the Subversion python bindings in this script, # but people.apache.org doesn't currently have them installed +# Futures (Python 2.5 compatibility) +from __future__ import with_statement + # Stuff we need import os import re @@ -88,6 +91,7 @@ secure_repos = 'https://svn.apache.org/r dist_repos = 'https://dist.apache.org/repos/dist' dist_dev_url = dist_repos + '/dev/subversion' dist_release_url = dist_repos + '/release/subversion' +KEYS = 'https://people.apache.org/keys/group/subversion-pmc.asc' extns = ['zip', 'tar.gz', 'tar.bz2'] @@ -374,7 +378,10 @@ def compare_changes(repos, branch, revis if stderr: raise RuntimeError('svn mergeinfo failed: %s' % stderr) if stdout: - raise RuntimeError('CHANGES has unmerged revisions: %s' % stdout) + # Treat this as a warning since we are now putting entries for future + # minor releases in CHANGES on trunk. + logging.warning('CHANGES has unmerged revisions: %s' % + stdout.replace("\n", " ")) def roll_tarballs(args): 'Create the release artifacts.' @@ -737,6 +744,15 @@ def check_sigs(args): print(" %s" % fp[1]) +def get_keys(args): + 'Import the LDAP-based KEYS file to gpg' + # We use a tempfile because urlopen() objects don't have a .fileno() + with tempfile.SpooledTemporaryFile() as fd: + fd.write(urllib2.urlopen(KEYS).read()) + fd.flush() + fd.seek(0) + subprocess.check_call(['gpg', '--import'], stdin=fd) + #---------------------------------------------------------------------- # Main entry point for argument parsing and handling @@ -844,6 +860,7 @@ def main(): subparser.add_argument('version', type=Version, help='''The release label, such as '1.7.0-alpha1'.''') + # write-announcement subparser = subparsers.add_parser('write-announcement', help='''Output to stdout template text for the emailed release announcement.''') @@ -851,6 +868,7 @@ def main(): subparser.add_argument('version', type=Version, help='''The release label, such as '1.7.0-alpha1'.''') + # write-downloads subparser = subparsers.add_parser('write-downloads', help='''Output to stdout template text for the download table for subversion.apache.org''') @@ -858,7 +876,7 @@ def main(): subparser.add_argument('version', type=Version, help='''The release label, such as '1.7.0-alpha1'.''') - # The check sigs subcommand + # check-sigs subparser = subparsers.add_parser('check-sigs', help='''Output to stdout the signatures collected for this release''') @@ -869,6 +887,11 @@ def main(): help='''The full path to the directory containing release artifacts.''') + # get-keys + subparser = subparsers.add_parser('get-keys', + help='''Import committers' public keys to ~/.gpg/''') + subparser.set_defaults(func=get_keys) + # A meta-target subparser = subparsers.add_parser('clean', help='''The same as the '--clean' switch, but as a
