Skip to content

Commit 9e11e9d

Browse files
authored
Merge pull request nodegit#1671 from implausible/feature/native-implementations-for-perf
Add additional getters to streamline information gathering (breaking change)
2 parents 5a230cc + f4926a0 commit 9e11e9d

File tree

10 files changed

+1319
-45
lines changed

10 files changed

+1319
-45
lines changed

generate/input/descriptor.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,6 +1504,7 @@
15041504
}
15051505
},
15061506
"dependencies": [
1507+
"../include/git_buf_converter.h",
15071508
"../include/filter_registry.h"
15081509
]
15091510
},
@@ -3241,7 +3242,9 @@
32413242
"selfFreeing": true,
32423243
"isSingleton": true,
32433244
"dependencies": [
3244-
"git2/sys/repository.h"
3245+
"git2/sys/repository.h",
3246+
"../include/submodule.h",
3247+
"../include/remote.h"
32453248
],
32463249
"functions": {
32473250
"git_repository_config": {
@@ -4220,7 +4223,10 @@
42204223
"git_worktree_prune_init_options": {
42214224
"ignore": true
42224225
}
4223-
}
4226+
},
4227+
"dependencies": [
4228+
"../include/git_buf_converter.h"
4229+
]
42244230
},
42254231
"writestream": {
42264232
"cType": "git_writestream",

generate/input/libgit2-supplement.json

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,94 @@
260260
"isErrorCode": true
261261
}
262262
},
263+
"git_repository_get_references": {
264+
"args": [
265+
{
266+
"name": "out",
267+
"type": "std::vector<git_reference *> *"
268+
},
269+
{
270+
"name": "repo",
271+
"type": "git_repository *"
272+
}
273+
],
274+
"type": "function",
275+
"isManual": true,
276+
"cFile": "generate/templates/manual/repository/get_references.cc",
277+
"isAsync": true,
278+
"isPrototypeMethod": true,
279+
"group": "repository",
280+
"return": {
281+
"type": "int",
282+
"isErrorCode": true
283+
}
284+
},
285+
"git_repository_get_submodules": {
286+
"args": [
287+
{
288+
"name": "out",
289+
"type": "std::vector<git_submodule *> *"
290+
},
291+
{
292+
"name": "repo",
293+
"type": "git_repository *"
294+
}
295+
],
296+
"type": "function",
297+
"isManual": true,
298+
"cFile": "generate/templates/manual/repository/get_submodules.cc",
299+
"isAsync": true,
300+
"isPrototypeMethod": true,
301+
"group": "repository",
302+
"return": {
303+
"type": "int",
304+
"isErrorCode": true
305+
}
306+
},
307+
"git_repository_get_remotes": {
308+
"args": [
309+
{
310+
"name": "out",
311+
"type": "std::vector<git_remote *> *"
312+
},
313+
{
314+
"name": "repo",
315+
"type": "git_repository *"
316+
}
317+
],
318+
"type": "function",
319+
"isManual": true,
320+
"cFile": "generate/templates/manual/repository/get_remotes.cc",
321+
"isAsync": true,
322+
"isPrototypeMethod": true,
323+
"group": "repository",
324+
"return": {
325+
"type": "int",
326+
"isErrorCode": true
327+
}
328+
},
329+
"git_repository_refresh_references": {
330+
"args": [
331+
{
332+
"name": "out",
333+
"type": "void *"
334+
},
335+
{
336+
"name": "repo",
337+
"type": "git_repository *"
338+
}
339+
],
340+
"type": "function",
341+
"isManual": true,
342+
"cFile": "generate/templates/manual/repository/refresh_references.cc",
343+
"isAsync": true,
344+
"isPrototypeMethod": true,
345+
"group": "repository",
346+
"return": {
347+
"type": "int",
348+
"isErrorCode": true
349+
}
350+
},
263351
"git_reset": {
264352
"type": "function",
265353
"file": "reset.h",
@@ -286,6 +374,32 @@
286374
},
287375
"group": "reset"
288376
},
377+
"git_revwalk_commit_walk": {
378+
"args": [
379+
{
380+
"name": "max_count",
381+
"type": "int"
382+
},
383+
{
384+
"name": "out",
385+
"type": "std::vector<git_commit *> *"
386+
},
387+
{
388+
"name": "walk",
389+
"type": "git_revwalk *"
390+
}
391+
],
392+
"type": "function",
393+
"isManual": true,
394+
"cFile": "generate/templates/manual/revwalk/commit_walk.cc",
395+
"isAsync": true,
396+
"isPrototypeMethod": true,
397+
"group": "revwalk",
398+
"return": {
399+
"type": "int",
400+
"isErrorCode": true
401+
}
402+
},
289403
"git_revwalk_fast_walk": {
290404
"args": [
291405
{
@@ -530,9 +644,19 @@
530644
"git_remote_reference_list"
531645
]
532646
],
647+
[
648+
"repository",
649+
[
650+
"git_repository_get_references",
651+
"git_repository_get_submodules",
652+
"git_repository_get_remotes",
653+
"git_repository_refresh_references"
654+
]
655+
],
533656
[
534657
"revwalk",
535658
[
659+
"git_revwalk_commit_walk",
536660
"git_revwalk_fast_walk",
537661
"git_revwalk_file_history_walk"
538662
]
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
NAN_METHOD(GitRepository::GetReferences)
2+
{
3+
if (info.Length() == 0 || !info[0]->IsFunction()) {
4+
return Nan::ThrowError("Callback is required and must be a Function.");
5+
}
6+
7+
GetReferencesBaton* baton = new GetReferencesBaton;
8+
9+
baton->error_code = GIT_OK;
10+
baton->error = NULL;
11+
baton->out = new std::vector<git_reference *>;
12+
baton->repo = Nan::ObjectWrap::Unwrap<GitRepository>(info.This())->GetValue();
13+
14+
Nan::Callback *callback = new Nan::Callback(Local<Function>::Cast(info[0]));
15+
GetReferencesWorker *worker = new GetReferencesWorker(baton, callback);
16+
worker->SaveToPersistent("repo", info.This());
17+
Nan::AsyncQueueWorker(worker);
18+
return;
19+
}
20+
21+
void GitRepository::GetReferencesWorker::Execute()
22+
{
23+
giterr_clear();
24+
25+
LockMaster lockMaster(true, baton->repo);
26+
git_repository *repo = baton->repo;
27+
28+
git_strarray reference_names;
29+
baton->error_code = git_reference_list(&reference_names, repo);
30+
31+
if (baton->error_code != GIT_OK) {
32+
if (giterr_last() != NULL) {
33+
baton->error = git_error_dup(giterr_last());
34+
}
35+
delete baton->out;
36+
baton->out = NULL;
37+
return;
38+
}
39+
40+
for (size_t reference_index = 0; reference_index < reference_names.count; ++reference_index) {
41+
git_reference *reference;
42+
baton->error_code = git_reference_lookup(&reference, repo, reference_names.strings[reference_index]);
43+
44+
// stop execution and return if there is an error
45+
if (baton->error_code != GIT_OK) {
46+
if (giterr_last() != NULL) {
47+
baton->error = git_error_dup(giterr_last());
48+
}
49+
50+
// unwind and return
51+
while (baton->out->size()) {
52+
git_reference *referenceToFree = baton->out->back();
53+
baton->out->pop_back();
54+
git_reference_free(referenceToFree);
55+
}
56+
57+
git_strarray_free(&reference_names);
58+
git_repository_free(repo);
59+
delete baton->out;
60+
baton->out = NULL;
61+
return;
62+
}
63+
64+
if (git_reference_type(reference) == GIT_REF_SYMBOLIC) {
65+
git_reference *resolved_reference;
66+
int resolve_result = git_reference_resolve(&resolved_reference, reference);
67+
git_reference_free(reference);
68+
69+
// if we can't resolve the ref, then just ignore it
70+
if (resolve_result == GIT_OK) {
71+
baton->out->push_back(resolved_reference);
72+
}
73+
} else {
74+
baton->out->push_back(reference);
75+
}
76+
}
77+
}
78+
79+
void GitRepository::GetReferencesWorker::HandleOKCallback()
80+
{
81+
if (baton->out != NULL)
82+
{
83+
unsigned int size = baton->out->size();
84+
Local<Array> result = Nan::New<Array>(size);
85+
for (unsigned int i = 0; i < size; i++) {
86+
git_reference *reference = baton->out->at(i);
87+
Nan::Set(
88+
result,
89+
Nan::New<Number>(i),
90+
GitRefs::New(
91+
reference,
92+
true,
93+
GitRepository::New(git_reference_owner(reference), true)->ToObject()
94+
)
95+
);
96+
}
97+
98+
delete baton->out;
99+
100+
Local<v8::Value> argv[2] = {
101+
Nan::Null(),
102+
result
103+
};
104+
callback->Call(2, argv, async_resource);
105+
}
106+
else if (baton->error)
107+
{
108+
Local<v8::Value> argv[1] = {
109+
Nan::Error(baton->error->message)
110+
};
111+
callback->Call(1, argv, async_resource);
112+
if (baton->error->message)
113+
{
114+
free((void *)baton->error->message);
115+
}
116+
117+
free((void *)baton->error);
118+
}
119+
else if (baton->error_code < 0)
120+
{
121+
Local<v8::Object> err = Nan::Error("Repository getReferences has thrown an error.")->ToObject();
122+
err->Set(Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
123+
err->Set(Nan::New("errorFunction").ToLocalChecked(), Nan::New("Repository.getReferences").ToLocalChecked());
124+
Local<v8::Value> argv[1] = {
125+
err
126+
};
127+
callback->Call(1, argv, async_resource);
128+
}
129+
else
130+
{
131+
callback->Call(0, NULL, async_resource);
132+
}
133+
}

0 commit comments

Comments
 (0)