Skip to content

Commit

Permalink
check_and_freshen_file: fix reversed success-check
Browse files Browse the repository at this point in the history
When we want to write out a loose object file, we have
always first made sure we don't already have the object
somewhere. Since 33d4221 (write_sha1_file: freshen existing
objects, 2014-10-15), we also update the timestamp on the
file, so that a simultaneous prune knows somebody is
likely to reference it soon.

If our utime() call fails, we treat this the same as not
having the object in the first place; the safe thing to do
is write out another copy. However, the loose-object check
accidentally inverts the utime() check; it returns failure
_only_ when the utime() call actually succeeded. Thus it was
failing to protect us there, and in the normal case where
utime() succeeds, it caused us to pointlessly write out and
link the object.

This passed our freshening tests, because writing out the
new object is certainly _one_ way of updating its utime. So
the normal case was inefficient, but not wrong.

While we're here, let's also drop a comment in front of the
check_and_freshen functions, making a note of their return
type (since it is not our usual "0 for success, -1 for
error").

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 Jul 8, 2015
1 parent 33d4221 commit 3096b2e
Showing 1 changed file with 9 additions and 1 deletion.
10 changes: 9 additions & 1 deletion sha1_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -442,18 +442,26 @@ void prepare_alt_odb(void)
read_info_alternates(get_object_directory(), 0);
}

/* Returns 1 if we have successfully freshened the file, 0 otherwise. */
static int freshen_file(const char *fn)
{
struct utimbuf t;
t.actime = t.modtime = time(NULL);
return !utime(fn, &t);
}

/*
* All of the check_and_freshen functions return 1 if the file exists and was
* freshened (if freshening was requested), 0 otherwise. If they return
* 0, you should not assume that it is safe to skip a write of the object (it
* either does not exist on disk, or has a stale mtime and may be subject to
* pruning).
*/
static int check_and_freshen_file(const char *fn, int freshen)
{
if (access(fn, F_OK))
return 0;
if (freshen && freshen_file(fn))
if (freshen && !freshen_file(fn))
return 0;
return 1;
}
Expand Down

0 comments on commit 3096b2e

Please sign in to comment.