Merge branch 'dl/reflog-with-single-entry'
After expiring a reflog and making a single commit, the reflog for the branch would record a single entry that knows both @{0} and @{1}, but we failed to answer "what commit were we on?", i.e. @{1} * dl/reflog-with-single-entry: refs: allow @{n} to work with n-sized reflog refs: factor out set_read_ref_cutoffs()
This commit is contained in:
commit
440acfbe0c
122
refs.c
122
refs.c
@ -882,59 +882,9 @@ struct read_ref_at_cb {
|
||||
int *cutoff_cnt;
|
||||
};
|
||||
|
||||
static int read_ref_at_ent(struct object_id *ooid, struct object_id *noid,
|
||||
const char *email, timestamp_t timestamp, int tz,
|
||||
const char *message, void *cb_data)
|
||||
static void set_read_ref_cutoffs(struct read_ref_at_cb *cb,
|
||||
timestamp_t timestamp, int tz, const char *message)
|
||||
{
|
||||
struct read_ref_at_cb *cb = cb_data;
|
||||
|
||||
cb->reccnt++;
|
||||
cb->tz = tz;
|
||||
cb->date = timestamp;
|
||||
|
||||
if (timestamp <= cb->at_time || cb->cnt == 0) {
|
||||
if (cb->msg)
|
||||
*cb->msg = xstrdup(message);
|
||||
if (cb->cutoff_time)
|
||||
*cb->cutoff_time = timestamp;
|
||||
if (cb->cutoff_tz)
|
||||
*cb->cutoff_tz = tz;
|
||||
if (cb->cutoff_cnt)
|
||||
*cb->cutoff_cnt = cb->reccnt - 1;
|
||||
/*
|
||||
* we have not yet updated cb->[n|o]oid so they still
|
||||
* hold the values for the previous record.
|
||||
*/
|
||||
if (!is_null_oid(&cb->ooid)) {
|
||||
oidcpy(cb->oid, noid);
|
||||
if (!oideq(&cb->ooid, noid))
|
||||
warning(_("log for ref %s has gap after %s"),
|
||||
cb->refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822)));
|
||||
}
|
||||
else if (cb->date == cb->at_time)
|
||||
oidcpy(cb->oid, noid);
|
||||
else if (!oideq(noid, cb->oid))
|
||||
warning(_("log for ref %s unexpectedly ended on %s"),
|
||||
cb->refname, show_date(cb->date, cb->tz,
|
||||
DATE_MODE(RFC2822)));
|
||||
oidcpy(&cb->ooid, ooid);
|
||||
oidcpy(&cb->noid, noid);
|
||||
cb->found_it = 1;
|
||||
return 1;
|
||||
}
|
||||
oidcpy(&cb->ooid, ooid);
|
||||
oidcpy(&cb->noid, noid);
|
||||
if (cb->cnt > 0)
|
||||
cb->cnt--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_ref_at_ent_oldest(struct object_id *ooid, struct object_id *noid,
|
||||
const char *email, timestamp_t timestamp,
|
||||
int tz, const char *message, void *cb_data)
|
||||
{
|
||||
struct read_ref_at_cb *cb = cb_data;
|
||||
|
||||
if (cb->msg)
|
||||
*cb->msg = xstrdup(message);
|
||||
if (cb->cutoff_time)
|
||||
@ -943,6 +893,69 @@ static int read_ref_at_ent_oldest(struct object_id *ooid, struct object_id *noid
|
||||
*cb->cutoff_tz = tz;
|
||||
if (cb->cutoff_cnt)
|
||||
*cb->cutoff_cnt = cb->reccnt;
|
||||
}
|
||||
|
||||
static int read_ref_at_ent(struct object_id *ooid, struct object_id *noid,
|
||||
const char *email, timestamp_t timestamp, int tz,
|
||||
const char *message, void *cb_data)
|
||||
{
|
||||
struct read_ref_at_cb *cb = cb_data;
|
||||
int reached_count;
|
||||
|
||||
cb->tz = tz;
|
||||
cb->date = timestamp;
|
||||
|
||||
/*
|
||||
* It is not possible for cb->cnt == 0 on the first iteration because
|
||||
* that special case is handled in read_ref_at().
|
||||
*/
|
||||
if (cb->cnt > 0)
|
||||
cb->cnt--;
|
||||
reached_count = cb->cnt == 0 && !is_null_oid(ooid);
|
||||
if (timestamp <= cb->at_time || reached_count) {
|
||||
set_read_ref_cutoffs(cb, timestamp, tz, message);
|
||||
/*
|
||||
* we have not yet updated cb->[n|o]oid so they still
|
||||
* hold the values for the previous record.
|
||||
*/
|
||||
if (!is_null_oid(&cb->ooid) && !oideq(&cb->ooid, noid))
|
||||
warning(_("log for ref %s has gap after %s"),
|
||||
cb->refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822)));
|
||||
if (reached_count)
|
||||
oidcpy(cb->oid, ooid);
|
||||
else if (!is_null_oid(&cb->ooid) || cb->date == cb->at_time)
|
||||
oidcpy(cb->oid, noid);
|
||||
else if (!oideq(noid, cb->oid))
|
||||
warning(_("log for ref %s unexpectedly ended on %s"),
|
||||
cb->refname, show_date(cb->date, cb->tz,
|
||||
DATE_MODE(RFC2822)));
|
||||
cb->found_it = 1;
|
||||
}
|
||||
cb->reccnt++;
|
||||
oidcpy(&cb->ooid, ooid);
|
||||
oidcpy(&cb->noid, noid);
|
||||
return cb->found_it;
|
||||
}
|
||||
|
||||
static int read_ref_at_ent_newest(struct object_id *ooid, struct object_id *noid,
|
||||
const char *email, timestamp_t timestamp,
|
||||
int tz, const char *message, void *cb_data)
|
||||
{
|
||||
struct read_ref_at_cb *cb = cb_data;
|
||||
|
||||
set_read_ref_cutoffs(cb, timestamp, tz, message);
|
||||
oidcpy(cb->oid, noid);
|
||||
/* We just want the first entry */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_ref_at_ent_oldest(struct object_id *ooid, struct object_id *noid,
|
||||
const char *email, timestamp_t timestamp,
|
||||
int tz, const char *message, void *cb_data)
|
||||
{
|
||||
struct read_ref_at_cb *cb = cb_data;
|
||||
|
||||
set_read_ref_cutoffs(cb, timestamp, tz, message);
|
||||
oidcpy(cb->oid, ooid);
|
||||
if (is_null_oid(cb->oid))
|
||||
oidcpy(cb->oid, noid);
|
||||
@ -967,6 +980,11 @@ int read_ref_at(struct ref_store *refs, const char *refname,
|
||||
cb.cutoff_cnt = cutoff_cnt;
|
||||
cb.oid = oid;
|
||||
|
||||
if (cb.cnt == 0) {
|
||||
refs_for_each_reflog_ent_reverse(refs, refname, read_ref_at_ent_newest, &cb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
refs_for_each_reflog_ent_reverse(refs, refname, read_ref_at_ent, &cb);
|
||||
|
||||
if (!cb.reccnt) {
|
||||
|
@ -86,8 +86,8 @@ test_expect_success 'fails silently when using -q' '
|
||||
test_expect_success 'fails silently when using -q with deleted reflogs' '
|
||||
ref=$(git rev-parse HEAD) &&
|
||||
git update-ref --create-reflog -m "message for refs/test" refs/test "$ref" &&
|
||||
git reflog delete --updateref --rewrite refs/test@{0} &&
|
||||
test_must_fail git rev-parse -q --verify refs/test@{0} >error 2>&1 &&
|
||||
git reflog delete --updateref --rewrite refs/test@{1} &&
|
||||
test_must_fail git rev-parse -q --verify refs/test@{1} >error 2>&1 &&
|
||||
test_must_be_empty error
|
||||
'
|
||||
|
||||
|
@ -99,4 +99,17 @@ test_expect_success 'create path with @' '
|
||||
check "@:normal" blob content
|
||||
check "@:fun@ny" blob content
|
||||
|
||||
test_expect_success '@{1} works with only one reflog entry' '
|
||||
git checkout -B newbranch master &&
|
||||
git reflog expire --expire=now refs/heads/newbranch &&
|
||||
git commit --allow-empty -m "first after expiration" &&
|
||||
test_cmp_rev newbranch~ newbranch@{1}
|
||||
'
|
||||
|
||||
test_expect_success '@{0} works with empty reflog' '
|
||||
git checkout -B newbranch master &&
|
||||
git reflog expire --expire=now refs/heads/newbranch &&
|
||||
test_cmp_rev newbranch newbranch@{0}
|
||||
'
|
||||
|
||||
test_done
|
||||
|
Loading…
Reference in New Issue
Block a user