commit 8bf5b3c9ffbda6ccd1cbcc790feead341d31c357 from: Stefan Sperling date: Sat Mar 17 16:42:48 2018 UTC rewrite 'got log' without recursion commit - 4589e373fff0c98840470d28d0271c905eb65d32 commit + 8bf5b3c9ffbda6ccd1cbcc790feead341d31c357 blob - 3ae4fc609a39598209ccaf1ba6d24074b0d5661a blob + 176c6094f97ba96eef191fd7cce0f0fb50a415f8 --- got/got.c +++ got/got.c @@ -230,55 +230,105 @@ done: } static const struct got_error * -print_commit_object(struct got_object *, struct got_object_id *, - struct got_repository *); - -static const struct got_error * -print_parent_commits(struct got_commit_object *commit, +print_commit(struct got_commit_object *commit, struct got_object_id *id, struct got_repository *repo) { - struct got_parent_id *pid; const struct got_error *err = NULL; - struct got_object *obj; + char *buf; - SIMPLEQ_FOREACH(pid, &commit->parent_ids, entry) { - err = got_object_open(&obj, repo, pid->id); - if (err != NULL) - return err; - if (got_object_get_type(obj) != GOT_OBJ_TYPE_COMMIT) - return got_error(GOT_ERR_OBJ_TYPE); - err = print_commit_object(obj, pid->id, repo); - got_object_close(obj); - } + err = got_object_id_str(&buf, id); + if (err) + return err; - return err; + printf("-----------------------------------------------\n"); + printf("commit: %s\n", buf); + printf("Author: %s\n", commit->author); + printf("\n%s\n", commit->logmsg); + + free(buf); + return NULL; } + +struct commit_queue_entry { + TAILQ_ENTRY(commit_queue_entry) entry; + struct got_object_id *id; + struct got_commit_object *commit; +}; static const struct got_error * -print_commit_object(struct got_object *obj, struct got_object_id *id, +print_commits(struct got_object *root_obj, struct got_object_id *root_id, struct got_repository *repo) { - struct got_commit_object *commit; - char *buf; const struct got_error *err; + struct got_commit_object *root_commit; + TAILQ_HEAD(, commit_queue_entry) commits; + struct commit_queue_entry *entry; - err = got_object_commit_open(&commit, repo, obj); - if (err) - return err; + TAILQ_INIT(&commits); - err = got_object_id_str(&buf, id); + err = got_object_commit_open(&root_commit, repo, root_obj); if (err) return err; - printf("-----------------------------------------------\n"); - printf("commit: %s\n", buf); - printf("Author: %s\n", commit->author); - printf("\n%s\n", commit->logmsg); + entry = calloc(1, sizeof(*entry)); + if (entry == NULL) + return got_error(GOT_ERR_NO_MEM); + entry->id = got_object_id_dup(root_id); + if (entry->id == NULL) { + free(entry); + return got_error(GOT_ERR_NO_MEM); + } + entry->commit = root_commit; + TAILQ_INSERT_HEAD(&commits, entry, entry); + + while (!TAILQ_EMPTY(&commits)) { + struct got_parent_id *pid; - free(buf); + entry = TAILQ_FIRST(&commits); + err = print_commit(entry->commit, entry->id, repo); + if (err) + break; - err = print_parent_commits(commit, repo); - got_object_commit_close(commit); + SIMPLEQ_FOREACH(pid, &entry->commit->parent_ids, entry) { + struct got_object *obj; + struct got_commit_object *pcommit; + struct commit_queue_entry *pentry; + + err = got_object_open(&obj, repo, pid->id); + if (err) + break; + if (got_object_get_type(obj) != GOT_OBJ_TYPE_COMMIT) { + err = got_error(GOT_ERR_OBJ_TYPE); + break; + } + + err = got_object_commit_open(&pcommit, repo, obj); + got_object_close(obj); + if (err) + break; + + pentry = calloc(1, sizeof(*pentry)); + if (pentry == NULL) { + err = got_error(GOT_ERR_NO_MEM); + got_object_commit_close(pcommit); + break; + } + pentry->id = got_object_id_dup(pid->id); + if (pentry->id == NULL) { + err = got_error(GOT_ERR_NO_MEM); + got_object_commit_close(pcommit); + break; + } + pentry->commit = pcommit; + TAILQ_INSERT_TAIL(&commits, pentry, entry); + } + + TAILQ_REMOVE(&commits, entry, entry); + got_object_commit_close(entry->commit); + free(entry->id); + free(entry); + } + return err; } @@ -325,17 +375,15 @@ cmd_log(int argc, char *argv[]) error = got_object_open(&obj, repo, id); if (error != NULL) return error; - if (got_object_get_type(obj) == GOT_OBJ_TYPE_COMMIT) { - error = print_commit_object(obj, id, repo); - if (error) - return error; - } else - return got_error(GOT_ERR_OBJ_TYPE); + if (got_object_get_type(obj) == GOT_OBJ_TYPE_COMMIT) + error = print_commits(obj, id, repo); + else + error = got_error(GOT_ERR_OBJ_TYPE); got_object_close(obj); free(id); got_ref_close(head_ref); got_repo_close(repo); - return NULL; + return error; } #ifdef notyet blob - 3b482fc85dbef3b4a9d488ad30c56ea85f7d6e2b blob + 93541c410d6bcbd0f98b87d10418b2f3138911f4 --- include/got_object.h +++ include/got_object.h @@ -57,6 +57,7 @@ struct got_repository; const struct got_error *got_object_id_str(char **, struct got_object_id *); int got_object_id_cmp(struct got_object_id *, struct got_object_id *); +struct got_object_id *got_object_id_dup(struct got_object_id *); int got_object_get_type(struct got_object *); const struct got_error *got_object_open(struct got_object **, struct got_repository *, struct got_object_id *); blob - b1f7520044fe4677b1abf79fb72406632d489757 blob + f5cf92ac0828894e6d7a620a84503b2b07231860 --- lib/object.c +++ lib/object.c @@ -75,6 +75,18 @@ int got_object_id_cmp(struct got_object_id *id1, struct got_object_id *id2) { return memcmp(id1->sha1, id2->sha1, SHA1_DIGEST_LENGTH); +} + +struct got_object_id * +got_object_id_dup(struct got_object_id *id1) +{ + struct got_object_id *id2; + + id2 = malloc(sizeof(*id2)); + if (id2 == NULL) + return NULL; + memcpy(id2, id1, sizeof(*id2)); + return id2; } int