Commit 52ba17f3 by yuangli

Merge branch 'pr/pks-t/5254' into shallow-clone-local

parents fbea439d 70a332a5
...@@ -228,6 +228,7 @@ typedef enum { ...@@ -228,6 +228,7 @@ typedef enum {
GIT_OPT_SET_EXTENSIONS, GIT_OPT_SET_EXTENSIONS,
GIT_OPT_GET_OWNER_VALIDATION, GIT_OPT_GET_OWNER_VALIDATION,
GIT_OPT_SET_OWNER_VALIDATION GIT_OPT_SET_OWNER_VALIDATION
GIT_OPT_ENABLE_SHALLOW
} git_libgit2_opt_t; } git_libgit2_opt_t;
/** /**
...@@ -465,6 +466,9 @@ typedef enum { ...@@ -465,6 +466,9 @@ typedef enum {
* > to support repositories with the `noop` extension but does want * > to support repositories with the `noop` extension but does want
* > to support repositories with the `newext` extension. * > to support repositories with the `newext` extension.
* *
* opts(GIT_OPT_ENABLE_SHALLOW, int enabled)
* > Enable or disable shallow clone support completely.
*
* opts(GIT_OPT_GET_OWNER_VALIDATION, int *enabled) * opts(GIT_OPT_GET_OWNER_VALIDATION, int *enabled)
* > Gets the owner validation setting for repository * > Gets the owner validation setting for repository
* > directories. * > directories.
......
...@@ -109,7 +109,8 @@ typedef enum { ...@@ -109,7 +109,8 @@ typedef enum {
GIT_ERROR_WORKTREE, GIT_ERROR_WORKTREE,
GIT_ERROR_SHA, GIT_ERROR_SHA,
GIT_ERROR_HTTP, GIT_ERROR_HTTP,
GIT_ERROR_INTERNAL GIT_ERROR_INTERNAL,
GIT_ERROR_GRAFTS
} git_error_t; } git_error_t;
/** /**
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "types.h" #include "types.h"
#include "oid.h" #include "oid.h"
#include "buffer.h" #include "buffer.h"
#include "oidarray.h"
/** /**
* @file git2/repository.h * @file git2/repository.h
......
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "grafts.h"
#include "futils.h"
#include "oidarray.h"
#include "parse.h"
bool git_shallow__enabled = false;
struct git_grafts {
/* Map of `git_commit_graft`s */
git_oidmap *commits;
/* File backing the graft. NULL if it's an in-memory graft */
char *path;
git_oid path_checksum;
};
int git_grafts_new(git_grafts **out)
{
git_grafts *grafts;
grafts = git__calloc(1, sizeof(*grafts));
GIT_ERROR_CHECK_ALLOC(grafts);
if ((git_oidmap_new(&grafts->commits)) < 0) {
git__free(grafts);
return -1;
}
*out = grafts;
return 0;
}
int git_grafts_from_file(git_grafts **out, const char *path)
{
git_grafts *grafts = NULL;
int error;
if ((error = git_grafts_new(&grafts)) < 0)
goto error;
grafts->path = git__strdup(path);
GIT_ERROR_CHECK_ALLOC(grafts->path);
if ((error = git_grafts_refresh(grafts)) < 0)
goto error;
*out = grafts;
error:
if (error < 0)
git_grafts_free(grafts);
return error;
}
void git_grafts_free(git_grafts *grafts)
{
if (!grafts)
return;
git__free(grafts->path);
git_grafts_clear(grafts);
git_oidmap_free(grafts->commits);
git__free(grafts);
}
void git_grafts_clear(git_grafts *grafts)
{
git_commit_graft *graft;
assert(grafts);
git_oidmap_foreach_value(grafts->commits, graft, {
git__free(graft->parents.ptr);
git__free(graft);
});
git_oidmap_clear(grafts->commits);
}
int git_grafts_refresh(git_grafts *grafts)
{
git_buf contents = GIT_BUF_INIT;
int error, updated = 0;
assert(grafts);
if (!grafts->path)
return 0;
error = git_futils_readbuffer_updated(&contents, grafts->path,
&grafts->path_checksum, &updated);
if (error < 0 || error == GIT_ENOTFOUND || !updated) {
if (error == GIT_ENOTFOUND) {
git_grafts_clear(grafts);
error = 0;
}
goto cleanup;
}
if ((error = git_grafts_parse(grafts, contents.ptr, contents.size)) < 0)
goto cleanup;
cleanup:
git_buf_dispose(&contents);
return error;
}
int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen)
{
git_array_oid_t parents = GIT_ARRAY_INIT;
git_parse_ctx parser;
int error;
git_grafts_clear(grafts);
if ((error = git_parse_ctx_init(&parser, content, contentlen)) < 0)
goto error;
for (; parser.remain_len; git_parse_advance_line(&parser)) {
const char *line_start = parser.line, *line_end = parser.line + parser.line_len;
git_oid graft_oid;
if ((error = git_oid_fromstrn(&graft_oid, line_start, GIT_OID_HEXSZ)) < 0) {
git_error_set(GIT_ERROR_GRAFTS, "invalid graft OID at line %" PRIuZ, parser.line_num);
goto error;
}
line_start += GIT_OID_HEXSZ;
while (line_start < line_end && *line_start == ' ') {
git_oid *id = git_array_alloc(parents);
GIT_ERROR_CHECK_ALLOC(id);
if ((error = git_oid_fromstrn(id, ++line_start, GIT_OID_HEXSZ)) < 0) {
git_error_set(GIT_ERROR_GRAFTS, "invalid parent OID at line %" PRIuZ, parser.line_num);
goto error;
}
line_start += GIT_OID_HEXSZ;
}
if ((error = git_grafts_add(grafts, &graft_oid, parents)) < 0)
goto error;
git_array_clear(parents);
}
error:
git_array_clear(parents);
return error;
}
int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents)
{
git_commit_graft *graft;
git_oid *parent_oid;
int error;
size_t i;
assert(grafts && oid);
graft = git__calloc(1, sizeof(*graft));
GIT_ERROR_CHECK_ALLOC(graft);
git_array_init_to_size(graft->parents, git_array_size(parents));
git_array_foreach(parents, i, parent_oid) {
git_oid *id = git_array_alloc(graft->parents);
GIT_ERROR_CHECK_ALLOC(id);
git_oid_cpy(id, parent_oid);
}
git_oid_cpy(&graft->oid, oid);
if ((error = git_grafts_remove(grafts, &graft->oid)) < 0 && error != GIT_ENOTFOUND)
goto cleanup;
if ((error = git_oidmap_set(grafts->commits, &graft->oid, graft)) < 0)
goto cleanup;
return 0;
cleanup:
git_array_clear(graft->parents);
git__free(graft);
return error;
}
int git_grafts_remove(git_grafts *grafts, const git_oid *oid)
{
git_commit_graft *graft;
int error;
assert(grafts && oid);
if ((graft = git_oidmap_get(grafts->commits, oid)) == NULL)
return GIT_ENOTFOUND;
if ((error = git_oidmap_delete(grafts->commits, oid)) < 0)
return error;
git__free(graft->parents.ptr);
git__free(graft);
return 0;
}
int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oid)
{
assert(out && grafts && oid);
if ((*out = git_oidmap_get(grafts->commits, oid)) == NULL)
return GIT_ENOTFOUND;
return 0;
}
int git_grafts_get_oids(git_oidarray *out, git_grafts *grafts)
{
git_array_oid_t oids = GIT_ARRAY_INIT;
const git_oid *oid;
size_t i = 0;
int error;
assert(out && grafts);
while ((error = git_oidmap_iterate(NULL, grafts->commits, &i, &oid)) == 0) {
git_oid *cpy = git_array_alloc(oids);
GIT_ERROR_CHECK_ALLOC(cpy);
git_oid_cpy(cpy, oid);
}
git_oidarray__from_array(out, &oids);
return 0;
}
size_t git_grafts_size(git_grafts *grafts)
{
return git_oidmap_size(grafts->commits);
}
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_graft_h__
#define INCLUDE_graft_h__
#include "common.h"
#include "oidarray.h"
#include "oidmap.h"
/** graft commit */
typedef struct {
git_oid oid;
git_array_oid_t parents;
} git_commit_graft;
typedef struct git_grafts git_grafts;
extern bool git_shallow__enabled;
int git_grafts_new(git_grafts **out);
int git_grafts_from_file(git_grafts **out, const char *path);
void git_grafts_free(git_grafts *grafts);
void git_grafts_clear(git_grafts *grafts);
int git_grafts_refresh(git_grafts *grafts);
int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen);
int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents);
int git_grafts_remove(git_grafts *grafts, const git_oid *oid);
int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oid);
int git_grafts_get_oids(git_oidarray *out, git_grafts *grafts);
size_t git_grafts_size(git_grafts *grafts);
#endif
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "object.h" #include "object.h"
#include "array.h" #include "array.h"
#include "oidarray.h" #include "oidarray.h"
#include "grafts.h"
void git_commit__free(void *_commit) void git_commit__free(void *_commit)
{ {
...@@ -417,10 +418,6 @@ static int commit_parse(git_commit *commit, const char *data, size_t size, unsig ...@@ -417,10 +418,6 @@ static int commit_parse(git_commit *commit, const char *data, size_t size, unsig
buffer += tree_len; buffer += tree_len;
} }
/*
* TODO: commit grafts!
*/
while (git_oid__parse(&parent_id, &buffer, buffer_end, "parent ") == 0) { while (git_oid__parse(&parent_id, &buffer, buffer_end, "parent ") == 0) {
git_oid *new_id = git_array_alloc(commit->parent_ids); git_oid *new_id = git_array_alloc(commit->parent_ids);
GIT_ERROR_CHECK_ALLOC(new_id); GIT_ERROR_CHECK_ALLOC(new_id);
...@@ -504,7 +501,34 @@ int git_commit__parse_raw(void *commit, const char *data, size_t size) ...@@ -504,7 +501,34 @@ int git_commit__parse_raw(void *commit, const char *data, size_t size)
int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned int flags) int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned int flags)
{ {
return commit_parse(commit, git_odb_object_data(odb_obj), git_odb_object_size(odb_obj), flags);
int error;
if ((error = commit_parse(commit, git_odb_object_data(odb_obj),
git_odb_object_size(odb_obj), flags)) < 0)
return error;
if (!git_shallow__enabled)
return 0;
git_repository *repo = git_object_owner((git_object *)commit);
git_commit_graft *graft;
/* Perform necessary grafts */
if (git_grafts_get(&graft, repo->grafts, git_odb_object_id(odb_obj)) == 0 ||
git_grafts_get(&graft, repo->shallow_grafts, git_odb_object_id(odb_obj)) == 0) {
size_t idx;
git_oid *oid;
git_array_clear(commit->parent_ids);
git_array_init_to_size(commit->parent_ids, git_array_size(graft->parents));
git_array_foreach(graft->parents, idx, oid) {
git_oid *id = git_array_alloc(commit->parent_ids);
GIT_ERROR_CHECK_ALLOC(id);
git_oid_cpy(id, oid);
}
}
return 0;
} }
int git_commit__parse(void *_commit, git_odb_object *odb_obj) int git_commit__parse(void *_commit, git_odb_object *odb_obj)
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "cache.h" #include "cache.h"
#include "common.h" #include "common.h"
#include "filter.h" #include "filter.h"
#include "grafts.h"
#include "hash.h" #include "hash.h"
#include "index.h" #include "index.h"
#include "merge_driver.h" #include "merge_driver.h"
...@@ -412,6 +413,8 @@ int git_libgit2_opts(int key, ...) ...@@ -412,6 +413,8 @@ int git_libgit2_opts(int key, ...)
case GIT_OPT_SET_OWNER_VALIDATION: case GIT_OPT_SET_OWNER_VALIDATION:
git_repository__validate_ownership = (va_arg(ap, int) != 0); git_repository__validate_ownership = (va_arg(ap, int) != 0);
case GIT_OPT_ENABLE_SHALLOW:
git_shallow__enabled = (va_arg(ap, int) != 0);
break; break;
default: default:
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "buf.h" #include "buf.h"
#include "common.h" #include "common.h"
#include "commit.h" #include "commit.h"
#include "grafts.h"
#include "tag.h" #include "tag.h"
#include "blob.h" #include "blob.h"
#include "futils.h" #include "futils.h"
...@@ -150,6 +151,8 @@ int git_repository__cleanup(git_repository *repo) ...@@ -150,6 +151,8 @@ int git_repository__cleanup(git_repository *repo)
git_repository_submodule_cache_clear(repo); git_repository_submodule_cache_clear(repo);
git_cache_clear(&repo->objects); git_cache_clear(&repo->objects);
git_attr_cache_flush(repo); git_attr_cache_flush(repo);
git_grafts_free(repo->grafts);
git_grafts_free(repo->shallow_grafts);
set_config(repo, NULL); set_config(repo, NULL);
set_index(repo, NULL); set_index(repo, NULL);
...@@ -727,6 +730,27 @@ out: ...@@ -727,6 +730,27 @@ out:
return error; return error;
} }
static int load_grafts(git_repository *repo)
{
git_buf path = GIT_BUF_INIT;
int error;
if ((error = git_repository_item_path(&path, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 ||
(error = git_buf_joinpath(&path, path.ptr, "grafts")) < 0 ||
(error = git_grafts_from_file(&repo->grafts, path.ptr)) < 0)
goto error;
git_buf_clear(&path);
if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0 ||
(error = git_grafts_from_file(&repo->shallow_grafts, path.ptr)) < 0)
goto error;
error:
git_buf_dispose(&path);
return error;
}
int git_repository_open_bare( int git_repository_open_bare(
git_repository **repo_ptr, git_repository **repo_ptr,
const char *bare_path) const char *bare_path)
...@@ -1016,6 +1040,9 @@ int git_repository_open_ext( ...@@ -1016,6 +1040,9 @@ int git_repository_open_ext(
if ((error = check_extensions(config, version)) < 0) if ((error = check_extensions(config, version)) < 0)
goto cleanup; goto cleanup;
if (git_shallow__enabled && (error = load_grafts(repo)) < 0)
goto cleanup;
if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0) { if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0) {
repo->is_bare = 1; repo->is_bare = 1;
} else { } else {
...@@ -1402,6 +1429,20 @@ int git_repository_set_index(git_repository *repo, git_index *index) ...@@ -1402,6 +1429,20 @@ int git_repository_set_index(git_repository *repo, git_index *index)
return 0; return 0;
} }
int git_repository_grafts__weakptr(git_grafts **out, git_repository *repo)
{
assert(out && repo && repo->grafts);
*out = repo->grafts;
return 0;
}
int git_repository_shallow_grafts__weakptr(git_grafts **out, git_repository *repo)
{
assert(out && repo && repo->shallow_grafts);
*out = repo->shallow_grafts;
return 0;
}
int git_repository_set_namespace(git_repository *repo, const char *namespace) int git_repository_set_namespace(git_repository *repo, const char *namespace)
{ {
git__free(repo->namespace); git__free(repo->namespace);
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include "attrcache.h" #include "attrcache.h"
#include "submodule.h" #include "submodule.h"
#include "diff_driver.h" #include "diff_driver.h"
#include "grafts.h"
#include "oidarray.h"
#define DOT_GIT ".git" #define DOT_GIT ".git"
#define GIT_DIR DOT_GIT "/" #define GIT_DIR DOT_GIT "/"
...@@ -156,6 +158,9 @@ struct git_repository { ...@@ -156,6 +158,9 @@ struct git_repository {
unsigned int lru_counter; unsigned int lru_counter;
git_grafts *grafts;
git_grafts *shallow_grafts;
git_atomic32 attr_session_key; git_atomic32 attr_session_key;
intptr_t configmap_cache[GIT_CONFIGMAP_CACHE_MAX]; intptr_t configmap_cache[GIT_CONFIGMAP_CACHE_MAX];
...@@ -187,6 +192,8 @@ int git_repository_config__weakptr(git_config **out, git_repository *repo); ...@@ -187,6 +192,8 @@ int git_repository_config__weakptr(git_config **out, git_repository *repo);
int git_repository_odb__weakptr(git_odb **out, git_repository *repo); int git_repository_odb__weakptr(git_odb **out, git_repository *repo);
int git_repository_refdb__weakptr(git_refdb **out, git_repository *repo); int git_repository_refdb__weakptr(git_refdb **out, git_repository *repo);
int git_repository_index__weakptr(git_index **out, git_repository *repo); int git_repository_index__weakptr(git_index **out, git_repository *repo);
int git_repository_grafts__weakptr(git_grafts **out, git_repository *repo);
int git_repository_shallow_grafts__weakptr(git_grafts **out, git_repository *repo);
/* /*
* Configuration map cache * Configuration map cache
......
#include "clar_libgit2.h"
#include "futils.h"
#include "grafts.h"
static git_repository *g_repo;
void test_grafts_basic__initialize(void)
{
git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1);
g_repo = cl_git_sandbox_init("grafted.git");
}
void test_grafts_basic__cleanup(void)
{
git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0);
cl_git_sandbox_cleanup();
}
void test_grafts_basic__graft_add(void)
{
git_array_oid_t parents = GIT_ARRAY_INIT;
git_oid oid_src, *oid1;
git_commit_graft *graft;
git_grafts *grafts;
cl_git_pass(git_grafts_new(&grafts));
cl_assert(oid1 = git_array_alloc(parents));
cl_git_pass(git_oid_fromstr(&oid_src, "2f3053cbff8a4ca2f0666de364ddb734a28a31a9"));
git_oid_cpy(oid1, &oid_src);
git_oid_fromstr(&oid_src, "f503807ffa920e407a600cfaee96b7152259acc7");
cl_git_pass(git_grafts_add(grafts, &oid_src, parents));
git_array_clear(parents);
cl_assert_equal_i(1, git_grafts_size(grafts));
cl_git_pass(git_grafts_get(&graft, grafts, &oid_src));
cl_assert_equal_s("f503807ffa920e407a600cfaee96b7152259acc7", git_oid_tostr_s(&graft->oid));
cl_assert_equal_i(1, git_array_size(graft->parents));
cl_assert_equal_s("2f3053cbff8a4ca2f0666de364ddb734a28a31a9", git_oid_tostr_s(git_array_get(graft->parents, 0)));
git_grafts_free(grafts);
}
void test_grafts_basic__grafted_revwalk(void)
{
git_revwalk *w;
git_oid oids[10];
size_t i = 0;
git_commit *commit;
cl_git_pass(git_revwalk_new(&w, g_repo));
cl_git_pass(git_revwalk_push_ref(w, "refs/heads/branch"));
cl_git_pass(git_revwalk_next(&oids[i++], w));
cl_assert_equal_s(git_oid_tostr_s(&oids[0]), "8a00e91619098618be97c0d2ceabb05a2c58edd9");
cl_git_pass(git_revwalk_next(&oids[i++], w));
cl_assert_equal_s(git_oid_tostr_s(&oids[1]), "f503807ffa920e407a600cfaee96b7152259acc7");
cl_git_pass(git_revwalk_next(&oids[i++], w));
cl_assert_equal_s(git_oid_tostr_s(&oids[2]), "2f3053cbff8a4ca2f0666de364ddb734a28a31a9");
cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oids[i++], w));
cl_git_pass(git_commit_lookup(&commit, g_repo, &oids[0]));
cl_assert_equal_i(1, git_commit_parentcount(commit));
git_commit_free(commit);
git_revwalk_free(w);
}
void test_grafts_basic__grafted_objects(void)
{
git_oid oid;
git_commit *commit;
cl_git_pass(git_oid_fromstr(&oid, "f503807ffa920e407a600cfaee96b7152259acc7"));
cl_git_pass(git_commit_lookup(&commit, g_repo, &oid));
cl_assert_equal_i(1, git_commit_parentcount(commit));
git_commit_free(commit);
cl_git_pass(git_oid_fromstr(&oid, "0512adebd3782157f0d5c9b22b043f87b4aaff9e"));
cl_git_pass(git_commit_lookup(&commit, g_repo, &oid));
cl_assert_equal_i(1, git_commit_parentcount(commit));
git_commit_free(commit);
cl_git_pass(git_oid_fromstr(&oid, "66cc22a015f6ca75b34c82d28f78ba663876bade"));
cl_git_pass(git_commit_lookup(&commit, g_repo, &oid));
cl_assert_equal_i(4, git_commit_parentcount(commit));
git_commit_free(commit);
}
void test_grafts_basic__grafted_merge_revwalk(void)
{
git_revwalk *w;
git_oid oids[10];
size_t i = 0;
cl_git_pass(git_revwalk_new(&w, g_repo));
cl_git_pass(git_revwalk_push_ref(w, "refs/heads/bottom"));
cl_git_pass(git_revwalk_next(&oids[i++], w));
cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "66cc22a015f6ca75b34c82d28f78ba663876bade");
cl_git_pass(git_revwalk_next(&oids[i++], w));
cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "e414f42f4e6bc6934563a2349a8600f0ab68618e");
cl_git_pass(git_revwalk_next(&oids[i++], w));
cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "8a00e91619098618be97c0d2ceabb05a2c58edd9");
cl_git_pass(git_revwalk_next(&oids[i++], w));
cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "1c18e80a276611bb9b146590616bbc5aebdf2945");
cl_git_pass(git_revwalk_next(&oids[i++], w));
cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "d7224d49d6d5aff6ade596ed74f4bcd4f77b29e2");
cl_git_pass(git_revwalk_next(&oids[i++], w));
cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "0512adebd3782157f0d5c9b22b043f87b4aaff9e");
cl_git_pass(git_revwalk_next(&oids[i++], w));
cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "f503807ffa920e407a600cfaee96b7152259acc7");
cl_git_pass(git_revwalk_next(&oids[i++], w));
cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "2f3053cbff8a4ca2f0666de364ddb734a28a31a9");
cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oids[i++], w));
git_revwalk_free(w);
}
#include "clar_libgit2.h"
#include "grafts.h"
#define OID0 "c0368f9f9743e950e6cfe1f45a649f8a9dfcd97e"
#define OID1 "cfc50a0db87ce908fb8a8c5b8f7b4ab96eee8643"
#define OID2 "6914d97cd08b9edf5e855fca211c750fa82fd80a"
#define OID3 "516521937d0e9ce9d0d836149a0702671f326b4a"
#define OID4 "e2c29d67ef2f217650196f94c796f0532b8caad6"
#define OID5 "79bcb936596cb50353fe7be28b7444e66e4a2842"
#define OID6 "b9c54107d57c17dbcaf646c4d52f66eb9e69d23d"
#define OID7 "9f8a746e9ad7b58cc840016bc3944d5ad262acb5"
#define OID8 "392f4beef7d0d15b2bc5b1abe1a754eba0ec36da"
#define OID_TRUNCATED "392f4beef7d0d15b2bc5b1abe1a754eba0ec36d"
#define OID_NONHEX "9f8a746e9ax7b58cc840016bc3944d5ad262acb5"
static git_grafts *grafts;
void test_grafts_parse__initialize(void)
{
cl_git_pass(git_grafts_new(&grafts));
}
void test_grafts_parse__cleanup(void)
{
git_grafts_free(grafts);
grafts = NULL;
}
static void assert_parse_succeeds(git_grafts *grafts, const char *string, size_t n)
{
cl_git_pass(git_grafts_parse(grafts, string, strlen(string)));
cl_assert_equal_i(git_grafts_size(grafts), n);
}
static void assert_parse_fails(git_grafts *grafts, const char *string)
{
cl_git_fail(git_grafts_parse(grafts, string, strlen(string)));
}
static void assert_graft_contains(git_grafts *grafts, const char *graft, size_t n, ...)
{
git_commit_graft *commit;
git_oid oid;
va_list ap;
size_t i = 0;
cl_git_pass(git_oid_fromstr(&oid, graft));
cl_git_pass(git_grafts_get(&commit, grafts, &oid));
cl_assert_equal_oid(&commit->oid, &oid);
cl_assert_equal_i(commit->parents.size, n);
va_start(ap, n);
while (i < n) {
cl_git_pass(git_oid_fromstr(&oid, va_arg(ap, const char *)));
cl_assert_equal_oid(&commit->parents.ptr[i], &oid);
i++;
}
va_end(ap);
}
void test_grafts_parse__single_oid(void)
{
assert_parse_succeeds(grafts, OID1, 1);
assert_graft_contains(grafts, OID1, 0);
}
void test_grafts_parse__single_oid_with_newline(void)
{
assert_parse_succeeds(grafts, OID1 "\n", 1);
assert_graft_contains(grafts, OID1, 0);
}
void test_grafts_parse__multiple_oids(void)
{
assert_parse_succeeds(grafts, OID1 "\n" OID2 "\n" OID3, 3);
assert_graft_contains(grafts, OID1, 0);
assert_graft_contains(grafts, OID2, 0);
assert_graft_contains(grafts, OID3, 0);
}
void test_grafts_parse__same_oid(void)
{
assert_parse_succeeds(grafts, OID1 "\n" OID1, 1);
assert_graft_contains(grafts, OID1, 0);
}
void test_grafts_parse__oid_with_parent(void)
{
assert_parse_succeeds(grafts, OID1 " " OID2, 1);
assert_graft_contains(grafts, OID1, 1, OID2);
}
void test_grafts_parse__oid_with_parent_and_newline(void)
{
assert_parse_succeeds(grafts, OID1 " " OID2 "\n", 1);
assert_graft_contains(grafts, OID1, 1, OID2);
}
void test_grafts_parse__oid_with_multiple_parents(void)
{
assert_parse_succeeds(grafts, OID1 " " OID2 " " OID3 " " OID4 " " OID5, 1);
assert_graft_contains(grafts, OID1, 4, OID2, OID3, OID4, OID5);
}
void test_grafts_parse__multiple_oids_with_multiple_parents(void)
{
assert_parse_succeeds(grafts,
OID1 " " OID2 " " OID3 " " OID4 " " OID5 "\n"
OID6 " " OID7 " " OID8 "\n" , 2);
assert_graft_contains(grafts, OID1, 4, OID2, OID3, OID4, OID5);
assert_graft_contains(grafts, OID6, 2, OID7, OID8);
}
void test_grafts_parse__multiple_spaces_fails(void)
{
assert_parse_fails(grafts, OID1 " " OID2);
}
void test_grafts_parse__trailing_space_fails(void)
{
assert_parse_fails(grafts, OID1 " " OID2 " ");
}
void test_grafts_parse__invalid_character_inbetween_fails(void)
{
assert_parse_fails(grafts, OID1 " x " OID2);
}
void test_grafts_parse__truncated_oid_fails(void)
{
assert_parse_fails(grafts, OID_TRUNCATED);
}
void test_grafts_parse__truncated_parent_fails(void)
{
assert_parse_fails(grafts, OID1 " " OID_TRUNCATED);
}
void test_grafts_parse__invalid_oid_fails(void)
{
assert_parse_fails(grafts, OID_NONHEX);
}
void test_grafts_parse__invalid_parent_fails(void)
{
assert_parse_fails(grafts, OID1 " " OID_NONHEX);
}
#include "clar_libgit2.h"
#include "futils.h"
#include "grafts.h"
#include "repository.h"
static git_repository *g_repo;
static git_oid g_shallow_oid;
void test_grafts_shallow__set_feature_flag(void)
{
cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1));
}
void test_grafts_shallow__unset_feature_flag(void)
{
cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0));
}
void test_grafts_shallow__initialize(void)
{
git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1);
cl_git_pass(git_oid_fromstr(&g_shallow_oid, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"));
}
void test_grafts_shallow__cleanup(void)
{
git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0);
cl_git_sandbox_cleanup();
}
void test_grafts_shallow__no_shallow_file(void)
{
g_repo = cl_git_sandbox_init("testrepo.git");
cl_assert_equal_i(0, git_repository_is_shallow(g_repo));
}
void test_grafts_shallow__empty_shallow_file(void)
{
g_repo = cl_git_sandbox_init("testrepo.git");
cl_git_mkfile("testrepo.git/shallow", "");
cl_assert_equal_i(0, git_repository_is_shallow(g_repo));
}
void test_grafts_shallow__shallow_repo(void)
{
g_repo = cl_git_sandbox_init("shallow.git");
cl_assert_equal_i(1, git_repository_is_shallow(g_repo));
}
void test_grafts_shallow__clears_errors(void)
{
g_repo = cl_git_sandbox_init("testrepo.git");
cl_assert_equal_i(0, git_repository_is_shallow(g_repo));
cl_assert_equal_p(NULL, git_error_last());
}
void test_grafts_shallow__shallow_oids(void)
{
git_commit_graft *graft;
git_grafts *grafts;
g_repo = cl_git_sandbox_init("shallow.git");
cl_git_pass(git_repository_shallow_grafts__weakptr(&grafts, g_repo));
cl_assert_equal_i(1, git_grafts_size(grafts));
cl_git_pass(git_grafts_get(&graft, grafts, &g_shallow_oid));
}
void test_grafts_shallow__cache_clearing(void)
{
git_commit_graft *graft;
git_grafts *grafts;
git_oid tmp_oid;
cl_git_pass(git_oid_fromstr(&tmp_oid, "0000000000000000000000000000000000000000"));
g_repo = cl_git_sandbox_init("shallow.git");
cl_git_pass(git_repository_shallow_grafts__weakptr(&grafts, g_repo));
cl_assert_equal_i(1, git_grafts_size(grafts));
cl_git_pass(git_grafts_get(&graft, grafts, &g_shallow_oid));
cl_git_mkfile("shallow.git/shallow",
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644\n"
"0000000000000000000000000000000000000000\n"
);
cl_git_pass(git_grafts_refresh(grafts));
cl_assert_equal_i(2, git_grafts_size(grafts));
cl_git_pass(git_grafts_get(&graft, grafts, &g_shallow_oid));
cl_git_pass(git_grafts_get(&graft, grafts, &tmp_oid));
cl_git_pass(p_unlink("shallow.git/shallow"));
cl_git_pass(git_grafts_refresh(grafts));
cl_assert_equal_i(0, git_grafts_size(grafts));
}
void test_grafts_shallow__errors_on_borked(void)
{
git_grafts *grafts;
g_repo = cl_git_sandbox_init("shallow.git");
cl_git_mkfile("shallow.git/shallow", "lolno");
cl_git_pass(git_repository_shallow_grafts__weakptr(&grafts, g_repo));
cl_git_fail(git_grafts_refresh(grafts));
cl_assert_equal_i(0, git_grafts_size(grafts));
cl_git_mkfile("shallow.git/shallow", "lolno\n");
cl_git_pass(git_repository_shallow_grafts__weakptr(&grafts, g_repo));
cl_git_fail(git_grafts_refresh(grafts));
cl_assert_equal_i(0, git_grafts_size(grafts));
}
void test_grafts_shallow__revwalk_behavior(void)
{
git_revwalk *w;
git_oid oid_1, oid_2, oid_3;
g_repo = cl_git_sandbox_init("shallow.git");
cl_git_pass(git_revwalk_new(&w, g_repo));
cl_git_pass(git_revwalk_push_head(w));
cl_git_pass(git_revwalk_next(&oid_1, w)); // a65fedf39aefe402d3bb6e24df4d4f5fe4547750
cl_git_pass(git_revwalk_next(&oid_2, w)); // be3563ae3f795b2b4353bcce3a527ad0a4f7f644
cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oid_3, w));
cl_assert_equal_s(git_oid_tostr_s(&oid_1), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
cl_assert_equal_s(git_oid_tostr_s(&oid_2), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
git_revwalk_free(w);
}
void test_grafts_shallow__grafted_object(void)
{
git_commit *commit;
g_repo = cl_git_sandbox_init("shallow.git");
cl_git_pass(git_commit_lookup(&commit, g_repo, &g_shallow_oid));
cl_assert_equal_i(0, git_commit_parentcount(commit));
git_commit_free(commit);
}
[core]
repositoryformatversion = 0
filemode = true
bare = true
ignorecase = true
precomposeunicode = true
f503807ffa920e407a600cfaee96b7152259acc7 2f3053cbff8a4ca2f0666de364ddb734a28a31a9
0512adebd3782157f0d5c9b22b043f87b4aaff9e 2f3053cbff8a4ca2f0666de364ddb734a28a31a9
66cc22a015f6ca75b34c82d28f78ba663876bade e414f42f4e6bc6934563a2349a8600f0ab68618e 8a00e91619098618be97c0d2ceabb05a2c58edd9 1c18e80a276611bb9b146590616bbc5aebdf2945 2f3053cbff8a4ca2f0666de364ddb734a28a31a9
66cc22a015f6ca75b34c82d28f78ba663876bade
8a00e91619098618be97c0d2ceabb05a2c58edd9
2f3053cbff8a4ca2f0666de364ddb734a28a31a9
1c18e80a276611bb9b146590616bbc5aebdf2945
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment