Commit 68bbcefd by yuangli

Merge branch 'transportPR' into shallow-clone-network

parents a491917f f19ffc8a
......@@ -754,11 +754,16 @@ typedef struct {
* Extra headers for this fetch operation
*/
git_strarray custom_headers;
/**
* Depth of the fetch to perform
*/
int depth;
} git_fetch_options;
#define GIT_FETCH_OPTIONS_VERSION 1
#define GIT_FETCH_OPTIONS_INIT { GIT_FETCH_OPTIONS_VERSION, GIT_REMOTE_CALLBACKS_INIT, GIT_FETCH_PRUNE_UNSPECIFIED, 1, \
GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, GIT_PROXY_OPTIONS_INIT }
GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, GIT_PROXY_OPTIONS_INIT, { NULL }, -1 }
/**
* Initialize git_fetch_options structure
......
......@@ -923,6 +923,17 @@ GIT_EXTERN(const char *) git_repository_get_namespace(git_repository *repo);
GIT_EXTERN(int) git_repository_is_shallow(git_repository *repo);
/**
* Determine the shallow roots of the repository
*
* This oidarray is owned by the library. Do not free it.
*
* @param out An array of shallow oids.
* @param repo The repository
* @return 0 on success, an error otherwise.
*/
GIT_EXTERN(int) git_repository_shallow_roots(git_oidarray *out, git_repository *repo);
/**
* Retrieve the configured identity to use for reflogs
*
* The memory is owned by the repository and must not be freed by the
......
......@@ -25,6 +25,24 @@
GIT_BEGIN_DECL
/**
* Flags to pass to transport
*
* Currently unused.
*/
typedef enum {
GIT_TRANSPORTFLAGS_NONE = 0,
} git_transport_flags_t;
typedef struct git_shallowarray git_shallowarray;
typedef struct {
const git_remote_head * const *refs;
size_t count;
git_shallowarray *shallow_roots;
int depth;
} git_fetch_negotiation;
struct git_transport {
unsigned int version; /**< The struct version */
......@@ -84,8 +102,7 @@ struct git_transport {
int GIT_CALLBACK(negotiate_fetch)(
git_transport *transport,
git_repository *repo,
const git_remote_head * const *refs,
size_t count);
const git_fetch_negotiation *fetch_data);
/**
* Start downloading the packfile from the remote repository.
......@@ -430,6 +447,11 @@ GIT_EXTERN(int) git_smart_subtransport_ssh(
git_transport *owner,
void *param);
GIT_EXTERN(size_t) git_shallowarray_count(git_shallowarray *array);
GIT_EXTERN(const git_oid *) git_shallowarray_get(git_shallowarray *array, size_t idx);
GIT_EXTERN(int) git_shallowarray_add(git_shallowarray *array, git_oid *oid);
GIT_EXTERN(int) git_shallowarray_remove(git_shallowarray *array, git_oid *oid);
/** @} */
GIT_END_DECL
#endif
......@@ -409,8 +409,9 @@ static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch
memcpy(&fetch_opts, opts, sizeof(git_fetch_options));
fetch_opts.update_fetchhead = 0;
if (fetch_opts.depth == -1)
fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL;
git_str_printf(&reflog_message, "clone: from %s", git_remote_url(remote));
git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote));
if ((error = git_remote_fetch(remote, NULL, &fetch_opts, git_str_cstr(&reflog_message))) != 0)
goto cleanup;
......
......@@ -20,6 +20,7 @@
#include "netops.h"
#include "repository.h"
#include "refs.h"
#include "transports/smart.h"
static int maybe_want(git_remote *remote, git_remote_head *head, git_refspec *tagspec, git_remote_autotag_option_t tagopt)
{
......@@ -184,20 +185,42 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts)
* Now we have everything set up so we can start tell the
* server what we want and what we have.
*/
remote->nego.refs = (const git_remote_head * const *)remote->refs.contents;
remote->nego.count = remote->refs.length;
remote->nego.depth = opts->depth;
remote->nego.shallow_roots = git__malloc(sizeof(git_shallowarray));
git_array_init(remote->nego.shallow_roots->array);
git_repository__shallow_roots(&remote->nego.shallow_roots->array, remote->repo);
return t->negotiate_fetch(t,
remote->repo,
(const git_remote_head * const *)remote->refs.contents,
remote->refs.length);
&remote->nego);
}
int git_fetch_download_pack(git_remote *remote)
{
git_transport *t = remote->transport;
git_indexer_progress_cb progress = NULL;
void *payload = NULL;
int error;
if (!remote->need_pack)
return 0;
return t->download_pack(t, remote->repo, &remote->stats);
if (callbacks) {
progress = callbacks->transfer_progress;
payload = callbacks->payload;
}
if ((error = t->download_pack(t, remote->repo, &remote->stats, progress, payload)) < 0)
return error;
if ((error = git_repository__shallow_roots_write(remote->repo, remote->nego.shallow_roots->array)) < 0)
return error;
return 0;
}
int git_fetch_options_init(git_fetch_options *opts, unsigned int version)
......
......@@ -104,15 +104,13 @@ int git_object__from_raw(
return 0;
}
int git_object__from_odb_object(
int git_object__init_from_odb_object(
git_object **object_out,
git_repository *repo,
git_odb_object *odb_obj,
git_object_t type)
{
int error;
size_t object_size;
git_object_def *def;
git_object *object = NULL;
GIT_ASSERT_ARG(object_out);
......@@ -139,6 +137,23 @@ int git_object__from_odb_object(
object->cached.size = odb_obj->cached.size;
object->repo = repo;
*object_out = object;
return 0;
}
int git_object__from_odb_object(
git_object **object_out,
git_repository *repo,
git_odb_object *odb_obj,
git_object_t type)
{
int error;
git_object_def *def;
git_object *object = NULL;
if ((error = git_object__init_from_odb_object(&object, repo, odb_obj, type)) < 0)
return error;
/* Parse raw object data */
def = &git_objects_table[odb_obj->cached.type];
GIT_ASSERT(def->free && def->parse);
......
......@@ -35,6 +35,12 @@ int git_object__from_raw(
size_t size,
git_object_t type);
int git_object__init_from_odb_object(
git_object **object_out,
git_repository *repo,
git_odb_object *odb_obj,
git_object_t type);
int git_object__from_odb_object(
git_object **object_out,
git_repository *repo,
......
......@@ -37,6 +37,7 @@ struct git_remote {
git_remote_autotag_option_t download_tags;
int prune_refs;
int passed_refspecs;
git_fetch_negotiation nego;
};
int git_remote__urlfordirection(git_str *url_out, struct git_remote *remote, int direction, const git_remote_callbacks *callbacks);
......
......@@ -3340,6 +3340,161 @@ int git_repository_state_cleanup(git_repository *repo)
return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files));
}
// int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo)
// {
// git_buf path = GIT_BUF_INIT;
// git_buf contents = GIT_BUF_INIT;
// int error, updated, line_num = 1;
// char *line;
// chror = git_futils_readbuffer_updated(&contents, git_buf_cstr(&path), &repo->shallow_grafts->git_grafts->path_checksum, &updated);
// git_buf_dispose(&path);
// if (error < 0 && error != GIT_ENOTFOUND)
// return error;
// /* cancel out GIT_ENOTFOUND */
// git_error_clear();
// error = 0;
// if (!updated) {
// out = repo->shallow_grafts;
// goto cleanup;
// }
// git_array_clear(repo->shallow_grafts);
// buffer = contents.ptr;
// while ((line = git__strsep(&buffer, "\n")) != NULL) {
// git_oid *oid = git_array_alloc(repo->shallow_grafts);
// error = git_oid_fromstr(oid, line);
// if (error < 0) {
// git_error_set(GIT_ERROR_REPOSITORY, "Invalid OID at line %d", line_num);
// git_array_clear(repo->shallow_grafts);
// error = -1;
// goto cleanup;
// }
// ++line_num;
// }
// if (*buffer) {
// git_error_set(GIT_ERROR_REPOSITORY, "No EOL at line %d", line_num);
// git_array_clear(repo->shallow_grafts);
// error = -1;
// goto cleanup;
// }
// *out = repo->shallow_grafts;
// cleanup:
// git_buf_dispose(&contents);
// return error;ar *buffer;
// assert(out && repo);
// if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0)
// return error;
// //error = git_futils_readbuffer_updated(&contents, git_buf_cstr(&path), &repo->shallow_checksum, &updated);
// error = git_futils_readbuffer_updated(&contents, git_buf_cstr(&path), &repo->shallow_grafts->git_grafts->path_checksum, &updated);
// git_buf_dispose(&path);
// if (error < 0 && error != GIT_ENOTFOUND)
// return error;
// /* cancel out GIT_ENOTFOUND */
// git_error_clear();
// error = 0;
// if (!updated) {
// out = repo->shallow_grafts;
// goto cleanup;
// }
// git_array_clear(repo->shallow_grafts);
// buffer = contents.ptr;
// while ((line = git__strsep(&buffer, "\n")) != NULL) {
// git_oid *oid = git_array_alloc(repo->shallow_grafts);
// error = git_oid_fromstr(oid, line);
// if (error < 0) {
// git_error_set(GIT_ERROR_REPOSITORY, "Invalid OID at line %d", line_num);
// git_array_clear(repo->shallow_grafts);
// error = -1;
// goto cleanup;
// }
// ++line_num;
// }
// if (*buffer) {
// git_error_set(GIT_ERROR_REPOSITORY, "No EOL at line %d", line_num);
// git_array_clear(repo->shallow_grafts);
// error = -1;
// goto cleanup;
// }
// *out = repo->shallow_grafts;
// cleanup:
// git_buf_dispose(&contents);
// return error;
// }
int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo) {
int error =0;
if (!repo->shallow_grafts)
load_grafts(repo);
git_grafts_refresh(repo->shallow_grafts);
return git_grafts_get_oids(out, repo->shallow_grafts);
}
int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t roots)
{
git_filebuf file = GIT_FILEBUF_INIT;
git_buf path = GIT_BUF_INIT;
int error = 0;
size_t idx;
git_oid *oid;
assert(repo);
if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0)
return error;
if ((error = git_filebuf_open(&file, git_buf_cstr(&path), GIT_FILEBUF_HASH_CONTENTS, 0666)) < 0)
return error;
git_array_foreach(roots, idx, oid) {
git_filebuf_write(&file, git_oid_tostr_s(oid), GIT_OID_HEXSZ);
git_filebuf_write(&file, "\n", 1);
}
git_filebuf_commit(&file);
if (load_grafts(repo) < 0)
return -1;
return 0;
}
int git_repository_shallow_roots(git_oidarray *out, git_repository *repo)
{
int ret;
git_array_oid_t array = GIT_ARRAY_INIT;
assert(out);
ret = git_repository__shallow_roots(&array, repo);
git_oidarray__from_array(out, &array);
return ret;
}
int git_repository_is_shallow(git_repository *repo)
{
git_str path = GIT_STR_INIT;
......
......@@ -244,6 +244,9 @@ extern size_t git_repository__reserved_names_posix_len;
bool git_repository__reserved_names(
git_str **out, size_t *outlen, git_repository *repo, bool include_ntfs);
int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo);
int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t roots);
/*
* The default branch for the repository; the `init.defaultBranch`
* configuration option, if set, or `master` if it is not.
......
......@@ -284,15 +284,13 @@ static int local_ls(const git_remote_head ***out, size_t *size, git_transport *t
static int local_negotiate_fetch(
git_transport *transport,
git_repository *repo,
const git_remote_head * const *refs,
size_t count)
const git_fetch_negotiation *wants)
{
transport_local *t = (transport_local*)transport;
git_remote_head *rhead;
unsigned int i;
GIT_UNUSED(refs);
GIT_UNUSED(count);
GIT_UNUSED(wants);
/* Fill in the loids */
git_vector_foreach(&t->refs, i, rhead) {
......
......@@ -482,3 +482,31 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param)
*out = (git_transport *) t;
return 0;
}
size_t git_shallowarray_count(git_shallowarray *array)
{
return git_array_size(array->array);
}
const git_oid * git_shallowarray_get(git_shallowarray *array, size_t idx)
{
return git_array_get(array->array, idx);
}
int git_shallowarray_add(git_shallowarray *array, git_oid *oid)
{
size_t oid_index;
if (git_array_search(&oid_index, array->array, (git_array_compare_cb)git_oid_cmp, &oid) < 0) {
git_oid *tmp = git_array_alloc(array->array);
git_oid_cpy(tmp, oid);
}
return 0;
}
int git_shallowarray_remove(git_shallowarray *array, git_oid *oid)
{
GIT_UNUSED(array);
GIT_UNUSED(oid);
/* no git_array_remove… meh */
return -1;
}
......@@ -14,6 +14,7 @@
#include "netops.h"
#include "push.h"
#include "str.h"
#include "oidarray.h"
#include "git2/sys/transport.h"
#define GIT_SIDE_BAND_DATA 1
......@@ -32,6 +33,7 @@
#define GIT_CAP_SYMREF "symref"
#define GIT_CAP_WANT_TIP_SHA1 "allow-tip-sha1-in-want"
#define GIT_CAP_WANT_REACHABLE_SHA1 "allow-reachable-sha1-in-want"
#define GIT_CAP_SHALLOW "shallow"
extern bool git_smart__ofs_delta_enabled;
......@@ -48,7 +50,9 @@ typedef enum {
GIT_PKT_PROGRESS,
GIT_PKT_OK,
GIT_PKT_NG,
GIT_PKT_UNPACK
GIT_PKT_UNPACK,
GIT_PKT_SHALLOW,
GIT_PKT_UNSHALLOW,
} git_pkt_type;
/* Used for multi_ack and multi_ack_detailed */
......@@ -120,6 +124,11 @@ typedef struct {
int unpack_ok;
} git_pkt_unpack;
typedef struct {
git_pkt_type type;
git_oid oid;
} git_pkt_shallow;
typedef struct transport_smart_caps {
unsigned int common:1,
ofs_delta:1,
......@@ -132,7 +141,8 @@ typedef struct transport_smart_caps {
report_status:1,
thin_pack:1,
want_tip_sha1:1,
want_reachable_sha1:1;
want_reachable_sha1:1,
shallow:1;
} transport_smart_caps;
typedef int (*packetsize_cb)(size_t received, void *payload);
......@@ -167,8 +177,7 @@ int git_smart__push(git_transport *transport, git_push *push);
int git_smart__negotiate_fetch(
git_transport *transport,
git_repository *repo,
const git_remote_head * const *refs,
size_t count);
const git_fetch_negotiation *wants);
int git_smart__download_pack(
git_transport *transport,
......@@ -186,8 +195,12 @@ int git_pkt_parse_line(git_pkt **head, const char **endptr, const char *line, si
int git_pkt_buffer_flush(git_str *buf);
int git_pkt_send_flush(GIT_SOCKET s);
int git_pkt_buffer_done(git_str *buf);
int git_pkt_buffer_wants(const git_remote_head * const *refs, size_t count, transport_smart_caps *caps, git_str *buf);
int git_pkt_buffer_wants(const git_fetch_negotiation *wants, transport_smart_caps *caps, git_str *buf);
int git_pkt_buffer_have(git_oid *oid, git_str *buf);
void git_pkt_free(git_pkt *pkt);
struct git_shallowarray {
git_array_oid_t array;
};
#endif
......@@ -366,6 +366,50 @@ static int unpack_pkt(git_pkt **out, const char *line, size_t len)
return 0;
}
static int shallow_pkt(git_pkt **out, const char *line, size_t len)
{
git_pkt_shallow *pkt;
pkt = git__calloc(1, sizeof(git_pkt_shallow));
GIT_ERROR_CHECK_ALLOC(pkt);
pkt->type = GIT_PKT_SHALLOW;
line += 7;
len -= 7;
if (len >= GIT_OID_HEXSZ) {
git_oid_fromstr(&pkt->oid, line + 1);
line += GIT_OID_HEXSZ + 1;
len -= GIT_OID_HEXSZ + 1;
}
*out = (git_pkt *) pkt;
return 0;
}
static int unshallow_pkt(git_pkt **out, const char *line, size_t len)
{
git_pkt_shallow *pkt;
pkt = git__calloc(1, sizeof(git_pkt_shallow));
GIT_ERROR_CHECK_ALLOC(pkt);
pkt->type = GIT_PKT_UNSHALLOW;
line += 9;
len -= 9;
if (len >= GIT_OID_HEXSZ) {
git_oid_fromstr(&pkt->oid, line + 1);
line += GIT_OID_HEXSZ + 1;
len -= GIT_OID_HEXSZ + 1;
}
*out = (git_pkt *) pkt;
return 0;
}
static int parse_len(size_t *out, const char *line, size_t linelen)
{
char num[PKT_LEN_SIZE + 1];
......@@ -492,6 +536,10 @@ int git_pkt_parse_line(
error = ng_pkt(pkt, line, len);
else if (!git__prefixncmp(line, len, "unpack"))
error = unpack_pkt(pkt, line, len);
else if (!git__prefixcmp(line, "shallow"))
error = shallow_pkt(pkt, line, len);
else if (!git__prefixcmp(line, "unshallow"))
error = unshallow_pkt(pkt, line, len);
else
error = ref_pkt(pkt, line, len);
......@@ -557,6 +605,9 @@ static int buffer_want_with_caps(const git_remote_head *head, transport_smart_ca
if (caps->ofs_delta)
git_str_puts(&str, GIT_CAP_OFS_DELTA " ");
if (caps->shallow)
git_str_puts(&str, GIT_CAP_SHALLOW " ");
if (git_str_oom(&str))
return -1;
......@@ -586,8 +637,7 @@ static int buffer_want_with_caps(const git_remote_head *head, transport_smart_ca
*/
int git_pkt_buffer_wants(
const git_remote_head * const *refs,
size_t count,
const git_fetch_negotiation *wants,
transport_smart_caps *caps,
git_str *buf)
{
......@@ -595,22 +645,22 @@ int git_pkt_buffer_wants(
const git_remote_head *head;
if (caps->common) {
for (; i < count; ++i) {
head = refs[i];
for (; i < wants->count; ++i) {
head = wants->refs[i];
if (!head->local)
break;
}
if (buffer_want_with_caps(refs[i], caps, buf) < 0)
if (buffer_want_with_caps(wants->refs[i], caps, buf) < 0)
return -1;
i++;
}
for (; i < count; ++i) {
for (; i < wants->count; ++i) {
char oid[GIT_OID_SHA1_HEXSIZE];
head = refs[i];
head = wants->refs[i];
if (head->local)
continue;
......@@ -622,6 +672,32 @@ int git_pkt_buffer_wants(
return -1;
}
/* Tell the server about our shallow objects */
for (i = 0; i < git_shallowarray_count(wants->shallow_roots); i++) {
char oid[GIT_OID_HEXSZ];
git_buf shallow_buf = GIT_BUF_INIT;
git_oid_fmt(oid, git_shallowarray_get(wants->shallow_roots, i));
git_buf_puts(&shallow_buf, "shallow ");
git_buf_put(&shallow_buf, oid, GIT_OID_HEXSZ);
git_buf_putc(&shallow_buf, '\n');
git_buf_printf(buf, "%04x%s", (unsigned int)git_buf_len(&shallow_buf) + 4, git_buf_cstr(&shallow_buf));
if (git_buf_oom(buf))
return -1;
}
if (wants->depth > 0) {
git_buf deepen_buf = GIT_BUF_INIT;
git_buf_printf(&deepen_buf, "deepen %d\n", wants->depth);
git_buf_printf(buf,"%04x%s", (unsigned int)git_buf_len(&deepen_buf) + 4, git_buf_cstr(&deepen_buf));
if (git_buf_oom(buf))
return -1;
}
return git_pkt_buffer_flush(buf);
}
......
......@@ -214,6 +214,11 @@ int git_smart__detect_caps(git_pkt_ref *pkt, transport_smart_caps *caps, git_vec
if (!git__prefixcmp(ptr, GIT_CAP_WANT_REACHABLE_SHA1)) {
caps->common = caps->want_reachable_sha1 = 1;
ptr += strlen(GIT_CAP_DELETE_REFS);
}
if (!git__prefixcmp(ptr, GIT_CAP_SHALLOW)) {
caps->common = caps->shallow = 1;
ptr += strlen(GIT_CAP_SHALLOW);
continue;
}
......@@ -317,7 +322,26 @@ static int wait_while_ack(gitno_buffer *buf)
return 0;
}
int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, const git_remote_head * const *wants, size_t count)
static int cap_not_sup_err(const char *cap_name)
{
git_error_set(GIT_ERROR_NET, "server doesn't support %s", cap_name);
return GIT_EINVALID;
}
/* Disables server capabilities we're not interested in */
static int setup_caps(transport_smart_caps *caps, const git_fetch_negotiation *wants)
{
if (wants->depth) {
if (!caps->shallow)
return cap_not_sup_err(GIT_CAP_SHALLOW);
} else {
caps->shallow = 0;
}
return 0;
}
int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, const git_fetch_negotiation *wants)
{
transport_smart *t = (transport_smart *)transport;
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
......@@ -329,7 +353,10 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
unsigned int i;
git_oid oid;
if ((error = git_pkt_buffer_wants(wants, count, &t->caps, &data)) < 0)
if ((error = setup_caps(&t->caps, wants)) < 0)
return error;
if ((error = git_pkt_buffer_wants(wants, &t->caps, &data)) < 0)
return error;
if ((error = git_revwalk_new(&walk, repo)) < 0)
......@@ -339,6 +366,33 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
if ((error = git_revwalk__push_glob(walk, "refs/*", &opts)) < 0)
goto on_error;
if (wants->depth > 0) {
git_pkt_shallow *pkt;
if ((error = git_smart__negotiation_step(&t->parent, data.ptr, data.size)) < 0)
goto on_error;
while ((error = recv_pkt((git_pkt **)&pkt, NULL, buf)) == 0) {
if (pkt->type == GIT_PKT_SHALLOW) {
printf("shallow %s\n", git_oid_tostr_s(&pkt->oid));
git_shallowarray_add(wants->shallow_roots, &pkt->oid);
} else if (pkt->type == GIT_PKT_UNSHALLOW) {
printf("unshallow %s\n", git_oid_tostr_s(&pkt->oid));
git_shallowarray_remove(wants->shallow_roots, &pkt->oid);
} else if (pkt->type == GIT_PKT_FLUSH) {
/* Server is done, stop processing shallow oids */
break;
} else {
git_error_set(GIT_ERROR_NET, "Unexpected pkt type");
goto on_error;
}
}
if (error < 0) {
goto on_error;
}
}
/*
* Our support for ACK extensions is simply to parse them. On
* the first ACK we will accept that as enough common
......@@ -401,7 +455,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
git_pkt_ack *pkt;
unsigned int j;
if ((error = git_pkt_buffer_wants(wants, count, &t->caps, &data)) < 0)
if ((error = git_pkt_buffer_wants(wants, &t->caps, &data)) < 0)
goto on_error;
git_vector_foreach(&t->common, j, pkt) {
......@@ -421,7 +475,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
git_pkt_ack *pkt;
unsigned int j;
if ((error = git_pkt_buffer_wants(wants, count, &t->caps, &data)) < 0)
if ((error = git_pkt_buffer_wants(wants, &t->caps, &data)) < 0)
goto on_error;
git_vector_foreach(&t->common, j, pkt) {
......
......@@ -85,12 +85,14 @@ on_oom:
#define git_array_foreach(a, i, element) \
for ((i) = 0; (i) < (a).size && ((element) = &(a).ptr[(i)]); (i)++)
typedef int (*git_array_compare_cb)(const void *, const void *);
GIT_INLINE(int) git_array__search(
size_t *out,
void *array_ptr,
size_t item_size,
size_t array_len,
int (*compare)(const void *, const void *),
git_array_compare_cb compare,
const void *key)
{
size_t lim;
......
#include "clar_libgit2.h"
#include "futils.h"
#include "repository.h"
void test_clone_shallow__initialize(void)
{
cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1));
}
void test_clone_shallow__cleanup(void)
{
git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0);
cl_git_sandbox_cleanup();
}
static int remote_single_branch(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload)
{
GIT_UNUSED(payload);
cl_git_pass(git_remote_create_with_fetchspec(out, repo, name, url, "+refs/heads/master:refs/remotes/origin/master"));
return 0;
}
void test_clone_shallow__clone_depth_one(void)
{
git_buf path = GIT_BUF_INIT;
git_repository *repo;
git_revwalk *walk;
git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
git_oid oid;
git_oidarray roots;
size_t num_commits = 0;
int error = 0;
clone_opts.fetch_opts.depth = 1;
clone_opts.remote_cb = remote_single_branch;
git_buf_joinpath(&path, clar_sandbox_path(), "shallowclone_1");
cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_buf_cstr(&path), &clone_opts));
cl_assert_equal_b(true, git_repository_is_shallow(repo));
cl_git_pass(git_repository_shallow_roots(&roots, repo));
cl_assert_equal_i(1, roots.count);
cl_assert_equal_s("49322bb17d3acc9146f98c97d078513228bbf3c0", git_oid_tostr_s(&roots.ids[0]));
git_revwalk_new(&walk, repo);
git_revwalk_push_head(walk);
while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) {
num_commits++;
}
cl_assert_equal_i(num_commits, 1);
cl_assert_equal_i(error, GIT_ITEROVER);
git_buf_dispose(&path);
git_revwalk_free(walk);
git_repository_free(repo);
}
void test_clone_shallow__clone_depth_five(void)
{
git_buf path = GIT_BUF_INIT;
git_repository *repo;
git_revwalk *walk;
git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
git_oid oid;
git_oidarray roots;
size_t num_commits = 0;
int error = 0;
clone_opts.fetch_opts.depth = 5;
clone_opts.remote_cb = remote_single_branch;
git_buf_joinpath(&path, clar_sandbox_path(), "shallowclone_5");
cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_buf_cstr(&path), &clone_opts));
cl_assert_equal_b(true, git_repository_is_shallow(repo));
cl_git_pass(git_repository_shallow_roots(&roots, repo));
cl_assert_equal_i(3, roots.count);
cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&roots.ids[0]));
cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&roots.ids[1]));
cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&roots.ids[2]));
git_revwalk_new(&walk, repo);
git_revwalk_push_head(walk);
while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) {
num_commits++;
}
cl_assert_equal_i(num_commits, 13);
cl_assert_equal_i(error, GIT_ITEROVER);
git_buf_dispose(&path);
git_revwalk_free(walk);
git_repository_free(repo);
}
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