Skip to content

Commit ab5b3f3

Browse files
authored
Merge pull request libgit2#6095 from yoichi/better-compatiblity-for-at-time-notation
Better revparse compatibility for at time notation
2 parents 4b27009 + 7bb206a commit ab5b3f3

File tree

12 files changed

+71
-32
lines changed

12 files changed

+71
-32
lines changed

src/date.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -853,7 +853,7 @@ static git_time_t approxidate_str(const char *date,
853853
}
854854
pending_number(&tm, &number);
855855
if (!touched)
856-
*error_ret = 1;
856+
*error_ret = -1;
857857
return update_tm(&tm, &now, 0);
858858
}
859859

@@ -872,7 +872,7 @@ int git_date_parse(git_time_t *out, const char *date)
872872
return -1;
873873

874874
*out = approxidate_str(date, time_sec, &error_ret);
875-
return error_ret;
875+
return error_ret;
876876
}
877877

878878
int git_date_rfc2822_fmt(git_str *out, git_time_t time, int offset)

src/revparse.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ static int retrieve_oid_from_reflog(git_oid *oid, git_reference *ref, size_t ide
208208
{
209209
git_reflog *reflog;
210210
size_t numentries;
211-
const git_reflog_entry *entry;
211+
const git_reflog_entry *entry = NULL;
212212
bool search_by_pos = (identifier <= 100000000);
213213

214214
if (git_reflog_read(&reflog, git_reference_owner(ref), git_reference_name(ref)) < 0)
@@ -237,8 +237,15 @@ static int retrieve_oid_from_reflog(git_oid *oid, git_reference *ref, size_t ide
237237
break;
238238
}
239239

240-
if (i == numentries)
241-
goto notfound;
240+
if (i == numentries) {
241+
if (entry == NULL)
242+
goto notfound;
243+
244+
/*
245+
* TODO: emit a warning (log for 'branch' only goes back to ...)
246+
*/
247+
git_oid_cpy(oid, git_reflog_entry_id_new(entry));
248+
}
242249
}
243250

244251
git_reflog_free(reflog);
@@ -345,8 +352,10 @@ static int handle_at_syntax(git_object **out, git_reference **ref, const char *s
345352
goto cleanup;
346353
}
347354

348-
if (git_date_parse(&timestamp, curly_braces_content) < 0)
355+
if (git_date_parse(&timestamp, curly_braces_content) < 0) {
356+
error = GIT_EINVALIDSPEC;
349357
goto cleanup;
358+
}
350359

351360
error = retrieve_revobject_from_reflog(out, ref, repo, git_str_cstr(&identifier), (size_t)timestamp);
352361

tests/date/date.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,10 @@ void test_date_date__overflow(void)
1313
cl_assert(d2038 < d2039);
1414
#endif
1515
}
16+
17+
void test_date_date__invalid_date(void)
18+
{
19+
git_time_t d;
20+
cl_git_fail(git_date_parse(&d, ""));
21+
cl_git_fail(git_date_parse(&d, "NEITHER_INTEGER_NOR_DATETIME"));
22+
}

tests/fetchhead/nonetwork.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ void test_fetchhead_nonetwork__create_with_multiple_refspecs(void)
508508
int i;
509509
struct prefix_count prefix_counts[] = {
510510
{"refs/notes/", 0, 1},
511-
{"refs/heads/", 0, 12},
511+
{"refs/heads/", 0, 13},
512512
{"refs/tags/", 0, 7},
513513
{NULL, 0, 0},
514514
};

tests/network/fetchlocal.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ void test_network_fetchlocal__complete(void)
4545
cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
4646

4747
cl_git_pass(git_reference_list(&refnames, repo));
48-
cl_assert_equal_i(19, (int)refnames.count);
48+
cl_assert_equal_i(20, (int)refnames.count);
4949
cl_assert(callcount > 0);
5050

5151
git_strarray_dispose(&refnames);
@@ -74,7 +74,7 @@ void test_network_fetchlocal__prune(void)
7474
cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
7575

7676
cl_git_pass(git_reference_list(&refnames, repo));
77-
cl_assert_equal_i(19, (int)refnames.count);
77+
cl_assert_equal_i(20, (int)refnames.count);
7878
cl_assert(callcount > 0);
7979
git_strarray_dispose(&refnames);
8080
git_remote_free(origin);
@@ -88,7 +88,7 @@ void test_network_fetchlocal__prune(void)
8888
cl_git_pass(git_remote_prune(origin, &options.callbacks));
8989

9090
cl_git_pass(git_reference_list(&refnames, repo));
91-
cl_assert_equal_i(18, (int)refnames.count);
91+
cl_assert_equal_i(19, (int)refnames.count);
9292
git_strarray_dispose(&refnames);
9393
git_remote_free(origin);
9494

@@ -101,7 +101,7 @@ void test_network_fetchlocal__prune(void)
101101
cl_git_pass(git_remote_prune(origin, &options.callbacks));
102102

103103
cl_git_pass(git_reference_list(&refnames, repo));
104-
cl_assert_equal_i(17, (int)refnames.count);
104+
cl_assert_equal_i(18, (int)refnames.count);
105105
git_strarray_dispose(&refnames);
106106
git_remote_free(origin);
107107

@@ -166,7 +166,7 @@ void test_network_fetchlocal__prune_overlapping(void)
166166
assert_ref_exists(repo, "refs/remotes/origin/master");
167167
assert_ref_exists(repo, "refs/remotes/origin/pr/42");
168168
cl_git_pass(git_reference_list(&refnames, repo));
169-
cl_assert_equal_i(20, (int)refnames.count);
169+
cl_assert_equal_i(21, (int)refnames.count);
170170
git_strarray_dispose(&refnames);
171171

172172
cl_git_pass(git_config_delete_multivar(config, "remote.origin.fetch", "refs"));
@@ -181,7 +181,7 @@ void test_network_fetchlocal__prune_overlapping(void)
181181
assert_ref_exists(repo, "refs/remotes/origin/master");
182182
assert_ref_exists(repo, "refs/remotes/origin/pr/42");
183183
cl_git_pass(git_reference_list(&refnames, repo));
184-
cl_assert_equal_i(20, (int)refnames.count);
184+
cl_assert_equal_i(21, (int)refnames.count);
185185
git_strarray_dispose(&refnames);
186186

187187
cl_git_pass(git_config_delete_multivar(config, "remote.origin.fetch", "refs"));
@@ -221,7 +221,7 @@ void test_network_fetchlocal__fetchprune(void)
221221
cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
222222

223223
cl_git_pass(git_reference_list(&refnames, repo));
224-
cl_assert_equal_i(19, (int)refnames.count);
224+
cl_assert_equal_i(20, (int)refnames.count);
225225
cl_assert(callcount > 0);
226226
git_strarray_dispose(&refnames);
227227
git_remote_free(origin);
@@ -235,7 +235,7 @@ void test_network_fetchlocal__fetchprune(void)
235235
cl_git_pass(git_remote_prune(origin, &options.callbacks));
236236

237237
cl_git_pass(git_reference_list(&refnames, repo));
238-
cl_assert_equal_i(18, (int)refnames.count);
238+
cl_assert_equal_i(19, (int)refnames.count);
239239
git_strarray_dispose(&refnames);
240240
git_remote_free(origin);
241241

@@ -251,7 +251,7 @@ void test_network_fetchlocal__fetchprune(void)
251251
cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
252252

253253
cl_git_pass(git_reference_list(&refnames, repo));
254-
cl_assert_equal_i(17, (int)refnames.count);
254+
cl_assert_equal_i(18, (int)refnames.count);
255255
git_strarray_dispose(&refnames);
256256
git_remote_free(origin);
257257

@@ -335,7 +335,7 @@ void test_network_fetchlocal__partial(void)
335335
git_strarray_dispose(&refnames);
336336

337337
cl_git_pass(git_reference_list(&refnames, repo));
338-
cl_assert_equal_i(20, (int)refnames.count); /* 18 remote + 1 local */
338+
cl_assert_equal_i(21, (int)refnames.count); /* 18 remote + 1 local */
339339
cl_assert(callcount > 0);
340340

341341
git_strarray_dispose(&refnames);
@@ -418,15 +418,15 @@ void test_network_fetchlocal__multi_remotes(void)
418418
cl_git_pass(git_remote_fetch(test, NULL, &options, NULL));
419419

420420
cl_git_pass(git_reference_list(&refnames, repo));
421-
cl_assert_equal_i(33, (int)refnames.count);
421+
cl_assert_equal_i(35, (int)refnames.count);
422422
git_strarray_dispose(&refnames);
423423

424424
cl_git_pass(git_remote_set_url(repo, "test_with_pushurl", cl_git_fixture_url("testrepo.git")));
425425
cl_git_pass(git_remote_lookup(&test2, repo, "test_with_pushurl"));
426426
cl_git_pass(git_remote_fetch(test2, NULL, &options, NULL));
427427

428428
cl_git_pass(git_reference_list(&refnames, repo));
429-
cl_assert_equal_i(45, (int)refnames.count);
429+
cl_assert_equal_i(48, (int)refnames.count);
430430

431431
git_strarray_dispose(&refnames);
432432
git_remote_free(test);

tests/network/remote/local.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ void test_network_remote_local__retrieve_advertised_references(void)
6161

6262
cl_git_pass(git_remote_ls(&refs, &refs_len, remote));
6363

64-
cl_assert_equal_i(refs_len, 29);
64+
cl_assert_equal_i(refs_len, 30);
6565
}
6666

6767
void test_network_remote_local__retrieve_advertised_before_connect(void)
@@ -85,7 +85,7 @@ void test_network_remote_local__retrieve_advertised_references_after_disconnect(
8585

8686
cl_git_pass(git_remote_ls(&refs, &refs_len, remote));
8787

88-
cl_assert_equal_i(refs_len, 29);
88+
cl_assert_equal_i(refs_len, 30);
8989
}
9090

9191
void test_network_remote_local__retrieve_advertised_references_from_spaced_repository(void)
@@ -100,7 +100,7 @@ void test_network_remote_local__retrieve_advertised_references_from_spaced_repos
100100

101101
cl_git_pass(git_remote_ls(&refs, &refs_len, remote));
102102

103-
cl_assert_equal_i(refs_len, 29);
103+
cl_assert_equal_i(refs_len, 30);
104104

105105
git_remote_free(remote); /* Disconnect from the "spaced repo" before the cleanup */
106106
remote = NULL;

tests/refs/branches/iterator.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ static void assert_retrieval(unsigned int flags, unsigned int expected_count)
4848

4949
void test_refs_branches_iterator__retrieve_all_branches(void)
5050
{
51-
assert_retrieval(GIT_BRANCH_ALL, 14);
51+
assert_retrieval(GIT_BRANCH_ALL, 15);
5252
}
5353

5454
void test_refs_branches_iterator__retrieve_remote_branches(void)
@@ -58,7 +58,7 @@ void test_refs_branches_iterator__retrieve_remote_branches(void)
5858

5959
void test_refs_branches_iterator__retrieve_local_branches(void)
6060
{
61-
assert_retrieval(GIT_BRANCH_LOCAL, 12);
61+
assert_retrieval(GIT_BRANCH_LOCAL, 13);
6262
}
6363

6464
struct expectations {

tests/refs/foreachglob.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ static void assert_retrieval(const char *glob, int expected_count)
4848

4949
void test_refs_foreachglob__retrieve_all_refs(void)
5050
{
51-
/* 12 heads (including one packed head) + 1 note + 2 remotes + 7 tags + 1 blob */
52-
assert_retrieval("*", 23);
51+
/* 13 heads (including one packed head) + 1 note + 2 remotes + 7 tags + 1 blob */
52+
assert_retrieval("*", 24);
5353
}
5454

5555
void test_refs_foreachglob__retrieve_remote_branches(void)
@@ -59,7 +59,7 @@ void test_refs_foreachglob__retrieve_remote_branches(void)
5959

6060
void test_refs_foreachglob__retrieve_local_branches(void)
6161
{
62-
assert_retrieval("refs/heads/*", 12);
62+
assert_retrieval("refs/heads/*", 13);
6363
}
6464

6565
void test_refs_foreachglob__retrieve_nonexistant(void)

tests/refs/iterator.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ static const char *refnames[] = {
2828
"refs/heads/test",
2929
"refs/heads/track-local",
3030
"refs/heads/trailing",
31+
"refs/heads/with-empty-log",
3132
"refs/notes/fanout",
3233
"refs/remotes/test/master",
3334
"refs/tags/annotated_tag_to_blob",
@@ -58,6 +59,7 @@ static const char *refnames_with_symlink[] = {
5859
"refs/heads/test",
5960
"refs/heads/track-local",
6061
"refs/heads/trailing",
62+
"refs/heads/with-empty-log",
6163
"refs/notes/fanout",
6264
"refs/remotes/test/master",
6365
"refs/tags/annotated_tag_to_blob",

tests/refs/revparse.c

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ void test_refs_revparse__date(void)
399399
* a65fedf HEAD@{1335806603 -0900}: commit:
400400
* be3563a HEAD@{1335806563 -0700}: clone: from /Users/ben/src/libgit2/tests/resour
401401
*/
402-
test_object("HEAD@{10 years ago}", NULL);
402+
test_object("HEAD@{10 years ago}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
403403

404404
test_object("HEAD@{1 second}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
405405
test_object("HEAD@{1 second ago}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
@@ -417,11 +417,12 @@ void test_refs_revparse__date(void)
417417

418418

419419
/*
420-
* $ git reflog -1 "master@{2012-04-30 17:22:42 +0000}"
421-
* warning: Log for 'master' only goes back to Mon, 30 Apr 2012 09:22:43 -0800.
420+
* $ git rev-parse "master@{2012-04-30 17:22:42 +0000}"
421+
* warning: log for 'master' only goes back to Mon, 30 Apr 2012 09:22:43 -0800
422+
* be3563ae3f795b2b4353bcce3a527ad0a4f7f644
422423
*/
423-
test_object("master@{2012-04-30 17:22:42 +0000}", NULL);
424-
test_object("master@{2012-04-30 09:22:42 -0800}", NULL);
424+
test_object("master@{2012-04-30 17:22:42 +0000}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
425+
test_object("master@{2012-04-30 09:22:42 -0800}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
425426

426427
/*
427428
* $ git reflog -1 "master@{2012-04-30 17:22:43 +0000}"
@@ -451,6 +452,25 @@ void test_refs_revparse__date(void)
451452
*/
452453
test_object("master@{1335806603}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
453454
test_object("master@{1335806602}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
455+
456+
/*
457+
* $ git rev-parse "with-empty-log@{2 days ago}" --
458+
* fatal: log for refs/heads/with-empty-log is empty
459+
*/
460+
test_object("with-empty-log@{2 days ago}", NULL);
461+
}
462+
463+
void test_refs_revparse__invalid_date(void)
464+
{
465+
/*
466+
* $ git rev-parse HEAD@{} --
467+
* fatal: bad revision 'HEAD@{}'
468+
*
469+
* $ git rev-parse HEAD@{NEITHER_INTEGER_NOR_DATETIME} --
470+
* fatal: bad revision 'HEAD@{NEITHER_INTEGER_NOR_DATETIME}'
471+
*/
472+
test_object("HEAD@{}", NULL);
473+
test_object("HEAD@{NEITHER_INTEGER_NOR_DATETIME}", NULL);
454474
}
455475

456476
void test_refs_revparse__colon(void)

0 commit comments

Comments
 (0)