8
8
#include "diff.h"
9
9
#include "revision.h"
10
10
#include "commit-slab.h"
11
+ #include "sigchain.h"
11
12
12
13
static int is_shallow = -1 ;
13
- static struct stat shallow_stat ;
14
+ static struct stat_validity shallow_stat ;
14
15
static char * alternate_shallow_file ;
15
16
16
17
void set_alternate_shallow_file (const char * path , int override )
@@ -52,12 +53,12 @@ int is_repository_shallow(void)
52
53
* shallow file should be used. We could just open it and it
53
54
* will likely fail. But let's do an explicit check instead.
54
55
*/
55
- if (!* path ||
56
- stat (path , & shallow_stat ) ||
57
- (fp = fopen (path , "r" )) == NULL ) {
56
+ if (!* path || (fp = fopen (path , "r" )) == NULL ) {
57
+ stat_validity_clear (& shallow_stat );
58
58
is_shallow = 0 ;
59
59
return is_shallow ;
60
60
}
61
+ stat_validity_update (& shallow_stat , fileno (fp ));
61
62
is_shallow = 1 ;
62
63
63
64
while (fgets (buf , sizeof (buf ), fp )) {
@@ -137,21 +138,11 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
137
138
138
139
void check_shallow_file_for_update (void )
139
140
{
140
- struct stat st ;
141
-
142
- if (!is_shallow )
143
- return ;
144
- else if (is_shallow == -1 )
141
+ if (is_shallow == -1 )
145
142
die ("BUG: shallow must be initialized by now" );
146
143
147
- if (stat (git_path ("shallow" ), & st ))
148
- die ("shallow file was removed during fetch" );
149
- else if (st .st_mtime != shallow_stat .st_mtime
150
- #ifdef USE_NSEC
151
- || ST_MTIME_NSEC (st ) != ST_MTIME_NSEC (shallow_stat )
152
- #endif
153
- )
154
- die ("shallow file was changed during fetch" );
144
+ if (!stat_validity_check (& shallow_stat , git_path ("shallow" )))
145
+ die ("shallow file has changed since we read it" );
155
146
}
156
147
157
148
#define SEEN_ONLY 1
@@ -216,27 +207,53 @@ int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
216
207
return write_shallow_commits_1 (out , use_pack_protocol , extra , 0 );
217
208
}
218
209
219
- char * setup_temporary_shallow (const struct sha1_array * extra )
210
+ static struct strbuf temporary_shallow = STRBUF_INIT ;
211
+
212
+ static void remove_temporary_shallow (void )
213
+ {
214
+ if (temporary_shallow .len ) {
215
+ unlink_or_warn (temporary_shallow .buf );
216
+ strbuf_reset (& temporary_shallow );
217
+ }
218
+ }
219
+
220
+ static void remove_temporary_shallow_on_signal (int signo )
221
+ {
222
+ remove_temporary_shallow ();
223
+ sigchain_pop (signo );
224
+ raise (signo );
225
+ }
226
+
227
+ const char * setup_temporary_shallow (const struct sha1_array * extra )
220
228
{
229
+ static int installed_handler ;
221
230
struct strbuf sb = STRBUF_INIT ;
222
231
int fd ;
223
232
233
+ if (temporary_shallow .len )
234
+ die ("BUG: attempt to create two temporary shallow files" );
235
+
224
236
if (write_shallow_commits (& sb , 0 , extra )) {
225
- struct strbuf path = STRBUF_INIT ;
226
- strbuf_addstr (& path , git_path ("shallow_XXXXXX" ));
227
- fd = xmkstemp (path .buf );
237
+ strbuf_addstr (& temporary_shallow , git_path ("shallow_XXXXXX" ));
238
+ fd = xmkstemp (temporary_shallow .buf );
239
+
240
+ if (!installed_handler ) {
241
+ atexit (remove_temporary_shallow );
242
+ sigchain_push_common (remove_temporary_shallow_on_signal );
243
+ }
244
+
228
245
if (write_in_full (fd , sb .buf , sb .len ) != sb .len )
229
246
die_errno ("failed to write to %s" ,
230
- path .buf );
247
+ temporary_shallow .buf );
231
248
close (fd );
232
249
strbuf_release (& sb );
233
- return strbuf_detach ( & path , NULL ) ;
250
+ return temporary_shallow . buf ;
234
251
}
235
252
/*
236
253
* is_repository_shallow() sees empty string as "no shallow
237
254
* file".
238
255
*/
239
- return xstrdup ( "" ) ;
256
+ return temporary_shallow . buf ;
240
257
}
241
258
242
259
void setup_alternate_shallow (struct lock_file * shallow_lock ,
@@ -246,9 +263,9 @@ void setup_alternate_shallow(struct lock_file *shallow_lock,
246
263
struct strbuf sb = STRBUF_INIT ;
247
264
int fd ;
248
265
249
- check_shallow_file_for_update ();
250
266
fd = hold_lock_file_for_update (shallow_lock , git_path ("shallow" ),
251
267
LOCK_DIE_ON_ERROR );
268
+ check_shallow_file_for_update ();
252
269
if (write_shallow_commits (& sb , 0 , extra )) {
253
270
if (write_in_full (fd , sb .buf , sb .len ) != sb .len )
254
271
die_errno ("failed to write to %s" ,
@@ -293,9 +310,9 @@ void prune_shallow(int show_only)
293
310
strbuf_release (& sb );
294
311
return ;
295
312
}
296
- check_shallow_file_for_update ();
297
313
fd = hold_lock_file_for_update (& shallow_lock , git_path ("shallow" ),
298
314
LOCK_DIE_ON_ERROR );
315
+ check_shallow_file_for_update ();
299
316
if (write_shallow_commits_1 (& sb , 0 , NULL , SEEN_ONLY )) {
300
317
if (write_in_full (fd , sb .buf , sb .len ) != sb .len )
301
318
die_errno ("failed to write to %s" ,
0 commit comments