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/12 13:07:19 UTC
svn commit: r1719665 - in /subversion/branches/ra-git/subversion:
libsvn_ra_git/commit.c tests/libsvn_client/git-client-test.c
Author: rhuijben
Date: Sat Dec 12 12:07:19 2015
New Revision: 1719665
URL: http://svn.apache.org/viewvc?rev=1719665&view=rev
Log:
On the ra-git branch: Extend commit support with handling of copies within
a branch.
* subversion/libsvn_ra_git/commit.c
(git_commit_node_baton_t): Add base revision variable.
(git_root): New helper function.
(git_commit__add_directory): Implement copying a directory.
(git_commit__open_directory): Remove too strict base rev check.
(git_commit__change_dir_prop): Add check here for future reference.
(git_commit__add_file): Handle copying.
(git_commit__close_file): Handle closing copied files.
* subversion/tests/libsvn_client/git-client-test.c
(test_git_add_nodes): Extend test.
Modified:
subversion/branches/ra-git/subversion/libsvn_ra_git/commit.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=1719665&r1=1719664&r2=1719665&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_git/commit.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_git/commit.c Sat Dec 12 12:07:19 2015
@@ -76,6 +76,7 @@ typedef struct git_commit_node_baton_t
struct git_commit_node_baton_t *pb;
git_commit_edit_baton_t *eb;
svn_boolean_t added;
+ svn_revnum_t base_rev;
apr_pool_t *pool;
@@ -93,6 +94,27 @@ typedef struct git_commit_node_baton_t
} git_commit_node_baton_t;
+static const char *
+git_root(const char *repos_relpath,
+ apr_pool_t *result_pool)
+{
+ const char *rp;
+
+ rp = svn_relpath_skip_ancestor("trunk", repos_relpath);
+ if (rp)
+ return "trunk";
+
+ rp = svn_relpath_skip_ancestor("branches", repos_relpath);
+ if (rp)
+ return svn_relpath_prefix(repos_relpath, 2, result_pool);
+
+ rp = svn_relpath_skip_ancestor("tags", repos_relpath);
+ if (rp)
+ return svn_relpath_prefix(repos_relpath, 2, result_pool);
+
+ return NULL;
+}
+
static svn_error_t *
setup_change_trees(git_commit_node_baton_t *db,
apr_pool_t *scratch_pool)
@@ -441,7 +463,9 @@ 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;
+ apr_pool_t *scratch_pool = result_pool;
const char *name;
+ svn_node_kind_t kind;
SVN_ERR(ensure_mutable(pb, path, SVN_INVALID_REVNUM,
result_pool));
@@ -458,11 +482,79 @@ git_commit__add_directory(const char *pa
db->node_path = svn_relpath_join(pb->node_path, name,
result_pool);
+ /* We just check the builder instead of db->root, as that handles
+ replacement caching for us... and we only have to check for existance
+ anyway */
+ 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);
+
if (copyfrom_path)
{
- /* TODO: LOOKUP copyfrom in git... setup dir_builder,
- root and root_path */
- return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+
+ svn_revnum_t created_rev;
+ svn_string_t *oid_value;
+ const char *git_root_path;
+
+ copyfrom_path = svn_uri_skip_ancestor(eb->sess->repos_root_url,
+ copyfrom_path, scratch_pool);
+
+ SVN_ERR(svn_fs_revision_root(&db->root, svn_repos_fs(eb->repos),
+ copyfrom_revision, result_pool));
+ db->root_path = copyfrom_path;
+
+ SVN_ERR(svn_fs_check_path(&kind, db->root, db->root_path, scratch_pool));
+
+ git_root_path = git_root(db->root_path, scratch_pool);
+
+ if (kind != svn_node_dir || !git_root_path || !*git_root_path)
+ return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL, NULL);
+
+ SVN_ERR(svn_fs_node_created_rev(&created_rev, db->root, db->root_path,
+ scratch_pool));
+
+ SVN_ERR(svn_fs_revision_prop2(&oid_value, svn_repos_fs(eb->repos),
+ created_rev,
+ "svn:git-commit-id", FALSE,
+ scratch_pool, scratch_pool));
+
+ if (oid_value)
+ {
+ git_oid oid;
+ const git_commit *commit;
+ const git_tree_entry *t_entry;
+ const git_tree *tree;
+
+ GIT2_ERR(git_oid_fromstr(&oid, oid_value->data));
+
+ SVN_ERR(svn_git__commit_lookup(&commit, eb->repository,
+ &oid, eb->pool));
+
+ SVN_ERR(svn_git__commit_tree_entry(&t_entry, commit,
+ svn_relpath_skip_ancestor(
+ git_root_path,
+ db->root_path),
+ result_pool, result_pool));
+
+ if (pb->dir_builder)
+ GIT2_ERR(git_treebuilder_insert(NULL, pb->dir_builder, name,
+ git_tree_entry_id(t_entry),
+ git_tree_entry_filemode(t_entry)));
+
+ 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, db->eb->repository,
+ tree, db->pool));
+ }
+
}
else
{
@@ -470,21 +562,13 @@ git_commit__add_directory(const char *pa
db->root_path = NULL;
}
- *child_baton = db;
+ if (!db->dir_builder)
+ SVN_ERR(svn_git__treebuilder_new(&db->dir_builder, db->eb->repository, NULL,
+ db->pool));
- 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);
+ *child_baton = db;
- SVN_ERR(svn_git__treebuilder_new(&db->dir_builder, db->eb->repository, NULL,
- result_pool));
return SVN_NO_ERROR;
}
@@ -531,16 +615,7 @@ git_commit__open_directory(const char *p
if (kind != svn_node_dir)
return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL, NULL);
- if (SVN_IS_VALID_REVNUM(base_revision) && db->root)
- {
- svn_revnum_t created_rev;
-
- SVN_ERR(svn_fs_node_created_rev(&created_rev, db->root, db->root_path,
- result_pool));
-
- if (created_rev > base_revision)
- return svn_error_create(SVN_ERR_FS_OUT_OF_DATE, NULL, NULL);
- }
+ db->base_rev = base_revision;
*child_baton = db;
return SVN_NO_ERROR;
@@ -557,6 +632,17 @@ git_commit__change_dir_prop(void *dir_ba
SVN_ERR(ensure_mutable(db, NULL, SVN_INVALID_REVNUM,
scratch_pool));
+ if (!db->added && SVN_IS_VALID_REVNUM(db->base_rev) && db->root)
+ {
+ svn_revnum_t created_rev;
+
+ SVN_ERR(svn_fs_node_created_rev(&created_rev, db->root, db->root_path,
+ scratch_pool));
+
+ if (created_rev > db->base_rev)
+ return svn_error_create(SVN_ERR_FS_OUT_OF_DATE, NULL, NULL);
+ }
+
return svn_error_create(APR_ENOTIMPL, NULL, NULL);
}
@@ -615,23 +701,90 @@ git_commit__add_file(const char *path,
void **file_baton)
{
git_commit_node_baton_t *pb = parent_baton;
+ git_commit_edit_baton_t *eb = pb->eb;
git_commit_node_baton_t *fb;
+ apr_pool_t *scratch_pool = result_pool;
+ 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,
- svn_relpath_basename(path, NULL),
+ fb->node_path = svn_relpath_join(pb->node_path, name,
result_pool);
+ fb->added = TRUE;
- if (copyfrom_path)
+ /* We just check the builder instead of db->root, as that handles
+ replacement caching for us... and we only have to check for existance
+ anyway */
+ 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
return svn_error_create(APR_ENOTIMPL, NULL, NULL);
- fb->added = TRUE;
+ if (copyfrom_path)
+ {
+ svn_node_kind_t kind;
+ svn_revnum_t created_rev;
+ svn_string_t *oid_value;
+ const char *git_root_path;
+
+ copyfrom_path = svn_uri_skip_ancestor(eb->sess->repos_root_url,
+ copyfrom_path, scratch_pool);
+
+ SVN_ERR(svn_fs_revision_root(&fb->root, svn_repos_fs(eb->repos),
+ copyfrom_revision, result_pool));
+ fb->root_path = copyfrom_path;
+
+ SVN_ERR(svn_fs_check_path(&kind, fb->root, fb->root_path, scratch_pool));
+
+ git_root_path = git_root(fb->root_path, scratch_pool);
+
+ if (kind != svn_node_file || !git_root_path || !*git_root_path)
+ return svn_error_create(SVN_ERR_FS_NOT_FILE, NULL, NULL);
+
+ SVN_ERR(svn_fs_node_created_rev(&created_rev, fb->root, fb->root_path,
+ scratch_pool));
+
+ SVN_ERR(svn_fs_revision_prop2(&oid_value, svn_repos_fs(eb->repos),
+ created_rev,
+ "svn:git-commit-id", FALSE,
+ scratch_pool, scratch_pool));
+
+ if (oid_value && pb->dir_builder)
+ {
+ git_oid oid;
+ const git_commit *commit;
+ const git_tree_entry *t_entry;
+
+ GIT2_ERR(git_oid_fromstr(&oid, oid_value->data));
+
+ SVN_ERR(svn_git__commit_lookup(&commit, eb->repository,
+ &oid, eb->pool));
+
+ SVN_ERR(svn_git__commit_tree_entry(&t_entry, commit,
+ svn_relpath_skip_ancestor(
+ git_root_path,
+ fb->root_path),
+ result_pool, result_pool));
+
+ GIT2_ERR(git_treebuilder_insert(NULL, pb->dir_builder, name,
+ git_tree_entry_id(t_entry),
+ git_tree_entry_filemode(t_entry)));
+ }
+ }
+
*file_baton = fb;
return SVN_NO_ERROR;
@@ -798,11 +951,9 @@ git_commit__close_file(void *file_baton,
NULL),
&blob_oid,
GIT_FILEMODE_BLOB));
-
- return SVN_NO_ERROR;
}
- return svn_error_create(APR_ENOTIMPL, NULL, NULL);
+ return SVN_NO_ERROR;
}
static svn_error_t *
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=1719665&r1=1719664&r2=1719665&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 Sat Dec 12 12:07:19 2015
@@ -339,6 +339,26 @@ test_git_add_nodes(const svn_test_opts_t
SVN_ERR(ls_recursive(&names, trunk_url, ctx, pool, subpool));
SVN_TEST_INT_ASSERT(apr_hash_count(names), 23);
+ svn_pool_clear(subpool);
+
+ SVN_ERR(svn_client__mtcc_create(&mtcc,
+ svn_path_url_add_component2(trunk_url, "A",
+ subpool),
+ 4, ctx, subpool, subpool));
+ SVN_ERR(svn_client__mtcc_add_copy("D", 2, "DD", mtcc, subpool));
+ SVN_ERR(svn_client__mtcc_add_copy("D/G/rho", 2, "rho", mtcc, subpool));
+ SVN_ERR(svn_client__mtcc_add_copy("D/G/rho", 2, "DD/rho", mtcc, subpool));
+
+ SVN_ERR(svn_client__mtcc_commit(apr_hash_make(subpool),
+ verify_commit, NULL, mtcc, subpool));
+
+ svn_pool_clear(subpool);
+
+ SVN_ERR(ls_recursive(&names, trunk_url, ctx, pool, subpool));
+ SVN_TEST_INT_ASSERT(apr_hash_count(names), 35);
+
+ svn_pool_clear(subpool);
+
return SVN_NO_ERROR;
}