|  | #include "cache.h" | 
|  | #include "commit.h" | 
|  | #include "tag.h" | 
|  |  | 
|  | 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); | 
|  | } | 
|  |  | 
|  | int is_repository_shallow(void) | 
|  | { | 
|  | 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; | 
|  | } | 
|  |  | 
|  | struct commit_list *get_shallow_commits(struct object_array *heads, int depth, | 
|  | int shallow_flag, int not_shallow_flag) | 
|  | { | 
|  | 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 *) | 
|  | deref_tag(heads->objects[i++].item, NULL, 0); | 
|  | if (!commit || commit->object.type != OBJ_COMMIT) { | 
|  | commit = NULL; | 
|  | continue; | 
|  | } | 
|  | if (!commit->util) | 
|  | commit->util = xmalloc(sizeof(int)); | 
|  | *(int *)commit->util = 0; | 
|  | cur_depth = 0; | 
|  | } else { | 
|  | commit = (struct commit *) | 
|  | stack.objects[--stack.nr].item; | 
|  | cur_depth = *(int *)commit->util; | 
|  | } | 
|  | } | 
|  | if (parse_commit(commit)) | 
|  | die("invalid commit"); | 
|  | commit->object.flags |= not_shallow_flag; | 
|  | 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; | 
|  | } | 
|  | } else { | 
|  | commit_list_insert(p->item, &result); | 
|  | p->item->object.flags |= shallow_flag; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | return result; | 
|  | } |