commit - bbfe163a911251028ccdcd91b7af7d9fb71919eb
commit + 11995603330208ca0b2abf919ffc862d461bfc60
blob - 3be1c839cfa699e335c8b75c57ba02b9b159a78a
blob + eeca74e22721ef756289ffa1d8fa2578b8bb99c4
--- include/got_object.h
+++ include/got_object.h
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-struct got_object {
+struct got_object_id {
u_int8_t sha1[SHA1_DIGEST_LENGTH];
};
blob - 874712f177a4a427bd773e1ed642c3c96a8c85cf
blob + 4c5b34a12566dc8a3a51e81f070f896ba32184e5
--- include/got_refs.h
+++ include/got_refs.h
#define GOT_REF_MERGE_HEAD "MERGE_HEAD"
#define GOT_REF_FETCH_HEAD "FETCH_HEAD"
-const struct got_error *
-got_ref_open(struct got_reference **, const char *, const char *);
+struct got_repository;
+struct got_object_id;
+const struct got_error * got_ref_open(struct got_reference **,
+ struct got_repository *, const char *);
void got_ref_close(struct got_reference *);
-
+struct got_reference *got_ref_dup(struct got_reference *);
+const struct got_error *got_ref_resolve(struct got_object_id **,
+ struct got_repository *, struct got_reference *);
blob - 89c33530b2b3ba77bc2946816c911d6b4cd636e0
blob + 7d9c9c23fc76ace9f171b147f75245d418254d7c
--- include/got_repository.h
+++ include/got_repository.h
/* Get the absolute path to the top-level directory of a repository. */
const char *got_repo_get_path(struct got_repository *);
+char *got_repo_get_path_git_dir(struct got_repository *);
+char *got_repo_get_path_objects(struct got_repository *);
+char *got_repo_get_path_refs(struct got_repository *);
+
+struct got_reference;
+
/* Get a reference, by name, from a repository. */
const struct got_error *got_repo_get_reference(struct got_reference **,
struct got_repository *, const char *);
blob - c520fc26b393adf1b5feed2c3bce6189be8297a3
blob + a51fefdc0e2f99ba8911531fa5ba38c3d664a020
--- lib/refs.c
+++ lib/refs.c
#include <stdlib.h>
#include <string.h>
#include <util.h>
+#include <limits.h>
+#include <errno.h>
#include "got_error.h"
+#include "got_object.h"
+#include "got_repository.h"
#include "got_refs.h"
#include "path.h"
+
static const struct got_error *
parse_symref(struct got_reference **ref, const char *name, const char *line)
{
}
static int
+parse_xdigit(uint8_t *val, const char *hex)
+{
+ char *ep;
+ long lval;
+
+ errno = 0;
+ lval = strtol(hex, &ep, 16);
+ if (hex[0] == '\0' || *ep != '\0')
+ return 0;
+ if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
+ return 0;
+
+ *val = (uint8_t)lval;
+ return 1;
+}
+
+static int
parse_sha1_digest(uint8_t *digest, const char *line)
{
- uint8_t b;
- int i, n;
+ uint8_t b = 0;
+ char hex[3] = {'\0', '\0', '\0'};
+ int i, j;
- memset(digest, 0, SHA1_DIGEST_LENGTH);
for (i = 0; i < SHA1_DIGEST_LENGTH; i++) {
- n = sscanf(line, "%hhx", &b);
- if (n == 1)
- digest[i] = b;
- else
+ if (line[0] == '\0' || line[1] == '\0')
return 0;
+ for (j = 0; j < 2; j++) {
+ hex[j] = *line;
+ line++;
+ }
+ if (!parse_xdigit(&b, hex))
+ return 0;
+ digest[i] = b;
}
return 1;
return err;
}
+static char *
+get_refs_dir_path(struct got_repository *repo, const char *refname)
+{
+ /* Some refs live in the .git directory. */
+ if (strcmp(refname, GOT_REF_HEAD) == 0 ||
+ strcmp(refname, GOT_REF_ORIG_HEAD) == 0 ||
+ strcmp(refname, GOT_REF_MERGE_HEAD) == 0 ||
+ strcmp(refname, GOT_REF_FETCH_HEAD) == 0)
+ return got_repo_get_path_git_dir(repo);
+
+ /* Is the ref name relative to the .git directory? */
+ if (strncmp(refname, "refs/", 5) == 0)
+ return got_repo_get_path_git_dir(repo);
+
+ return got_repo_get_path_refs(repo);
+}
+
const struct got_error *
-got_ref_open(struct got_reference **ref, const char *path_refs,
+got_ref_open(struct got_reference **ref, struct got_repository *repo,
const char *refname)
{
const struct got_error *err = NULL;
char *path_ref = NULL;
char *normpath = NULL;
const char *parent_dir;
+ char *path_refs = get_refs_dir_path(repo, refname);
+
+ if (path_refs == NULL) {
+ err = got_error(GOT_ERR_NO_MEM);
+ goto done;
+ }
/* XXX For now, this assumes that refs exist in the filesystem. */
goto done;
}
- err = parse_ref_file(ref, refname, normpath ? normpath : path_refs);
+ err = parse_ref_file(ref, refname, normpath);
done:
free(normpath);
free(path_ref);
+ free(path_refs);
return err;
}
free(ref->ref.ref.name);
free(ref);
}
+
+struct got_reference *
+got_ref_dup(struct got_reference *ref)
+{
+ struct got_reference *ret = calloc(1, sizeof(*ret));
+ char *name = NULL;
+ char *symref = NULL;
+
+ if (ret == NULL)
+ return NULL;
+
+ ret->flags = ref->flags;
+ if (ref->flags & GOT_REF_IS_SYMBOLIC) {
+ ret->ref.symref.name = strdup(ref->ref.symref.name);
+ if (ret->ref.symref.name == NULL) {
+ free(ret);
+ return NULL;
+ }
+ ret->ref.symref.ref = strdup(ref->ref.symref.ref);
+ if (ret->ref.symref.ref == NULL) {
+ free(ret->ref.symref.name);
+ free(ret);
+ return NULL;
+ }
+ } else {
+ ref->ref.ref.name = strdup(ref->ref.ref.name);
+ if (ref->ref.ref.name == NULL) {
+ free(ret);
+ return NULL;
+ }
+ memcpy(ret->ref.ref.sha1, ref->ref.ref.sha1,
+ SHA1_DIGEST_LENGTH);
+ }
+
+ return ret;
+}
+
+static const struct got_error *
+resolve_symbolic_ref(struct got_reference **resolved,
+ struct got_repository *repo, struct got_reference *ref)
+{
+ struct got_reference *nextref;
+ const struct got_error *err;
+
+ err = got_ref_open(&nextref, repo, ref->ref.symref.ref);
+ if (err)
+ return err;
+
+ if (nextref->flags & GOT_REF_IS_SYMBOLIC)
+ err = resolve_symbolic_ref(resolved, repo, nextref);
+ else
+ *resolved = got_ref_dup(nextref);
+
+ got_ref_close(nextref);
+ return err;
+}
+
+const struct got_error *
+got_ref_resolve(struct got_object_id **id, struct got_repository *repo,
+ struct got_reference *ref)
+{
+ const struct got_error *err;
+
+ if (ref->flags & GOT_REF_IS_SYMBOLIC) {
+ struct got_reference *resolved = NULL;
+ err = resolve_symbolic_ref(&resolved, repo, ref);
+ if (err == NULL)
+ err = got_ref_resolve(id, repo, resolved);
+ free(resolved);
+ return err;
+ }
+
+ *id = calloc(1, sizeof(**id));
+ if (*id == NULL)
+ return got_error(GOT_ERR_NO_MEM);
+ memcpy((*id)->sha1, ref->ref.ref.sha1, SHA1_DIGEST_LENGTH);
+ return NULL;
+}
blob - 6d7b5ecf1b90ffd234386b4628cee19748d53983
blob + 9e794a4d7f4135d316e402f7d6740e6612b55756
--- lib/repository.c
+++ lib/repository.c
#define GOT_FETCH_HEAD_FILE "FETCH_HEAD"
#define GOT_ORIG_HEAD_FILE "ORIG_HEAD"
-static char *
-get_path_git_dir(struct got_repository *repo)
+char *
+got_repo_get_path_git_dir(struct got_repository *repo)
{
char *path_git;
return path_child;
}
-static char *
-get_path_objects(struct got_repository *repo)
+char *
+got_repo_get_path_objects(struct got_repository *repo)
{
return get_path_git_child(repo, GOT_OBJECTS_DIR);
}
-static char *
-get_path_refs(struct got_repository *repo)
+char *
+got_repo_get_path_refs(struct got_repository *repo)
{
return get_path_git_child(repo, GOT_REFS_DIR);
}
static int
is_git_repo(struct got_repository *repo)
{
- char *path_git = get_path_git_dir(repo);
- char *path_objects = get_path_objects(repo);
- char *path_refs = get_path_refs(repo);
+ char *path_git = got_repo_get_path_git_dir(repo);
+ char *path_objects = got_repo_get_path_objects(repo);
+ char *path_refs = got_repo_get_path_refs(repo);
char *path_head = get_path_head(repo);
int ret;
{
return repo->path;
}
-
-const struct got_error *
-got_repo_get_reference(struct got_reference **ref,
- struct got_repository *repo, const char *refname)
-{
- const struct got_error *err = NULL;
- char *path_refs;
-
- /* Some refs live in the .git directory. */
- if (strcmp(refname, GOT_REF_HEAD) == 0 ||
- strcmp(refname, GOT_REF_ORIG_HEAD) == 0 ||
- strcmp(refname, GOT_REF_MERGE_HEAD) == 0 ||
- strcmp(refname, GOT_REF_FETCH_HEAD) == 0)
- path_refs = get_path_git_dir(repo);
- else
- path_refs = get_path_refs(repo);
-
- err = got_ref_open(ref, path_refs, refname);
- free(path_refs);
- return err;
-}
blob - f70ab8cdc937290abf9b2d0afd92733f30acc517
blob + 1973fa4e78449a49c05220759400edfa491d4c4b
--- regress/repository/repository_test.c
+++ regress/repository/repository_test.c
#include <sha1.h>
#include "got_error.h"
+#include "got_object.h"
#include "got_refs.h"
#include "got_repository.h"
err = got_repo_open(&repo, repo_path);
if (err != NULL || repo == NULL)
return 0;
- err = got_repo_get_reference(&head_ref, repo, GOT_REF_HEAD);
+ err = got_ref_open(&head_ref, repo, GOT_REF_HEAD);
if (err != NULL || head_ref == NULL)
return 0;
got_ref_close(head_ref);
return 1;
}
+static int
+repo_resolve_head_ref(const char *repo_path)
+{
+ const struct got_error *err;
+ struct got_repository *repo;
+ struct got_reference *head_ref;
+ struct got_object_id *id;
+ int ret;
+
+ err = got_repo_open(&repo, repo_path);
+ if (err != NULL || repo == NULL)
+ return 0;
+ err = got_ref_open(&head_ref, repo, GOT_REF_HEAD);
+ if (err != NULL || head_ref == NULL)
+ return 0;
+ err = got_ref_resolve(&id, repo, head_ref);
+ if (err != NULL || head_ref == NULL)
+ return 0;
+ free(id);
+ got_ref_close(head_ref);
+ got_repo_close(repo);
+ return 1;
+}
+
int
main(int argc, const char *argv[])
{
RUN_TEST(repo_open_test(repo_path), "repo_open");
RUN_TEST(repo_get_head_ref(repo_path), "get_head_ref");
+ RUN_TEST(repo_resolve_head_ref(repo_path), "resolve_head_ref");
return failure ? 1 : 0;
}