diff --git a/cache.h b/cache.h index ce377e1354..55dd4e3c8e 100644 --- a/cache.h +++ b/cache.h @@ -1236,6 +1236,8 @@ __attribute__((format (printf, 2, 3))) extern void trace_argv_printf(const char **argv, const char *format, ...); extern void trace_repo_setup(const char *prefix); extern int trace_want(const char *key); +__attribute__((format (printf, 2, 3))) +extern void trace_printf_key(const char *key, const char *fmt, ...); extern void trace_strbuf(const char *key, const struct strbuf *buf); void packet_trace_identity(const char *prog); diff --git a/commit.h b/commit.h index 1faf717212..9ead93bffb 100644 --- a/commit.h +++ b/commit.h @@ -193,6 +193,8 @@ extern struct commit_list *get_octopus_merge_bases(struct commit_list *in); /* largest positive number a signed 32-bit integer can contain */ #define INFINITE_DEPTH 0x7fffffff +struct sha1_array; +struct ref; extern int register_shallow(const unsigned char *sha1); extern int unregister_shallow(const unsigned char *sha1); extern int for_each_commit_graft(each_commit_graft_fn, void *); @@ -209,6 +211,19 @@ extern void setup_alternate_shallow(struct lock_file *shallow_lock, extern char *setup_temporary_shallow(const struct sha1_array *extra); extern void advertise_shallow_grafts(int); +struct shallow_info { + struct sha1_array *shallow; + int *ours, nr_ours; + int *theirs, nr_theirs; + struct sha1_array *ref; +}; + +extern void prepare_shallow_info(struct shallow_info *, struct sha1_array *); +extern void clear_shallow_info(struct shallow_info *); +extern void remove_nonexistent_theirs_shallow(struct shallow_info *); +extern void remove_nonexistent_ours_in_pack(struct shallow_info *, + struct packed_git *); + int is_descendant_of(struct commit *, struct commit_list *); int in_merge_bases(struct commit *, struct commit *); int in_merge_bases_many(struct commit *, int, struct commit **); diff --git a/shallow.c b/shallow.c index 822c626600..ecd950fd04 100644 --- a/shallow.c +++ b/shallow.c @@ -2,6 +2,12 @@ #include "commit.h" #include "tag.h" #include "pkt-line.h" +#include "remote.h" +#include "refs.h" +#include "sha1-array.h" +#include "diff.h" +#include "revision.h" +#include "commit-slab.h" static int is_shallow = -1; static struct stat shallow_stat; @@ -245,3 +251,69 @@ void advertise_shallow_grafts(int fd) return; for_each_commit_graft(advertise_shallow_grafts_cb, &fd); } + +#define TRACE_KEY "GIT_TRACE_SHALLOW" + +/* + * Step 1, split sender shallow commits into "ours" and "theirs" + * Step 2, clean "ours" based on .git/shallow + */ +void prepare_shallow_info(struct shallow_info *info, struct sha1_array *sa) +{ + int i; + trace_printf_key(TRACE_KEY, "shallow: prepare_shallow_info\n"); + memset(info, 0, sizeof(*info)); + info->shallow = sa; + if (!sa) + return; + info->ours = xmalloc(sizeof(*info->ours) * sa->nr); + info->theirs = xmalloc(sizeof(*info->theirs) * sa->nr); + for (i = 0; i < sa->nr; i++) { + if (has_sha1_file(sa->sha1[i])) { + struct commit_graft *graft; + graft = lookup_commit_graft(sa->sha1[i]); + if (graft && graft->nr_parent < 0) + continue; + info->ours[info->nr_ours++] = i; + } else + info->theirs[info->nr_theirs++] = i; + } +} + +void clear_shallow_info(struct shallow_info *info) +{ + free(info->ours); + free(info->theirs); +} + +/* Step 4, remove non-existent ones in "theirs" after getting the pack */ + +void remove_nonexistent_theirs_shallow(struct shallow_info *info) +{ + unsigned char (*sha1)[20] = info->shallow->sha1; + int i, dst; + trace_printf_key(TRACE_KEY, "shallow: remove_nonexistent_theirs_shallow\n"); + for (i = dst = 0; i < info->nr_theirs; i++) { + if (i != dst) + info->theirs[dst] = info->theirs[i]; + if (has_sha1_file(sha1[info->theirs[i]])) + dst++; + } + info->nr_theirs = dst; +} + +/* Step 5, remove non-existent ones in "ours" in the pack */ +void remove_nonexistent_ours_in_pack(struct shallow_info *info, + struct packed_git *p) +{ + unsigned char (*sha1)[20] = info->shallow->sha1; + int i, dst; + trace_printf_key(TRACE_KEY, "shallow: remove_nonexistent_ours_in_pack\n"); + for (i = dst = 0; i < info->nr_ours; i++) { + if (i != dst) + info->ours[dst] = info->ours[i]; + if (find_pack_entry_one(sha1[info->ours[i]], p)) + dst++; + } + info->nr_ours = dst; +} diff --git a/trace.c b/trace.c index 3d744d1d4d..08180a90bc 100644 --- a/trace.c +++ b/trace.c @@ -76,7 +76,7 @@ static void trace_vprintf(const char *key, const char *fmt, va_list ap) } __attribute__((format (printf, 2, 3))) -static void trace_printf_key(const char *key, const char *fmt, ...) +void trace_printf_key(const char *key, const char *fmt, ...) { va_list ap; va_start(ap, fmt);