Skip to content

Commit adcc5c5

Browse files
committed
Move getReferences to C++
1 parent 99cca73 commit adcc5c5

File tree

3 files changed

+170
-39
lines changed

3 files changed

+170
-39
lines changed

generate/input/libgit2-supplement.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,28 @@
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+
},
263285
"git_repository_get_remotes": {
264286
"args": [
265287
{
@@ -555,6 +577,7 @@
555577
[
556578
"repository",
557579
[
580+
"git_repository_get_references",
558581
"git_repository_get_remotes"
559582
]
560583
],
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+
}

lib/repository.js

Lines changed: 14 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ var TreeBuilder = NodeGit.Treebuilder;
2424
var _discover = Repository.discover;
2525
var _initExt = Repository.initExt;
2626
var _fetchheadForeach = Repository.prototype.fetchheadForeach;
27+
var _getReferences = Repository.prototype.getReferences;
2728
var _mergeheadForeach = Repository.prototype.mergeheadForeach;
2829

2930
function applySelectedLinesToTarget
@@ -349,44 +350,21 @@ Repository.initExt = function(repo_path, opts) {
349350
};
350351

351352

352-
Repository.getReferences = function(repo, type, refNamesOnly, callback) {
353-
return Reference.list(repo).then(function(refList) {
354-
var refFilterPromises = [];
355-
var filteredRefs = [];
356-
357-
refList.forEach(function(refName) {
358-
refFilterPromises.push(Reference.lookup(repo, refName)
359-
.then(function(ref) {
360-
if (type == Reference.TYPE.LISTALL || ref.type() == type) {
361-
if (refNamesOnly) {
362-
filteredRefs.push(refName);
363-
return;
364-
}
365-
366-
if (ref.isSymbolic()) {
367-
return ref.resolve().then(function(resolvedRef) {
368-
resolvedRef.repo = repo;
369-
370-
filteredRefs.push(resolvedRef);
371-
})
372-
.catch(function() {
373-
// If we can't resolve the ref then just ignore it.
374-
});
375-
}
376-
else {
377-
filteredRefs.push(ref);
378-
}
379-
}
380-
})
381-
);
353+
Repository.getReferences = function(repo, type, refNamesOnly) {
354+
return repo.getReferences().then(function(refList) {
355+
var filteredRefList = refList;
356+
357+
filteredRefList.filter(function(reference) {
358+
return type == Reference.TYPE.LISTALL || ref.type === type
382359
});
383360

384-
return Promise.all(refFilterPromises).then(function() {
385-
if (typeof callback === "function") {
386-
callback(null, filteredRefs);
387-
}
388-
return filteredRefs;
389-
}, callback);
361+
if (refNamesOnly) {
362+
filteredRefList.map(function(reference) {
363+
return reference.name();
364+
});
365+
}
366+
367+
return filteredRefList;
390368
});
391369
};
392370

@@ -1289,9 +1267,6 @@ Repository.prototype.getReferenceNames = function(type, callback) {
12891267
* @param {Reference.TYPE} type Type of reference to look up
12901268
* @return {Array<Reference>}
12911269
*/
1292-
Repository.prototype.getReferences = function(type, callback) {
1293-
return Repository.getReferences(this, type, false, callback);
1294-
};
12951270

12961271
/**
12971272
* Gets a remote from the repo

0 commit comments

Comments
 (0)