commit 3f338f0a096f8648ea0bb148ba5e4383d6434eaa from: Stefan Sperling date: Tue Jul 27 13:08:51 2021 UTC track the last modification time of references commit - e746ca7f4f68ff664bee61f8f658f551f8f7ec02 commit + 3f338f0a096f8648ea0bb148ba5e4383d6434eaa blob - f666e84083ffb2ad05eab02a4fe4cc4a06853221 blob + 89ec5aabb1b27cad61902560dc7e83551e00665b --- include/got_reference.h +++ include/got_reference.h @@ -59,6 +59,9 @@ const char *got_ref_get_name(struct got_reference *); /* Get the name of the reference which a symoblic reference points at. */ const char *got_ref_get_symref_target(struct got_reference *); +/* Get the last modification timestamp of the reference. */ +time_t got_ref_get_mtime(struct got_reference *); + /* * Create a duplicate copy of a reference. * The caller must dispose of this copy with got_ref_close(). blob - ee703d1487de86d26b7373621514084605d208eb blob + 1f7e7d1033f43108af0c239bd50be641dccfc47d --- lib/reference.c +++ lib/reference.c @@ -87,11 +87,12 @@ struct got_reference { } ref; struct got_lockfile *lf; + time_t mtime; }; static const struct got_error * alloc_ref(struct got_reference **ref, const char *name, - struct got_object_id *id, int flags) + struct got_object_id *id, int flags, time_t mtime) { const struct got_error *err = NULL; @@ -102,6 +103,7 @@ alloc_ref(struct got_reference **ref, const char *name memcpy((*ref)->ref.ref.sha1, id->sha1, sizeof((*ref)->ref.ref.sha1)); (*ref)->flags = flags; (*ref)->ref.ref.name = strdup(name); + (*ref)->mtime = mtime; if ((*ref)->ref.ref.name == NULL) { err = got_error_from_errno("strdup"); got_ref_close(*ref); @@ -147,7 +149,8 @@ parse_symref(struct got_reference **ref, const char *n } static const struct got_error * -parse_ref_line(struct got_reference **ref, const char *name, const char *line) +parse_ref_line(struct got_reference **ref, const char *name, const char *line, + time_t mtime) { struct got_object_id id; @@ -159,7 +162,7 @@ parse_ref_line(struct got_reference **ref, const char if (!got_parse_sha1_digest(id.sha1, line)) return got_error(GOT_ERR_BAD_REF_DATA); - return alloc_ref(ref, name, &id, 0); + return alloc_ref(ref, name, &id, 0, mtime); } static const struct got_error * @@ -172,6 +175,7 @@ parse_ref_file(struct got_reference **ref, const char size_t linesize = 0; ssize_t linelen; struct got_lockfile *lf = NULL; + struct stat sb; if (lock) { err = got_lockfile_lock(&lf, abspath, -1); @@ -192,6 +196,10 @@ parse_ref_file(struct got_reference **ref, const char got_lockfile_unlock(lf, -1); return err; } + if (fstat(fileno(f), &sb) == -1) { + err = got_error_from_errno2("fstat", abspath); + goto done; + } linelen = getline(&line, &linesize, f); if (linelen == -1) { @@ -214,7 +222,7 @@ parse_ref_file(struct got_reference **ref, const char linelen--; } - err = parse_ref_line(ref, absname, line); + err = parse_ref_line(ref, absname, line, sb.st_mtime); if (lock) { if (err) got_lockfile_unlock(lf, -1); @@ -315,7 +323,7 @@ got_ref_alloc(struct got_reference **ref, const char * if (!is_valid_ref_name(name)) return got_error_path(name, GOT_ERR_BAD_REF_NAME); - return alloc_ref(ref, name, id, 0); + return alloc_ref(ref, name, id, 0, 0); } const struct got_error * @@ -330,7 +338,7 @@ got_ref_alloc_symref(struct got_reference **ref, const static const struct got_error * parse_packed_ref_line(struct got_reference **ref, const char *abs_refname, - const char *line) + const char *line, time_t mtime) { struct got_object_id id; const char *name; @@ -350,12 +358,12 @@ parse_packed_ref_line(struct got_reference **ref, cons } else name = line + SHA1_DIGEST_STRING_LENGTH; - return alloc_ref(ref, name, &id, GOT_REF_IS_PACKED); + return alloc_ref(ref, name, &id, GOT_REF_IS_PACKED, mtime); } static const struct got_error * open_packed_ref(struct got_reference **ref, FILE *f, const char **subdirs, - int nsubdirs, const char *refname) + int nsubdirs, const char *refname, time_t mtime) { const struct got_error *err = NULL; char *abs_refname; @@ -383,7 +391,8 @@ open_packed_ref(struct got_reference **ref, FILE *f, c asprintf(&abs_refname, "refs/%s/%s", subdirs[i], refname) == -1) return got_error_from_errno("asprintf"); - err = parse_packed_ref_line(ref, abs_refname, line); + err = parse_packed_ref_line(ref, abs_refname, line, + mtime); if (!ref_is_absolute) free(abs_refname); if (err || *ref != NULL) @@ -486,8 +495,14 @@ got_ref_open(struct got_reference **ref, struct got_re f = fopen(packed_refs_path, "rb"); free(packed_refs_path); if (f != NULL) { + struct stat sb; + if (fstat(fileno(f), &sb) == -1) { + err = got_error_from_errno2("fstat", + packed_refs_path); + goto done; + } err = open_packed_ref(ref, f, subdirs, nitems(subdirs), - refname); + refname, sb.st_mtime); if (!err) { if (fclose(f) == EOF) { err = got_error_from_errno("fclose"); @@ -668,6 +683,12 @@ got_ref_get_symref_target(struct got_reference *ref) return ref->ref.symref.ref; return NULL; +} + +time_t +got_ref_get_mtime(struct got_reference *ref) +{ + return ref->mtime; } const struct got_error * @@ -1013,6 +1034,12 @@ got_ref_list(struct got_reflist_head *refs, struct got if (f) { size_t linesize = 0; ssize_t linelen; + struct stat sb; + + if (fstat(fileno(f), &sb) == -1) { + err = got_error_from_errno2("fstat", packed_refs_path); + goto done; + } for (;;) { linelen = getline(&line, &linesize, f); if (linelen == -1) { @@ -1023,7 +1050,8 @@ got_ref_list(struct got_reflist_head *refs, struct got } if (linelen > 0 && line[linelen - 1] == '\n') line[linelen - 1] = '\0'; - err = parse_packed_ref_line(&ref, NULL, line); + err = parse_packed_ref_line(&ref, NULL, line, + sb.st_mtime); if (err) goto done; if (ref) { @@ -1201,6 +1229,12 @@ got_ref_write(struct got_reference *ref, struct got_re } free(tmppath); tmppath = NULL; + + if (stat(path, &sb) == -1) { + err = got_error_from_errno2("stat", path); + goto done; + } + ref->mtime = sb.st_mtime; done: if (ref->lf == NULL && lf) unlock_err = got_lockfile_unlock(lf, -1); @@ -1268,7 +1302,7 @@ delete_packed_ref(struct got_reference *delref, struct } if (linelen > 0 && line[linelen - 1] == '\n') line[linelen - 1] = '\0'; - err = parse_packed_ref_line(&ref, NULL, line); + err = parse_packed_ref_line(&ref, NULL, line, 0); if (err) goto done; if (ref == NULL)