Index: subversion/libsvn_fs_fs/fs_fs.c =================================================================== --- subversion/libsvn_fs_fs/fs_fs.c (revision 1560210) +++ subversion/libsvn_fs_fs/fs_fs.c (working copy) @@ -6944,7 +6944,6 @@ svn_fs_fs__set_entry(svn_fs_t *fs, if (!rep || !rep->txn_id) { - const char *unique_suffix; apr_hash_t *entries; /* Before we can modify the directory, we need to dump its old @@ -6964,8 +6963,16 @@ svn_fs_fs__set_entry(svn_fs_t *fs, rep = apr_pcalloc(pool, sizeof(*rep)); rep->revision = SVN_INVALID_REVNUM; rep->txn_id = txn_id; - SVN_ERR(get_new_txn_node_id(&unique_suffix, fs, txn_id, pool)); - rep->uniquifier = apr_psprintf(pool, "%s/%s", txn_id, unique_suffix); + + if (ffd->format >= SVN_FS_FS__MIN_REP_SHARING_FORMAT) + { + const char *unique_suffix; + + SVN_ERR(get_new_txn_node_id(&unique_suffix, fs, txn_id, pool)); + rep->uniquifier = apr_psprintf(pool, "%s/%s", txn_id, + unique_suffix); + } + parent_noderev->data_rep = rep; SVN_ERR(svn_fs_fs__put_node_revision(fs, parent_noderev->id, parent_noderev, FALSE, pool)); @@ -7545,10 +7552,10 @@ static svn_error_t * rep_write_contents_close(void *baton) { struct rep_write_baton *b = baton; - const char *unique_suffix; representation_t *rep; representation_t *old_rep; apr_off_t offset; + fs_fs_data_t *ffd = b->fs->fsap_data; rep = apr_pcalloc(b->parent_pool, sizeof(*rep)); rep->offset = b->rep_offset; @@ -7565,9 +7572,17 @@ rep_write_contents_close(void *baton) /* Fill in the rest of the representation field. */ rep->expanded_size = b->rep_size; rep->txn_id = svn_fs_fs__id_txn_id(b->noderev->id); - SVN_ERR(get_new_txn_node_id(&unique_suffix, b->fs, rep->txn_id, b->pool)); - rep->uniquifier = apr_psprintf(b->parent_pool, "%s/%s", rep->txn_id, - unique_suffix); + + if (ffd->format >= SVN_FS_FS__MIN_REP_SHARING_FORMAT) + { + const char *unique_suffix; + + SVN_ERR(get_new_txn_node_id(&unique_suffix, b->fs, + rep->txn_id, b->pool)); + rep->uniquifier = apr_psprintf(b->parent_pool, "%s/%s", rep->txn_id, + unique_suffix); + } + rep->revision = SVN_INVALID_REVNUM; /* Finalize the checksum. */ @@ -8875,8 +8890,17 @@ svn_fs_fs__create(svn_fs_t *fs, SVN_ERR(write_revision_zero(fs)); - SVN_ERR(write_config(fs, pool)); + /* Grab the r1547454 from trunk. This is completely unrelated to the fix + but makes the check_hotcopy_fsfs helper work for the added 'hotcopy + non-empty --compatible-version=1.3' cmdline test: + Create the fsfs.conf file if supported. Older server versions would + simply ignore the file but that might result in a different behavior + than with the later releases. Also, hotcopy would ignore, i.e. not + copy, a fsfs.conf with old formats. */ + if (ffd->format >= SVN_FS_FS__MIN_CONFIG_FILE) + SVN_ERR(write_config(fs, pool)); + SVN_ERR(read_config(ffd, fs->path, pool)); /* Create the min unpacked rev file. */ @@ -9063,7 +9087,8 @@ recover_find_max_ids(svn_fs_t *fs, svn_revnum_t re stored in the representation. */ baton.file = rev_file; baton.pool = pool; - baton.remaining = data_rep->expanded_size; + baton.remaining = data_rep->expanded_size ? + data_rep->expanded_size : data_rep->size; stream = svn_stream_create(&baton, pool); svn_stream_set_read(stream, read_handler_recover); @@ -10893,8 +10918,10 @@ hotcopy_update_current(svn_revnum_t *dst_youngest, svn_revnum_t new_youngest, apr_pool_t *scratch_pool) { - char next_node_id[MAX_KEY_SIZE] = "0"; - char next_copy_id[MAX_KEY_SIZE] = "0"; + char *next_node_id = NULL; + char *next_copy_id = NULL; + char next_node_id_buf[MAX_KEY_SIZE]; + char next_copy_id_buf[MAX_KEY_SIZE]; fs_fs_data_t *dst_ffd = dst_fs->fsap_data; if (*dst_youngest >= new_youngest) @@ -10903,8 +10930,11 @@ hotcopy_update_current(svn_revnum_t *dst_youngest, /* If necessary, get new current next_node and next_copy IDs. */ if (dst_ffd->format < SVN_FS_FS__MIN_NO_GLOBAL_IDS_FORMAT) { + char max_node_id[MAX_KEY_SIZE] = "0"; + char max_copy_id[MAX_KEY_SIZE] = "0"; apr_off_t root_offset; apr_file_t *rev_file; + apr_size_t len; if (dst_ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT) SVN_ERR(update_min_unpacked_rev(dst_fs, scratch_pool)); @@ -10914,9 +10944,18 @@ hotcopy_update_current(svn_revnum_t *dst_youngest, SVN_ERR(get_root_changes_offset(&root_offset, NULL, rev_file, dst_fs, new_youngest, scratch_pool)); SVN_ERR(recover_find_max_ids(dst_fs, new_youngest, rev_file, - root_offset, next_node_id, next_copy_id, + root_offset, max_node_id, max_copy_id, scratch_pool)); SVN_ERR(svn_io_file_close(rev_file, scratch_pool)); + + /* Now that we have the maximum node-id and copy-id, we can bump them + to get the next of each. */ + len = strlen(max_node_id); + svn_fs_fs__next_key(max_node_id, &len, next_node_id_buf); + next_node_id = next_node_id_buf; + len = strlen(max_copy_id); + svn_fs_fs__next_key(max_copy_id, &len, next_copy_id_buf); + next_copy_id = next_copy_id_buf; } /* Update 'current'. */ Index: subversion/tests/cmdline/svnadmin_tests.py =================================================================== --- subversion/tests/cmdline/svnadmin_tests.py (revision 1560210) +++ subversion/tests/cmdline/svnadmin_tests.py (working copy) @@ -1824,6 +1824,27 @@ def recover_old(sbox): svntest.main.run_svnadmin("recover", sbox.repo_dir) +@SkipUnless(svntest.main.is_fs_type_fsfs) +def fsfs_recover_old_non_empty(sbox): + "fsfs recover non-empty --compatible-version=1.3" + + sbox.build(create_wc=False, minor_version=3) + svntest.actions.run_and_verify_svnadmin(None, None, [], "recover", + sbox.repo_dir) + + +@SkipUnless(svntest.main.is_fs_type_fsfs) +def fsfs_hotcopy_old_non_empty(sbox): + "fsfs hotcopy non-empty --compatible-version=1.3" + + sbox.build(create_wc=False, minor_version=3) + backup_dir, backup_url = sbox.add_repo_path('backup') + svntest.actions.run_and_verify_svnadmin(None, None, [], "hotcopy", + sbox.repo_dir, backup_dir) + + check_hotcopy_fsfs(sbox.repo_dir, backup_dir) + + ######################################################################## # Run the tests @@ -1860,6 +1881,8 @@ test_list = [ None, locking, mergeinfo_race, recover_old, + fsfs_recover_old_non_empty, + fsfs_hotcopy_old_non_empty ] if __name__ == '__main__':