Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions generate/input/descriptor.json
Original file line number Diff line number Diff line change
Expand Up @@ -2269,13 +2269,14 @@
"ignore": true
},
"git_oid_fromstr": {
"isAsync": false
"ignore": true
},
"git_oid_fromstrn": {
"ignore": true
},
"git_oid_fromstrp": {
"ignore": true
"isAsync": false,
"jsFunctionName": "fromString"
},
"git_oid_nfmt": {
"ignore": true
Expand Down Expand Up @@ -3067,7 +3068,15 @@
"ignore": true
},
"git_repository_ident": {
"ignore": true
"args": {
"name": {
"isReturn": true
},
"email": {
"isReturn": true
}
},
"isAsync": false
},
"git_repository_init_init_options": {
"ignore": true
Expand Down Expand Up @@ -3251,7 +3260,10 @@
"dupFunction": "git_signature_dup",
"functions": {
"git_signature_default": {
"isAsync": false
"isAsync": true,
"return": {
"isErrorCode": true
}
},
"git_signature_dup": {
"ignore": true
Expand All @@ -3263,7 +3275,15 @@
"isAsync": false
},
"git_signature_now": {
"isAsync": false
"isAsync": false,
"args": {
"sig_out": {
"isReturn": true
}
},
"return": {
"isErrorCode": true
}
}
}
},
Expand Down
12 changes: 6 additions & 6 deletions generate/templates/partials/sync_function.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ NAN_METHOD({{ cppClassName }}::{{ cppFunctionName }}) {
{%endeach%}
);

{%if .|hasReturnValue %} {{ return.cType }} result = {%endif%}
{%if .|hasReturnType %} {{ return.cType }} result = {%endif%}
{{ cFunctionName }}(
{%each args|argsInfo as arg %}
{%if arg.isReturn %}
Expand All @@ -67,15 +67,15 @@ NAN_METHOD({{ cppClassName }}::{{ cppFunctionName }}) {
{%endeach%}
);

{%if .|hasReturnValue |and return.isErrorCode %}
{%if .|hasReturnType |and return.isErrorCode %}
if (result != GIT_OK) {
{%each args|argsInfo as arg %}
{%if arg.shouldAlloc %}
free({{ arg.name }});
{%elsif arg | isOid %}
{%if arg | isOid %}
if (info[{{ arg.jsArg }}]->IsString()) {
free({{ arg.name }});
free((void *)from_{{ arg.name }});
}
{%elsif arg.shouldAlloc %}
free({{ arg.name }});
{%endif%}
{%endeach%}

Expand Down
120 changes: 120 additions & 0 deletions lib/reference.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,123 @@ Reference.prototype.isValid = function() {
Reference.prototype.toString = function() {
return this.name();
};

const getTerminal = (repo, refName, depth = 10, prevRef = null) => {
if (depth <= 0) {
return Promise.resolve({
error: NodeGit.Error.CODE.ENOTFOUND,
out: prevRef
});
}

return NodeGit.Reference.lookup(repo, refName)
.then((ref) => {
if (ref.type() === NodeGit.Reference.TYPE.OID) {
return {
error: NodeGit.Error.CODE.OK,
out: ref
};
} else {
return getTerminal(repo, ref.symbolicTarget(), depth - 1, ref)
.then(({ error, out }) => {
if (error === NodeGit.Error.CODE.ENOTFOUND && !out) {
return { error, out: ref };
} else {
return { error, out };
}
});
}
})
.catch((error) => {
return {
error: error.errno,
out: null
};
});
};

const getSignatureForReflog = (repo) => {
const { email, name } = repo.ident();
if (email && name) {
return Promise.resolve(NodeGit.Signature.now(name, email));
}

return NodeGit.Signature.default(repo)
.catch(() => NodeGit.Signature.now("unknown", "unknown"));
};

/**
* Given a reference name, follows symbolic links and updates the direct
* reference to point to a given OID. Updates the reflog with a given message.
*
* @async
* @param {Repository} repo The repo where the reference and objects live
* @param {String} refName The reference name to update
* @param {Oid} oid The target OID that the reference will point to
* @param {String} logMessage The reflog message to be writted
* @param {Signature} signature Optional signature to use for the reflog entry
*/
Reference.updateTerminal = function (

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you JSDoc this?

repo,
refName,
oid,
logMessage,
signature
) {
let signatureToUse;
let promiseChain = Promise.resolve();

if (!signature) {
promiseChain = promiseChain
.then(() => getSignatureForReflog(repo))
.then((sig) => {
signatureToUse = sig;
return Promise.resolve();
});
} else {
signatureToUse = signature;
}

return promiseChain
.then(() => getTerminal(repo, refName))
.then(({ error, out }) => {
if (error === NodeGit.Error.CODE.ENOTFOUND && out) {
return NodeGit.Reference.create(
repo,
out.symbolicTarget(),
oid,
0,
logMessage
);
} else if (error === NodeGit.Error.CODE.ENOTFOUND) {
return NodeGit.Reference.create(
repo,
refName,
oid,
0,
logMessage
);
} else {
return NodeGit.Reference.createMatching(
repo,
out.name(),
oid,
1,
out.target(),
logMessage
);
}
})
.then(() => NodeGit.Reflog.read(repo, refName))
.then((reflog) => {
// Janky, but works. Ideally, we would want to generate the correct reflog
// entry in the first place, rather than drop the most recent entry and
// write the correct one.
// NOTE: There is a theoretical race condition that could happen here.
// We may want to consider some kind of transactional logic to make sure
// that the reflog on disk isn't modified before we can write back.
reflog.drop(0, 1);
reflog.append(oid, signatureToUse, logMessage);
return reflog.write();
});
};
Loading