Skip to content

Commit bb0ced7

Browse files
committed
Merge branch 'rs/read-ref-at'
* rs/read-ref-at: refs.c: change read_ref_at to use the reflog iterators
2 parents d0d5ba7 + 4207ed2 commit bb0ced7

File tree

2 files changed

+105
-107
lines changed

2 files changed

+105
-107
lines changed

refs.c

Lines changed: 103 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -2943,119 +2943,117 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
29432943
return 0;
29442944
}
29452945

2946-
static char *ref_msg(const char *line, const char *endp)
2947-
{
2948-
const char *ep;
2949-
line += 82;
2950-
ep = memchr(line, '\n', endp - line);
2951-
if (!ep)
2952-
ep = endp;
2953-
return xmemdupz(line, ep - line);
2946+
struct read_ref_at_cb {
2947+
const char *refname;
2948+
unsigned long at_time;
2949+
int cnt;
2950+
int reccnt;
2951+
unsigned char *sha1;
2952+
int found_it;
2953+
2954+
unsigned char osha1[20];
2955+
unsigned char nsha1[20];
2956+
int tz;
2957+
unsigned long date;
2958+
char **msg;
2959+
unsigned long *cutoff_time;
2960+
int *cutoff_tz;
2961+
int *cutoff_cnt;
2962+
};
2963+
2964+
static int read_ref_at_ent(unsigned char *osha1, unsigned char *nsha1,
2965+
const char *email, unsigned long timestamp, int tz,
2966+
const char *message, void *cb_data)
2967+
{
2968+
struct read_ref_at_cb *cb = cb_data;
2969+
2970+
cb->reccnt++;
2971+
cb->tz = tz;
2972+
cb->date = timestamp;
2973+
2974+
if (timestamp <= cb->at_time || cb->cnt == 0) {
2975+
if (cb->msg)
2976+
*cb->msg = xstrdup(message);
2977+
if (cb->cutoff_time)
2978+
*cb->cutoff_time = timestamp;
2979+
if (cb->cutoff_tz)
2980+
*cb->cutoff_tz = tz;
2981+
if (cb->cutoff_cnt)
2982+
*cb->cutoff_cnt = cb->reccnt - 1;
2983+
/*
2984+
* we have not yet updated cb->[n|o]sha1 so they still
2985+
* hold the values for the previous record.
2986+
*/
2987+
if (!is_null_sha1(cb->osha1)) {
2988+
hashcpy(cb->sha1, nsha1);
2989+
if (hashcmp(cb->osha1, nsha1))
2990+
warning("Log for ref %s has gap after %s.",
2991+
cb->refname, show_date(cb->date, cb->tz, DATE_RFC2822));
2992+
}
2993+
else if (cb->date == cb->at_time)
2994+
hashcpy(cb->sha1, nsha1);
2995+
else if (hashcmp(nsha1, cb->sha1))
2996+
warning("Log for ref %s unexpectedly ended on %s.",
2997+
cb->refname, show_date(cb->date, cb->tz,
2998+
DATE_RFC2822));
2999+
hashcpy(cb->osha1, osha1);
3000+
hashcpy(cb->nsha1, nsha1);
3001+
cb->found_it = 1;
3002+
return 1;
3003+
}
3004+
hashcpy(cb->osha1, osha1);
3005+
hashcpy(cb->nsha1, nsha1);
3006+
if (cb->cnt > 0)
3007+
cb->cnt--;
3008+
return 0;
3009+
}
3010+
3011+
static int read_ref_at_ent_oldest(unsigned char *osha1, unsigned char *nsha1,
3012+
const char *email, unsigned long timestamp,
3013+
int tz, const char *message, void *cb_data)
3014+
{
3015+
struct read_ref_at_cb *cb = cb_data;
3016+
3017+
if (cb->msg)
3018+
*cb->msg = xstrdup(message);
3019+
if (cb->cutoff_time)
3020+
*cb->cutoff_time = timestamp;
3021+
if (cb->cutoff_tz)
3022+
*cb->cutoff_tz = tz;
3023+
if (cb->cutoff_cnt)
3024+
*cb->cutoff_cnt = cb->reccnt;
3025+
hashcpy(cb->sha1, osha1);
3026+
if (is_null_sha1(cb->sha1))
3027+
hashcpy(cb->sha1, nsha1);
3028+
/* We just want the first entry */
3029+
return 1;
29543030
}
29553031

29563032
int read_ref_at(const char *refname, unsigned long at_time, int cnt,
29573033
unsigned char *sha1, char **msg,
29583034
unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
29593035
{
2960-
const char *logfile, *logdata, *logend, *rec, *lastgt, *lastrec;
2961-
char *tz_c;
2962-
int logfd, tz, reccnt = 0;
2963-
struct stat st;
2964-
unsigned long date;
2965-
unsigned char logged_sha1[20];
2966-
void *log_mapped;
2967-
size_t mapsz;
3036+
struct read_ref_at_cb cb;
29683037

2969-
logfile = git_path("logs/%s", refname);
2970-
logfd = open(logfile, O_RDONLY, 0);
2971-
if (logfd < 0)
2972-
die_errno("Unable to read log '%s'", logfile);
2973-
fstat(logfd, &st);
2974-
if (!st.st_size)
2975-
die("Log %s is empty.", logfile);
2976-
mapsz = xsize_t(st.st_size);
2977-
log_mapped = xmmap(NULL, mapsz, PROT_READ, MAP_PRIVATE, logfd, 0);
2978-
logdata = log_mapped;
2979-
close(logfd);
3038+
memset(&cb, 0, sizeof(cb));
3039+
cb.refname = refname;
3040+
cb.at_time = at_time;
3041+
cb.cnt = cnt;
3042+
cb.msg = msg;
3043+
cb.cutoff_time = cutoff_time;
3044+
cb.cutoff_tz = cutoff_tz;
3045+
cb.cutoff_cnt = cutoff_cnt;
3046+
cb.sha1 = sha1;
3047+
3048+
for_each_reflog_ent_reverse(refname, read_ref_at_ent, &cb);
3049+
3050+
if (!cb.reccnt)
3051+
die("Log for %s is empty.", refname);
3052+
if (cb.found_it)
3053+
return 0;
3054+
3055+
for_each_reflog_ent(refname, read_ref_at_ent_oldest, &cb);
29803056

2981-
lastrec = NULL;
2982-
rec = logend = logdata + st.st_size;
2983-
while (logdata < rec) {
2984-
reccnt++;
2985-
if (logdata < rec && *(rec-1) == '\n')
2986-
rec--;
2987-
lastgt = NULL;
2988-
while (logdata < rec && *(rec-1) != '\n') {
2989-
rec--;
2990-
if (*rec == '>')
2991-
lastgt = rec;
2992-
}
2993-
if (!lastgt)
2994-
die("Log %s is corrupt.", logfile);
2995-
date = strtoul(lastgt + 1, &tz_c, 10);
2996-
if (date <= at_time || cnt == 0) {
2997-
tz = strtoul(tz_c, NULL, 10);
2998-
if (msg)
2999-
*msg = ref_msg(rec, logend);
3000-
if (cutoff_time)
3001-
*cutoff_time = date;
3002-
if (cutoff_tz)
3003-
*cutoff_tz = tz;
3004-
if (cutoff_cnt)
3005-
*cutoff_cnt = reccnt - 1;
3006-
if (lastrec) {
3007-
if (get_sha1_hex(lastrec, logged_sha1))
3008-
die("Log %s is corrupt.", logfile);
3009-
if (get_sha1_hex(rec + 41, sha1))
3010-
die("Log %s is corrupt.", logfile);
3011-
if (hashcmp(logged_sha1, sha1)) {
3012-
warning("Log %s has gap after %s.",
3013-
logfile, show_date(date, tz, DATE_RFC2822));
3014-
}
3015-
}
3016-
else if (date == at_time) {
3017-
if (get_sha1_hex(rec + 41, sha1))
3018-
die("Log %s is corrupt.", logfile);
3019-
}
3020-
else {
3021-
if (get_sha1_hex(rec + 41, logged_sha1))
3022-
die("Log %s is corrupt.", logfile);
3023-
if (hashcmp(logged_sha1, sha1)) {
3024-
warning("Log %s unexpectedly ended on %s.",
3025-
logfile, show_date(date, tz, DATE_RFC2822));
3026-
}
3027-
}
3028-
munmap(log_mapped, mapsz);
3029-
return 0;
3030-
}
3031-
lastrec = rec;
3032-
if (cnt > 0)
3033-
cnt--;
3034-
}
3035-
3036-
rec = logdata;
3037-
while (rec < logend && *rec != '>' && *rec != '\n')
3038-
rec++;
3039-
if (rec == logend || *rec == '\n')
3040-
die("Log %s is corrupt.", logfile);
3041-
date = strtoul(rec + 1, &tz_c, 10);
3042-
tz = strtoul(tz_c, NULL, 10);
3043-
if (get_sha1_hex(logdata, sha1))
3044-
die("Log %s is corrupt.", logfile);
3045-
if (is_null_sha1(sha1)) {
3046-
if (get_sha1_hex(logdata + 41, sha1))
3047-
die("Log %s is corrupt.", logfile);
3048-
}
3049-
if (msg)
3050-
*msg = ref_msg(logdata, logend);
3051-
munmap(log_mapped, mapsz);
3052-
3053-
if (cutoff_time)
3054-
*cutoff_time = date;
3055-
if (cutoff_tz)
3056-
*cutoff_tz = tz;
3057-
if (cutoff_cnt)
3058-
*cutoff_cnt = reccnt;
30593057
return 1;
30603058
}
30613059

t/t1400-update-ref.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ test_expect_success \
235235
'rm -f o e &&
236236
git rev-parse --verify "master@{2005-05-26 23:33:01}" >o 2>e &&
237237
test '"$B"' = $(cat o) &&
238-
test "warning: Log .git/logs/'"$m has gap after $gd"'." = "$(cat e)"'
238+
test "warning: Log for ref '"$m has gap after $gd"'." = "$(cat e)"'
239239
test_expect_success \
240240
'Query "master@{2005-05-26 23:38:00}" (middle of history)' \
241241
'rm -f o e &&
@@ -253,7 +253,7 @@ test_expect_success \
253253
'rm -f o e &&
254254
git rev-parse --verify "master@{2005-05-28}" >o 2>e &&
255255
test '"$D"' = $(cat o) &&
256-
test "warning: Log .git/logs/'"$m unexpectedly ended on $ld"'." = "$(cat e)"'
256+
test "warning: Log for ref '"$m unexpectedly ended on $ld"'." = "$(cat e)"'
257257

258258

259259
rm -f .git/$m .git/logs/$m expect

0 commit comments

Comments
 (0)