Trying attachment again, now with .txt extension.

On Thu, Feb 4, 2010 at 11:10 AM, Lieven Govaerts <svn...@mobsol.be> wrote:
> Attached some tests I'm working on for svn_client_blame5 and
> svn_repos_get_file_revs2.
>
> I started moving some code to create a repository, ra session (...) to
> tests/svn_test_fs.c so that these can be reused in other tests.
> The test for svn_client_blame5 isn't finished yet.
>
> @DanielN: This might be useful for you, feel free to reuse and improve
> in any way you see fit. I'll probably commit later this week.
>
> Lieven
>
Index: subversion/tests/svn_test_fs.h
===================================================================
--- subversion/tests/svn_test_fs.h      (revision 902368)
+++ subversion/tests/svn_test_fs.h      (working copy)
@@ -73,6 +73,13 @@ svn_test__create_repos(svn_repos_t **repos_p,
                        const svn_test_opts_t *opts,
                        apr_pool_t *pool);
 
+/* Set URL to a "file://" url for the current directory, suffixed by the
+   forward-slash-style relative path SUFFIX, performing all allocation
+   in POOL. */
+svn_error_t *
+svn_test__current_directory_url(const char **url,
+                                const char *suffix,
+                                apr_pool_t *pool);
 
 /* Read all data from a generic read STREAM, and return it in STRING.
    Allocate the svn_stringbuf_t in APRPOOL.  (All data in STRING will be
@@ -169,7 +176,20 @@ svn_error_t *
 svn_test__create_greek_tree(svn_fs_root_t *txn_root,
                             apr_pool_t *pool);
 
+/* Create the Greek Tree under TXN_ROOT at dir ROOT_DIR.  */
+svn_error_t *
+svn_test__create_greek_tree_at(svn_fs_root_t *txn_root,
+                               const char *root_dir,
+                               apr_pool_t *pool);
 
+/* Create a new repository with a greek tree, trunk, branch and some
+   merges between them. */
+svn_error_t *
+svn_test__create_blame_repository(svn_repos_t **out_repos,
+                                  const char *test_name,
+                                  const svn_test_opts_t *opts,
+                                  apr_pool_t *pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
Index: subversion/tests/libsvn_ra_local/ra-local-test.c
===================================================================
--- subversion/tests/libsvn_ra_local/ra-local-test.c    (revision 902368)
+++ subversion/tests/libsvn_ra_local/ra-local-test.c    (working copy)
@@ -26,15 +26,6 @@
 #include <apr_general.h>
 #include <apr_pools.h>
 
-#ifdef _MSC_VER
-#include <direct.h>
-#define getcwd _getcwd
-#else
-#include <unistd.h> /* for getcwd() */
-#endif
-
-#include "svn_string.h"
-#include "svn_utf.h"
 #include "svn_error.h"
 #include "svn_delta.h"
 #include "svn_ra.h"
@@ -49,37 +40,7 @@
 /** Helper routines. **/
 
 
-/* Helper function.  Set URL to a "file://" url for the current directory,
-   suffixed by the forward-slash-style relative path SUFFIX, performing all
-   allocation in POOL. */
 static svn_error_t *
-current_directory_url(const char **url,
-                      const char *suffix,
-                      apr_pool_t *pool)
-{
-  /* 8KB is a lot, but it almost guarantees that any path will fit. */
-  char curdir[8192];
-  const char *utf8_ls_curdir, *utf8_is_curdir, *unencoded_url;
-
-  if (! getcwd(curdir, sizeof(curdir)))
-    return svn_error_create(SVN_ERR_BASE, NULL, "getcwd() failed");
-
-  SVN_ERR(svn_utf_cstring_to_utf8(&utf8_ls_curdir, curdir, pool));
-  utf8_is_curdir = svn_path_internal_style(utf8_ls_curdir, pool);
-
-  unencoded_url = apr_psprintf(pool, "file://%s%s%s%s",
-                               (utf8_is_curdir[0] != '/') ? "/" : "",
-                               utf8_is_curdir,
-                               (suffix[0] && suffix[0] != '/') ? "/" : "",
-                               suffix);
-
-  *url = svn_path_uri_encode(unencoded_url, pool);
-
-  return SVN_NO_ERROR;
-}
-
-
-static svn_error_t *
 make_and_open_local_repos(svn_ra_session_t **session,
                           const char *repos_name,
                           const svn_test_opts_t *opts,
@@ -94,7 +55,7 @@ make_and_open_local_repos(svn_ra_session_t **sessi
   SVN_ERR(svn_test__create_repos(&repos, repos_name, opts, pool));
   SVN_ERR(svn_ra_initialize(pool));
 
-  SVN_ERR(current_directory_url(&url, repos_name, pool));
+  SVN_ERR(svn_test__current_directory_url(&url, repos_name, pool));
 
   SVN_ERR(svn_ra_open3(session,
                        url,
@@ -262,7 +223,7 @@ check_split_url(const char *repos_path,
   /* Create a filesystem and repository */
   SVN_ERR(svn_test__create_repos(&repos, repos_path, opts, pool));
 
-  SVN_ERR(current_directory_url(&root_url, repos_path, pool));
+  SVN_ERR(svn_test__current_directory_url(&root_url, repos_path, pool));
   if (in_repos_path)
     url = apr_pstrcat(pool, root_url, in_repos_path, NULL);
   else
Index: subversion/tests/libsvn_client/client-test.c
===================================================================
--- subversion/tests/libsvn_client/client-test.c        (revision 902368)
+++ subversion/tests/libsvn_client/client-test.c        (working copy)
@@ -26,8 +26,10 @@
 #include "../../libsvn_client/mergeinfo.h"
 #include "svn_pools.h"
 #include "svn_client.h"
+#include "svn_ra.h"
 
 #include "../svn_test.h"
+#include "../svn_test_fs.h"
 
 typedef struct {
   const char *path;
@@ -99,8 +101,7 @@ test_elide_mergeinfo_catalog(apr_pool_t *pool)
 
 static svn_error_t *
 test_args_to_target_array(apr_pool_t *pool)
-{
-  apr_size_t i;
+{  apr_size_t i;
   apr_pool_t *iterpool;
   svn_client_ctx_t *ctx;
   static struct {
@@ -199,6 +200,92 @@ test_args_to_target_array(apr_pool_t *pool)
   return SVN_NO_ERROR;
 }
 
+
+/* Tests for svn_client_blameN() */
+
+typedef struct {
+    svn_revnum_t rev;
+    const char *path;
+    svn_boolean_t result_of_merge;
+    const char *author;
+} file_revs_t;
+
+static svn_error_t *
+blame_receiver(void *baton,
+               apr_int64_t line_no,
+               svn_revnum_t revision,
+               apr_hash_t *rev_props,
+               svn_revnum_t merged_revision,
+               apr_hash_t *merged_rev_props,
+               const char *merged_path,
+               const char *line,
+               svn_boolean_t local_change,
+               apr_pool_t *pool)
+{
+  printf("%s %s\n", merged_path, line);
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_svn_client_blame(const svn_test_opts_t *opts,
+                      apr_pool_t *pool)
+{
+  svn_repos_t *repos = NULL;
+  svn_fs_t *fs;
+  svn_revnum_t youngest_rev = 0;
+  apr_pool_t *subpool = svn_pool_create(pool);
+  svn_client_ctx_t *ctx;
+  svn_opt_revision_t start_rev, end_rev, peg_rev;
+  const char *repos_name = "test-client-blame";
+  const char *url;
+  svn_ra_callbacks2_t *cbtable;
+  svn_ra_session_t *session;
+  svn_diff_file_options_t *diff_options = 
svn_diff_file_options_create(subpool);
+
+  /* Create the repository and verify blame results. */
+  SVN_ERR(svn_test__create_blame_repository(&repos, repos_name,
+                                            opts, subpool));
+  fs = svn_repos_fs(repos);
+
+  SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, subpool));
+
+  SVN_ERR(svn_client_create_context(&ctx, subpool));
+
+  /* Open ra_local session */
+  SVN_ERR(svn_ra_create_callbacks(&cbtable, pool));
+  SVN_ERR(svn_ra_initialize(subpool));
+
+  SVN_ERR(svn_test__current_directory_url(&url, repos_name, subpool));
+
+  printf("url: %s\n", url);
+  SVN_ERR(svn_ra_open3(&session,
+                       url,
+                       NULL,
+                       cbtable,
+                       NULL,
+                       NULL,
+                       subpool));
+
+  peg_rev.kind = svn_opt_revision_head;
+  start_rev.kind = svn_opt_revision_number;
+  start_rev.value.number = youngest_rev;
+  end_rev.kind = svn_opt_revision_head;
+  SVN_ERR(svn_client_blame5(svn_uri_join(url, "branches/1.0.x/A/mu", subpool),
+                            &peg_rev,
+                            &start_rev,
+                            &end_rev,
+                            diff_options,
+                            FALSE,
+                            TRUE,
+                            blame_receiver,
+                            NULL,
+                            ctx,
+                            subpool));
+
+  return SVN_NO_ERROR;
+}
+
+
 /* ========================================================================== 
*/
 
 struct svn_test_descriptor_t test_funcs[] =
@@ -208,5 +295,7 @@ struct svn_test_descriptor_t test_funcs[] =
                    "test svn_client__elide_mergeinfo_catalog"),
     SVN_TEST_PASS2(test_args_to_target_array,
                    "test svn_client_args_to_target_array"),
+    SVN_TEST_OPTS_PASS(test_svn_client_blame,
+                       "test svn_client_blame"),
     SVN_TEST_NULL
   };
Index: subversion/tests/libsvn_repos/repos-test.c
===================================================================
--- subversion/tests/libsvn_repos/repos-test.c  (revision 902368)
+++ subversion/tests/libsvn_repos/repos-test.c  (working copy)
@@ -2340,7 +2340,126 @@ get_logs(const svn_test_opts_t *opts,
   return SVN_NO_ERROR;
 }
 
+
+/* Tests for svn_repos_get_file_revsN() */
 
+typedef struct {
+    svn_revnum_t rev;
+    const char *path;
+    svn_boolean_t result_of_merge;
+    const char *author;
+} file_revs_t;
+
+/* Finds the revision REV in the hash table passed in in BATON, and checks
+   if the PATH and RESULT_OF_MERGE match are as expected. */
+static svn_error_t *
+file_rev_handler(void *baton, const char *path, svn_revnum_t rev,
+                 apr_hash_t *rev_props, svn_boolean_t result_of_merge,
+                 svn_txdelta_window_handler_t *delta_handler,
+                 void **delta_baton, apr_array_header_t *prop_diffs,
+                 apr_pool_t *pool)
+{
+  apr_hash_t *ht = baton;
+  const char *author;
+  file_revs_t *file_rev = apr_hash_get(ht, &rev, sizeof(svn_revnum_t));
+
+  if (!file_rev)
+    return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                             "Revision rev info not expected for rev %ld "
+                             "from path %s",
+                             rev, path);
+
+  author = svn_prop_get_value(rev_props,
+                              SVN_PROP_REVISION_AUTHOR);
+
+  SVN_TEST_STRING_ASSERT(author, file_rev->author);
+  SVN_TEST_STRING_ASSERT(path, file_rev->path);
+  SVN_TEST_ASSERT(rev == file_rev->rev);
+  SVN_TEST_ASSERT(result_of_merge == file_rev->result_of_merge);
+
+  /* Remove this revision from this list so we'll be able to verify that we
+     have seen all expected revisions. */
+  apr_hash_set(ht, &rev, sizeof(svn_revnum_t), NULL);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_get_file_revs(const svn_test_opts_t *opts,
+                   apr_pool_t *pool)
+{
+  svn_repos_t *repos = NULL;
+  svn_fs_t *fs;
+  svn_revnum_t youngest_rev = 0;
+  apr_pool_t *subpool = svn_pool_create(pool);
+  int i;
+
+  file_revs_t trunk_results[] = {
+    { 2, "/trunk/A/mu", FALSE, "initial" },
+    { 3, "/trunk/A/mu", FALSE, "user-trunk" },
+    { 4, "/branches/1.0.x/A/mu", TRUE, "copy" },
+    { 5, "/trunk/A/mu", FALSE, "user-trunk" },
+    { 6, "/branches/1.0.x/A/mu", TRUE, "user-branch" },
+    { 7, "/branches/1.0.x/A/mu", TRUE, "user-merge1" },
+    { 8, "/trunk/A/mu", FALSE, "user-merge2" },
+  };
+  file_revs_t branch_results[] = {
+    { 2, "/trunk/A/mu", FALSE, "initial" },
+    { 3, "/trunk/A/mu", FALSE, "user-trunk" },
+    { 4, "/branches/1.0.x/A/mu", FALSE, "copy" },
+    { 5, "/trunk/A/mu", TRUE, "user-trunk" },
+    { 6, "/branches/1.0.x/A/mu", FALSE, "user-branch" },
+    { 7, "/branches/1.0.x/A/mu", FALSE, "user-merge1" },
+  };
+  apr_hash_t *ht_trunk_results = apr_hash_make(subpool);
+  apr_hash_t *ht_branch_results = apr_hash_make(subpool);
+
+  for (i = 0; i < sizeof(trunk_results) / sizeof(trunk_results[0]); i++)
+    apr_hash_set(ht_trunk_results, &trunk_results[i].rev,
+                 sizeof(svn_revnum_t), &trunk_results[i]);
+
+  for (i = 0; i < sizeof(branch_results) / sizeof(branch_results[0]); i++)
+    apr_hash_set(ht_branch_results, &branch_results[i].rev,
+                 sizeof(svn_revnum_t), &branch_results[i]);
+
+  /* Create the repository and verify blame results. */
+  SVN_ERR(svn_test__create_blame_repository(&repos, "test-repo-get-filerevs",
+                                            opts, subpool));
+  fs = svn_repos_fs(repos);
+
+  SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, subpool));
+
+  /* Verify blame of /trunk/A/mu */
+  SVN_ERR(svn_repos_get_file_revs2(repos, "/trunk/A/mu", 0, youngest_rev,
+                                   1, NULL, NULL,
+                                   file_rev_handler,
+                                   ht_trunk_results,
+                                   subpool));
+  SVN_TEST_ASSERT(apr_hash_count(ht_trunk_results) == 0);
+
+  /* Verify blame of /branches/1.0.x/A/mu */
+  SVN_ERR(svn_repos_get_file_revs2(repos, "/branches/1.0.x/A/mu", 0,
+                                   youngest_rev,
+                                   1, NULL, NULL,
+                                   file_rev_handler,
+                                   ht_branch_results,
+                                   subpool));
+  SVN_TEST_ASSERT(apr_hash_count(ht_branch_results) == 0);
+
+  /* Verify blame of /branches/1.0.x/A/mu in range 6-7 */
+#if 0
+  /* This should only return revision 6, 7 and maximum one revision < 6. */
+  printf("=== branch range\n");
+  SVN_ERR(svn_repos_get_file_revs2(repos, "/branches/1.0.x/A/mu", 6, 7,
+                                   1, NULL, NULL,
+                                   file_rev_handler, NULL, subpool));
+#endif
+
+  svn_pool_destroy(subpool);
+
+  return SVN_NO_ERROR;
+}
+
 
 /* The test table.  */
 
@@ -2373,5 +2492,7 @@ struct svn_test_descriptor_t test_funcs[] =
                        "test if revprops are validated by repos"),
     SVN_TEST_OPTS_PASS(get_logs,
                        "test svn_repos_get_logs ranges and limits"),
+    SVN_TEST_OPTS_PASS(test_get_file_revs,
+                       "test svn_repos_get_file_revsN"),
     SVN_TEST_NULL
   };
Index: subversion/tests/svn_test_fs.c
===================================================================
--- subversion/tests/svn_test_fs.c      (revision 902368)
+++ subversion/tests/svn_test_fs.c      (working copy)
@@ -24,8 +24,17 @@
 #include <string.h>
 #include <apr_pools.h>
 
+#ifdef _MSC_VER
+#include <direct.h>
+#define getcwd _getcwd
+#else
+#include <unistd.h> /* for getcwd() */
+#endif
+
 #include "svn_test.h"
 
+#include "svn_string.h"
+#include "svn_utf.h"
 #include "svn_pools.h"
 #include "svn_error.h"
 #include "svn_fs.h"
@@ -227,7 +236,37 @@ svn_test__create_repos(svn_repos_t **repos_p,
 }
 
 
+/* Helper function.  Set URL to a "file://" url for the current directory,
+   suffixed by the forward-slash-style relative path SUFFIX, performing all
+   allocation in POOL. */
 svn_error_t *
+svn_test__current_directory_url(const char **url,
+                                const char *suffix,
+                                apr_pool_t *pool)
+{
+  /* 8KB is a lot, but it almost guarantees that any path will fit. */
+  char curdir[8192];
+  const char *utf8_ls_curdir, *utf8_is_curdir, *unencoded_url;
+
+  if (! getcwd(curdir, sizeof(curdir)))
+    return svn_error_create(SVN_ERR_BASE, NULL, "getcwd() failed");
+
+  SVN_ERR(svn_utf_cstring_to_utf8(&utf8_ls_curdir, curdir, pool));
+  utf8_is_curdir = svn_path_internal_style(utf8_ls_curdir, pool);
+
+  unencoded_url = apr_psprintf(pool, "file://%s%s%s%s",
+                               (utf8_is_curdir[0] != '/') ? "/" : "",
+                               utf8_is_curdir,
+                               (suffix[0] && suffix[0] != '/') ? "/" : "",
+                               suffix);
+
+  *url = svn_path_uri_encode(unencoded_url, pool);
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
 svn_test__stream_to_string(svn_stringbuf_t **string,
                            svn_stream_t *stream,
                            apr_pool_t *pool)
@@ -606,55 +645,186 @@ svn_test__check_greek_tree(svn_fs_root_t *root,
   return SVN_NO_ERROR;
 }
 
-
-
+/**
+ * Loads the greek tree in a directory at ROOT_DIR under transaction TXN_ROOT.
+ * ROOT_DIR should be created by the caller.
+ *
+ * Note: this function will not commit the transaction.
+ */
 svn_error_t *
-svn_test__create_greek_tree(svn_fs_root_t *txn_root,
-                            apr_pool_t *pool)
+svn_test__create_greek_tree_at(svn_fs_root_t *txn_root,
+                               const char *root_dir,
+                               apr_pool_t *pool)
 {
-  SVN_ERR(svn_fs_make_file(txn_root, "iota", pool));
+  char *iota =     svn_relpath_join(root_dir, "iota", pool);
+  char *A =        svn_relpath_join(root_dir, "A", pool);
+  char *Amu =      svn_relpath_join(root_dir, "A/mu", pool);
+  char *AB =       svn_relpath_join(root_dir, "A/B", pool);
+  char *ABlambda = svn_relpath_join(root_dir, "A/B/lambda", pool);
+  char *ABE =      svn_relpath_join(root_dir, "A/B/E", pool);
+  char *ABEalpha = svn_relpath_join(root_dir, "A/B/E/alpha", pool);
+  char *ABEbeta =  svn_relpath_join(root_dir, "A/B/E/beta", pool);
+  char *ABF =      svn_relpath_join(root_dir, "A/B/F", pool);
+  char *AC =       svn_relpath_join(root_dir, "A/C", pool);
+  char *AD =       svn_relpath_join(root_dir, "A/D", pool);
+  char *ADgamma =  svn_relpath_join(root_dir, "A/D/gamma", pool);
+  char *ADG =      svn_relpath_join(root_dir, "A/D/G", pool);
+  char *ADGpi =    svn_relpath_join(root_dir, "A/D/G/pi", pool);
+  char *ADGrho =   svn_relpath_join(root_dir, "A/D/G/rho", pool);
+  char *ADGtau =   svn_relpath_join(root_dir, "A/D/G/tau", pool);
+  char *ADH =      svn_relpath_join(root_dir, "A/D/H", pool);
+  char *ADHchi =   svn_relpath_join(root_dir, "A/D/H/chi", pool);
+  char *ADHpsi =   svn_relpath_join(root_dir, "A/D/H/psi", pool);
+  char *ADHomega = svn_relpath_join(root_dir, "A/D/H/omega", pool);
+
+  SVN_ERR(svn_fs_make_file(txn_root, iota, pool));
   SVN_ERR(svn_test__set_file_contents
-          (txn_root, "iota", "This is the file 'iota'.\n", pool));
-  SVN_ERR(svn_fs_make_dir  (txn_root, "A", pool));
-  SVN_ERR(svn_fs_make_file(txn_root, "A/mu", pool));
+          (txn_root, iota, "This is the file 'iota'.\n", pool));
+  SVN_ERR(svn_fs_make_dir  (txn_root, A, pool));
+  SVN_ERR(svn_fs_make_file(txn_root, Amu, pool));
   SVN_ERR(svn_test__set_file_contents
-          (txn_root, "A/mu", "This is the file 'mu'.\n", pool));
-  SVN_ERR(svn_fs_make_dir  (txn_root, "A/B", pool));
-  SVN_ERR(svn_fs_make_file(txn_root, "A/B/lambda", pool));
+          (txn_root, Amu, "This is the file 'mu'.\n", pool));
+  SVN_ERR(svn_fs_make_dir  (txn_root, AB, pool));
+  SVN_ERR(svn_fs_make_file(txn_root, ABlambda, pool));
   SVN_ERR(svn_test__set_file_contents
-          (txn_root, "A/B/lambda", "This is the file 'lambda'.\n", pool));
-  SVN_ERR(svn_fs_make_dir  (txn_root, "A/B/E", pool));
-  SVN_ERR(svn_fs_make_file(txn_root, "A/B/E/alpha", pool));
+          (txn_root, ABlambda, "This is the file 'lambda'.\n", pool));
+  SVN_ERR(svn_fs_make_dir  (txn_root, ABE, pool));
+  SVN_ERR(svn_fs_make_file(txn_root, ABEalpha, pool));
   SVN_ERR(svn_test__set_file_contents
-          (txn_root, "A/B/E/alpha", "This is the file 'alpha'.\n", pool));
-  SVN_ERR(svn_fs_make_file(txn_root, "A/B/E/beta", pool));
+          (txn_root, ABEalpha, "This is the file 'alpha'.\n", pool));
+  SVN_ERR(svn_fs_make_file(txn_root, ABEbeta, pool));
   SVN_ERR(svn_test__set_file_contents
-          (txn_root, "A/B/E/beta", "This is the file 'beta'.\n", pool));
-  SVN_ERR(svn_fs_make_dir  (txn_root, "A/B/F", pool));
-  SVN_ERR(svn_fs_make_dir  (txn_root, "A/C", pool));
-  SVN_ERR(svn_fs_make_dir  (txn_root, "A/D", pool));
-  SVN_ERR(svn_fs_make_file(txn_root, "A/D/gamma", pool));
+          (txn_root, ABEbeta, "This is the file 'beta'.\n", pool));
+  SVN_ERR(svn_fs_make_dir  (txn_root, ABF, pool));
+  SVN_ERR(svn_fs_make_dir  (txn_root, AC, pool));
+  SVN_ERR(svn_fs_make_dir  (txn_root, AD, pool));
+  SVN_ERR(svn_fs_make_file(txn_root, ADgamma, pool));
   SVN_ERR(svn_test__set_file_contents
-          (txn_root, "A/D/gamma", "This is the file 'gamma'.\n", pool));
-  SVN_ERR(svn_fs_make_dir  (txn_root, "A/D/G", pool));
-  SVN_ERR(svn_fs_make_file(txn_root, "A/D/G/pi", pool));
+          (txn_root, ADgamma, "This is the file 'gamma'.\n", pool));
+  SVN_ERR(svn_fs_make_dir  (txn_root, ADG, pool));
+  SVN_ERR(svn_fs_make_file(txn_root, ADGpi, pool));
   SVN_ERR(svn_test__set_file_contents
-          (txn_root, "A/D/G/pi", "This is the file 'pi'.\n", pool));
-  SVN_ERR(svn_fs_make_file(txn_root, "A/D/G/rho", pool));
+          (txn_root, ADGpi, "This is the file 'pi'.\n", pool));
+  SVN_ERR(svn_fs_make_file(txn_root, ADGrho, pool));
   SVN_ERR(svn_test__set_file_contents
-          (txn_root, "A/D/G/rho", "This is the file 'rho'.\n", pool));
-  SVN_ERR(svn_fs_make_file(txn_root, "A/D/G/tau", pool));
+          (txn_root, ADGrho, "This is the file 'rho'.\n", pool));
+  SVN_ERR(svn_fs_make_file(txn_root, ADGtau, pool));
   SVN_ERR(svn_test__set_file_contents
-          (txn_root, "A/D/G/tau", "This is the file 'tau'.\n", pool));
-  SVN_ERR(svn_fs_make_dir  (txn_root, "A/D/H", pool));
-  SVN_ERR(svn_fs_make_file(txn_root, "A/D/H/chi", pool));
+          (txn_root, ADGtau, "This is the file 'tau'.\n", pool));
+  SVN_ERR(svn_fs_make_dir  (txn_root, ADH, pool));
+  SVN_ERR(svn_fs_make_file(txn_root, ADHchi, pool));
   SVN_ERR(svn_test__set_file_contents
-          (txn_root, "A/D/H/chi", "This is the file 'chi'.\n", pool));
-  SVN_ERR(svn_fs_make_file(txn_root, "A/D/H/psi", pool));
+          (txn_root, ADHchi, "This is the file 'chi'.\n", pool));
+  SVN_ERR(svn_fs_make_file(txn_root, ADHpsi, pool));
   SVN_ERR(svn_test__set_file_contents
-          (txn_root, "A/D/H/psi", "This is the file 'psi'.\n", pool));
-  SVN_ERR(svn_fs_make_file(txn_root, "A/D/H/omega", pool));
+          (txn_root, ADHpsi, "This is the file 'psi'.\n", pool));
+  SVN_ERR(svn_fs_make_file(txn_root, ADHomega, pool));
   SVN_ERR(svn_test__set_file_contents
-          (txn_root, "A/D/H/omega", "This is the file 'omega'.\n", pool));
+          (txn_root, ADHomega, "This is the file 'omega'.\n", pool));
   return SVN_NO_ERROR;
 }
+
+svn_error_t *
+svn_test__create_greek_tree(svn_fs_root_t *txn_root,
+                            apr_pool_t *pool)
+{
+  return svn_test__create_greek_tree_at(txn_root, "", pool);
+}
+
+svn_error_t *
+svn_test__create_blame_repository(svn_repos_t **out_repos,
+                                  const char *test_name,
+                                  const svn_test_opts_t *opts,
+                                  apr_pool_t *pool)
+{
+  svn_repos_t *repos;
+  svn_fs_t *fs;
+  svn_fs_txn_t *txn;
+  svn_fs_root_t *txn_root, *revision_root;
+  svn_revnum_t youngest_rev = 0;
+
+  /* Create a filesystem and repository. */
+  SVN_ERR(svn_test__create_repos(&repos, test_name,
+                                 opts, pool));
+  *out_repos = repos;
+
+  fs = svn_repos_fs(repos);
+
+  /* Revision 1:  Add trunk, tags, branches. */
+  SVN_ERR(svn_repos_fs_begin_txn_for_commit(&txn, repos, youngest_rev,
+                                            "initial", "log msg", pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_fs_make_dir(txn_root, "trunk", pool));
+  SVN_ERR(svn_fs_make_dir(txn_root, "tags", pool));
+  SVN_ERR(svn_fs_make_dir(txn_root, "branches", pool));
+  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
+
+  /* Revision 2:  Add the Greek tree on the trunk. */
+  SVN_ERR(svn_repos_fs_begin_txn_for_commit(&txn, repos, youngest_rev,
+                                            "initial", "log msg", pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_test__create_greek_tree_at(txn_root, "trunk", pool));
+  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
+
+  /* Revision 3:  Tweak trunk/A/mu. */
+  SVN_ERR(svn_repos_fs_begin_txn_for_commit(&txn, repos, youngest_rev,
+                                            "user-trunk", "log msg", pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_test__set_file_contents(txn_root, "trunk/A/mu",
+                                      "A\nB\nC\nD\nE\nF\nG\nH\nI", pool));
+  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
+
+  /* Revision 4:  Copy trunk to branches/1.0.x. */
+  SVN_ERR(svn_repos_fs_begin_txn_for_commit(&txn, repos, youngest_rev,
+                                            "copy", "log msg", pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_fs_revision_root(&revision_root, fs, youngest_rev, pool));
+  SVN_ERR(svn_fs_copy(revision_root, "trunk",
+                      txn_root, "branches/1.0.x",
+                      pool));
+  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
+
+  /* Revision 5:  Tweak trunk/A/mu. */
+  SVN_ERR(svn_repos_fs_begin_txn_for_commit(&txn, repos, youngest_rev,
+                                            "user-trunk", "log msg", pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_test__set_file_contents(txn_root, "trunk/A/mu",
+                                      "A\nB\nC -- trunk 
edit\nD\nE\nF\nG\nH\nI",
+                                      pool));
+  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
+
+  /* Revision 6:  Tweak branches/1.0.x/A/mu. */
+  SVN_ERR(svn_repos_fs_begin_txn_for_commit(&txn, repos, youngest_rev,
+                                            "user-branch", "log msg", pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_test__set_file_contents(txn_root, "branches/1.0.x/A/mu",
+                                      "A\nB\nC\nD -- branch 
edit\nE\nF\nG\nH\nI",
+                                      pool));
+  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
+
+  /* Revision 7:  Merge trunk to branch. */
+  SVN_ERR(svn_repos_fs_begin_txn_for_commit(&txn, repos, youngest_rev,
+                                            "user-merge1", "log msg", pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_test__set_file_contents(txn_root, "branches/1.0.x/A/mu",
+                                      "A\nB\nC -- trunk edit\nD -- branch edit"
+                                      "\nE\nF\nG\nH\nI", pool));
+  SVN_ERR(svn_fs_change_node_prop(txn_root, "/branches/1.0.x", "svn:mergeinfo",
+                                  svn_string_create("/trunk:4-6", pool),
+                                  pool));
+  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
+
+  /* Revision 8:  Merge branch to trunk. */
+  SVN_ERR(svn_repos_fs_begin_txn_for_commit(&txn, repos, youngest_rev,
+                                            "user-merge2", "log msg", pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_test__set_file_contents(txn_root, "trunk/A/mu",
+                                      "A\nB\nC -- trunk edit\nD -- branch 
edit\n"
+                                      "E\nF\nG\nH\nI", pool));
+  SVN_ERR(svn_fs_change_node_prop(txn_root, "/trunk", "svn:mergeinfo",
+                                  svn_string_create("/branches/1.0.x:4-7", 
pool),
+                                  pool));
+  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
+
+  return SVN_NO_ERROR;
+}

Reply via email to