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
,
169 const struct sha1_array
*extra
)
171 struct write_shallow_data data
;
174 data
.use_pack_protocol
= use_pack_protocol
;
176 for_each_commit_graft(write_one_shallow
, &data
);
179 for (i
= 0; i
< extra
->nr
; i
++) {
180 strbuf_addstr(out
, sha1_to_hex(extra
->sha1
[i
]));
181 strbuf_addch(out
, '\n');
187 char *setup_temporary_shallow(const struct sha1_array
*extra
)
189 struct strbuf sb
= STRBUF_INIT
;
192 if (write_shallow_commits(&sb
, 0, extra
)) {
193 struct strbuf path
= STRBUF_INIT
;
194 strbuf_addstr(&path
, git_path("shallow_XXXXXX"));
195 fd
= xmkstemp(path
.buf
);
196 if (write_in_full(fd
, sb
.buf
, sb
.len
) != sb
.len
)
197 die_errno("failed to write to %s",
201 return strbuf_detach(&path
, NULL
);
204 * is_repository_shallow() sees empty string as "no shallow
210 void setup_alternate_shallow(struct lock_file
*shallow_lock
,
211 const char **alternate_shallow_file
,
212 const struct sha1_array
*extra
)
214 struct strbuf sb
= STRBUF_INIT
;
217 check_shallow_file_for_update();
218 fd
= hold_lock_file_for_update(shallow_lock
, git_path("shallow"),
220 if (write_shallow_commits(&sb
, 0, extra
)) {
221 if (write_in_full(fd
, sb
.buf
, sb
.len
) != sb
.len
)
222 die_errno("failed to write to %s",
223 shallow_lock
->filename
);
224 *alternate_shallow_file
= shallow_lock
->filename
;
227 * is_repository_shallow() sees empty string as "no
230 *alternate_shallow_file
= "";
234 static int advertise_shallow_grafts_cb(const struct commit_graft
*graft
, void *cb
)
237 if (graft
->nr_parent
== -1)
238 packet_write(fd
, "shallow %s\n", sha1_to_hex(graft
->sha1
));
242 void advertise_shallow_grafts(int fd
)
244 if (!is_repository_shallow())
246 for_each_commit_graft(advertise_shallow_grafts_cb
, &fd
);