Commit Diff


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;