Commit 62484f52d1d4dbbfd83a11f54a3a742c75de5032

Edward Thomson 2016-03-08T14:09:55

git_odb_expand_ids: accept git_odb_expand_id array Take (and write to) an array of a struct, `git_odb_expand_id`.

diff --git a/include/git2/odb.h b/include/git2/odb.h
index 010b9c1..b3ed270 100644
--- a/include/git2/odb.h
+++ b/include/git2/odb.h
@@ -174,6 +174,27 @@ GIT_EXTERN(int) git_odb_exists_prefix(
 	git_oid *out, git_odb *db, const git_oid *short_id, size_t len);
 
 /**
+ * The information about object IDs to query in `git_odb_expand_ids`,
+ * which will be populated upon return.
+ */
+typedef struct git_odb_expand_id {
+	/** The object ID to expand */
+	git_oid id;
+
+	/**
+	 * The length of the object ID (in nibbles, or packets of 4 bits; the
+	 * number of hex characters)
+	 * */
+	unsigned short length;
+
+	/**
+	 * The (optional) type of the object to search for; leave as `0` or set
+	 * to `GIT_OBJ_ANY` to query for any object matching the ID.
+	 */
+	git_otype type;
+} git_odb_expand_id;
+
+/**
  * Determine if one or more objects can be found in the object database
  * by their abbreviated object ID and type.  The given array will be
  * updated in place:  for each abbreviated ID that is unique in the
@@ -187,20 +208,14 @@ GIT_EXTERN(int) git_odb_exists_prefix(
  * not found (which is unlike other object database operations.)
  *
  * @param db The database to be searched for the given objects.
- * @param ids An array of object IDs to search for
- * @param id_lengths The corresponding length of each entry in the `ids`
- *                   array
- * @param types The corresponding type of each entry in the `ids` array
- *              (or null to lookup an object of any type)
- * @param cnt The length of the `ids`, `id_lengths` and `types` arrays
+ * @param ids An array of short object IDs to search for
+ * @param count The length of the `ids` array
  * @return 0 on success or an error code on failure
  */
 GIT_EXTERN(int) git_odb_expand_ids(
 	git_odb *db,
-	git_oid *ids,
-	size_t *id_lengths,
-	git_otype *types,
-	size_t cnt);
+	git_odb_expand_id *ids,
+	size_t count);
 
 /**
  * Refresh the object database to load newly added files.
diff --git a/src/odb.c b/src/odb.c
index de05a6b..90336c0 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -744,64 +744,51 @@ int git_odb_exists_prefix(
 
 int git_odb_expand_ids(
 	git_odb *db,
-	git_oid *ids,
-	size_t *id_lengths,
-	git_otype *types,
-	size_t cnt)
+	git_odb_expand_id *ids,
+	size_t count)
 {
 	size_t len, i;
 	int error;
 
-	assert(db && ids && id_lengths);
+	assert(db && ids);
 
-	for (i = 0; i < cnt; i++) {
+	for (i = 0; i < count; i++) {
+		git_odb_expand_id *query = &ids[i];
 		git_oid *actual_id = NULL, tmp;
+		git_otype query_type = (query->type == GIT_OBJ_ANY) ? 0 : query->type;
 		git_otype actual_type = 0;
 
 		/* if we were given a full object ID, simply look it up */
-		if (id_lengths[i] >= GIT_OID_HEXSZ) {
-			error = git_odb_read_header(&len, &actual_type, db, &ids[i]);
+		if (query->length >= GIT_OID_HEXSZ) {
+			error = git_odb_read_header(&len, &actual_type, db, &query->id);
 		}
 
 		/* otherwise, resolve the short id to full, then (optionally)
 		 * read the header.
 		 */
-		else if (id_lengths[i] >= GIT_OID_MINPREFIXLEN) {
+		else if (query->length >= GIT_OID_MINPREFIXLEN) {
 	    	error = odb_exists_prefix_1(&tmp,
-				db, &ids[i], id_lengths[i], false);
+				db, &query->id, query->length, false);
 
 			if (!error) {
 				actual_id = &tmp;
-
-				if (types)
-					error = git_odb_read_header(&len, &actual_type, db, &tmp);
-				else
-					actual_type = GIT_OBJ_ANY;
+				error = git_odb_read_header(&len, &actual_type, db, &tmp);
 			}
 		}
 
 		if (error < 0 && error != GIT_ENOTFOUND && error != GIT_EAMBIGUOUS)
 			break;
 
-		error = 0;
-
-		if (types && types[i] != GIT_OBJ_ANY && types[i] != actual_type)
-			actual_type = 0;
-
-		if (!actual_type) {
-			memset(&ids[i], 0, sizeof(git_oid));
-			id_lengths[i] = 0;
-
-			if (types)
-				types[i] = 0;
-		} else {
+		if (error == 0 && (query_type == actual_type || !query_type)) {
 			if (actual_id)
-				git_oid_cpy(&ids[i], actual_id);
+				git_oid_cpy(&query->id, actual_id);
 
-			id_lengths[i] = GIT_OID_HEXSZ;
-
-			if (types)
-				types[i] = actual_type;
+			query->length = GIT_OID_HEXSZ;
+			query->type = actual_type;
+		} else {
+			memset(&query->id, 0, sizeof(git_oid));
+			query->length = 0;
+			query->type = 0;
 		}
 	}
 
diff --git a/tests/odb/mixed.c b/tests/odb/mixed.c
index 57364e4..0e728b8 100644
--- a/tests/odb/mixed.c
+++ b/tests/odb/mixed.c
@@ -146,35 +146,31 @@ struct expand_id_test_data expand_id_test_data[] = {
 };
 
 static void setup_prefix_query(
-	git_oid **out_ids,
-	size_t **out_lengths,
-	git_otype **out_types,
+	git_odb_expand_id **out_ids,
 	size_t *out_num)
 {
-	git_oid *ids;
-	git_otype *types;
-	size_t num, *lengths, i;
+	git_odb_expand_id *ids;
+	size_t num, i;
 
 	num = ARRAY_SIZE(expand_id_test_data);
 
-	cl_assert((ids = git__calloc(num, sizeof(git_oid))));
-	cl_assert((lengths = git__calloc(num, sizeof(size_t))));
-	cl_assert((types = git__calloc(num, sizeof(git_otype))));
+	cl_assert((ids = git__calloc(num, sizeof(git_odb_expand_id))));
 
 	for (i = 0; i < num; i++) {
-		lengths[i] = strlen(expand_id_test_data[i].lookup_id);
-		git_oid_fromstrn(&ids[i], expand_id_test_data[i].lookup_id, lengths[i]);
-		types[i] = expand_id_test_data[i].expected_type;
+		git_odb_expand_id *id = &ids[i];
+
+		size_t len = strlen(expand_id_test_data[i].lookup_id);
+
+		git_oid_fromstrn(&id->id, expand_id_test_data[i].lookup_id, len);
+		id->length = (unsigned short)len;
+		id->type = expand_id_test_data[i].expected_type;
 	}
 
 	*out_ids = ids;
-	*out_lengths = lengths;
-	*out_types = types;
 	*out_num = num;
 }
 
-static void assert_found_objects(
-	git_oid *ids, size_t *lengths, git_otype *types)
+static void assert_found_objects(git_odb_expand_id *ids)
 {
 	size_t num, i;
 
@@ -191,16 +187,13 @@ static void assert_found_objects(
 			expected_type = expand_id_test_data[i].expected_type;
 		}
 
-		cl_assert_equal_i(expected_len, lengths[i]);
-		cl_assert_equal_oid(&expected_id, &ids[i]);
-
-		if (types)
-			cl_assert_equal_i(expected_type, types[i]);
+		cl_assert_equal_oid(&expected_id, &ids[i].id);
+		cl_assert_equal_i(expected_len, ids[i].length);
+		cl_assert_equal_i(expected_type, ids[i].type);
 	}
 }
 
-static void assert_notfound_objects(
-	git_oid *ids, size_t *lengths, git_otype *types)
+static void assert_notfound_objects(git_odb_expand_id *ids)
 {
 	git_oid expected_id = {{0}};
 	size_t num, i;
@@ -208,54 +201,56 @@ static void assert_notfound_objects(
 	num = ARRAY_SIZE(expand_id_test_data);
 
 	for (i = 0; i < num; i++) {
-		cl_assert_equal_i(0, lengths[i]);
-		cl_assert_equal_oid(&expected_id, &ids[i]);
-
-		if (types)
-			cl_assert_equal_i(0, types[i]);
+		cl_assert_equal_oid(&expected_id, &ids[i].id);
+		cl_assert_equal_i(0, ids[i].length);
+		cl_assert_equal_i(0, ids[i].type);
 	}
 }
 
 void test_odb_mixed__expand_ids(void)
 {
-	git_oid *ids;
-	size_t i, num, *lengths;
-	git_otype *types;
+	git_odb_expand_id *ids;
+	size_t i, num;
 
 	/* test looking for the actual (correct) types */
 
-	setup_prefix_query(&ids, &lengths, &types, &num);
-	cl_git_pass(git_odb_expand_ids(_odb, ids, lengths, types, num));
-	assert_found_objects(ids, lengths, types);
-	git__free(ids); git__free(lengths); git__free(types);
+	setup_prefix_query(&ids, &num);
+	cl_git_pass(git_odb_expand_ids(_odb, ids, num));
+	assert_found_objects(ids);
+	git__free(ids);
+
+	/* test looking for an explicit `type == 0` */
 
-	/* test looking for no specified types (types array == NULL) */
+	setup_prefix_query(&ids, &num);
+
+	for (i = 0; i < num; i++)
+		ids[i].type = 0;
 
-	setup_prefix_query(&ids, &lengths, &types, &num);
-	cl_git_pass(git_odb_expand_ids(_odb, ids, lengths, NULL, num));
-	assert_found_objects(ids, lengths, NULL);
-	git__free(ids); git__free(lengths); git__free(types);
+	cl_git_pass(git_odb_expand_ids(_odb, ids, num));
+	assert_found_objects(ids);
+	git__free(ids);
 
 	/* test looking for an explicit GIT_OBJ_ANY */
 
-	setup_prefix_query(&ids, &lengths, &types, &num);
+	setup_prefix_query(&ids, &num);
 
 	for (i = 0; i < num; i++)
-		types[i] = GIT_OBJ_ANY;
+		ids[i].type = GIT_OBJ_ANY;
 
-	cl_git_pass(git_odb_expand_ids(_odb, ids, lengths, types, num));
-	assert_found_objects(ids, lengths, types);
-	git__free(ids); git__free(lengths); git__free(types);
+	cl_git_pass(git_odb_expand_ids(_odb, ids, num));
+	assert_found_objects(ids);
+	git__free(ids);
 
 	/* test looking for the completely wrong type */
 
-	setup_prefix_query(&ids, &lengths, &types, &num);
+	setup_prefix_query(&ids, &num);
 
 	for (i = 0; i < num; i++)
-		types[i] = (types[i] == GIT_OBJ_BLOB) ? GIT_OBJ_TREE : GIT_OBJ_BLOB;
+		ids[i].type = (ids[i].type == GIT_OBJ_BLOB) ?
+			GIT_OBJ_TREE : GIT_OBJ_BLOB;
 
-	cl_git_pass(git_odb_expand_ids(_odb, ids, lengths, types, num));
-	assert_notfound_objects(ids, lengths, types);
-	git__free(ids); git__free(lengths); git__free(types);
+	cl_git_pass(git_odb_expand_ids(_odb, ids, num));
+	assert_notfound_objects(ids);
+	git__free(ids);
 }