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 */
}