summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2021-12-23 14:09:09 -0500
committerGitHub <noreply@github.com>2021-12-23 14:09:09 -0500
commitab5b3f37f5e74805250685a08fa9f4220e5dba12 (patch)
tree9be0bddcf37b3ed9e869e8f349a6fcf55276cf17
parent4b27009cadb1bf09ad272f72745310a881762d78 (diff)
parent7bb206a76dca70b7db236315d348c6c9fc325cab (diff)
downloadlibgit2-ab5b3f37f5e74805250685a08fa9f4220e5dba12.tar.gz
Merge pull request #6095 from yoichi/better-compatiblity-for-at-time-notation
Better revparse compatibility for at time notation
-rw-r--r--src/date.c4
-rw-r--r--src/revparse.c17
-rw-r--r--tests/date/date.c7
-rw-r--r--tests/fetchhead/nonetwork.c2
-rw-r--r--tests/network/fetchlocal.c24
-rw-r--r--tests/network/remote/local.c6
-rw-r--r--tests/refs/branches/iterator.c4
-rw-r--r--tests/refs/foreachglob.c6
-rw-r--r--tests/refs/iterator.c2
-rw-r--r--tests/refs/revparse.c30
-rw-r--r--tests/resources/testrepo.git/logs/refs/heads/with-empty-log0
-rw-r--r--tests/resources/testrepo.git/refs/heads/with-empty-log1
12 files changed, 71 insertions, 32 deletions
diff --git a/src/date.c b/src/date.c
index 1529276e2..0e5ffc96b 100644
--- a/src/date.c
+++ b/src/date.c
@@ -853,7 +853,7 @@ static git_time_t approxidate_str(const char *date,
}
pending_number(&tm, &number);
if (!touched)
- *error_ret = 1;
+ *error_ret = -1;
return update_tm(&tm, &now, 0);
}
@@ -872,7 +872,7 @@ int git_date_parse(git_time_t *out, const char *date)
return -1;
*out = approxidate_str(date, time_sec, &error_ret);
- return error_ret;
+ return error_ret;
}
int git_date_rfc2822_fmt(git_str *out, git_time_t time, int offset)
diff --git a/src/revparse.c b/src/revparse.c
index 52dd0720b..5d3ff77ed 100644
--- a/src/revparse.c
+++ b/src/revparse.c
@@ -208,7 +208,7 @@ static int retrieve_oid_from_reflog(git_oid *oid, git_reference *ref, size_t ide
{
git_reflog *reflog;
size_t numentries;
- const git_reflog_entry *entry;
+ const git_reflog_entry *entry = NULL;
bool search_by_pos = (identifier <= 100000000);
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
break;
}
- if (i == numentries)
- goto notfound;
+ if (i == numentries) {
+ if (entry == NULL)
+ goto notfound;
+
+ /*
+ * TODO: emit a warning (log for 'branch' only goes back to ...)
+ */
+ git_oid_cpy(oid, git_reflog_entry_id_new(entry));
+ }
}
git_reflog_free(reflog);
@@ -345,8 +352,10 @@ static int handle_at_syntax(git_object **out, git_reference **ref, const char *s
goto cleanup;
}
- if (git_date_parse(&timestamp, curly_braces_content) < 0)
+ if (git_date_parse(&timestamp, curly_braces_content) < 0) {
+ error = GIT_EINVALIDSPEC;
goto cleanup;
+ }
error = retrieve_revobject_from_reflog(out, ref, repo, git_str_cstr(&identifier), (size_t)timestamp);
diff --git a/tests/date/date.c b/tests/date/date.c
index f70b4fea9..82b5c6728 100644
--- a/tests/date/date.c
+++ b/tests/date/date.c
@@ -13,3 +13,10 @@ void test_date_date__overflow(void)
cl_assert(d2038 < d2039);
#endif
}
+
+void test_date_date__invalid_date(void)
+{
+ git_time_t d;
+ cl_git_fail(git_date_parse(&d, ""));
+ cl_git_fail(git_date_parse(&d, "NEITHER_INTEGER_NOR_DATETIME"));
+}
diff --git a/tests/fetchhead/nonetwork.c b/tests/fetchhead/nonetwork.c
index 0e446d94e..ab31d3610 100644
--- a/tests/fetchhead/nonetwork.c
+++ b/tests/fetchhead/nonetwork.c
@@ -508,7 +508,7 @@ void test_fetchhead_nonetwork__create_with_multiple_refspecs(void)
int i;
struct prefix_count prefix_counts[] = {
{"refs/notes/", 0, 1},
- {"refs/heads/", 0, 12},
+ {"refs/heads/", 0, 13},
{"refs/tags/", 0, 7},
{NULL, 0, 0},
};
diff --git a/tests/network/fetchlocal.c b/tests/network/fetchlocal.c
index e299d3ec8..c54f45472 100644
--- a/tests/network/fetchlocal.c
+++ b/tests/network/fetchlocal.c
@@ -45,7 +45,7 @@ void test_network_fetchlocal__complete(void)
cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
cl_git_pass(git_reference_list(&refnames, repo));
- cl_assert_equal_i(19, (int)refnames.count);
+ cl_assert_equal_i(20, (int)refnames.count);
cl_assert(callcount > 0);
git_strarray_dispose(&refnames);
@@ -74,7 +74,7 @@ void test_network_fetchlocal__prune(void)
cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
cl_git_pass(git_reference_list(&refnames, repo));
- cl_assert_equal_i(19, (int)refnames.count);
+ cl_assert_equal_i(20, (int)refnames.count);
cl_assert(callcount > 0);
git_strarray_dispose(&refnames);
git_remote_free(origin);
@@ -88,7 +88,7 @@ void test_network_fetchlocal__prune(void)
cl_git_pass(git_remote_prune(origin, &options.callbacks));
cl_git_pass(git_reference_list(&refnames, repo));
- cl_assert_equal_i(18, (int)refnames.count);
+ cl_assert_equal_i(19, (int)refnames.count);
git_strarray_dispose(&refnames);
git_remote_free(origin);
@@ -101,7 +101,7 @@ void test_network_fetchlocal__prune(void)
cl_git_pass(git_remote_prune(origin, &options.callbacks));
cl_git_pass(git_reference_list(&refnames, repo));
- cl_assert_equal_i(17, (int)refnames.count);
+ cl_assert_equal_i(18, (int)refnames.count);
git_strarray_dispose(&refnames);
git_remote_free(origin);
@@ -166,7 +166,7 @@ void test_network_fetchlocal__prune_overlapping(void)
assert_ref_exists(repo, "refs/remotes/origin/master");
assert_ref_exists(repo, "refs/remotes/origin/pr/42");
cl_git_pass(git_reference_list(&refnames, repo));
- cl_assert_equal_i(20, (int)refnames.count);
+ cl_assert_equal_i(21, (int)refnames.count);
git_strarray_dispose(&refnames);
cl_git_pass(git_config_delete_multivar(config, "remote.origin.fetch", "refs"));
@@ -181,7 +181,7 @@ void test_network_fetchlocal__prune_overlapping(void)
assert_ref_exists(repo, "refs/remotes/origin/master");
assert_ref_exists(repo, "refs/remotes/origin/pr/42");
cl_git_pass(git_reference_list(&refnames, repo));
- cl_assert_equal_i(20, (int)refnames.count);
+ cl_assert_equal_i(21, (int)refnames.count);
git_strarray_dispose(&refnames);
cl_git_pass(git_config_delete_multivar(config, "remote.origin.fetch", "refs"));
@@ -221,7 +221,7 @@ void test_network_fetchlocal__fetchprune(void)
cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
cl_git_pass(git_reference_list(&refnames, repo));
- cl_assert_equal_i(19, (int)refnames.count);
+ cl_assert_equal_i(20, (int)refnames.count);
cl_assert(callcount > 0);
git_strarray_dispose(&refnames);
git_remote_free(origin);
@@ -235,7 +235,7 @@ void test_network_fetchlocal__fetchprune(void)
cl_git_pass(git_remote_prune(origin, &options.callbacks));
cl_git_pass(git_reference_list(&refnames, repo));
- cl_assert_equal_i(18, (int)refnames.count);
+ cl_assert_equal_i(19, (int)refnames.count);
git_strarray_dispose(&refnames);
git_remote_free(origin);
@@ -251,7 +251,7 @@ void test_network_fetchlocal__fetchprune(void)
cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL));
cl_git_pass(git_reference_list(&refnames, repo));
- cl_assert_equal_i(17, (int)refnames.count);
+ cl_assert_equal_i(18, (int)refnames.count);
git_strarray_dispose(&refnames);
git_remote_free(origin);
@@ -335,7 +335,7 @@ void test_network_fetchlocal__partial(void)
git_strarray_dispose(&refnames);
cl_git_pass(git_reference_list(&refnames, repo));
- cl_assert_equal_i(20, (int)refnames.count); /* 18 remote + 1 local */
+ cl_assert_equal_i(21, (int)refnames.count); /* 18 remote + 1 local */
cl_assert(callcount > 0);
git_strarray_dispose(&refnames);
@@ -418,7 +418,7 @@ void test_network_fetchlocal__multi_remotes(void)
cl_git_pass(git_remote_fetch(test, NULL, &options, NULL));
cl_git_pass(git_reference_list(&refnames, repo));
- cl_assert_equal_i(33, (int)refnames.count);
+ cl_assert_equal_i(35, (int)refnames.count);
git_strarray_dispose(&refnames);
cl_git_pass(git_remote_set_url(repo, "test_with_pushurl", cl_git_fixture_url("testrepo.git")));
@@ -426,7 +426,7 @@ void test_network_fetchlocal__multi_remotes(void)
cl_git_pass(git_remote_fetch(test2, NULL, &options, NULL));
cl_git_pass(git_reference_list(&refnames, repo));
- cl_assert_equal_i(45, (int)refnames.count);
+ cl_assert_equal_i(48, (int)refnames.count);
git_strarray_dispose(&refnames);
git_remote_free(test);
diff --git a/tests/network/remote/local.c b/tests/network/remote/local.c
index f174044d7..2007f3776 100644
--- a/tests/network/remote/local.c
+++ b/tests/network/remote/local.c
@@ -61,7 +61,7 @@ void test_network_remote_local__retrieve_advertised_references(void)
cl_git_pass(git_remote_ls(&refs, &refs_len, remote));
- cl_assert_equal_i(refs_len, 29);
+ cl_assert_equal_i(refs_len, 30);
}
void test_network_remote_local__retrieve_advertised_before_connect(void)
@@ -85,7 +85,7 @@ void test_network_remote_local__retrieve_advertised_references_after_disconnect(
cl_git_pass(git_remote_ls(&refs, &refs_len, remote));
- cl_assert_equal_i(refs_len, 29);
+ cl_assert_equal_i(refs_len, 30);
}
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
cl_git_pass(git_remote_ls(&refs, &refs_len, remote));
- cl_assert_equal_i(refs_len, 29);
+ cl_assert_equal_i(refs_len, 30);
git_remote_free(remote); /* Disconnect from the "spaced repo" before the cleanup */
remote = NULL;
diff --git a/tests/refs/branches/iterator.c b/tests/refs/branches/iterator.c
index ca366c9f3..e086681e5 100644
--- a/tests/refs/branches/iterator.c
+++ b/tests/refs/branches/iterator.c
@@ -48,7 +48,7 @@ static void assert_retrieval(unsigned int flags, unsigned int expected_count)
void test_refs_branches_iterator__retrieve_all_branches(void)
{
- assert_retrieval(GIT_BRANCH_ALL, 14);
+ assert_retrieval(GIT_BRANCH_ALL, 15);
}
void test_refs_branches_iterator__retrieve_remote_branches(void)
@@ -58,7 +58,7 @@ void test_refs_branches_iterator__retrieve_remote_branches(void)
void test_refs_branches_iterator__retrieve_local_branches(void)
{
- assert_retrieval(GIT_BRANCH_LOCAL, 12);
+ assert_retrieval(GIT_BRANCH_LOCAL, 13);
}
struct expectations {
diff --git a/tests/refs/foreachglob.c b/tests/refs/foreachglob.c
index 3ff18a27a..b208a95a2 100644
--- a/tests/refs/foreachglob.c
+++ b/tests/refs/foreachglob.c
@@ -48,8 +48,8 @@ static void assert_retrieval(const char *glob, int expected_count)
void test_refs_foreachglob__retrieve_all_refs(void)
{
- /* 12 heads (including one packed head) + 1 note + 2 remotes + 7 tags + 1 blob */
- assert_retrieval("*", 23);
+ /* 13 heads (including one packed head) + 1 note + 2 remotes + 7 tags + 1 blob */
+ assert_retrieval("*", 24);
}
void test_refs_foreachglob__retrieve_remote_branches(void)
@@ -59,7 +59,7 @@ void test_refs_foreachglob__retrieve_remote_branches(void)
void test_refs_foreachglob__retrieve_local_branches(void)
{
- assert_retrieval("refs/heads/*", 12);
+ assert_retrieval("refs/heads/*", 13);
}
void test_refs_foreachglob__retrieve_nonexistant(void)
diff --git a/tests/refs/iterator.c b/tests/refs/iterator.c
index 8d52755c2..a4f9e62ec 100644
--- a/tests/refs/iterator.c
+++ b/tests/refs/iterator.c
@@ -28,6 +28,7 @@ static const char *refnames[] = {
"refs/heads/test",
"refs/heads/track-local",
"refs/heads/trailing",
+ "refs/heads/with-empty-log",
"refs/notes/fanout",
"refs/remotes/test/master",
"refs/tags/annotated_tag_to_blob",
@@ -58,6 +59,7 @@ static const char *refnames_with_symlink[] = {
"refs/heads/test",
"refs/heads/track-local",
"refs/heads/trailing",
+ "refs/heads/with-empty-log",
"refs/notes/fanout",
"refs/remotes/test/master",
"refs/tags/annotated_tag_to_blob",
diff --git a/tests/refs/revparse.c b/tests/refs/revparse.c
index d02249754..5fb758504 100644
--- a/tests/refs/revparse.c
+++ b/tests/refs/revparse.c
@@ -399,7 +399,7 @@ void test_refs_revparse__date(void)
* a65fedf HEAD@{1335806603 -0900}: commit:
* be3563a HEAD@{1335806563 -0700}: clone: from /Users/ben/src/libgit2/tests/resour
*/
- test_object("HEAD@{10 years ago}", NULL);
+ test_object("HEAD@{10 years ago}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
test_object("HEAD@{1 second}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
test_object("HEAD@{1 second ago}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
@@ -417,11 +417,12 @@ void test_refs_revparse__date(void)
/*
- * $ git reflog -1 "master@{2012-04-30 17:22:42 +0000}"
- * warning: Log for 'master' only goes back to Mon, 30 Apr 2012 09:22:43 -0800.
+ * $ git rev-parse "master@{2012-04-30 17:22:42 +0000}"
+ * warning: log for 'master' only goes back to Mon, 30 Apr 2012 09:22:43 -0800
+ * be3563ae3f795b2b4353bcce3a527ad0a4f7f644
*/
- test_object("master@{2012-04-30 17:22:42 +0000}", NULL);
- test_object("master@{2012-04-30 09:22:42 -0800}", NULL);
+ test_object("master@{2012-04-30 17:22:42 +0000}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
+ test_object("master@{2012-04-30 09:22:42 -0800}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
/*
* $ git reflog -1 "master@{2012-04-30 17:22:43 +0000}"
@@ -451,6 +452,25 @@ void test_refs_revparse__date(void)
*/
test_object("master@{1335806603}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
test_object("master@{1335806602}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
+
+ /*
+ * $ git rev-parse "with-empty-log@{2 days ago}" --
+ * fatal: log for refs/heads/with-empty-log is empty
+ */
+ test_object("with-empty-log@{2 days ago}", NULL);
+}
+
+void test_refs_revparse__invalid_date(void)
+{
+ /*
+ * $ git rev-parse HEAD@{} --
+ * fatal: bad revision 'HEAD@{}'
+ *
+ * $ git rev-parse HEAD@{NEITHER_INTEGER_NOR_DATETIME} --
+ * fatal: bad revision 'HEAD@{NEITHER_INTEGER_NOR_DATETIME}'
+ */
+ test_object("HEAD@{}", NULL);
+ test_object("HEAD@{NEITHER_INTEGER_NOR_DATETIME}", NULL);
}
void test_refs_revparse__colon(void)
diff --git a/tests/resources/testrepo.git/logs/refs/heads/with-empty-log b/tests/resources/testrepo.git/logs/refs/heads/with-empty-log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/resources/testrepo.git/logs/refs/heads/with-empty-log
diff --git a/tests/resources/testrepo.git/refs/heads/with-empty-log b/tests/resources/testrepo.git/refs/heads/with-empty-log
new file mode 100644
index 000000000..dae4cb2b0
--- /dev/null
+++ b/tests/resources/testrepo.git/refs/heads/with-empty-log
@@ -0,0 +1 @@
+8496071c1b46c854b31185ea97743be6a8774479