Skip to content

Commit 0d85f1b

Browse files
author
Vicent Marti
committed
Merge pull request #584 from libgit2/vmg/expand-oids
The new Expand OIDs API
2 parents d253612 + c519063 commit 0d85f1b

File tree

3 files changed

+53
-35
lines changed

3 files changed

+53
-35
lines changed

ext/rugged/rugged_repo.c

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,10 +1045,13 @@ static VALUE rb_git_repo_read_header(VALUE self, VALUE hex)
10451045
/**
10461046
* call-seq:
10471047
* repo.expand_oids([oid..], object_type = :any) -> hash
1048+
* repo.expand_oids([oid..], object_type = [type..]) -> hash
10481049
*
10491050
* Expand a list of short oids to their full value, assuming they exist
1050-
* in the repository. If `object_type` is passed, OIDs are expected to be
1051-
* of the given type.
1051+
* in the repository. If `object_type` is passed and is an array, it must
1052+
* be the same length as the OIDs array. If it's a single type name, all
1053+
* OIDs will be expected to resolve to that object type. OIDs that don't
1054+
* match the expected object types will not be expanded.
10521055
*
10531056
* Returns a hash of `{ short_oid => full_oid }` for the short OIDs which
10541057
* exist in the repository and match the expected object type. Missing OIDs
@@ -1058,59 +1061,64 @@ static VALUE rb_git_repo_expand_oids(int argc, VALUE *argv, VALUE self)
10581061
{
10591062
VALUE rb_result, rb_oids, rb_expected_type;
10601063

1061-
git_otype expected_type = GIT_OBJ_ANY;
1062-
10631064
git_repository *repo;
1064-
git_oid oid;
10651065
git_odb *odb;
1066-
int i, error;
1066+
git_odb_expand_id *expand;
1067+
long i, expand_count;
1068+
int error;
10671069

10681070
Data_Get_Struct(self, git_repository, repo);
1069-
10701071
rb_scan_args(argc, argv, "11", &rb_oids, &rb_expected_type);
10711072

10721073
Check_Type(rb_oids, T_ARRAY);
1073-
expected_type = rugged_otype_get(rb_expected_type);
1074+
expand_count = RARRAY_LEN(rb_oids);
1075+
expand = alloca(expand_count * sizeof(git_odb_expand_id));
10741076

1075-
error = git_repository_odb(&odb, repo);
1076-
rugged_exception_check(error);
1077+
for (i = 0; i < expand_count; ++i) {
1078+
VALUE rb_hex = rb_ary_entry(rb_oids, i);
1079+
Check_Type(rb_hex, T_STRING);
10771080

1078-
rb_result = rb_hash_new();
1081+
rugged_exception_check(
1082+
git_oid_fromstrn(&expand[i].id, RSTRING_PTR(rb_hex), RSTRING_LEN(rb_hex))
1083+
);
1084+
expand[i].length = RSTRING_LEN(rb_hex);
1085+
}
10791086

1080-
for (i = 0; i < RARRAY_LEN(rb_oids); ++i) {
1081-
VALUE hex_oid = rb_ary_entry(rb_oids, i);
1082-
git_oid found_oid;
1087+
if (TYPE(rb_expected_type) == T_ARRAY) {
1088+
if (RARRAY_LEN(rb_expected_type) != expand_count)
1089+
rb_raise(rb_eRuntimeError,
1090+
"the `object_type` array must be the same length as the `oids` array");
10831091

1084-
if (TYPE(hex_oid) != T_STRING) {
1085-
git_odb_free(odb);
1086-
rb_raise(rb_eTypeError, "Expected a SHA1 OID");
1092+
for (i = 0; i < expand_count; ++i) {
1093+
VALUE rb_type = rb_ary_entry(rb_expected_type, i);
1094+
expand[i].type = rugged_otype_get(rb_type);
10871095
}
1096+
} else {
1097+
git_otype expected_type = GIT_OBJ_ANY;
10881098

1089-
error = git_oid_fromstrn(&oid, RSTRING_PTR(hex_oid), RSTRING_LEN(hex_oid));
1090-
if (error < 0) {
1091-
git_odb_free(odb);
1092-
rugged_exception_check(error);
1093-
}
1099+
if (!NIL_P(rb_expected_type))
1100+
expected_type = rugged_otype_get(rb_expected_type);
10941101

1095-
error = git_odb_exists_prefix(&found_oid, odb, &oid, RSTRING_LEN(hex_oid));
1102+
for (i = 0; i < expand_count; ++i)
1103+
expand[i].type = expected_type;
1104+
}
10961105

1097-
if (!error) {
1098-
if (expected_type != GIT_OBJ_ANY) {
1099-
size_t found_size;
1100-
git_otype found_type;
1106+
error = git_repository_odb(&odb, repo);
1107+
rugged_exception_check(error);
11011108

1102-
if (git_odb_read_header(&found_size, &found_type, odb, &found_oid) < 0)
1103-
continue;
1109+
error = git_odb_expand_ids(odb, expand, (size_t)expand_count);
1110+
git_odb_free(odb);
1111+
rugged_exception_check(error);
11041112

1105-
if (found_type != expected_type)
1106-
continue;
1107-
}
1113+
rb_result = rb_hash_new();
11081114

1109-
rb_hash_aset(rb_result, hex_oid, rugged_create_oid(&found_oid));
1115+
for (i = 0; i < expand_count; ++i) {
1116+
if (expand[i].length) {
1117+
rb_hash_aset(rb_result,
1118+
rb_ary_entry(rb_oids, i), rugged_create_oid(&expand[i].id));
11101119
}
11111120
}
11121121

1113-
git_odb_free(odb);
11141122
return rb_result;
11151123
}
11161124

test/repo_test.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,16 @@ def test_expand_objects
256256
def test_expand_and_filter_objects
257257
assert_equal 2, @repo.expand_oids(['a4a7dce8', '1385f264af']).size
258258
assert_equal 1, @repo.expand_oids(['a4a7dce8', '1385f264af'], :commit).size
259+
assert_equal 2, @repo.expand_oids(['a4a7dce8', '1385f264af'], ['commit', 'blob']).size
260+
assert_equal 1, @repo.expand_oids(['a4a7dce8', '1385f264af'], [:commit, :tag]).size
261+
262+
assert_raises RuntimeError do
263+
@repo.expand_oids(['a4a7dce8', '1385f264af'], [:commit, :tag, :commit]).size
264+
end
265+
266+
assert_raises RuntimeError do
267+
@repo.expand_oids(['a4a7dce8', '1385f264af'], [:commit]).size
268+
end
259269
end
260270

261271
def test_descendant_of

0 commit comments

Comments
 (0)