1+ #define SET_ON_OBJECT (obj, field, data ) Nan::Set(obj, Nan::New(field).ToLocalChecked(), data)
2+
3+ v8::Local<v8::Object> signatureToJavascript (const git_signature *signature) {
4+ v8::Local<v8::Object> signatureObject = Nan::New<v8::Object>();
5+ SET_ON_OBJECT (signatureObject, " name" , Nan::New (signature->name ).ToLocalChecked ());
6+ SET_ON_OBJECT (signatureObject, " email" , Nan::New (signature->email ).ToLocalChecked ());
7+ SET_ON_OBJECT (signatureObject, " date" , Nan::New<v8::Number>(signature->when .time * 1000 ));
8+ std::stringstream fullSignature;
9+ fullSignature << signature->name << " <" << signature << " >" ;
10+ SET_ON_OBJECT (signatureObject, " full" , Nan::New (fullSignature.str ()).ToLocalChecked ());
11+ return signatureObject;
12+ }
13+
14+ #include < iostream>
15+ class CommitModel {
16+ public:
17+ CommitModel (git_commit *commit, bool fetchSignature):
18+ commit (commit),
19+ fetchSignature (fetchSignature),
20+ signature ({ 0 , 0 , 0 }),
21+ signedData ({ 0 , 0 , 0 })
22+ {
23+ if (fetchSignature) {
24+ const int error = git_commit_extract_signature (
25+ &signature,
26+ &signedData,
27+ git_commit_owner (commit),
28+ const_cast <git_oid *>(git_commit_id (commit)),
29+ NULL
30+ );
31+ if (error != GIT_ENOTFOUND) {
32+ assert (error == GIT_OK);
33+ }
34+ }
35+
36+ const size_t parentCount = git_commit_parentcount (commit);
37+ parentIds.reserve (parentCount);
38+ for (size_t parentIndex = 0 ; parentIndex < parentCount; ++parentIndex) {
39+ parentIds.push_back (git_oid_tostr_s (git_commit_parent_id (commit, parentIndex)));
40+ }
41+ }
42+
43+ v8::Local<v8::Value> toJavascript () {
44+ if (!fetchSignature) {
45+ v8::Local<v8::Value> commitObject = GitCommit::New (
46+ commit,
47+ true ,
48+ Nan::To<v8::Object>(GitRepository::New (
49+ git_commit_owner (commit),
50+ true
51+ )).ToLocalChecked ()
52+ );
53+ commit = NULL ;
54+ return commitObject;
55+ }
56+
57+ v8::Local<v8::Object> commitModel = Nan::New<v8::Object>();
58+ SET_ON_OBJECT (commitModel, " sha" , Nan::New (git_oid_tostr_s (git_commit_id (commit))).ToLocalChecked ());
59+ SET_ON_OBJECT (commitModel, " message" , Nan::New (git_commit_message (commit)).ToLocalChecked ());
60+ SET_ON_OBJECT (commitModel, " author" , signatureToJavascript (git_commit_author (commit)));
61+ SET_ON_OBJECT (commitModel, " committer" , signatureToJavascript (git_commit_committer (commit)));
62+
63+ size_t parentCount = parentIds.size ();
64+ v8::Local<v8::Array> parents = Nan::New<v8::Array>(parentCount);
65+ for (size_t parentIndex = 0 ; parentIndex < parentCount; ++parentIndex) {
66+ Nan::Set (parents, Nan::New<v8::Number>(parentIndex), Nan::New (parentIds[parentIndex]).ToLocalChecked ());
67+ }
68+ SET_ON_OBJECT (commitModel, " parents" , parents);
69+
70+ if (signature.size != 0 || signedData.size != 0 ) {
71+ v8::Local<v8::Object> gpgSignature = Nan::New<v8::Object>();
72+ if (signature.size != 0 ) {
73+ SET_ON_OBJECT (gpgSignature, " signature" , Nan::New (signature.ptr ).ToLocalChecked ());
74+ } else {
75+ SET_ON_OBJECT (gpgSignature, " signature" , Nan::Null ());
76+ }
77+
78+ if (signedData.size != 0 ) {
79+ SET_ON_OBJECT (gpgSignature, " signedData" , Nan::New (signedData.ptr ).ToLocalChecked ());
80+ } else {
81+ SET_ON_OBJECT (gpgSignature, " signedData" , Nan::Null ());
82+ }
83+
84+ SET_ON_OBJECT (commitModel, " gpgSignature" , gpgSignature);
85+ }
86+
87+ return commitModel;
88+ }
89+
90+ ~CommitModel () {
91+ git_buf_dispose (&signature);
92+ git_buf_dispose (&signedData);
93+ if (commit) {
94+ git_commit_free (commit);
95+ }
96+ }
97+
98+ private:
99+ git_commit *commit;
100+ bool fetchSignature;
101+ git_buf signature, signedData;
102+ std::vector<std::string> parentIds;
103+ };
104+
1105NAN_METHOD (GitRevwalk::CommitWalk) {
2106 if (info.Length () == 0 || !info[0 ]->IsNumber ()) {
3107 return Nan::ThrowError (" Max count is required and must be a number." );
4108 }
5109
6- if (info.Length () == 1 || !info[1 ]->IsFunction ()) {
110+ if (info.Length () == 1 || (info. Length () == 2 && !info[1 ]->IsFunction () )) {
7111 return Nan::ThrowError (" Callback is required and must be a Function." );
8112 }
9113
114+ if (info.Length () >= 3 ) {
115+ if (!info[1 ]->IsNull () && !info[1 ]->IsUndefined () && !info[1 ]->IsObject ()) {
116+ return Nan::ThrowError (" Options must be an object, null, or undefined." );
117+ }
118+
119+ if (!info[2 ]->IsFunction ()) {
120+ return Nan::ThrowError (" Callback is required and must be a Function." );
121+ }
122+ }
123+
10124 CommitWalkBaton* baton = new CommitWalkBaton;
11125
12126 baton->error_code = GIT_OK;
13127 baton->error = NULL ;
14128 baton->max_count = Nan::To<unsigned int >(info[0 ]).FromJust ();
15- baton->out = new std::vector<git_commit *>;
16- baton->out ->reserve (baton->max_count );
129+ std::vector<CommitModel *> *out = new std::vector<CommitModel *>;
130+ out->reserve (baton->max_count );
131+ baton->out = static_cast <void *>(out);
132+ if (info.Length () == 3 && info[1 ]->IsObject ()) {
133+ v8::Local<v8::Object> options = Nan::To<v8::Object>(info[1 ]).ToLocalChecked ();
134+ v8::Local<v8::String> propName = Nan::New (" returnPlainObjects" ).ToLocalChecked ();
135+ if (Nan::Has (options, propName).FromJust ()) {
136+ baton->returnPlainObjects = Nan::Get (options, propName).ToLocalChecked ()->IsTrue ();
137+ } else {
138+ baton->returnPlainObjects = false ;
139+ }
140+ } else {
141+ baton->returnPlainObjects = false ;
142+ }
17143 baton->walk = Nan::ObjectWrap::Unwrap<GitRevwalk>(info.This ())->GetValue ();
18-
19- Nan::Callback *callback = new Nan::Callback (Local<Function>::Cast (info[1 ]));
144+ Nan::Callback *callback = new Nan::Callback (Local<Function>::Cast (info[1 ]->IsFunction () ? info[1 ] : info[2 ]));
20145 CommitWalkWorker *worker = new CommitWalkWorker (baton, callback);
21- worker->SaveToPersistent (" fastWalk " , info.This ());
146+ worker->SaveToPersistent (" commitWalk " , info.This ());
22147
23148 Nan::AsyncQueueWorker (worker);
24149 return ;
@@ -27,6 +152,7 @@ NAN_METHOD(GitRevwalk::CommitWalk) {
27152void GitRevwalk::CommitWalkWorker::Execute () {
28153 giterr_clear ();
29154
155+ std::vector<CommitModel *> *out = static_cast <std::vector<CommitModel *> *>(baton->out );
30156 for (int i = 0 ; i < baton->max_count ; i++) {
31157 git_oid next_commit_id;
32158 baton->error_code = git_revwalk_next (&next_commit_id, baton->walk );
@@ -41,12 +167,12 @@ void GitRevwalk::CommitWalkWorker::Execute() {
41167 baton->error = git_error_dup (giterr_last ());
42168 }
43169
44- while (baton-> out ->size ()) {
45- git_commit_free (baton-> out ->back () );
46- baton-> out ->pop_back ();
170+ while (out->size ()) {
171+ delete out->back ();
172+ out->pop_back ();
47173 }
48174
49- delete baton-> out ;
175+ delete out;
50176 baton->out = NULL ;
51177
52178 return ;
@@ -60,39 +186,37 @@ void GitRevwalk::CommitWalkWorker::Execute() {
60186 baton->error = git_error_dup (giterr_last ());
61187 }
62188
63- while (baton-> out ->size ()) {
64- git_commit_free (baton-> out ->back () );
65- baton-> out ->pop_back ();
189+ while (out->size ()) {
190+ delete out->back ();
191+ out->pop_back ();
66192 }
67193
68- delete baton-> out ;
194+ delete out;
69195 baton->out = NULL ;
70196
71197 return ;
72198 }
73199
74- baton-> out ->push_back (commit);
200+ out->push_back (new CommitModel ( commit, baton-> returnPlainObjects ) );
75201 }
76202}
77203
78204void GitRevwalk::CommitWalkWorker::HandleOKCallback () {
79205 if (baton->out != NULL ) {
80- unsigned int size = baton->out ->size ();
206+ std::vector<CommitModel *> *out = static_cast <std::vector<CommitModel *> *>(baton->out );
207+ const unsigned int size = out->size ();
81208 Local<Array> result = Nan::New<Array>(size);
82209 for (unsigned int i = 0 ; i < size; i++) {
83- git_commit *commit = baton-> out ->at (i);
210+ CommitModel *commitModel = out->at (i);
84211 Nan::Set (
85212 result,
86213 Nan::New<Number>(i),
87- GitCommit::New (
88- commit,
89- true ,
90- Nan::To<v8::Object>(GitRepository::New (git_commit_owner (commit), true )).ToLocalChecked ()
91- )
214+ commitModel->toJavascript ()
92215 );
216+ delete commitModel;
93217 }
94218
95- delete baton-> out ;
219+ delete out;
96220
97221 Local<v8::Value> argv[2 ] = {
98222 Nan::Null (),
0 commit comments