shallow.c 2.3 KB
Newer Older
1 2
#include "cache.h"
#include "commit.h"
3
#include "tag.h"
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

static int is_shallow = -1;

int register_shallow(const unsigned char *sha1)
{
	struct commit_graft *graft =
		xmalloc(sizeof(struct commit_graft));
	struct commit *commit = lookup_commit(sha1);

	hashcpy(graft->sha1, sha1);
	graft->nr_parent = -1;
	if (commit && commit->object.parsed)
		commit->parents = NULL;
	return register_commit_graft(graft, 0);
}

20
int is_repository_shallow(void)
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
{
	FILE *fp;
	char buf[1024];

	if (is_shallow >= 0)
		return is_shallow;

	fp = fopen(git_path("shallow"), "r");
	if (!fp) {
		is_shallow = 0;
		return is_shallow;
	}
	is_shallow = 1;

	while (fgets(buf, sizeof(buf), fp)) {
		unsigned char sha1[20];
		if (get_sha1_hex(buf, sha1))
			die("bad shallow line: %s", buf);
		register_shallow(sha1);
	}
	fclose(fp);
	return is_shallow;
}

45 46
struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
		int shallow_flag, int not_shallow_flag)
47 48 49 50 51 52 53 54 55 56 57
{
	int i = 0, cur_depth = 0;
	struct commit_list *result = NULL;
	struct object_array stack = {0, 0, NULL};
	struct commit *commit = NULL;

	while (commit || i < heads->nr || stack.nr) {
		struct commit_list *p;
		if (!commit) {
			if (i < heads->nr) {
				commit = (struct commit *)
58
					deref_tag(heads->objects[i++].item, NULL, 0);
59 60 61 62
				if (commit->object.type != OBJ_COMMIT) {
					commit = NULL;
					continue;
				}
63 64 65
				if (!commit->util)
					commit->util = xmalloc(sizeof(int));
				*(int *)commit->util = 0;
66 67 68 69 70 71 72 73
				cur_depth = 0;
			} else {
				commit = (struct commit *)
					stack.objects[--stack.nr].item;
				cur_depth = *(int *)commit->util;
			}
		}
		parse_commit(commit);
74
		commit->object.flags |= not_shallow_flag;
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
		cur_depth++;
		for (p = commit->parents, commit = NULL; p; p = p->next) {
			if (!p->item->util) {
				int *pointer = xmalloc(sizeof(int));
				p->item->util = pointer;
				*pointer =  cur_depth;
			} else {
				int *pointer = p->item->util;
				if (cur_depth >= *pointer)
					continue;
				*pointer = cur_depth;
			}
			if (cur_depth < depth) {
				if (p->next)
					add_object_array(&p->item->object,
							NULL, &stack);
				else {
					commit = p->item;
					cur_depth = *(int *)commit->util;
				}
95
			} else {
96
				commit_list_insert(p->item, &result);
97 98
				p->item->object.flags |= shallow_flag;
			}
99 100 101 102 103
		}
	}

	return result;
}