Skip to content

Commit

Permalink
shallow: use stat_validity to check for up-to-date file
Browse files Browse the repository at this point in the history
When we are about to write the shallow file, we check that
it has not changed since we last read it. Instead of
hand-rolling this, we can use stat_validity. This is built
around the index stat-check, so it is more robust than just
checking the mtime, as we do now (it uses the same check as
we do for index files).

The new code also handles the case of a shallow file
appearing unexpectedly. With the current code, two
simultaneous processes making us shallow (e.g., two "git
fetch --depth=1" running at the same time in a non-shallow
repository) can race to overwrite each other.

As a bonus, we also remove a race in determining the stat
information of what we read (we stat and then open, leaving
a race window; instead we should open and then fstat the
descriptor).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Jeff King authored and Junio C Hamano committed Feb 27, 2014
1 parent 5f95c9f commit 0cc77c3
Showing 1 changed file with 7 additions and 17 deletions.
24 changes: 7 additions & 17 deletions shallow.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include "commit-slab.h"

static int is_shallow = -1;
static struct stat shallow_stat;
static struct stat_validity shallow_stat;
static char *alternate_shallow_file;

void set_alternate_shallow_file(const char *path, int override)
Expand Down Expand Up @@ -52,12 +52,12 @@ int is_repository_shallow(void)
* shallow file should be used. We could just open it and it
* will likely fail. But let's do an explicit check instead.
*/
if (!*path ||
stat(path, &shallow_stat) ||
(fp = fopen(path, "r")) == NULL) {
if (!*path || (fp = fopen(path, "r")) == NULL) {
stat_validity_clear(&shallow_stat);
is_shallow = 0;
return is_shallow;
}
stat_validity_update(&shallow_stat, fileno(fp));
is_shallow = 1;

while (fgets(buf, sizeof(buf), fp)) {
Expand Down Expand Up @@ -137,21 +137,11 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,

void check_shallow_file_for_update(void)
{
struct stat st;

if (!is_shallow)
return;
else if (is_shallow == -1)
if (is_shallow == -1)
die("BUG: shallow must be initialized by now");

if (stat(git_path("shallow"), &st))
die("shallow file was removed during fetch");
else if (st.st_mtime != shallow_stat.st_mtime
#ifdef USE_NSEC
|| ST_MTIME_NSEC(st) != ST_MTIME_NSEC(shallow_stat)
#endif
)
die("shallow file was changed during fetch");
if (!stat_validity_check(&shallow_stat, git_path("shallow")))
die("shallow file has changed since we read it");
}

#define SEEN_ONLY 1
Expand Down

0 comments on commit 0cc77c3

Please sign in to comment.