You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2015/12/11 15:56:35 UTC

svn commit: r1719439 - in /subversion/branches/ra-git/subversion: libsvn_ra_git/commit.c libsvn_ra_git/fetch.c libsvn_ra_git/ra_git.h libsvn_ra_git/session.c tests/libsvn_client/git-client-test.c

Author: rhuijben
Date: Fri Dec 11 14:56:35 2015
New Revision: 1719439

URL: http://svn.apache.org/viewvc?rev=1719439&view=rev
Log:
On the ra-git branch: Extend commit support. Start allowing some change
scenarios instead of only adding new nodes.

* subversion/libsvn_ra_git/commit.c
  (git_commit_node_baton_t): Extend struct to handle existing files.
  (setup_change_trees): Lookup existing trees.
  (git_commit__open_root): Setup root to allow checking existing nodes.
  (git_commit__delete_entry): Implement basic delete support.
  (git_commit__add_directory): Verify that we are not overwriting something.
  (git_commit__open_directory): Add basic support.
  (git_commit__add_file,
   git_commit__open_file,
   git_commit__apply_textdelta): Implement.
  (git_commit__close_file): Create file representation in git.

* subversion/libsvn_ra_git/fetch.c
  (svn_ra_git__split_url): Don't call svn_ra_git__wrap_git_error() on no
    git error as that raises an assertion.
  (svn_ra_git__push_commit): Determine proper location of trunk. Fetch
    actual author and date in fs.

* subversion/libsvn_ra_git/ra_git.h
  (svn_ra_git__session_t): Store branches.

* subversion/libsvn_ra_git/session.c
  (ra_git_open): Store branches.

* subversion/tests/libsvn_client/git-client-test.c
  (verify_commit): New function.
  (create_git_repos): Use dual pools.
  (create_git_repos_greek): New function.
  (test_git_mkdir): Update caller. Add file.
  (test_git_checkout): Use the greek tree. Perform checkout and update.
  (test_funcs): Mark test PASS.

Modified:
    subversion/branches/ra-git/subversion/libsvn_ra_git/commit.c
    subversion/branches/ra-git/subversion/libsvn_ra_git/fetch.c
    subversion/branches/ra-git/subversion/libsvn_ra_git/ra_git.h
    subversion/branches/ra-git/subversion/libsvn_ra_git/session.c
    subversion/branches/ra-git/subversion/tests/libsvn_client/git-client-test.c

Modified: subversion/branches/ra-git/subversion/libsvn_ra_git/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_ra_git/commit.c?rev=1719439&r1=1719438&r2=1719439&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_git/commit.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_git/commit.c Fri Dec 11 14:56:35 2015
@@ -73,14 +73,20 @@ typedef struct git_commit_node_baton_t
 {
   struct git_commit_node_baton_t *pb;
   git_commit_edit_baton_t *eb;
+  svn_boolean_t added;
 
   apr_pool_t *pool;
 
   svn_fs_root_t *root;
+  const char *root_path;
   const char *node_path;
 
   git_treebuilder *dir_builder;
-  svn_boolean_t added;
+
+  const char *tmp_abspath;
+  svn_checksum_t *result_checksum;
+  svn_checksum_t *base_checksum;
+  svn_checksum_t *expected_base_checks;
 
 } git_commit_node_baton_t;
 
@@ -88,9 +94,69 @@ static svn_error_t *
 setup_change_trees(git_commit_node_baton_t *db,
                    apr_pool_t *scratch_pool)
 {
+  git_commit_edit_baton_t *eb = db->eb;
+
   if (db->dir_builder)
     return SVN_NO_ERROR;
 
+  if (!db->pb)
+    {
+      if (strcmp(db->eb->root_path, db->node_path) == 0)
+        {
+          svn_node_kind_t kind;
+
+          /* We are creating or opening the branch */
+          SVN_ERR(svn_fs_check_path(&kind, eb->root, db->node_path,
+                                    scratch_pool));
+
+          db->root = eb->root;
+          db->root_path = db->node_path;
+
+          if (kind == svn_node_none)
+            SVN_ERR(svn_git__treebuilder_new(&db->dir_builder, eb->repository,
+                                             NULL, db->pool));
+          else if (kind == svn_node_dir)
+            {
+              int root_depth;
+              const git_tree *tree;
+              const char *root_relpath;
+
+              if (svn_relpath_skip_ancestor("trunk", db->node_path))
+                root_depth = 1;
+              else
+                root_depth = 2;
+
+              root_relpath = svn_relpath_skip_ancestor(
+                                svn_relpath_prefix(db->node_path, root_depth,
+                                                   scratch_pool),
+                                db->node_path);
+
+              if (eb->created_rev == 0)
+                tree = NULL;
+              else
+                {
+                  git_tree_entry *t_entry;
+
+                  SVN_ERR(svn_git__commit_tree_entry(&t_entry, eb->commit,
+                                                     root_relpath,
+                                                     db->pool, scratch_pool));
+
+                  if (!t_entry)
+                    return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
+                                             _("'%s' not found in git tree"),
+                                             root_relpath);
+
+                  SVN_ERR(svn_git__tree_lookup(&tree, eb->repository,
+                                               git_tree_entry_id(t_entry),
+                                               db->pool));
+                }
+
+              SVN_ERR(svn_git__treebuilder_new(&db->dir_builder, eb->repository,
+                                               tree, db->pool));
+            }
+        }
+    }
+
   if (db->pb && !db->pb->dir_builder)
     SVN_ERR(setup_change_trees(db->pb, scratch_pool));
 
@@ -121,6 +187,8 @@ setup_change_trees(git_commit_node_baton
 
   if (strcmp(db->eb->root_path, db->node_path))
     {
+      db->root = db->eb->root;
+      db->root_path = db->node_path;
     }
 
   return SVN_NO_ERROR;
@@ -249,13 +317,17 @@ git_commit__open_root(void *edit_baton,
                       void **root_baton)
 {
   git_commit_node_baton_t *nb = apr_pcalloc(result_pool, sizeof(*nb));
-  nb->eb = edit_baton;
+  git_commit_edit_baton_t *eb = edit_baton;
+  nb->eb = eb;
   nb->pool = result_pool;
 
   nb->node_path = svn_uri_skip_ancestor(nb->eb->sess->repos_root_url,
                                         nb->eb->sess->session_url_buf->data,
                                         result_pool);
 
+  nb->root = eb->root;
+  nb->root_path = nb->node_path;
+
   *root_baton = nb;
 
   return SVN_NO_ERROR;
@@ -268,10 +340,24 @@ git_commit__delete_entry(const char *pat
                          apr_pool_t *scratch_pool)
 {
   git_commit_node_baton_t *pb = parent_baton;
+  const git_tree_entry *t_entry;
+  const char *name;
 
   SVN_ERR(ensure_mutable(pb, path, revision, scratch_pool));
 
-  return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+  if (!pb->dir_builder)
+    return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+
+  name = svn_relpath_basename(path, NULL);
+
+  t_entry = git_treebuilder_get(pb->dir_builder, name);
+
+  if (!t_entry)
+    return svn_error_create(SVN_ERR_FS_NOT_FOUND, NULL, NULL);
+
+  GIT2_ERR(git_treebuilder_remove(pb->dir_builder, name));
+
+  return SVN_NO_ERROR;
 }
 
 static svn_error_t *
@@ -285,7 +371,7 @@ git_commit__add_directory(const char *pa
   git_commit_node_baton_t *pb = parent_baton;
   git_commit_edit_baton_t *eb = pb->eb;
   git_commit_node_baton_t *db;
-  const char *relpath;
+  const char *name;
 
   SVN_ERR(ensure_mutable(pb, path, SVN_INVALID_REVNUM,
                          result_pool));
@@ -293,18 +379,40 @@ git_commit__add_directory(const char *pa
   if (!pb->eb->change_mode)
     return svn_error_create(APR_ENOTIMPL, NULL, NULL);
 
+  name = svn_relpath_basename(path, NULL);
+
   db = apr_pcalloc(result_pool, sizeof(*db));
   db->pb = pb;
   db->eb = eb;
   db->pool = result_pool;
-  db->node_path = svn_relpath_join(pb->node_path,
-                                   svn_relpath_basename(path, NULL),
+  db->node_path = svn_relpath_join(pb->node_path, name,
                                    result_pool);
 
-  relpath = svn_relpath_skip_ancestor(eb->root_path, db->node_path);
+  if (copyfrom_path)
+    {
+      /* TODO: LOOKUP copyfrom in git... setup dir_builder,
+               root and root_path */
+      return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+    }
+  else
+    {
+      db->root = NULL;
+      db->root_path = NULL;
+    }
 
   *child_baton = db;
 
+  if (pb->dir_builder)
+    {
+      const git_tree_entry *t_entry = git_treebuilder_get(pb->dir_builder,
+                                                          name);
+
+      if (t_entry)
+        return svn_error_create(SVN_ERR_FS_ALREADY_EXISTS, NULL, NULL);
+    }
+  else if (strcmp(db->node_path, eb->root_path) != 0)
+    return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+
   SVN_ERR(svn_git__treebuilder_new(&db->dir_builder, db->eb->repository, NULL,
                                    result_pool));
 
@@ -319,8 +427,42 @@ git_commit__open_directory(const char *p
                            void **child_baton)
 {
   git_commit_node_baton_t *pb = parent_baton;
+  git_commit_edit_baton_t *eb = pb->eb;
+  git_commit_node_baton_t *db;
+  const char *name;
+  svn_node_kind_t kind;
 
-  return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+  /* Hmm... not nice, but works for now */
+  SVN_ERR(ensure_mutable(pb, path, SVN_INVALID_REVNUM,
+                         result_pool));
+ 
+ if (!pb->eb->change_mode)
+    return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+
+  name = svn_relpath_basename(path, NULL);
+
+  db = apr_pcalloc(result_pool, sizeof(*db));
+  db->pb = pb;
+  db->eb = eb;
+  db->pool = result_pool;
+  db->node_path = svn_relpath_join(pb->node_path, name,
+                                   result_pool);
+  if (pb->root)
+    {
+      db->root = pb->root;
+      db->root_path = svn_relpath_join(pb->root_path, name,
+                                       result_pool);
+
+      SVN_ERR(svn_fs_check_path(&kind, db->root, db->root_path, result_pool));
+    }
+  else
+    kind = svn_node_none;
+
+  if (kind != svn_node_dir)
+    return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL, NULL);
+
+  *child_baton = db;
+  return SVN_NO_ERROR;
 }
 
 static svn_error_t *
@@ -372,11 +514,26 @@ git_commit__add_file(const char *path,
                      void **file_baton)
 {
   git_commit_node_baton_t *pb = parent_baton;
+  git_commit_node_baton_t *fb;
 
   SVN_ERR(ensure_mutable(pb, path, SVN_INVALID_REVNUM,
                          result_pool));
 
-  return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+  fb = apr_pcalloc(result_pool, sizeof(*fb));
+  fb->pb = pb;
+  fb->eb = pb->eb;
+  fb->pool = result_pool;
+  fb->node_path = svn_relpath_join(pb->node_path,
+                                   svn_relpath_basename(path, NULL),
+                                   result_pool);
+
+  if (copyfrom_path)
+    return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+
+  fb->added = TRUE;
+  *file_baton = fb;
+
+  return SVN_NO_ERROR;
 }
 
 static svn_error_t *
@@ -386,7 +543,41 @@ git_commit__open_file(const char *path,
                       apr_pool_t *result_pool,
                       void **file_baton)
 {
-  return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+  git_commit_node_baton_t *pb = parent_baton;
+  git_commit_node_baton_t *fb;
+  svn_node_kind_t kind;
+  const char *name;
+
+  SVN_ERR(ensure_mutable(pb, path, SVN_INVALID_REVNUM,
+                         result_pool));
+
+  name = svn_relpath_basename(path, NULL);
+
+  fb = apr_pcalloc(result_pool, sizeof(*fb));
+  fb->pb = pb;
+  fb->eb = pb->eb;
+  fb->pool = result_pool;
+  fb->node_path = svn_relpath_join(pb->node_path, name,
+                                   result_pool);
+
+  if (!pb->root)
+    kind = svn_node_none;
+  else
+    {
+      fb->root = pb->root;
+      fb->root_path = svn_relpath_join(pb->root_path, name,
+                                       result_pool);
+
+      SVN_ERR(svn_fs_check_path(&kind, fb->root, fb->root_path,
+                                result_pool));
+    }
+
+  if (kind != svn_node_file)
+    return svn_error_create(SVN_ERR_FS_NOT_FILE, NULL, NULL);
+
+  *file_baton = fb;
+
+  return SVN_NO_ERROR;
 }
 
 static svn_error_t *
@@ -396,7 +587,36 @@ git_commit__apply_textdelta(void *file_b
                             svn_txdelta_window_handler_t *handler,
                             void **handler_baton)
 {
-  return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+  git_commit_node_baton_t *fb = file_baton;
+  apr_file_t *fnew;
+  svn_stream_t *base_stream;
+
+  if (base_checksum)
+    SVN_ERR(svn_checksum_parse_hex(&fb->expected_base_checks, svn_checksum_md5,
+                                   base_checksum, fb->pool));
+
+  SVN_ERR(svn_io_open_unique_file3(&fnew, &fb->tmp_abspath, NULL,
+                                   svn_io_file_del_on_pool_cleanup,
+                                   fb->pool, result_pool));
+
+  if (fb->added)
+    base_stream = svn_stream_empty(result_pool);
+  else
+    SVN_ERR(svn_fs_file_contents(&base_stream, fb->root, fb->root_path,
+                                 result_pool));
+
+  svn_txdelta_apply(svn_stream_checksummed2(
+                        base_stream,
+                        &fb->base_checksum, NULL, svn_checksum_md5, TRUE,
+                        result_pool),
+                    svn_stream_checksummed2(
+                        svn_stream_from_aprfile2(fnew, FALSE, result_pool),
+                        NULL, &fb->result_checksum, svn_checksum_md5, FALSE,
+                        result_pool),
+                    NULL, NULL, result_pool,
+                    handler, handler_baton);
+
+  return SVN_NO_ERROR;
 }
 
 static svn_error_t *
@@ -413,7 +633,26 @@ git_commit__close_file(void *file_baton,
                        const char *text_checksum,
                        apr_pool_t *scratch_pool)
 {
-  return SVN_NO_ERROR;
+  git_commit_node_baton_t *fb = file_baton;
+
+  /* TODO: Verify checksums! */
+
+  if (fb->pb->dir_builder && fb->tmp_abspath)
+    {
+      git_oid blob_oid;
+      GIT2_ERR(git_blob_create_fromdisk(&blob_oid, fb->eb->repository,
+                                        fb->tmp_abspath));
+
+      GIT2_ERR(git_treebuilder_insert(NULL, fb->pb->dir_builder,
+                                      svn_relpath_basename(fb->node_path,
+                                                           NULL),
+                                      &blob_oid,
+                                      GIT_FILEMODE_BLOB));
+
+      return SVN_NO_ERROR;
+    }
+
+  return svn_error_create(APR_ENOTIMPL, NULL, NULL);
 }
 
 static svn_error_t *

Modified: subversion/branches/ra-git/subversion/libsvn_ra_git/fetch.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_ra_git/fetch.c?rev=1719439&r1=1719438&r2=1719439&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_git/fetch.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_git/fetch.c Fri Dec 11 14:56:35 2015
@@ -210,11 +210,9 @@ svn_ra_git__split_url(const char **repos
       *git_remote_url = apr_pstrdup(result_pool, remote_url_buf->data);
     }
   else
-    return svn_error_compose_create(
-      svn_ra_git__wrap_git_error(),
-      svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
-                        _("No git repository found at URL '%s'"),
-                        url));
+    return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
+                             _("No git repository found at URL '%s'"),
+                             url);
 
   SVN_DBG(("found remote url '%s', fs_path: '%s'\n",
            *repos_root_url, *repos_relpath));
@@ -292,6 +290,24 @@ svn_ra_git__push_commit(svn_ra_session_t
   git_remote *remote;
   git_remote_callbacks *callbacks;
   apr_pool_t *subpool;
+  const char *to_ref = "refs/heads/master";
+
+  if (strcmp(edit_relpath, "trunk") == 0)
+    {
+      int i;
+      for (i = 0; i < sess->branches->nelts; i++)
+        {
+          svn_ra_git_branch_t *br = APR_ARRAY_IDX(sess->branches, i,
+                                                  svn_ra_git_branch_t *);
+
+          if (br->symref_target && !strcasecmp(br->name, "HEAD"))
+            to_ref = br->symref_target;
+        }
+    }
+  else
+    {
+      /* TODO: Determine proper branch reference from edit path */
+    }
 
   /* Create subpool, to allow closing handles early on */
   subpool = svn_pool_create(scratch_pool);
@@ -309,7 +325,7 @@ svn_ra_git__push_commit(svn_ra_session_t
     refspecs.strings = &refspec;
 
     push_opts.callbacks = *callbacks;
-    refspec = apr_pstrcat(scratch_pool, "+", reference, ":refs/heads/master",
+    refspec = apr_pstrcat(scratch_pool, "+", reference, ":", to_ref,
                           SVN_VA_NULL);
 
     GIT2_ERR(git_remote_push(remote, &refspecs, &push_opts));
@@ -321,14 +337,21 @@ svn_ra_git__push_commit(svn_ra_session_t
 
   if (callback)
     {
+      apr_hash_t *revprops;
       svn_commit_info_t *info = svn_create_commit_info(subpool);
 
-      info->author = "Q";
-      info->date = svn_time_to_cstring(apr_time_now(), subpool);
-
+      /* Should we really handle cases where this isn't the last
+         revision? */
       SVN_ERR(sess->local_session->vtable->get_latest_revnum(
-                  sess->local_session, &info->revision,
-                  subpool));
+        sess->local_session, &info->revision,
+        subpool));
+
+      SVN_ERR(sess->local_session->vtable->rev_proplist(
+        sess->local_session, info->revision, &revprops, subpool));
+
+      info->author = svn_prop_get_value(revprops, SVN_PROP_REVISION_AUTHOR);
+      info->date = svn_prop_get_value(revprops, SVN_PROP_REVISION_DATE);
+      info->repos_root = sess->repos_root_url;
 
       SVN_ERR(callback(info, callback_baton, scratch_pool));
     }

Modified: subversion/branches/ra-git/subversion/libsvn_ra_git/ra_git.h
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_ra_git/ra_git.h?rev=1719439&r1=1719438&r2=1719439&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_git/ra_git.h (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_git/ra_git.h Fri Dec 11 14:56:35 2015
@@ -35,6 +35,7 @@ typedef struct svn_ra_git__session_t
 
   /* The URL of the session. */
   const char *repos_root_url;
+  apr_array_header_t *branches;
 
   /* The file:/// session backing the git session*/
   svn_ra_session_t *local_session;

Modified: subversion/branches/ra-git/subversion/libsvn_ra_git/session.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_ra_git/session.c?rev=1719439&r1=1719438&r2=1719439&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_git/session.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_git/session.c Fri Dec 11 14:56:35 2015
@@ -291,12 +291,11 @@ ra_git_open(svn_ra_session_t *session,
  * the repository (in sess->fs_path). */
   {
     const char *repos_relpath;
-    apr_array_header_t *branches;
 
     SVN_ERR(svn_ra_git__split_url(&sess->repos_root_url,
                                   &repos_relpath,
                                   &sess->git_remote_url,
-                                  &branches,
+                                  &sess->branches,
                                   sess, session_URL,
                                   result_pool, scratch_pool));
 

Modified: subversion/branches/ra-git/subversion/tests/libsvn_client/git-client-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_client/git-client-test.c?rev=1719439&r1=1719438&r2=1719439&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_client/git-client-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_client/git-client-test.c Fri Dec 11 14:56:35 2015
@@ -35,36 +35,94 @@
 #include "../svn_test.h"
 #include "../svn_test_fs.h"
 
+static svn_error_t *
+verify_commit(const svn_commit_info_t *commit_info,
+              void *baton,
+              apr_pool_t *pool)
+{
+  SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(commit_info->revision));
+  SVN_TEST_ASSERT(commit_info->repos_root != NULL);
+
+  return SVN_NO_ERROR;
+}
 
 /* Create a GIT repository */
 static svn_error_t *
 create_git_repos(const char **repos_url,
                  const char *name,
-                 apr_pool_t *pool)
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
 {
   const char *fs_dir;
   svn_fs_t *fs;
 
-  apr_pool_t *subpool = svn_pool_create(pool);
-
-  SVN_ERR(svn_dirent_get_absolute(&fs_dir, name, subpool));
-  SVN_ERR(svn_io_remove_dir2(fs_dir, TRUE, NULL, NULL, subpool));
+  SVN_ERR(svn_dirent_get_absolute(&fs_dir, name, scratch_pool));
+  SVN_ERR(svn_io_remove_dir2(fs_dir, TRUE, NULL, NULL, scratch_pool));
   svn_test_add_dir_cleanup(fs_dir);
 
   {
-    apr_hash_t *fs_config = apr_hash_make(subpool);
+    apr_hash_t *fs_config = apr_hash_make(scratch_pool);
     svn_hash_sets(fs_config, SVN_FS_CONFIG_FS_TYPE, SVN_FS_TYPE_GIT);
 
-    SVN_ERR(svn_fs_create2(&fs, fs_dir, fs_config, subpool, subpool));
+    SVN_ERR(svn_fs_create2(&fs, fs_dir, fs_config,
+                           scratch_pool, scratch_pool));
   }
 
-  fs_dir = svn_dirent_join(fs_dir, "git", subpool);
+  fs_dir = svn_dirent_join(fs_dir, "git", scratch_pool);
 
-  SVN_ERR(svn_uri_get_file_url_from_dirent(repos_url, fs_dir, subpool));
+  SVN_ERR(svn_uri_get_file_url_from_dirent(repos_url, fs_dir, scratch_pool));
 
-  *repos_url = apr_pstrcat(pool, "git+", *repos_url, SVN_VA_NULL);
+  *repos_url = apr_pstrcat(result_pool, "git+", *repos_url, SVN_VA_NULL);
 
-  svn_pool_destroy(subpool);
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+create_git_repos_greek(const char **repos_url,
+                       const char *name,
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool)
+{
+  svn_client_ctx_t *ctx;
+  svn_client__mtcc_t *mtcc;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  const svn_test__tree_entry_t *ge;
+
+  SVN_ERR(create_git_repos(repos_url, name, result_pool, iterpool));
+
+  SVN_ERR(svn_client_create_context2(&ctx, NULL, scratch_pool));
+  SVN_ERR(svn_test__init_auth_baton(&ctx->auth_baton, scratch_pool));
+
+  SVN_ERR(svn_client__mtcc_create(&mtcc, *repos_url, 0, ctx,
+                                  scratch_pool, iterpool));
+
+  SVN_ERR(svn_client__mtcc_add_mkdir("trunk", mtcc, iterpool));
+
+  for (ge = svn_test__greek_tree_nodes; ge->path; ge++)
+    {
+      const char *relpath;
+      svn_pool_clear(iterpool);
+
+      relpath = svn_relpath_join("trunk", ge->path, iterpool);
+
+      if (!ge->contents)
+        SVN_ERR(svn_client__mtcc_add_mkdir(relpath, mtcc, iterpool));
+      else
+        SVN_ERR(svn_client__mtcc_add_add_file(
+                    relpath,
+                    svn_stream_from_string(
+                        svn_string_create(ge->contents,
+                                          scratch_pool),
+                        scratch_pool),
+                    NULL,
+                    mtcc, iterpool));
+    }
+
+  SVN_ERR(svn_client__mtcc_commit(apr_hash_make(iterpool),
+                                  verify_commit, NULL,
+                                  mtcc, iterpool));
+
+  svn_pool_destroy(iterpool);
   return SVN_NO_ERROR;
 }
 
@@ -78,12 +136,14 @@ test_git_mkdir(const svn_test_opts_t *op
   const char *trunk_url;
   apr_pool_t *subpool = svn_pool_create(pool);
 
-  SVN_ERR(create_git_repos(&repos_url, "git-mkdir", subpool));
+  SVN_ERR(create_git_repos(&repos_url, "git-mkdir", pool, subpool));
 
-  SVN_ERR(svn_dirent_get_absolute(&wc_dir, "git-mkdir-wc", subpool));
+  SVN_ERR(svn_dirent_get_absolute(&wc_dir, "git-mkdir-wc", pool));
   SVN_ERR(svn_io_remove_dir2(wc_dir, TRUE, NULL, NULL, subpool));
   svn_test_add_dir_cleanup(wc_dir);
 
+  svn_pool_clear(subpool);
+
   SVN_ERR(svn_client_create_context2(&ctx, NULL, pool));
 
   trunk_url = svn_path_url_add_component2(repos_url, "trunk", pool);
@@ -108,12 +168,12 @@ test_git_mkdir(const svn_test_opts_t *op
   SVN_ERR(svn_client__mtcc_add_mkdir("trunk/A", mtcc, subpool));
   SVN_ERR(svn_client__mtcc_add_mkdir("trunk/A/E", mtcc, subpool));
 
-  //SVN_ERR(svn_client__mtcc_add_add_file(
-  //  "trunk/iota",
-  //  svn_stream_from_string(svn_string_create("This is the file 'iota'\n",
-  //                                           subpool),
-  //                         subpool),
-  //  NULL, mtcc, subpool));
+  SVN_ERR(svn_client__mtcc_add_add_file(
+    "trunk/iota",
+    svn_stream_from_string(svn_string_create("This is the file 'iota'\n",
+                                             subpool),
+                           subpool),
+    NULL, mtcc, subpool));
 
   SVN_ERR(svn_client__mtcc_commit(apr_hash_make(subpool),
                                   NULL, NULL, mtcc, subpool));
@@ -130,49 +190,40 @@ test_git_checkout(const svn_test_opts_t
   const char *wc_dir;
   svn_client_ctx_t *ctx;
   svn_client__mtcc_t *mtcc;
+  svn_opt_revision_t head_rev;
+  svn_revnum_t rev;
   const char *trunk_url;
   apr_pool_t *subpool = svn_pool_create(pool);
 
-  SVN_ERR(create_git_repos(&repos_url, "git-checkout-repos", subpool));
+  SVN_ERR(create_git_repos_greek(&repos_url, "git-checkout-repos",
+                                 pool, subpool));
 
-  SVN_ERR(svn_dirent_get_absolute(&wc_dir, "git-checkout-wc", subpool));
+  SVN_ERR(svn_dirent_get_absolute(&wc_dir, "git-checkout-wc", pool));
   SVN_ERR(svn_io_remove_dir2(wc_dir, TRUE, NULL, NULL, subpool));
   svn_test_add_dir_cleanup(wc_dir);
 
   SVN_ERR(svn_client_create_context2(&ctx, NULL, pool));
-
   trunk_url = svn_path_url_add_component2(repos_url, "trunk", pool);
-  //head_rev.kind = svn_opt_revision_head;
-  //SVN_ERR(svn_client_checkout3(&rev, trunk_url,
-  //                             wc_dir, &head_rev, &head_rev, svn_depth_infinity,
-  //                             FALSE, FALSE, ctx, pool));
-  //
-  //
-  //{
-  //  apr_array_header_t *revs;
-  //  apr_array_header_t *paths = apr_array_make(pool, 1, sizeof(const char *));
-  //  APR_ARRAY_PUSH(paths, const char *) = wc_dir;
-  //
-  //  SVN_ERR(svn_client_update4(&revs, paths, &head_rev, svn_depth_infinity, FALSE,
-  //                             FALSE, FALSE, FALSE, FALSE, ctx, pool));
-  //}
 
-  SVN_ERR(svn_client__mtcc_create(&mtcc, repos_url, 0, ctx, subpool, subpool));
+  svn_pool_clear(subpool);
 
-  SVN_ERR(svn_client__mtcc_add_mkdir("trunk", mtcc, subpool));
+  head_rev.kind = svn_opt_revision_head;
+  SVN_ERR(svn_client_checkout3(&rev, trunk_url,
+                               wc_dir, &head_rev, &head_rev, svn_depth_infinity,
+                               FALSE, FALSE, ctx, subpool));
 
-  SVN_ERR(svn_client__mtcc_add_add_file(
-    "trunk/iota",
-    svn_stream_from_string(svn_string_create("This is the file 'iota'\n",
-                                             subpool),
-                           subpool),
-    NULL, mtcc, subpool));
+  svn_pool_clear(subpool);
+  {
+    apr_array_header_t *revs;
+    apr_array_header_t *paths = apr_array_make(pool, 1, sizeof(const char *));
+    APR_ARRAY_PUSH(paths, const char *) = wc_dir;
+  
+    SVN_ERR(svn_client_update4(&revs, paths, &head_rev, svn_depth_infinity, FALSE,
+                               FALSE, FALSE, FALSE, FALSE, ctx, subpool));
+  }
 
-  SVN_ERR(svn_client__mtcc_commit(apr_hash_make(subpool),
-                                  NULL, NULL, mtcc, subpool));
 
   svn_pool_destroy(subpool);
-
   return SVN_NO_ERROR;
 }
 
@@ -186,7 +237,7 @@ static struct svn_test_descriptor_t test
   SVN_TEST_NULL,
   SVN_TEST_OPTS_PASS(test_git_mkdir,
                      "test git_mkdir"),
-  SVN_TEST_OPTS_XFAIL(test_git_checkout,
+  SVN_TEST_OPTS_PASS(test_git_checkout,
                      "test git_checkout"),
 
   SVN_TEST_NULL