6 static int is_shallow
= -1;
7 static struct stat shallow_stat
;
8 static char *alternate_shallow_file
;
10 void set_alternate_shallow_file(const char *path
)
13 die("BUG: is_repository_shallow must not be called before set_alternate_shallow_file");
14 free(alternate_shallow_file
);
15 alternate_shallow_file
= path
? xstrdup(path
) : NULL
;
18 int register_shallow(const unsigned char *sha1
)
20 struct commit_graft
*graft
=
21 xmalloc(sizeof(struct commit_graft
));
22 struct commit
*commit
= lookup_commit(sha1
);
24 hashcpy(graft
->sha1
, sha1
);
25 graft
->nr_parent
= -1;
26 if (commit
&& commit
->object
.parsed
)
27 commit
->parents
= NULL
;
28 return register_commit_graft(graft
, 0);
31 int is_repository_shallow(void)
35 const char *path
= alternate_shallow_file
;
41 path
= git_path("shallow");
43 * fetch-pack sets '--shallow-file ""' as an indicator that no
44 * shallow file should be used. We could just open it and it
45 * will likely fail. But let's do an explicit check instead.
48 stat(path
, &shallow_stat
) ||
49 (fp
= fopen(path
, "r")) == NULL
) {
55 while (fgets(buf
, sizeof(buf
), fp
)) {
56 unsigned char sha1
[20];
57 if (get_sha1_hex(buf
, sha1
))
58 die("bad shallow line: %s", buf
);
59 register_shallow(sha1
);
65 struct commit_list
*get_shallow_commits(struct object_array
*heads
, int depth
,
66 int shallow_flag
, int not_shallow_flag
)
68 int i
= 0, cur_depth
= 0;
69 struct commit_list
*result
= NULL
;
70 struct object_array stack
= OBJECT_ARRAY_INIT
;
71 struct commit
*commit
= NULL
;
73 while (commit
|| i
< heads
->nr
|| stack
.nr
) {
74 struct commit_list
*p
;
77 commit
= (struct commit
*)
78 deref_tag(heads
->objects
[i
++].item
, NULL
, 0);
79 if (!commit
|| commit
->object
.type
!= OBJ_COMMIT
) {
84 commit
->util
= xmalloc(sizeof(int));
85 *(int *)commit
->util
= 0;
88 commit
= (struct commit
*)
89 stack
.objects
[--stack
.nr
].item
;
90 cur_depth
= *(int *)commit
->util
;
93 if (parse_commit(commit
))
94 die("invalid commit");
96 if (cur_depth
>= depth
) {
97 commit_list_insert(commit
, &result
);
98 commit
->object
.flags
|= shallow_flag
;
102 commit
->object
.flags
|= not_shallow_flag
;
103 for (p
= commit
->parents
, commit
= NULL
; p
; p
= p
->next
) {
104 if (!p
->item
->util
) {
105 int *pointer
= xmalloc(sizeof(int));
106 p
->item
->util
= pointer
;
107 *pointer
= cur_depth
;
109 int *pointer
= p
->item
->util
;
110 if (cur_depth
>= *pointer
)
112 *pointer
= cur_depth
;
115 add_object_array(&p
->item
->object
,
119 cur_depth
= *(int *)commit
->util
;
127 void check_shallow_file_for_update(void)
133 else if (is_shallow
== -1)
134 die("BUG: shallow must be initialized by now");
136 if (stat(git_path("shallow"), &st
))
137 die("shallow file was removed during fetch");
138 else if (st
.st_mtime
!= shallow_stat
.st_mtime
140 || ST_MTIME_NSEC(st
) != ST_MTIME_NSEC(shallow_stat
)
143 die("shallow file was changed during fetch");
146 struct write_shallow_data
{
148 int use_pack_protocol
;
152 static int write_one_shallow(const struct commit_graft
*graft
, void *cb_data
)
154 struct write_shallow_data
*data
= cb_data
;
155 const char *hex
= sha1_to_hex(graft
->sha1
);
156 if (graft
->nr_parent
!= -1)
159 if (data
->use_pack_protocol
)
160 packet_buf_write(data
->out
, "shallow %s", hex
);
162 strbuf_addstr(data
->out
, hex
);
163 strbuf_addch(data
->out
, '\n');
168 int write_shallow_commits(struct strbuf
*out
, int use_pack_protocol
)
170 struct write_shallow_data data
;
172 data
.use_pack_protocol
= use_pack_protocol
;
174 for_each_commit_graft(write_one_shallow
, &data
);
178 char *setup_temporary_shallow(void)
180 struct strbuf sb
= STRBUF_INIT
;
183 if (write_shallow_commits(&sb
, 0)) {
184 struct strbuf path
= STRBUF_INIT
;
185 strbuf_addstr(&path
, git_path("shallow_XXXXXX"));
186 fd
= xmkstemp(path
.buf
);
187 if (write_in_full(fd
, sb
.buf
, sb
.len
) != sb
.len
)
188 die_errno("failed to write to %s",
192 return strbuf_detach(&path
, NULL
);
195 * is_repository_shallow() sees empty string as "no shallow
201 void setup_alternate_shallow(struct lock_file
*shallow_lock
,
202 const char **alternate_shallow_file
)
204 struct strbuf sb
= STRBUF_INIT
;
207 check_shallow_file_for_update();
208 fd
= hold_lock_file_for_update(shallow_lock
, git_path("shallow"),
210 if (write_shallow_commits(&sb
, 0)) {
211 if (write_in_full(fd
, sb
.buf
, sb
.len
) != sb
.len
)
212 die_errno("failed to write to %s",
213 shallow_lock
->filename
);
214 *alternate_shallow_file
= shallow_lock
->filename
;
217 * is_repository_shallow() sees empty string as "no
220 *alternate_shallow_file
= "";