Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit eb59779

Browse files
committed
filebuf: use a checksum to detect file changes
Instead of relying on the size and timestamp, which can hide changes performed in the same second, hash the file content's when we care about detecting changes.
1 parent a2f9647 commit eb59779

File tree

3 files changed

+33
-34
lines changed

3 files changed

+33
-34
lines changed

src/config_file.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@ typedef struct git_config_file_iter {
7777
(iter) = (tmp))
7878

7979
struct reader {
80-
time_t file_mtime;
81-
size_t file_size;
80+
git_oid checksum;
8281
char *file_path;
8382
git_buf buffer;
8483
char *read_ptr;
@@ -285,7 +284,7 @@ static int config_open(git_config_backend *cfg, git_config_level_t level)
285284

286285
git_buf_init(&reader->buffer, 0);
287286
res = git_futils_readbuffer_updated(
288-
&reader->buffer, b->file_path, &reader->file_mtime, &reader->file_size, NULL);
287+
&reader->buffer, b->file_path, &reader->checksum, NULL);
289288

290289
/* It's fine if the file doesn't exist */
291290
if (res == GIT_ENOTFOUND)
@@ -345,7 +344,7 @@ static int config_refresh(git_config_backend *cfg)
345344
reader = git_array_get(b->readers, i);
346345
error = git_futils_readbuffer_updated(
347346
&reader->buffer, reader->file_path,
348-
&reader->file_mtime, &reader->file_size, &updated);
347+
&reader->checksum, &updated);
349348

350349
if (error < 0 && error != GIT_ENOTFOUND)
351350
return error;
@@ -1618,7 +1617,7 @@ static int read_on_variable(
16181617
git_buf_init(&r->buffer, 0);
16191618

16201619
result = git_futils_readbuffer_updated(
1621-
&r->buffer, r->file_path, &r->file_mtime, &r->file_size, NULL);
1620+
&r->buffer, r->file_path, &r->checksum, NULL);
16221621

16231622
if (result == 0) {
16241623
result = config_read(parse_data->values, parse_data->cfg_file, r, parse_data->level, parse_data->depth+1);
@@ -1894,7 +1893,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
18941893
} else {
18951894
/* Lock the file */
18961895
if ((result = git_filebuf_open(
1897-
&file, cfg->file_path, 0, GIT_CONFIG_FILE_MODE)) < 0) {
1896+
&file, cfg->file_path, GIT_FILEBUF_HASH_CONTENTS, GIT_CONFIG_FILE_MODE)) < 0) {
18981897
git_buf_free(&reader->buffer);
18991898
return result;
19001899
}
@@ -1945,10 +1944,6 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
19451944
git_buf_attach(&cfg->locked_content, git_buf_detach(&buf), len);
19461945
} else {
19471946
git_filebuf_write(&file, git_buf_cstr(&buf), git_buf_len(&buf));
1948-
1949-
/* refresh stats - if this errors, then commit will error too */
1950-
(void)git_filebuf_stats(&reader->file_mtime, &reader->file_size, &file);
1951-
19521947
result = git_filebuf_commit(&file);
19531948
}
19541949

src/fileops.c

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,12 @@ int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len)
153153
}
154154

155155
int git_futils_readbuffer_updated(
156-
git_buf *buf, const char *path, time_t *mtime, size_t *size, int *updated)
156+
git_buf *buf, const char *path, git_oid *checksum, int *updated)
157157
{
158+
int error;
158159
git_file fd;
159160
struct stat st;
160-
bool changed = false;
161+
git_oid checksum_new;
161162

162163
assert(buf && path && *path);
163164

@@ -178,26 +179,6 @@ int git_futils_readbuffer_updated(
178179
return -1;
179180
}
180181

181-
/*
182-
* If we were given a time and/or a size, we only want to read the file
183-
* if it has been modified.
184-
*/
185-
if (size && *size != (size_t)st.st_size)
186-
changed = true;
187-
if (mtime && *mtime != (time_t)st.st_mtime)
188-
changed = true;
189-
if (!size && !mtime)
190-
changed = true;
191-
192-
if (!changed) {
193-
return 0;
194-
}
195-
196-
if (mtime != NULL)
197-
*mtime = st.st_mtime;
198-
if (size != NULL)
199-
*size = (size_t)st.st_size;
200-
201182
if ((fd = git_futils_open_ro(path)) < 0)
202183
return fd;
203184

@@ -208,6 +189,28 @@ int git_futils_readbuffer_updated(
208189

209190
p_close(fd);
210191

192+
if ((error = git_hash_buf(&checksum_new, buf->ptr, buf->size)) < 0) {
193+
git_buf_free(buf);
194+
return error;
195+
}
196+
197+
/*
198+
* If we were given a checksum, we only want to use it if it's different
199+
*/
200+
if (checksum && !git_oid__cmp(checksum, &checksum_new)) {
201+
git_buf_free(buf);
202+
if (updated)
203+
*updated = 0;
204+
205+
return 0;
206+
}
207+
208+
/*
209+
* If we're here, the file did change, or the user didn't have an old version
210+
*/
211+
if (checksum)
212+
git_oid_cpy(checksum, &checksum_new);
213+
211214
if (updated != NULL)
212215
*updated = 1;
213216

@@ -216,7 +219,7 @@ int git_futils_readbuffer_updated(
216219

217220
int git_futils_readbuffer(git_buf *buf, const char *path)
218221
{
219-
return git_futils_readbuffer_updated(buf, path, NULL, NULL, NULL);
222+
return git_futils_readbuffer_updated(buf, path, NULL, NULL);
220223
}
221224

222225
int git_futils_writebuffer(

src/fileops.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "path.h"
1414
#include "pool.h"
1515
#include "strmap.h"
16+
#include "oid.h"
1617

1718
/**
1819
* Filebuffer methods
@@ -21,7 +22,7 @@
2122
*/
2223
extern int git_futils_readbuffer(git_buf *obj, const char *path);
2324
extern int git_futils_readbuffer_updated(
24-
git_buf *obj, const char *path, time_t *mtime, size_t *size, int *updated);
25+
git_buf *obj, const char *path, git_oid *checksum, int *updated);
2526
extern int git_futils_readbuffer_fd(git_buf *obj, git_file fd, size_t len);
2627

2728
extern int git_futils_writebuffer(

0 commit comments

Comments
 (0)