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/02 12:26:47 UTC

svn commit: r1717609 - in /subversion/branches/ra-git/subversion/libsvn_fs_git: fs_git.h fsgit-metadata.sql fsgit-queries.sql gitdb.c revmap.c

Author: rhuijben
Date: Wed Dec  2 11:26:47 2015
New Revision: 1717609

URL: http://svn.apache.org/viewvc?rev=1717609&view=rev
Log:
On the ra-git branch: Implement importing branches and tags, separately
from 'trunk'. Extend storage a bit in preparation for more tag/branch
handling.

The current revision mapping is:
- whatever is in the current HEAD history and isn't mapped yet:
    -> map as commit on /trunk
- whatever is in a branch history and isn't mapped yet:
    -> map as commit on /branch/<branchname>
- whatever is in a tag and isn't mapped yet:
    -> map as commit on /tags/<tagname>
    (which actually creates a temporary branch in the tag namespace)

* subversion/libsvn_fs_git/fsgit-metadata.sql
  (REVMAP): Add prev_revnum to allow looking at copyfrom at sqlite level.

* subversion/libsvn_fs_git/fsgit-queries.sql
  (STMT_INSERT_COMMIT): Insert new value.

* subversion/libsvn_fs_git/fs_git.h
  (svn_fs_git__db_ensure_commit): Add a few arguments.

* subversion/libsvn_fs_git/gitdb.c
  (svn_fs_git__db_ensure_commit): Always return revision. Store prev_path
    and relpath in new created revisions.

* subversion/libsvn_fs_git/revmap.c
  (includes): Add svn_dirent_uri.h, svn_ctype.h.
  (revmap_update_branch): Pass oid and relpath as argument. Update caller.
  (revmap_update_tag): New function.
  (revmap_update): Walk HEAD, then branches, then tags.

Modified:
    subversion/branches/ra-git/subversion/libsvn_fs_git/fs_git.h
    subversion/branches/ra-git/subversion/libsvn_fs_git/fsgit-metadata.sql
    subversion/branches/ra-git/subversion/libsvn_fs_git/fsgit-queries.sql
    subversion/branches/ra-git/subversion/libsvn_fs_git/gitdb.c
    subversion/branches/ra-git/subversion/libsvn_fs_git/revmap.c

Modified: subversion/branches/ra-git/subversion/libsvn_fs_git/fs_git.h
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_git/fs_git.h?rev=1717609&r1=1717608&r2=1717609&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs_git/fs_git.h (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs_git/fs_git.h Wed Dec  2 11:26:47 2015
@@ -98,9 +98,12 @@ svn_fs_git__db_youngest_rev(svn_revnum_t
                             apr_pool_t *pool);
 
 svn_error_t *
-svn_fs_git__db_ensure_commit(svn_fs_t *fs,
+svn_fs_git__db_ensure_commit(svn_revnum_t *commit_rev,
+                             svn_fs_t *fs,
                              git_oid *oid,
-                             svn_revnum_t *latest_rev,
+                             svn_revnum_t youngest_rev,
+                             svn_revnum_t prev_rev,
+                             const char *relpath,
                              git_reference *ref);
 
 svn_error_t *

Modified: subversion/branches/ra-git/subversion/libsvn_fs_git/fsgit-metadata.sql
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_git/fsgit-metadata.sql?rev=1717609&r1=1717608&r2=1717609&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs_git/fsgit-metadata.sql (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs_git/fsgit-metadata.sql Wed Dec  2 11:26:47 2015
@@ -39,7 +39,9 @@ CREATE TABLE REVMAP (
   commit_id BINARY NOT NULL,
 
   /* The relpath below which we express this commit (E.g. 'trunk') */
-  relpath TEXT NOT NULL
+  relpath TEXT NOT NULL,
+
+  prev_revnum INTEGER NULL
 );
 
 CREATE UNIQUE INDEX I_REVMAP_COMMIT_ID ON REVMAP (commit_id);
@@ -72,7 +74,7 @@ CREATE TABLE CHECKSUMMAP (
 
   md5_checksum TEXT NOT NULL,
   sha1_checksum TEXT NOT NULL
-)
+);
 
 PRAGMA user_version =
 -- define: SVN_FS_GIT__VERSION

Modified: subversion/branches/ra-git/subversion/libsvn_fs_git/fsgit-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_git/fsgit-queries.sql?rev=1717609&r1=1717608&r2=1717609&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs_git/fsgit-queries.sql (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs_git/fsgit-queries.sql Wed Dec  2 11:26:47 2015
@@ -50,7 +50,8 @@ ORDER BY revnum DESC
 LIMIT 1
 
 -- STMT_INSERT_COMMIT
-INSERT INTO REVMAP (revnum, commit_id, relpath) VALUES (?1, ?2, ?3)
+INSERT INTO REVMAP (revnum, commit_id, relpath, prev_revnum)
+VALUES (?1, ?2, ?3, ?4)
 
 -- STMT_SELECT_CHECKSUM
 SELECT md5_checksum, sha1_checksum

Modified: subversion/branches/ra-git/subversion/libsvn_fs_git/gitdb.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_git/gitdb.c?rev=1717609&r1=1717608&r2=1717609&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs_git/gitdb.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs_git/gitdb.c Wed Dec  2 11:26:47 2015
@@ -63,9 +63,12 @@ svn_fs_git__db_youngest_rev(svn_revnum_t
 }
 
 svn_error_t *
-svn_fs_git__db_ensure_commit(svn_fs_t *fs,
+svn_fs_git__db_ensure_commit(svn_revnum_t *commit_rev,
+                             svn_fs_t *fs,
                              git_oid *oid,
-                             svn_revnum_t *latest_rev,
+                             svn_revnum_t youngest_rev,
+                             svn_revnum_t prev_rev,
+                             const char *relpath,
                              git_reference *ref)
 {
   svn_fs_git_fs_t *fgf = fs->fsap_data;
@@ -76,20 +79,21 @@ svn_fs_git__db_ensure_commit(svn_fs_t *f
   SVN_ERR(svn_sqlite__get_statement(&stmt, fgf->sdb, STMT_SELECT_REV_BY_COMMITID));
   SVN_ERR(svn_sqlite__bind_blob(stmt, 1, oid, sizeof(*oid)));
   SVN_ERR(svn_sqlite__step(&got_row, stmt));
+  if (got_row)
+    *commit_rev = svn_sqlite__column_revnum(stmt, 0);
   SVN_ERR(svn_sqlite__reset(stmt));
 
   if (got_row)
     return SVN_NO_ERROR;
 
-  new_rev = *latest_rev + 1;
+  *commit_rev = youngest_rev + 1;
   SVN_ERR(svn_sqlite__get_statement(&stmt, fgf->sdb, STMT_INSERT_COMMIT));
-  SVN_ERR(svn_sqlite__bind_revnum(stmt, 1, new_rev));
+  SVN_ERR(svn_sqlite__bind_revnum(stmt, 1, *commit_rev));
   SVN_ERR(svn_sqlite__bind_blob(stmt, 2, oid, sizeof(*oid)));
-  SVN_ERR(svn_sqlite__bind_text(stmt, 3, "trunk"));
+  SVN_ERR(svn_sqlite__bind_text(stmt, 3, relpath));
+  SVN_ERR(svn_sqlite__bind_revnum(stmt, 4, prev_rev));
   SVN_ERR(svn_sqlite__update(NULL, stmt));
 
-  *latest_rev = new_rev;
-
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/ra-git/subversion/libsvn_fs_git/revmap.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_git/revmap.c?rev=1717609&r1=1717608&r2=1717609&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs_git/revmap.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs_git/revmap.c Wed Dec  2 11:26:47 2015
@@ -25,17 +25,22 @@
 #include <string.h>
 
 #include "svn_pools.h"
+#include "svn_dirent_uri.h"
 #include "svn_fs.h"
+#include "svn_ctype.h"
 
 #include "private/svn_fs_private.h"
 #include "private/svn_sqlite.h"
 
 #include "fs_git.h"
 
+
 static svn_error_t *
 revmap_update_branch(svn_fs_t *fs,
                      svn_fs_git_fs_t *fgf,
                      git_reference *ref,
+                     const git_oid *walk_oid,
+                     const char *relpath,
                      svn_revnum_t *latest_rev,
                      svn_cancel_func_t cancel_func,
                      void *cancel_baton,
@@ -45,18 +50,47 @@ revmap_update_branch(svn_fs_t *fs,
   git_revwalk *revwalk = fgf->revwalk;
   int git_err;
   git_oid oid;
+  svn_revnum_t last_rev = SVN_INVALID_REVNUM;
+
+
+  /* ### TODO: Return if walk_oid is already mapped */
+
+  if (!relpath)
+    {
+      const char *n = strrchr(name, '/');
+
+      /* ### TODO: Improve algorithm */
+      if (n)
+        n++;
+      else
+        n = name;
+
+      relpath = svn_relpath_join("branches", n, scratch_pool);
+    }
 
   git_revwalk_reset(revwalk);
-  git_revwalk_push_ref(revwalk, name);
+  git_revwalk_push(revwalk, walk_oid);
   git_revwalk_simplify_first_parent(revwalk);
   git_revwalk_sorting(revwalk, GIT_SORT_REVERSE);
 
   while (!(git_err = git_revwalk_next(&oid, revwalk)))
     {
+      svn_revnum_t y_rev, rev;
       if (cancel_func)
         SVN_ERR(cancel_func(cancel_baton));
 
-      SVN_ERR(svn_fs_git__db_ensure_commit(fs, &oid, latest_rev, ref));
+      y_rev = *latest_rev;
+
+      SVN_ERR(svn_fs_git__db_ensure_commit(&rev, fs, &oid,
+                                           y_rev, last_rev,
+                                           relpath, ref));
+
+      if (rev > y_rev)
+        {
+          *latest_rev = rev;
+        }
+
+      last_rev = rev;
     }
 
   if (git_err != GIT_ITEROVER)
@@ -66,6 +100,134 @@ revmap_update_branch(svn_fs_t *fs,
 }
 
 static svn_error_t *
+revmap_update_tag(svn_fs_t *fs,
+                  svn_fs_git_fs_t *fgf,
+                  const char *name,
+                  const git_oid *oid,
+                  svn_revnum_t *latest_rev,
+                  svn_cancel_func_t cancel_func,
+                  void *cancel_baton,
+                  apr_pool_t *scratch_pool)
+{
+  svn_revnum_t rev;
+  const char *path;
+  git_object *obj;
+  git_oid walk_oid;
+  char *tagname = apr_pstrdup(scratch_pool, name);
+
+  if (!strncmp(tagname, "refs/tags/", 10))
+    tagname += 10;
+
+  {
+    char *c = tagname;
+
+    /* ### TODO: Improve algorithm */
+    while (*c)
+    {
+      if (!svn_ctype_isprint(*c))
+        *c = '_';
+      else if (strchr("/\\\"<>", *c))
+        *c = '_';
+
+      c++;
+    }
+  }
+
+  GIT2_ERR(git_object_lookup(&obj, fgf->repos, oid, GIT_OBJ_ANY));
+
+  if (git_object_type(obj) != GIT_OBJ_COMMIT)
+    {
+      git_object *commit;
+      int git_err = git_object_peel(&commit, obj,
+                                    GIT_OBJ_COMMIT);
+
+      if (!git_err)
+        {
+          git_object_free(obj);
+          obj = commit;
+        }
+    }
+
+  walk_oid = *git_object_id(obj);
+  git_object_free(obj);
+
+  SVN_ERR(svn_fs_git__db_fetch_rev(&rev, &path, fs, &walk_oid,
+                                   scratch_pool, scratch_pool));
+
+  if (!SVN_IS_VALID_REVNUM(rev))
+    {
+      const char *branchname;
+      svn_revnum_t y_rev = *latest_rev;
+
+      /* This commit doesn't exist on trunk or one of the branches...
+         Let's create a temporary branch.
+
+         The easiest to get 'free' path in the repository itself
+         is the tag itself */
+
+      branchname = svn_relpath_join("tags", tagname,
+                                    scratch_pool);
+
+      SVN_ERR(revmap_update_branch(fs, fgf, NULL, oid,
+                                   branchname,
+                                   latest_rev,
+                                   cancel_func, cancel_baton,
+                                   scratch_pool));
+
+      if (*latest_rev > y_rev)
+        {
+          rev = *latest_rev;
+          path = branchname;
+        }
+      else
+        {
+          /* The tag wasn't copied from a commit, and
+             doesn't have any unique commits */
+          SVN_ERR_MALFUNCTION();
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* Baton for revmap_update_tag_cb */
+typedef struct tag_update_baton_t
+{
+  svn_error_t *err;
+
+  svn_fs_t *fs;
+  svn_fs_git_fs_t *fgf;
+  svn_revnum_t *latest_rev;
+
+  apr_pool_t *iterpool;
+  svn_cancel_func_t cancel_func;
+  void *cancel_baton;
+
+} tag_update_baton_t;
+
+/* git_tag_foreach callback around revmap_update_tag */
+static int
+revmap_update_tag_cb(const char *name, git_oid *oid, void *payload)
+{
+  tag_update_baton_t *tub = payload;
+
+  if (!tub->err && tub->cancel_func)
+    tub->err = tub->cancel_func(tub->cancel_baton);
+
+  if (tub->err)
+    return 0;
+
+  svn_pool_clear(tub->iterpool);
+
+  tub->err = revmap_update_tag(tub->fs, tub->fgf,
+                               name, oid, tub->latest_rev,
+                               tub->cancel_func, tub->cancel_baton,
+                               tub->iterpool);
+
+  return 0;
+}
+
+static svn_error_t *
 revmap_update(svn_fs_t *fs,
               svn_fs_git_fs_t *fgf,
               svn_cancel_func_t cancel_func,
@@ -78,6 +240,7 @@ revmap_update(svn_fs_t *fs,
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   svn_error_t *err = NULL;
   svn_revnum_t latest_rev, youngest;
+  git_oid tmp_oid;
 
   SVN_ERR(svn_fs_git__db_youngest_rev(&youngest, fs, scratch_pool));
 
@@ -87,18 +250,67 @@ revmap_update(svn_fs_t *fs,
 
   latest_rev = youngest;
 
-  GIT2_ERR(git_branch_iterator_new(&iter, fgf->repos, GIT_BRANCH_ALL));
+  if (!git_repository_head_unborn(fgf->repos))
+    {
+      GIT2_ERR(git_repository_head(&ref, fgf->repos));
+
+      err = revmap_update_branch(fs, fgf, ref, git_reference_target(ref),
+                                 "trunk", &latest_rev,
+                                 cancel_func, cancel_baton,
+                                 iterpool);
+      git_reference_free(ref);
+      SVN_ERR(err);
+    }
 
+  GIT2_ERR(git_branch_iterator_new(&iter, fgf->repos, GIT_BRANCH_ALL));
   while (!git_branch_next(&ref, &branch_t, iter) && !err)
     {
+      const git_oid *walk_oid;
       svn_pool_clear(iterpool);
-      err = revmap_update_branch(fs, fgf, ref, &latest_rev,
+
+      walk_oid = git_reference_target(ref);
+
+      if (!walk_oid) {
+        git_reference *rr;
+        int git_err = git_reference_resolve(&rr, ref);
+
+        if (!git_err && rr)
+          {
+            tmp_oid = *git_reference_target(rr);
+            walk_oid = &tmp_oid;
+            git_reference_free(rr);
+          }
+      }
+
+      err = revmap_update_branch(fs, fgf, ref, walk_oid,
+                                 NULL, &latest_rev,
                                  cancel_func, cancel_baton,
                                  iterpool);
     }
 
   git_branch_iterator_free(iter);
 
+  {
+    int git_err;
+    tag_update_baton_t tub;
+
+    tub.fs = fs;
+    tub.fgf = fgf;
+    tub.latest_rev = &latest_rev;
+    tub.iterpool = iterpool;
+
+    tub.cancel_func = cancel_func;
+    tub.cancel_baton = cancel_baton;
+
+    tub.err = NULL;
+
+    git_err = git_tag_foreach(fgf->repos, revmap_update_tag_cb, &tub);
+
+    if (tub.err)
+      return svn_error_trace(tub.err);
+    GIT2_ERR(git_err);
+  }
+
   if (youngest < latest_rev) {
     /* TODO: Make sqlite optimize the order a bit */
   }