* git_revparse.
*/
typedef enum {
- /** The spec targeted a single object. */
- GIT_REVPARSE_SINGLE = 1 << 0,
- /** The spec targeted a range of commits. */
- GIT_REVPARSE_RANGE = 1 << 1,
- /** The spec used the '...' operator, which invokes special semantics. */
- GIT_REVPARSE_MERGE_BASE = 1 << 2,
+ /** The spec targeted a single object. */
+ GIT_REVPARSE_SINGLE = 1 << 0,
+ /** The spec targeted a range of commits. */
+ GIT_REVPARSE_RANGE = 1 << 1,
+ /** The spec used the '...' operator, which invokes special semantics. */
+ GIT_REVPARSE_MERGE_BASE = 1 << 2,
} git_revparse_flag_t;
/**
- * Find an object or range of commits as specified by a revision string.
- * See `man gitrevisions` or http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions
- * for information on the syntax accepted.
+ * Parse a revision string for left, right, and intent. See `man gitrevisions` or
+ * http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions for information
+ * on the syntax accepted.
*
* @param left buffer that receives the target of the left side of a range operator. If
* there is no range operator, this buffer receives the single target.
* @param right buffer that receives the target of the right side of a range operator.
- * This is only filled in if `spec` specifies a range of commits
- * @param flags buffer that receives a bitwise combination of `git_revparse_flag_t` values
+ * This is only filled in if `spec` specifies a range of commits. May
+ * be NULL.
+ * @param flags buffer that receives a bitwise combination of `git_revparse_flag_t` values.
+ * May be NULL.
* @param repo the repository to search in
* @param spec the rev-parse spec to parse
* @return 0 on success, GIT_INVALIDSPEC, GIT_ENOTFOUND, GIT_EAMBIGUOUS or an error code
*/
GIT_EXTERN(int) git_revparse(
- git_oid *left,
- git_oid *right,
- unsigned int *flags,
- git_repository *repo,
- const char *spec);
+ git_oid *left,
+ git_oid *right,
+ unsigned int *flags,
+ git_repository *repo,
+ const char *spec);
/** @} */
error = regcomp(regex, pattern, REG_EXTENDED);
if (!error)
return 0;
-
+
error = giterr_set_regex(regex, error);
regfree(regex);
if (substr == NULL)
return GIT_ENOTFOUND;
-
+
if (build_regex(®ex, ".+-[0-9]+-g[0-9a-fA-F]+") < 0)
return -1;
if ((error = git_branch_tracking(&tracking, ref)) < 0)
goto cleanup;
-
+
*base_ref = tracking;
cleanup:
int error;
git_oid oid;
git_object *obj;
-
+
while (!(error = git_revwalk_next(&oid, walk))) {
error = git_object_lookup(&obj, git_revwalk_repository(walk), &oid, GIT_OBJ_COMMIT);
if ((error = build_regex(&preg, pattern)) < 0)
return error;
-
+
if ((error = git_revwalk_new(&walk, repo)) < 0)
goto cleanup;
goto cleanup;
error = walk_and_search(out, walk, &preg);
-
+
cleanup:
regfree(&preg);
git_revwalk_free(walk);
git__free(revspec);
return error;
}
+
+
+int git_revparse(
+ git_oid *left,
+ git_oid *right,
+ unsigned int *flags,
+ git_repository *repo,
+ const char *spec)
+{
+ unsigned int lflags = 0;
+ const char *dotdot;
+ int error = 0;
+ git_object *obj = NULL;
+
+ assert(left && repo && spec);
+
+ if ((dotdot = strstr(spec, "..")) != NULL) {
+ char *lstr;
+ const char *rstr;
+ lflags = GIT_REVPARSE_RANGE;
+
+ lstr = git__substrdup(spec, dotdot-spec);
+ rstr = dotdot + 2;
+ if (dotdot[2] == '.') {
+ lflags |= GIT_REVPARSE_MERGE_BASE;
+ rstr++;
+ }
+
+ if (!(error = git_revparse_single(&obj, repo, lstr))) {
+ git_oid_cpy(left, git_object_id(obj));
+ git_object_free(obj);
+ }
+ if (right && !(error = git_revparse_single(&obj, repo, rstr))) {
+ git_oid_cpy(right, git_object_id(obj));
+ git_object_free(obj);
+ }
+
+ git__free((void*)lstr);
+ } else {
+ lflags = GIT_REVPARSE_SINGLE;
+ if (!(error = git_revparse_single(&obj, repo, spec))) {
+ git_oid_cpy(left, git_object_id(obj));
+ git_object_free(obj);
+ }
+ }
+
+ if (flags)
+ *flags = lflags;
+
+ return error;
+}
+
git_object_free(obj);
}
+static void test_id_inrepo(
+ const char *spec,
+ const char *expected_left,
+ const char *expected_right,
+ git_revparse_flag_t expected_flags,
+ git_repository *repo)
+{
+ git_oid l = {{0}}, r = {{0}};
+ git_revparse_flag_t flags = 0;
+
+ int error = git_revparse(&l, &r, &flags, repo, spec);
+
+ if (expected_left) {
+ char str[64] = {0};
+ cl_assert_equal_i(0, error);
+ git_oid_fmt(str, &l);
+ cl_assert_equal_s(str, expected_left);
+ } else {
+ cl_assert_equal_i(GIT_ENOTFOUND, error);
+ }
+
+ if (expected_right) {
+ char str[64] = {0};
+ git_oid_fmt(str, &r);
+ cl_assert_equal_s(str, expected_right);
+ }
+
+ if (expected_flags)
+ cl_assert_equal_i(expected_flags, flags);
+}
+
static void test_object(const char *spec, const char *expected_oid)
{
test_object_inrepo(spec, expected_oid, g_repo);
}
+static void test_id(
+ const char *spec,
+ const char *expected_left,
+ const char *expected_right,
+ git_revparse_flag_t expected_flags)
+{
+ test_id_inrepo(spec, expected_left, expected_right, expected_flags, g_repo);
+}
+
void test_refs_revparse__initialize(void)
{
cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git")));
test_rangelike("be3563a^1.be3563a", NULL, NULL, 0);
}
+
+void test_refs_revparse__validates_args(void)
+{
+ git_oid l={{0}}, r={{0}};
+ git_revparse_flag_t flags = 0;
+
+ cl_git_pass(git_revparse(&l,&r,NULL, g_repo, "HEAD"));
+ cl_git_pass(git_revparse(&l,NULL,&flags, g_repo, "HEAD"));
+ cl_assert_equal_i(GIT_EINVALIDSPEC, git_revparse(&l,&r,&flags, g_repo, "^&*("));
+}
+
+void test_refs_revparse__parses_range_operator(void)
+{
+ test_id("HEAD", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", NULL, GIT_REVPARSE_SINGLE);
+ test_id("HEAD~3..HEAD", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", GIT_REVPARSE_RANGE);
+ test_id("HEAD~3...HEAD", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
+ GIT_REVPARSE_RANGE | GIT_REVPARSE_MERGE_BASE);
+}
+