commit dd88155e484f5bbae1af4e3c8d020cabc2e647ab from: Stefan Sperling date: Sat Jun 29 21:26:36 2019 UTC disambiguate abbreviated object IDs based on object type commit - 461aee03b5f615d3fb11add47137103d3003b61e commit + dd88155e484f5bbae1af4e3c8d020cabc2e647ab blob - 033920c8cb17382860d142a8e5be46f083a80d90 blob + 7aaa8ea66b4803a68c636cf6a8f09903c0764f7b --- TODO +++ TODO @@ -9,7 +9,6 @@ lib: (maybe let got-read-pack cache ref/offset delta objects in object_cache.c?) - improve performance of usr.bin/diff and port these changes back to got (e.g. diffing between versions of sys/dev/pci/pcidevs is too slow) -- disambiguate abbreviated object IDs based on object type tog: - implement horizonal scrolling in all views blob - 63ce30e7bcc45b4859409015ccaceab0666be898 blob + aa4785ee303d42702c7d792697698e69b6b2f4cf --- got/got.c +++ got/got.c @@ -561,7 +561,7 @@ cmd_checkout(int argc, char *argv[]) if (commit_id_str) { struct got_object_id *commit_id; error = got_repo_match_object_id_prefix(&commit_id, - commit_id_str, repo); + commit_id_str, GOT_OBJ_TYPE_COMMIT, repo); if (error != NULL) goto done; error = check_linear_ancestry(commit_id, @@ -742,7 +742,7 @@ cmd_update(int argc, char *argv[]) goto done; } else { error = got_repo_match_object_id_prefix(&commit_id, - commit_id_str, repo); + commit_id_str, GOT_OBJ_TYPE_COMMIT, repo); if (error != NULL) goto done; } @@ -1191,7 +1191,7 @@ cmd_log(int argc, char *argv[]) } if (commit == NULL) { error = got_repo_match_object_id_prefix(&id, - start_commit, repo); + start_commit, GOT_OBJ_TYPE_COMMIT, repo); if (error != NULL) return error; } @@ -1429,7 +1429,8 @@ cmd_diff(int argc, char *argv[]) goto done; } - error = got_repo_match_object_id_prefix(&id1, id_str1, repo); + error = got_repo_match_object_id_prefix(&id1, id_str1, + GOT_OBJ_TYPE_ANY, repo); if (error) { struct got_reference *ref; if (error->code != GOT_ERR_BAD_OBJ_ID_STR) @@ -1454,7 +1455,8 @@ cmd_diff(int argc, char *argv[]) } } - error = got_repo_match_object_id_prefix(&id2, id_str2, repo); + error = got_repo_match_object_id_prefix(&id2, id_str2, + GOT_OBJ_TYPE_ANY, repo); if (error) { struct got_reference *ref; if (error->code != GOT_ERR_BAD_OBJ_ID_STR) @@ -1643,7 +1645,7 @@ cmd_blame(int argc, char *argv[]) goto done; } else { error = got_repo_match_object_id_prefix(&commit_id, - commit_id_str, repo); + commit_id_str, GOT_OBJ_TYPE_COMMIT, repo); if (error != NULL) goto done; } @@ -1875,7 +1877,7 @@ cmd_tree(int argc, char *argv[]) goto done; } else { error = got_repo_match_object_id_prefix(&commit_id, - commit_id_str, repo); + commit_id_str, GOT_OBJ_TYPE_COMMIT, repo); if (error != NULL) goto done; } @@ -2034,7 +2036,8 @@ add_ref(struct got_repository *repo, const char *refna struct got_object_id *id; struct got_reference *ref = NULL; - err = got_repo_match_object_id_prefix(&id, target, repo); + err = got_repo_match_object_id_prefix(&id, target, GOT_OBJ_TYPE_ANY, + repo); if (err) { struct got_reference *target_ref; @@ -2996,7 +2999,8 @@ cmd_cherrypick(int argc, char *argv[]) if (error) goto done; - error = got_repo_match_object_id_prefix(&commit_id, argv[0], repo); + error = got_repo_match_object_id_prefix(&commit_id, argv[0], + GOT_OBJ_TYPE_COMMIT, repo); if (error != NULL) { struct got_reference *ref; if (error->code != GOT_ERR_BAD_OBJ_ID_STR) @@ -3105,7 +3109,8 @@ cmd_backout(int argc, char *argv[]) if (error) goto done; - error = got_repo_match_object_id_prefix(&commit_id, argv[0], repo); + error = got_repo_match_object_id_prefix(&commit_id, argv[0], + GOT_OBJ_TYPE_COMMIT, repo); if (error != NULL) { struct got_reference *ref; if (error->code != GOT_ERR_BAD_OBJ_ID_STR) blob - 4f5a750057ad8008dfbb50f5e971a7e9988205a6 blob + 5e46d49dc5d829ba1d253df00d650c7dae466bbe --- include/got_object.h +++ include/got_object.h @@ -45,8 +45,10 @@ SIMPLEQ_HEAD(got_object_id_queue, got_object_qid); const struct got_error *got_object_qid_alloc(struct got_object_qid **, struct got_object_id *); void got_object_qid_free(struct got_object_qid *); +void got_object_id_queue_free(struct got_object_id_queue *); /* Object types. */ +#define GOT_OBJ_TYPE_ANY 0 /* wildcard value at run-time */ #define GOT_OBJ_TYPE_COMMIT 1 #define GOT_OBJ_TYPE_TREE 2 #define GOT_OBJ_TYPE_BLOB 3 blob - 69c2e095c3af4282d19b75475fcff80fe12aeef5 blob + d4ac915a022f60064bf883eaa2bc5b4bb7355611 --- include/got_repository.h +++ include/got_repository.h @@ -60,4 +60,4 @@ const struct got_error *got_repo_init(const char *); /* Attempt to find a unique object ID for a given ID string prefix. */ const struct got_error *got_repo_match_object_id_prefix(struct got_object_id **, - const char *, struct got_repository *); + const char *, int, struct got_repository *); blob - a5191eb2b7c3a8299b81d38016569cf8582cbfd5 blob + 7e7c69769bca88c55404098a3ff10d7603f937df --- lib/got_lib_pack.h +++ lib/got_lib_pack.h @@ -161,8 +161,8 @@ const struct got_error *got_packidx_open(struct got_pa const char *, int); const struct got_error *got_packidx_close(struct got_packidx *); int got_packidx_get_object_idx(struct got_packidx *, struct got_object_id *); -const struct got_error *got_packidx_match_id_str_prefix(struct got_object_id **, - struct got_packidx *, const char *); +const struct got_error *got_packidx_match_id_str_prefix( + struct got_object_id_queue *, struct got_packidx *, const char *); const struct got_error *got_packfile_open_object(struct got_object **, struct got_pack *, struct got_packidx *, int, struct got_object_id *); blob - 9559b3499f03914992d9378fd06de60541916cdd blob + d924810f4b5a46d8e58241ff8120b186f60fea41 --- lib/object_parse.c +++ lib/object_parse.c @@ -128,6 +128,18 @@ got_object_qid_free(struct got_object_qid *qid) free(qid); } +void +got_object_id_queue_free(struct got_object_id_queue *ids) +{ + struct got_object_qid *qid; + + while (!SIMPLEQ_EMPTY(ids)) { + qid = SIMPLEQ_FIRST(ids); + SIMPLEQ_REMOVE_HEAD(ids, entry); + got_object_qid_free(qid); + } +} + const struct got_error * got_object_parse_header(struct got_object **obj, char *buf, size_t len) { @@ -343,20 +355,13 @@ parse_commit_time(time_t *time, time_t *gmtoff, char * void got_object_commit_close(struct got_commit_object *commit) { - struct got_object_qid *qid; - if (commit->refcnt > 0) { commit->refcnt--; if (commit->refcnt > 0) return; - } - - while (!SIMPLEQ_EMPTY(&commit->parent_ids)) { - qid = SIMPLEQ_FIRST(&commit->parent_ids); - SIMPLEQ_REMOVE_HEAD(&commit->parent_ids, entry); - got_object_qid_free(qid); } + got_object_id_queue_free(&commit->parent_ids); free(commit->tree_id); free(commit->author); free(commit->committer); blob - b2200e9c73c6c68c0b87f34944ee0ab24bf48ed6 blob + f002e06327aacda24b3be226db6d6e62b6370188 --- lib/pack.c +++ lib/pack.c @@ -41,6 +41,7 @@ #include "got_lib_delta.h" #include "got_lib_inflate.h" #include "got_lib_object.h" +#include "got_lib_object_parse.h" #include "got_lib_privsep.h" #include "got_lib_pack.h" @@ -444,9 +445,10 @@ got_packidx_get_object_idx(struct got_packidx *packidx } const struct got_error * -got_packidx_match_id_str_prefix(struct got_object_id **unique_id, +got_packidx_match_id_str_prefix(struct got_object_id_queue *matched_ids, struct got_packidx *packidx, const char *id_str_prefix) { + const struct got_error *err = NULL; u_int8_t id0; uint32_t totobj = betoh32(packidx->hdr.fanout_table[0xff]); char hex[3]; @@ -454,7 +456,7 @@ got_packidx_match_id_str_prefix(struct got_object_id * struct got_packidx_object_id *oid; int i; - *unique_id = NULL; + SIMPLEQ_INIT(matched_ids); if (prefix_len < 2) return got_error(GOT_ERR_BAD_OBJ_ID_STR); @@ -472,6 +474,7 @@ got_packidx_match_id_str_prefix(struct got_object_id * oid = &packidx->hdr.sorted_ids[i]; while (i < totobj && oid->sha1[0] == id0) { char id_str[SHA1_DIGEST_STRING_LENGTH]; + struct got_object_qid *qid; int cmp; if (!got_sha1_digest_to_str(oid->sha1, id_str, sizeof(id_str))) @@ -484,17 +487,24 @@ got_packidx_match_id_str_prefix(struct got_object_id * } else if (cmp > 0) break; - if (*unique_id != NULL) - return got_error(GOT_ERR_AMBIGUOUS_ID); - *unique_id = malloc(sizeof(**unique_id)); - if (*unique_id == NULL) - return got_error_from_errno("malloc"); - memcpy((*unique_id)->sha1, oid->sha1, SHA1_DIGEST_LENGTH); + err = got_object_qid_alloc_partial(&qid); + if (err) + break; + memcpy(qid->id->sha1, oid->sha1, SHA1_DIGEST_LENGTH); + SIMPLEQ_INSERT_TAIL(matched_ids, qid, entry); oid = &packidx->hdr.sorted_ids[++i]; } - return NULL; + if (err) { + while (!SIMPLEQ_EMPTY(matched_ids)) { + struct got_object_qid *qid; + qid = SIMPLEQ_FIRST(matched_ids); + SIMPLEQ_REMOVE_HEAD(matched_ids, entry); + got_object_qid_free(qid); + } + } + return err; } const struct got_error * blob - 4bb4b6a375cb9ca3b1be8695a35b8dc74bda43c3 blob + 14de2007e20f81fb82bc8c0254ca9eeefe83563b --- lib/repository.c +++ lib/repository.c @@ -880,14 +880,17 @@ got_repo_init(const char *repo_path) static const struct got_error * match_packed_object(struct got_object_id **unique_id, - struct got_repository *repo, const char *id_str_prefix) + struct got_repository *repo, const char *id_str_prefix, int obj_type) { const struct got_error *err = NULL; char *path_packdir; DIR *packdir; struct dirent *dent; char *path_packidx; + struct got_object_id_queue matched_ids; + SIMPLEQ_INIT(&matched_ids); + path_packdir = got_repo_get_path_objects_pack(repo); if (path_packdir == NULL) return got_error_from_errno("got_repo_get_path_objects_pack"); @@ -900,7 +903,8 @@ match_packed_object(struct got_object_id **unique_id, while ((dent = readdir(packdir)) != NULL) { struct got_packidx *packidx; - struct got_object_id *unique_id_in_pack; + struct got_object_qid *qid; + if (!is_packidx_filename(dent->d_name, dent->d_namlen)) continue; @@ -916,29 +920,40 @@ match_packed_object(struct got_object_id **unique_id, if (err) break; - err = got_packidx_match_id_str_prefix(&unique_id_in_pack, + err = got_packidx_match_id_str_prefix(&matched_ids, packidx, id_str_prefix); if (err) { got_packidx_close(packidx); break; } err = got_packidx_close(packidx); - if (err) { - free(unique_id_in_pack); + if (err) break; - } - if (unique_id_in_pack) { + SIMPLEQ_FOREACH(qid, &matched_ids, entry) { + if (obj_type != GOT_OBJ_TYPE_ANY) { + int matched_type; + err = got_object_get_type(&matched_type, repo, + qid->id); + if (err) + goto done; + if (matched_type != obj_type) + continue; + } if (*unique_id == NULL) { - *unique_id = unique_id_in_pack; + *unique_id = got_object_id_dup(qid->id); + if (*unique_id == NULL) { + err = got_error_from_errno("malloc"); + goto done; + } } else { - free(unique_id_in_pack); err = got_error(GOT_ERR_AMBIGUOUS_ID); break; } } } done: + got_object_id_queue_free(&matched_ids); free(path_packdir); if (packdir && closedir(packdir) != 0 && err == NULL) err = got_error_from_errno("closedir"); @@ -951,7 +966,7 @@ done: static const struct got_error * match_loose_object(struct got_object_id **unique_id, const char *path_objects, - const char *object_dir, const char *id_str_prefix, + const char *object_dir, const char *id_str_prefix, int obj_type, struct got_repository *repo) { const struct got_error *err = NULL; @@ -1000,6 +1015,15 @@ match_loose_object(struct got_object_id **unique_id, c } if (*unique_id == NULL) { + if (obj_type != GOT_OBJ_TYPE_ANY) { + int matched_type; + err = got_object_get_type(&matched_type, repo, + &id); + if (err) + goto done; + if (matched_type != obj_type) + continue; + } *unique_id = got_object_id_dup(&id); if (*unique_id == NULL) { err = got_error_from_errno("got_object_id_dup"); @@ -1025,7 +1049,7 @@ done: const struct got_error * got_repo_match_object_id_prefix(struct got_object_id **id, - const char *id_str_prefix, struct got_repository *repo) + const char *id_str_prefix, int obj_type, struct got_repository *repo) { const struct got_error *err = NULL; char *path_objects = got_repo_get_path_objects(repo); @@ -1043,7 +1067,7 @@ got_repo_match_object_id_prefix(struct got_object_id * len = strlen(id_str_prefix); if (len >= 2) { - err = match_packed_object(id, repo, id_str_prefix); + err = match_packed_object(id, repo, id_str_prefix, obj_type); if (err) goto done; object_dir = strndup(id_str_prefix, 2); @@ -1052,7 +1076,7 @@ got_repo_match_object_id_prefix(struct got_object_id * goto done; } err = match_loose_object(id, path_objects, object_dir, - id_str_prefix, repo); + id_str_prefix, obj_type, repo); } else if (len == 1) { int i; for (i = 0; i < 0xf; i++) { @@ -1061,11 +1085,12 @@ got_repo_match_object_id_prefix(struct got_object_id * err = got_error_from_errno("asprintf"); goto done; } - err = match_packed_object(id, repo, object_dir); + err = match_packed_object(id, repo, object_dir, + obj_type); if (err) goto done; err = match_loose_object(id, path_objects, object_dir, - id_str_prefix, repo); + id_str_prefix, obj_type, repo); if (err) goto done; } blob - 79ae802838b0dee98d1c9dcf060003faa4c58629 blob + 9093d146d73b7a7a674302c46508a638d9c6a5af --- tog/tog.c +++ tog/tog.c @@ -2222,7 +2222,7 @@ cmd_log(int argc, char *argv[]) repo); else error = got_repo_match_object_id_prefix(&start_id, - start_commit, repo); + start_commit, GOT_OBJ_TYPE_COMMIT, repo); if (error != NULL) goto done; @@ -2830,11 +2830,13 @@ cmd_diff(int argc, char *argv[]) if (error) goto done; - error = got_repo_match_object_id_prefix(&id1, id_str1, repo); + error = got_repo_match_object_id_prefix(&id1, id_str1, + GOT_OBJ_TYPE_ANY, repo); if (error) goto done; - error = got_repo_match_object_id_prefix(&id2, id_str2, repo); + error = got_repo_match_object_id_prefix(&id2, id_str2, + GOT_OBJ_TYPE_ANY, repo); if (error) goto done; @@ -3685,7 +3687,7 @@ cmd_blame(int argc, char *argv[]) got_ref_close(head_ref); } else { error = got_repo_match_object_id_prefix(&commit_id, - commit_id_str, repo); + commit_id_str, GOT_OBJ_TYPE_COMMIT, repo); } if (error != NULL) goto done; @@ -4412,7 +4414,7 @@ cmd_tree(int argc, char *argv[]) error = get_head_commit_id(&commit_id, GOT_REF_HEAD, repo); else error = got_repo_match_object_id_prefix(&commit_id, - commit_id_arg, repo); + commit_id_arg, GOT_OBJ_TYPE_COMMIT, repo); if (error != NULL) goto done;