6
6
#include "tag.h"
7
7
#include "packfile.h"
8
8
#include "object-store.h"
9
+ #include "strbuf.h"
10
+
11
+ struct update_info_ctx {
12
+ FILE * cur_fp ;
13
+ FILE * old_fp ; /* becomes NULL if it differs from cur_fp */
14
+ struct strbuf cur_sb ;
15
+ struct strbuf old_sb ;
16
+ };
17
+
18
+ static void uic_mark_stale (struct update_info_ctx * uic )
19
+ {
20
+ fclose (uic -> old_fp );
21
+ uic -> old_fp = NULL ;
22
+ }
23
+
24
+ static int uic_is_stale (const struct update_info_ctx * uic )
25
+ {
26
+ return uic -> old_fp == NULL ;
27
+ }
28
+
29
+ static int uic_printf (struct update_info_ctx * uic , const char * fmt , ...)
30
+ {
31
+ va_list ap ;
32
+ int ret = -1 ;
33
+
34
+ va_start (ap , fmt );
35
+
36
+ if (uic_is_stale (uic )) {
37
+ ret = vfprintf (uic -> cur_fp , fmt , ap );
38
+ } else {
39
+ ssize_t r ;
40
+ struct strbuf * cur = & uic -> cur_sb ;
41
+ struct strbuf * old = & uic -> old_sb ;
42
+
43
+ strbuf_reset (cur );
44
+ strbuf_vinsertf (cur , 0 , fmt , ap );
45
+
46
+ strbuf_reset (old );
47
+ strbuf_grow (old , cur -> len );
48
+ r = fread (old -> buf , 1 , cur -> len , uic -> old_fp );
49
+ if (r != cur -> len || memcmp (old -> buf , cur -> buf , r ))
50
+ uic_mark_stale (uic );
51
+
52
+ if (fwrite (cur -> buf , 1 , cur -> len , uic -> cur_fp ) == cur -> len )
53
+ ret = 0 ;
54
+ }
55
+
56
+ va_end (ap );
57
+
58
+ return ret ;
59
+ }
9
60
10
61
/*
11
62
* Create the file "path" by writing to a temporary file and renaming
12
63
* it into place. The contents of the file come from "generate", which
13
64
* should return non-zero if it encounters an error.
14
65
*/
15
- static int update_info_file (char * path , int (* generate )(FILE * ))
66
+ static int update_info_file (char * path ,
67
+ int (* generate )(struct update_info_ctx * ),
68
+ int force )
16
69
{
17
70
char * tmp = mkpathdup ("%s_XXXXXX" , path );
18
71
int ret = -1 ;
19
72
int fd = -1 ;
20
- FILE * fp = NULL , * to_close ;
73
+ FILE * to_close ;
74
+ struct update_info_ctx uic = {
75
+ .cur_fp = NULL ,
76
+ .old_fp = NULL ,
77
+ .cur_sb = STRBUF_INIT ,
78
+ .old_sb = STRBUF_INIT
79
+ };
21
80
22
81
safe_create_leading_directories (path );
23
82
fd = git_mkstemp_mode (tmp , 0666 );
24
83
if (fd < 0 )
25
84
goto out ;
26
- to_close = fp = fdopen (fd , "w" );
27
- if (!fp )
85
+ to_close = uic . cur_fp = fdopen (fd , "w" );
86
+ if (!uic . cur_fp )
28
87
goto out ;
29
88
fd = -1 ;
30
- ret = generate (fp );
89
+
90
+ /* no problem on ENOENT and old_fp == NULL, it's stale, now */
91
+ if (!force )
92
+ uic .old_fp = fopen_or_warn (path , "r" );
93
+
94
+ /*
95
+ * uic_printf will compare incremental comparison aginst old_fp
96
+ * and mark uic as stale if needed
97
+ */
98
+ ret = generate (& uic );
31
99
if (ret )
32
100
goto out ;
33
- fp = NULL ;
101
+
102
+ /* new file may be shorter than the old one, check here */
103
+ if (!uic_is_stale (& uic )) {
104
+ struct stat st ;
105
+ long new_len = ftell (uic .cur_fp );
106
+ int old_fd = fileno (uic .old_fp );
107
+
108
+ if (new_len < 0 ) {
109
+ ret = -1 ;
110
+ goto out ;
111
+ }
112
+ if (fstat (old_fd , & st ) || (st .st_size != (size_t )new_len ))
113
+ uic_mark_stale (& uic );
114
+ }
115
+
116
+ uic .cur_fp = NULL ;
34
117
if (fclose (to_close ))
35
118
goto out ;
36
- if (adjust_shared_perm (tmp ) < 0 )
37
- goto out ;
38
- if (rename (tmp , path ) < 0 )
39
- goto out ;
119
+
120
+ if (uic_is_stale (& uic )) {
121
+ if (adjust_shared_perm (tmp ) < 0 )
122
+ goto out ;
123
+ if (rename (tmp , path ) < 0 )
124
+ goto out ;
125
+ } else {
126
+ unlink (tmp );
127
+ }
40
128
ret = 0 ;
41
129
42
130
out :
43
131
if (ret ) {
44
132
error_errno ("unable to update %s" , path );
45
- if (fp )
46
- fclose (fp );
133
+ if (uic . cur_fp )
134
+ fclose (uic . cur_fp );
47
135
else if (fd >= 0 )
48
136
close (fd );
49
137
unlink (tmp );
50
138
}
51
139
free (tmp );
140
+ if (uic .old_fp )
141
+ fclose (uic .old_fp );
142
+ strbuf_release (& uic .old_sb );
143
+ strbuf_release (& uic .cur_sb );
52
144
return ret ;
53
145
}
54
146
55
147
static int add_info_ref (const char * path , const struct object_id * oid ,
56
148
int flag , void * cb_data )
57
149
{
58
- FILE * fp = cb_data ;
150
+ struct update_info_ctx * uic = cb_data ;
59
151
struct object * o = parse_object (the_repository , oid );
60
152
if (!o )
61
153
return -1 ;
62
154
63
- if (fprintf ( fp , "%s %s\n" , oid_to_hex (oid ), path ) < 0 )
155
+ if (uic_printf ( uic , "%s %s\n" , oid_to_hex (oid ), path ) < 0 )
64
156
return -1 ;
65
157
66
158
if (o -> type == OBJ_TAG ) {
67
159
o = deref_tag (the_repository , o , path , 0 );
68
160
if (o )
69
- if (fprintf ( fp , "%s %s^{}\n" ,
161
+ if (uic_printf ( uic , "%s %s^{}\n" ,
70
162
oid_to_hex (& o -> oid ), path ) < 0 )
71
163
return -1 ;
72
164
}
73
165
return 0 ;
74
166
}
75
167
76
- static int generate_info_refs (FILE * fp )
168
+ static int generate_info_refs (struct update_info_ctx * uic )
77
169
{
78
- return for_each_ref (add_info_ref , fp );
170
+ return for_each_ref (add_info_ref , uic );
79
171
}
80
172
81
- static int update_info_refs (void )
173
+ static int update_info_refs (int force )
82
174
{
83
175
char * path = git_pathdup ("info/refs" );
84
- int ret = update_info_file (path , generate_info_refs );
176
+ int ret = update_info_file (path , generate_info_refs , force );
85
177
free (path );
86
178
return ret ;
87
179
}
@@ -236,14 +328,14 @@ static void free_pack_info(void)
236
328
free (info );
237
329
}
238
330
239
- static int write_pack_info_file (FILE * fp )
331
+ static int write_pack_info_file (struct update_info_ctx * uic )
240
332
{
241
333
int i ;
242
334
for (i = 0 ; i < num_pack ; i ++ ) {
243
- if (fprintf ( fp , "P %s\n" , pack_basename (info [i ]-> p )) < 0 )
335
+ if (uic_printf ( uic , "P %s\n" , pack_basename (info [i ]-> p )) < 0 )
244
336
return -1 ;
245
337
}
246
- if (fputc ( '\n' , fp ) == EOF )
338
+ if (uic_printf ( uic , "\n" ) < 0 )
247
339
return -1 ;
248
340
return 0 ;
249
341
}
@@ -254,7 +346,7 @@ static int update_info_packs(int force)
254
346
int ret ;
255
347
256
348
init_pack_info (infofile , force );
257
- ret = update_info_file (infofile , write_pack_info_file );
349
+ ret = update_info_file (infofile , write_pack_info_file , force );
258
350
free_pack_info ();
259
351
free (infofile );
260
352
return ret ;
@@ -269,7 +361,7 @@ int update_server_info(int force)
269
361
*/
270
362
int errs = 0 ;
271
363
272
- errs = errs | update_info_refs ();
364
+ errs = errs | update_info_refs (force );
273
365
errs = errs | update_info_packs (force );
274
366
275
367
/* remove leftover rev-cache file if there is any */
0 commit comments