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/10 12:20:26 UTC

svn commit: r1719065 - 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: Thu Dec 10 11:20:26 2015
New Revision: 1719065

URL: http://svn.apache.org/viewvc?rev=1719065&view=rev
Log:
On the ra-git branch: Following up on r1719060, commit the actual changes.

* subversion/libsvn_ra_git/commit.c
  New file.

* subversion/libsvn_ra_git/fetch.c
  (includes): Add ../libsvn_fs_git/svn_git.h.
  (cleanup_git_repos): Remove function.
  (svn_ra_git__push_commit): New function.
  (open_git_repos): Update caller.

* subversion/libsvn_ra_git/ra_git.h
  (svn_ra_git__wrap_git_error,
   GIT2_ERR,
   GIT2_ERR_NOTFOUND): Remove here.
  (svn_ra_git__push_commit,
   svn_ra_git__get_commit_editor): New function.

* subversion/libsvn_ra_git/session.c
  (ra_git_get_commit_editor): Add implementation.

* subversion/tests/libsvn_client/git-client-test.c
  New file.

Added:
    subversion/branches/ra-git/subversion/libsvn_ra_git/commit.c   (with props)
    subversion/branches/ra-git/subversion/tests/libsvn_client/git-client-test.c   (with props)
Modified:
    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

Added: 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=1719065&view=auto
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_git/commit.c (added)
+++ subversion/branches/ra-git/subversion/libsvn_ra_git/commit.c Thu Dec 10 11:20:26 2015
@@ -0,0 +1,551 @@
+/*
+ * commit.c : Handles some commit scenarios to a libsvn_fs_git backend.
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+#include "../libsvn_fs_git/svn_git.h"
+
+#include "svn_hash.h"
+#include "svn_dirent_uri.h"
+#include "svn_ra.h"
+#include "svn_repos.h"
+#include "svn_fs.h"
+#include "svn_pools.h"
+#include "svn_props.h"
+#include "svn_delta.h"
+
+#include "svn_private_config.h"
+#include "../libsvn_ra/ra_loader.h"
+#include "private/svn_atomic.h"
+#include "private/svn_fspath.h"
+
+#include "ra_git.h"
+
+typedef struct git_commit_edit_baton_t
+{
+  apr_pool_t *pool;
+  svn_ra_session_t *session;
+  svn_ra_git__session_t *sess;
+
+  svn_repos_t *repos;
+  svn_fs_root_t *root;
+  svn_revnum_t created_rev;
+
+  git_repository *repository;
+  const git_commit *commit;
+
+  svn_boolean_t aborted, done;
+
+  svn_commit_callback2_t commit_cb;
+  void *commit_baton;
+
+  apr_hash_t *revprops;
+
+  svn_boolean_t tag_mode;
+  svn_boolean_t change_mode;
+
+  const char *root_path;
+
+  svn_boolean_t tree_written;
+  git_oid tree_oid;
+
+} git_commit_edit_baton_t;
+
+typedef struct git_commit_node_baton_t
+{
+  struct git_commit_node_baton_t *pb;
+  git_commit_edit_baton_t *eb;
+
+  apr_pool_t *pool;
+
+  svn_fs_root_t *root;
+  const char *node_path;
+
+  git_treebuilder *dir_builder;
+  svn_boolean_t added;
+
+} git_commit_node_baton_t;
+
+static svn_error_t *
+setup_change_trees(git_commit_node_baton_t *db,
+                   apr_pool_t *scratch_pool)
+{
+  if (db->dir_builder)
+    return SVN_NO_ERROR;
+
+  if (db->pb && !db->pb->dir_builder)
+    SVN_ERR(setup_change_trees(db->pb, scratch_pool));
+
+  if (db->pb && db->pb->dir_builder)
+    {
+      const git_tree_entry *entry;
+      const git_tree *tree = NULL;
+      entry = git_treebuilder_get(db->dir_builder,
+                                  svn_relpath_basename(db->node_path, NULL));
+
+      if (entry)
+        {
+          const git_object *obj;
+
+          SVN_ERR(svn_git__tree_entry_to_object(&obj, db->eb->repository,
+                                                entry, db->pool));
+
+          tree = (const git_tree*)obj;
+        }
+
+      SVN_ERR(svn_git__treebuilder_new(&db->dir_builder, db->eb->repository, tree,
+                                       db->pool));
+      return SVN_NO_ERROR;
+    }
+
+  if (!db->node_path[0])
+    return SVN_NO_ERROR; /* Creating 'trunk' */
+
+  if (strcmp(db->eb->root_path, db->node_path))
+    {
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+ensure_mutable(git_commit_node_baton_t *nb,
+               const char *path,
+               svn_revnum_t base_rev,
+               apr_pool_t *scratch_pool)
+{
+  git_commit_edit_baton_t *eb = nb->eb;
+
+  if (!path)
+    path = nb->node_path;
+  else
+    path = svn_relpath_join(nb->node_path,
+                            svn_relpath_basename(path, NULL),
+                            scratch_pool);
+
+  if (!(eb->tag_mode || eb->change_mode))
+    {
+      if (svn_relpath_skip_ancestor("trunk", path))
+        {
+          eb->change_mode = TRUE;
+          eb->root_path = "trunk";
+        }
+      else if (svn_relpath_skip_ancestor("branches", path))
+        {
+          if (strlen(path) > 8)
+            {
+              eb->change_mode = TRUE;
+              eb->root_path = svn_relpath_prefix(path, 2, eb->pool);
+            }
+          else
+            {
+              eb->tag_mode = TRUE;
+              eb->root_path = "branches";
+            }
+        }
+      else if (!strcmp("tags", path))
+        {
+          eb->tag_mode = TRUE;
+          eb->root_path = "tags";
+        }
+      else
+        return svn_error_createf(SVN_ERR_RA_NOT_IMPLEMENTED, NULL,
+                                 _("Can't commit directly to '%s' "
+                                   "in a git repository"),
+                                 path);
+
+      if (eb->change_mode)
+        {
+          svn_revnum_t youngest;
+          svn_fs_t *fs;
+          const git_tree *tree = NULL;
+
+          SVN_ERR(svn_repos_open3(&eb->repos, eb->sess->local_repos_abspath, NULL,
+                                  eb->pool, scratch_pool));
+
+          fs = svn_repos_fs(eb->repos);
+          SVN_ERR(svn_fs_youngest_rev(&youngest, fs, scratch_pool));
+
+          SVN_ERR(svn_fs_revision_root(&eb->root, fs, youngest, scratch_pool));
+
+          SVN_ERR(svn_fs_node_created_rev(&eb->created_rev, eb->root,
+                                          eb->root_path, scratch_pool));
+
+          SVN_ERR(svn_git__repository_open(&eb->repository,
+                                           svn_dirent_join(
+                                             eb->sess->local_repos_abspath,
+                                             "db/git", scratch_pool),
+                                           eb->pool));
+
+          if (eb->created_rev > 0)
+            {
+              svn_string_t *oid_value;
+
+              SVN_ERR(svn_fs_revision_prop2(&oid_value, fs, eb->created_rev,
+                                            "svn:git-commit-id", FALSE,
+                                            scratch_pool, scratch_pool));
+
+              if (oid_value)
+                {
+                  git_oid oid;
+
+                  GIT2_ERR(git_oid_fromstr(&oid, oid_value->data));
+
+                  SVN_ERR(svn_git__commit_lookup(&eb->commit, eb->repository,
+                                                 &oid, eb->pool));
+
+                  if (eb->commit)
+                    SVN_ERR(svn_git__commit_tree(&tree, eb->commit, eb->pool));
+                }
+            }
+          else
+            tree = NULL;
+
+          SVN_ERR(setup_change_trees(nb, scratch_pool));
+        }
+    }
+
+  if (eb->change_mode)
+    {
+      if (!svn_relpath_skip_ancestor(eb->root_path, path))
+        return svn_error_createf(SVN_ERR_RA_NOT_IMPLEMENTED, NULL,
+                                 _("Can't commit to '%s' and '%s' in one commit"),
+                                 eb->root_path, path);
+    }
+  else
+    {
+      const char *rp = svn_relpath_skip_ancestor(eb->root_path, path);
+
+      if (!rp || !*rp || strchr(rp, '/'))
+        return svn_error_createf(SVN_ERR_RA_NOT_IMPLEMENTED, NULL,
+                                 _("Can't tag to '%s'"), path);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+git_commit__open_root(void *edit_baton,
+                      svn_revnum_t base_revision,
+                      apr_pool_t *result_pool,
+                      void **root_baton)
+{
+  git_commit_node_baton_t *nb = apr_pcalloc(result_pool, sizeof(*nb));
+  nb->eb = edit_baton;
+  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);
+
+  *root_baton = nb;
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+git_commit__delete_entry(const char *path,
+                         svn_revnum_t revision,
+                         void *parent_baton,
+                         apr_pool_t *scratch_pool)
+{
+  git_commit_node_baton_t *pb = parent_baton;
+
+  SVN_ERR(ensure_mutable(pb, path, revision, scratch_pool));
+
+  return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+}
+
+static svn_error_t *
+git_commit__add_directory(const char *path,
+                          void *parent_baton,
+                          const char *copyfrom_path,
+                          svn_revnum_t copyfrom_revision,
+                          apr_pool_t *result_pool,
+                          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 *relpath;
+
+  SVN_ERR(ensure_mutable(pb, path, SVN_INVALID_REVNUM,
+                         result_pool));
+
+  if (!pb->eb->change_mode)
+    return svn_error_create(APR_ENOTIMPL, NULL, 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),
+                                   result_pool);
+
+  relpath = svn_relpath_skip_ancestor(eb->root_path, db->node_path);
+
+  *child_baton = db;
+
+  SVN_ERR(svn_git__treebuilder_new(&db->dir_builder, db->eb->repository, NULL,
+                                   result_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+git_commit__open_directory(const char *path,
+                           void *parent_baton,
+                           svn_revnum_t base_revision,
+                           apr_pool_t *result_pool,
+                           void **child_baton)
+{
+  git_commit_node_baton_t *pb = parent_baton;
+
+  return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+}
+
+static svn_error_t *
+git_commit__change_dir_prop(void *dir_baton,
+                            const char *name,
+                            const svn_string_t *value,
+                            apr_pool_t *scratch_pool)
+{
+  git_commit_node_baton_t *db = dir_baton;
+
+  SVN_ERR(ensure_mutable(db, NULL, SVN_INVALID_REVNUM,
+                         scratch_pool));
+
+  return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+}
+
+static svn_error_t *
+git_commit__close_directory(void *dir_baton,
+                            apr_pool_t *scratch_pool)
+{
+  git_commit_node_baton_t *db = dir_baton;
+
+  if (db->dir_builder)
+    {
+      git_oid oid;
+
+      GIT2_ERR(git_treebuilder_write(&oid, db->dir_builder));
+
+      if (db->pb && db->pb->dir_builder)
+        GIT2_ERR(git_treebuilder_insert(NULL, db->pb->dir_builder,
+                                        svn_relpath_basename(db->node_path,
+                                                             NULL),
+                                        &oid, GIT_FILEMODE_TREE));
+      else if (!strcmp(db->node_path, db->eb->root_path))
+        {
+          db->eb->tree_oid = oid;
+          db->eb->tree_written = TRUE;
+        }
+    }
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+git_commit__add_file(const char *path,
+                     void *parent_baton,
+                     const char *copyfrom_path,
+                     svn_revnum_t copyfrom_revision,
+                     apr_pool_t *result_pool,
+                     void **file_baton)
+{
+  git_commit_node_baton_t *pb = parent_baton;
+
+  SVN_ERR(ensure_mutable(pb, path, SVN_INVALID_REVNUM,
+                         result_pool));
+
+  return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+}
+
+static svn_error_t *
+git_commit__open_file(const char *path,
+                      void *parent_baton,
+                      svn_revnum_t base_revision,
+                      apr_pool_t *result_pool,
+                      void **file_baton)
+{
+  return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+}
+
+static svn_error_t *
+git_commit__apply_textdelta(void *file_baton,
+                            const char *base_checksum,
+                            apr_pool_t *result_pool,
+                            svn_txdelta_window_handler_t *handler,
+                            void **handler_baton)
+{
+  return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+}
+
+static svn_error_t *
+git_commit__change_file_prop(void *file_baton,
+                             const char *name,
+                             const svn_string_t *value,
+                             apr_pool_t *scratch_pool)
+{
+  return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+}
+
+static svn_error_t *
+git_commit__close_file(void *file_baton,
+                       const char *text_checksum,
+                       apr_pool_t *scratch_pool)
+{
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+git_commit__close_edit(void *edit_baton,
+                       apr_pool_t *scratch_pool)
+{
+  git_commit_edit_baton_t *eb = edit_baton;
+
+  if (eb->done || eb->aborted)
+    return SVN_NO_ERROR;
+
+  if (eb->tree_written)
+    {
+      git_oid commit_oid;
+      git_signature *author;
+      int git_err;
+      svn_string_t *log_value;
+      svn_error_t *err;
+      const char *ref = svn_relpath_join("refs/tmp",
+                                         svn_uuid_generate(scratch_pool),
+                                         scratch_pool);
+      const git_tree *tree;
+
+      SVN_ERR(svn_git__tree_lookup(&tree, eb->repository, &eb->tree_oid,
+                                   scratch_pool));
+
+      git_err = git_signature_default(&author, eb->repository);
+      if (git_err != GIT_ENOTFOUND)
+        GIT2_ERR(git_err);
+      else
+        {
+          /* ### TODO: Fetch something better */
+          GIT2_ERR(git_signature_now(&author, "svn-dummy",
+                                     "svn-dummy@subversion.tigris.org"));
+        }
+
+      log_value = svn_hash_gets(eb->revprops, SVN_PROP_REVISION_LOG);
+
+      git_err = git_commit_create(&commit_oid, eb->repository, ref,
+                                  author, author,
+                                  "UTF-8",
+                                  log_value ? log_value->data : "",
+                                  tree,
+                                  eb->commit ? 1 : 0,
+                                  eb->commit ? &eb->commit : NULL);
+
+      git_signature_free(author);
+      GIT2_ERR(git_err);
+
+      /* Ok, we now have a commit... Let's push it to the actual server.
+
+         We can then fetch it back and return the revision of to the result */
+      err = svn_error_trace(
+              svn_ra_git__push_commit(eb->session,
+                                      ref, eb->root_path, &commit_oid,
+                                      eb->commit_cb, eb->commit_baton,
+                                      scratch_pool));
+
+      if (err)
+        {
+          git_reference_remove(eb->repository, ref);
+          giterr_clear();
+        }
+
+      eb->done = TRUE;
+      svn_pool_destroy(eb->pool);
+
+      return err;
+    }
+
+  //if (eb->treebuilder)
+  //  {
+  //    git_oid oid;
+  //
+  //    GIT2_ERR(git_treebuilder_write(&oid, eb->treebuilder));
+  //  }
+
+  return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+}
+
+static svn_error_t *
+git_commit__abort_edit(void *edit_baton,
+                       apr_pool_t *scratch_pool)
+{
+  git_commit_edit_baton_t *eb = edit_baton;
+  eb->aborted = TRUE;
+
+  if (!eb->done)
+    {
+      eb->done = TRUE;
+      svn_pool_destroy(eb->pool);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_ra_git__get_commit_editor(const svn_delta_editor_t **editor_p,
+                              void **edit_baton_p,
+                              svn_ra_session_t *session,
+                              apr_hash_t *revprop_table,
+                              svn_commit_callback2_t callback,
+                              void *callback_baton,
+                              apr_pool_t *pool)
+{
+  svn_ra_git__session_t *sess = session->priv;
+  git_commit_edit_baton_t *eb = apr_pcalloc(pool, sizeof(*eb));
+  svn_delta_editor_t *editor = svn_delta_default_editor(pool);
+
+  eb->pool = svn_pool_create(pool);
+  eb->revprops = revprop_table;
+  eb->commit_cb = callback;
+  eb->commit_baton = callback_baton;
+  eb->session = session;
+  eb->sess = sess;
+
+  editor->open_root        = git_commit__open_root;
+  editor->delete_entry     = git_commit__delete_entry;
+  editor->add_directory    = git_commit__add_directory;
+  editor->open_directory   = git_commit__open_directory;
+  editor->change_dir_prop  = git_commit__change_dir_prop;
+  editor->close_directory  = git_commit__close_directory;
+  editor->add_file         = git_commit__add_file;
+  editor->open_file        = git_commit__open_file;
+  editor->change_file_prop = git_commit__change_file_prop;
+  editor->apply_textdelta  = git_commit__apply_textdelta;
+  editor->close_file       = git_commit__close_file;
+
+  editor->close_edit       = git_commit__close_edit;
+  editor->abort_edit       = git_commit__abort_edit;
+
+  *editor_p = editor;
+  *edit_baton_p = eb;
+  return SVN_NO_ERROR;
+}

Propchange: subversion/branches/ra-git/subversion/libsvn_ra_git/commit.c
------------------------------------------------------------------------------
    svn:eol-style = native

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=1719065&r1=1719064&r2=1719065&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_git/fetch.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_git/fetch.c Thu Dec 10 11:20:26 2015
@@ -22,9 +22,7 @@
  * ====================================================================
  */
 
-#include <apr.h>
-
-#include <git2.h>
+#include "../libsvn_fs_git/svn_git.h"
 
 #include "svn_hash.h"
 #include "svn_ra.h"
@@ -78,13 +76,6 @@ svn_ra_git__wrap_git_error(void)
 }
 
 static apr_status_t
-cleanup_git_repos(void *baton)
-{
-  git_repository_free(baton);
-  return APR_SUCCESS;
-}
-
-static apr_status_t
 cleanup_git_remote(void *baton)
 {
   git_remote_free(baton);
@@ -287,6 +278,64 @@ svn_ra_git__git_fetch(svn_ra_session_t *
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_ra_git__push_commit(svn_ra_session_t *session,
+                        const char *reference,
+                        const char *edit_relpath,
+                        const struct git_oid *commit_oid,
+                        svn_commit_callback2_t callback,
+                        void *callback_baton,
+                        apr_pool_t *scratch_pool)
+{
+  svn_ra_git__session_t *sess = session->priv;
+  git_repository *repos;
+  git_remote *remote;
+  git_remote_callbacks *callbacks;
+  apr_pool_t *subpool;
+
+  /* Create subpool, to allow closing handles early on */
+  subpool = svn_pool_create(scratch_pool);
+
+  SVN_ERR(open_git_repos(&repos, &remote, &callbacks, sess,
+                         subpool, subpool));
+
+  SVN_DBG(("Pushing to %s\n", sess->git_remote_url));
+
+  {
+    git_push_options push_opts = GIT_PUSH_OPTIONS_INIT;
+    git_strarray refspecs;
+    char *refspec;
+    refspecs.count = 1;
+    refspecs.strings = &refspec;
+
+    push_opts.callbacks = *callbacks;
+    refspec = apr_pstrcat(scratch_pool, "+", reference, ":refs/heads/master",
+                          SVN_VA_NULL);
+
+    GIT2_ERR(git_remote_push(remote, &refspecs, &push_opts));
+  }
+
+  svn_pool_clear(subpool);
+
+  SVN_ERR(svn_ra_git__git_fetch(session, TRUE, subpool));
+
+  if (callback)
+    {
+      svn_commit_info_t *info = svn_create_commit_info(subpool);
+
+      info->author = "Q";
+      info->date = svn_time_to_cstring(apr_time_now(), subpool);
+
+      SVN_ERR(sess->local_session->vtable->get_latest_revnum(
+                  sess->local_session, &info->revision,
+                  subpool));
+
+      SVN_ERR(callback(info, callback_baton, scratch_pool));
+    }
+
+  svn_pool_destroy(subpool);
+  return SVN_NO_ERROR;
+}
 
 
 /* Fetch a username for use with SESS */
@@ -669,13 +718,10 @@ open_git_repos(git_repository **repos,
   SVN_ERR(svn_atomic__init_once(&do_libgit2_init_called, do_libgit2_init,
                                 NULL, scratch_pool));
 
-  GIT2_ERR(git_repository_open(repos,
-                               svn_dirent_join(sess->local_repos_abspath,
-                                               "db/git", scratch_pool)));
-
-  if (*repos)
-    apr_pool_cleanup_register(result_pool, *repos, cleanup_git_repos,
-                              apr_pool_cleanup_null);
+  SVN_ERR(svn_git__repository_open(repos,
+                                   svn_dirent_join(sess->local_repos_abspath,
+                                                   "db/git", scratch_pool),
+                                   result_pool));
 
   if (remote)
     {

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=1719065&r1=1719064&r2=1719065&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 Thu Dec 10 11:20:26 2015
@@ -63,27 +63,6 @@ typedef struct svn_ra_git__session_t
   apr_uint64_t progress_bytes;
 } svn_ra_git__session_t;
 
-svn_error_t *
-svn_ra_git__wrap_git_error(void);
-
-#define GIT2_ERR(expr)                        \
-  do {                                        \
-    int svn_err__git_temp = (expr);           \
-    if (svn_err__git_temp)                    \
-      return svn_ra_git__wrap_git_error();    \
-  } while (0)
-
-#define GIT2_ERR_NOTFOUND(x, expr)            \
-  do {                                        \
-    int svn_err__git_temp = (expr);           \
-    if (svn_err__git_temp == GIT_ENOTFOUND)   \
-      {                                       \
-        giterr_clear();                       \
-        *x = NULL;                            \
-      }                                       \
-    else if (svn_err__git_temp)               \
-      return svn_ra_git__wrap_git_error();    \
-  } while (0)
 
 /* Git repositories don't have a UUID so a static UUID is as good as any. */
 #define RA_GIT_UUID "a62d4ba0-b83e-11e3-8621-8f162a3365eb"
@@ -112,6 +91,26 @@ svn_ra_git__git_fetch(svn_ra_session_t *
                       svn_boolean_t refresh,
                       apr_pool_t *scratch_pool);
 
+struct git_oid;
+
+svn_error_t *
+svn_ra_git__push_commit(svn_ra_session_t *session,
+                        const char *reference,
+                        const char *edit_relpath,
+                        const struct git_oid *commit_oid,
+                        svn_commit_callback2_t callback,
+                        void *callback_baton,
+                        apr_pool_t *scratch_pool);
+
+svn_error_t *
+svn_ra_git__get_commit_editor(const svn_delta_editor_t **editor,
+                              void **edit_baton,
+                              svn_ra_session_t *session,
+                              apr_hash_t *revprop_table,
+                              svn_commit_callback2_t callback,
+                              void *callback_baton,
+                              apr_pool_t *pool);
+
 void
 svn_ra_git__libgit2_version(int *major,
                             int *minor,

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=1719065&r1=1719064&r2=1719065&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_git/session.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_git/session.c Thu Dec 10 11:20:26 2015
@@ -570,7 +570,16 @@ ra_git_get_commit_editor(svn_ra_session_
                          svn_boolean_t keep_locks,
                          apr_pool_t *pool)
 {
-  return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, NULL, NULL);
+  svn_ra_git__session_t *sess = session->priv;
+
+  SVN_ERR(ensure_local_session(session, pool));
+  SVN_ERR(svn_ra_git__git_fetch(session, TRUE, sess->scratch_pool));
+
+  return svn_error_trace(
+    svn_ra_git__get_commit_editor(editor, edit_baton,
+                                  session, revprop_table,
+                                  callback, callback_baton,
+                                  pool));
 }
 
 

Added: 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=1719065&view=auto
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_client/git-client-test.c (added)
+++ subversion/branches/ra-git/subversion/tests/libsvn_client/git-client-test.c Thu Dec 10 11:20:26 2015
@@ -0,0 +1,196 @@
+/*
+* Regression tests for logic in the libsvn_client library.
+*
+* ====================================================================
+*    Licensed to the Apache Software Foundation (ASF) under one
+*    or more contributor license agreements.  See the NOTICE file
+*    distributed with this work for additional information
+*    regarding copyright ownership.  The ASF licenses this file
+*    to you under the Apache License, Version 2.0 (the
+*    "License"); you may not use this file except in compliance
+*    with the License.  You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+*    Unless required by applicable law or agreed to in writing,
+*    software distributed under the License is distributed on an
+*    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+*    KIND, either express or implied.  See the License for the
+*    specific language governing permissions and limitations
+*    under the License.
+* ====================================================================
+*/
+
+#include "svn_pools.h"
+#include "svn_client.h"
+#include "private/svn_client_mtcc.h"
+
+#include "svn_repos.h"
+#include "svn_subst.h"
+#include "private/svn_sorts_private.h"
+#include "private/svn_wc_private.h"
+#include "svn_props.h"
+#include "svn_hash.h"
+
+#include "../svn_test.h"
+#include "../svn_test_fs.h"
+
+
+/* Create a GIT repository */
+static svn_error_t *
+create_git_repos(const char **repos_url,
+                 const char *name,
+                 apr_pool_t *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_test_add_dir_cleanup(fs_dir);
+
+  {
+    apr_hash_t *fs_config = apr_hash_make(subpool);
+    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));
+  }
+
+  fs_dir = svn_dirent_join(fs_dir, "git", subpool);
+
+  SVN_ERR(svn_uri_get_file_url_from_dirent(repos_url, fs_dir, subpool));
+
+  *repos_url = apr_pstrcat(pool, "git+", *repos_url, SVN_VA_NULL);
+
+  svn_pool_destroy(subpool);
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_git_mkdir(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+  const char *repos_url;
+  const char *wc_dir;
+  svn_client_ctx_t *ctx;
+  svn_client__mtcc_t *mtcc;
+  const char *trunk_url;
+  apr_pool_t *subpool = svn_pool_create(pool);
+
+  SVN_ERR(create_git_repos(&repos_url, "git-mkdir", subpool));
+
+  SVN_ERR(svn_dirent_get_absolute(&wc_dir, "git-mkdir-wc", subpool));
+  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_ERR(svn_client__mtcc_add_mkdir("trunk", mtcc, subpool));
+  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_commit(apr_hash_make(subpool),
+                                  NULL, NULL, mtcc, subpool));
+
+  svn_pool_destroy(subpool);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_git_checkout(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+  const char *repos_url;
+  const char *wc_dir;
+  svn_client_ctx_t *ctx;
+  svn_client__mtcc_t *mtcc;
+  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(svn_dirent_get_absolute(&wc_dir, "git-checkout-wc", subpool));
+  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_ERR(svn_client__mtcc_add_mkdir("trunk", 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));
+
+  svn_pool_destroy(subpool);
+
+  return SVN_NO_ERROR;
+}
+
+/* ========================================================================== */
+
+
+static int max_threads = 3;
+
+static struct svn_test_descriptor_t test_funcs[] =
+{
+  SVN_TEST_NULL,
+  SVN_TEST_OPTS_PASS(test_git_mkdir,
+                     "test git_mkdir"),
+  SVN_TEST_OPTS_XFAIL(test_git_checkout,
+                     "test git_checkout"),
+
+  SVN_TEST_NULL
+};
+
+SVN_TEST_MAIN
+

Propchange: subversion/branches/ra-git/subversion/tests/libsvn_client/git-client-test.c
------------------------------------------------------------------------------
    svn:eol-style = native