commit 199a402734c6e8d1b44fd3f607459b9fb94e0cb0 from: Stefan Sperling date: Sat Feb 02 14:00:28 2019 UTC make 'got log' show packed refs and HEAD ref (pther refs not shown yet) commit - e0e55b50ec1b9458bbd145dc18635a8a8265d4db commit + 199a402734c6e8d1b44fd3f607459b9fb94e0cb0 blob - f51496b4e866a28f5c434c1c9224ea9a7986724f blob + 587273c102a98dd8c5922774fd868a687ac32886 --- got/got.c +++ got/got.c @@ -610,20 +610,41 @@ get_datestr(time_t *time, char *datebuf) static const struct got_error * print_commit(struct got_commit_object *commit, struct got_object_id *id, - struct got_repository *repo, int show_patch, int diff_context) + struct got_repository *repo, int show_patch, int diff_context, + struct got_reflist_head *refs) { const struct got_error *err = NULL; char *id_str, *datestr, *logmsg0, *logmsg, *line; char datebuf[26]; time_t committer_time; const char *author, *committer; + char *refs_str = NULL; + struct got_reflist_entry *re; + SIMPLEQ_FOREACH(re, refs, entry) { + char *s; + const char *name; + if (got_object_id_cmp(re->id, id) != 0) + continue; + name = got_ref_get_name(re->ref); + if (strncmp(name, "refs/", 5) == 0) + name += 5; + s = refs_str; + if (asprintf(&refs_str, "%s%s%s", s ? s : "", s ? ", " : "", + name) == -1) { + err = got_error_from_errno(); + free(s); + break; + } + free(s); + } err = got_object_id_str(&id_str, id); if (err) return err; printf("-----------------------------------------------\n"); - printf("commit %s\n", id_str); + printf("commit %s%s%s%s\n", id_str, refs_str ? " (" : "", + refs_str ? refs_str : "", refs_str ? ")" : ""); free(id_str); printf("from: %s\n", got_object_commit_get_author(commit)); committer_time = got_object_commit_get_committer_time(commit); @@ -672,7 +693,7 @@ print_commit(struct got_commit_object *commit, struct static const struct got_error * print_commits(struct got_object_id *root_id, struct got_repository *repo, char *path, int show_patch, int diff_context, int limit, - int first_parent_traversal) + int first_parent_traversal, struct got_reflist_head *refs) { const struct got_error *err; struct got_commit_graph *graph; @@ -711,7 +732,8 @@ print_commits(struct got_object_id *root_id, struct go err = got_object_open_as_commit(&commit, repo, id); if (err) break; - err = print_commit(commit, id, repo, show_patch, diff_context); + err = print_commit(commit, id, repo, show_patch, diff_context, + refs); got_object_commit_close(commit); if (err || (limit && --limit == 0)) break; @@ -741,6 +763,7 @@ cmd_log(int argc, char *argv[]) int diff_context = 3, ch; int show_patch = 0, limit = 0, first_parent_traversal = 0; const char *errstr; + struct got_reflist_head refs; #ifndef PROFILE if (pledge("stdio rpath wpath cpath flock proc exec sendfd unveil", @@ -881,9 +904,14 @@ cmd_log(int argc, char *argv[]) free(path); path = in_repo_path; } + + SIMPLEQ_INIT(&refs); + error = got_ref_list(&refs, repo); + if (error) + goto done; error = print_commits(id, repo, path, show_patch, - diff_context, limit, first_parent_traversal); + diff_context, limit, first_parent_traversal, &refs); done: free(path); free(repo_path); blob - 3845b3eb503de4c17e6c6393d03d9ed1d8294dcd blob + 18c0c225b798cff70d3e761c60fdd025660ad701 --- include/got_reference.h +++ include/got_reference.h @@ -54,3 +54,15 @@ const struct got_error *got_ref_resolve(struct got_obj * The caller must dispose of it with free(3). */ char *got_ref_to_str(struct got_reference *); + +/* A list of references and the object ID which they resolve to. */ +struct got_reflist_entry { + SIMPLEQ_ENTRY(got_reflist_entry) entry; + struct got_reference *ref; + struct got_object_id *id; +}; +SIMPLEQ_HEAD(got_reflist_head, got_reflist_entry); + +/* Append all known references to a caller-provided ref list head. */ +const struct got_error *got_ref_list(struct got_reflist_head *, + struct got_repository *); blob - b10ac6f0ab6d2274599af6367b05460f121abe76 blob + 8cf17a7dc99101cfd244574281974a3b86e0d666 --- lib/reference.c +++ lib/reference.c @@ -182,12 +182,15 @@ parse_packed_ref_line(struct got_reference **ref, cons if (!got_parse_sha1_digest(digest, line)) return got_error(GOT_ERR_NOT_REF); - if (strcmp(line + SHA1_DIGEST_STRING_LENGTH, abs_refname) != 0) - return NULL; + if (abs_refname) { + if (strcmp(line + SHA1_DIGEST_STRING_LENGTH, abs_refname) != 0) + return NULL; - name = strdup(abs_refname); - if (name == NULL) - return got_error_from_errno(); + name = strdup(abs_refname); + if (name == NULL) + return got_error_from_errno(); + } else + name = strdup(line + SHA1_DIGEST_STRING_LENGTH); *ref = calloc(1, sizeof(**ref)); if (*ref == NULL) @@ -424,4 +427,72 @@ got_ref_get_name(struct got_reference *ref) return ref->ref.symref.name; return ref->ref.ref.name; +} + +static const struct got_error * +append_ref(struct got_reflist_head *refs, struct got_reference *ref, + struct got_repository *repo) +{ + const struct got_error *err; + struct got_object_id *id; + struct got_reflist_entry *entry; + + err = got_ref_resolve(&id, repo, ref); + if (err) + return err; + entry = malloc(sizeof(*entry)); + if (entry == NULL) + return got_error_from_errno(); + entry->ref = ref; + entry->id = id; + SIMPLEQ_INSERT_TAIL(refs, entry, entry); + return NULL; } + +const struct got_error * +got_ref_list(struct got_reflist_head *refs, struct got_repository *repo) +{ + const struct got_error *err; + char *packed_refs_path, *path_refs; + FILE *f; + struct got_reference *ref; + + packed_refs_path = got_repo_get_path_packed_refs(repo); + if (packed_refs_path == NULL) + return got_error_from_errno(); + + f = fopen(packed_refs_path, "r"); + free(packed_refs_path); + if (f) { + char *line; + size_t len; + const char delim[3] = {'\0', '\0', '\0'}; + while (1) { + line = fparseln(f, &len, NULL, delim, 0); + if (line == NULL) + break; + err = parse_packed_ref_line(&ref, NULL, line); + if (err) + goto done; + if (ref) + append_ref(refs, ref, repo); + } + } + + /* HEAD ref should always exist. */ + path_refs = get_refs_dir_path(repo, GOT_REF_HEAD); + if (path_refs == NULL) { + err = got_error_from_errno(); + goto done; + } + err = open_ref(&ref, path_refs, "", GOT_REF_HEAD); + free(path_refs); + if (err) + goto done; + append_ref(refs, ref, repo); + +done: + if (f) + fclose(f); + return err; +}