1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
#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 = OBJECT_ARRAY_INIT;
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");
cur_depth++;
if (cur_depth >= depth) {
commit_list_insert(commit, &result);
commit->object.flags |= shallow_flag;
commit = NULL;
continue;
}
commit->object.flags |= not_shallow_flag;
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 (p->next)
add_object_array(&p->item->object,
NULL, &stack);
else {
commit = p->item;
cur_depth = *(int *)commit->util;
}
}
}
return result;
}
|