You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm investigating code generation instead of manually writing bindings libgit2. This branch code-gen's an easy class, GitOid, from a JSON description of the libgit2 interface. The JSON is based on the data from here, http://libgit2.github.com/libgit2/v0.18.0.json, but highly modified
IN THEORY you just mark methods as "async", "prototype", "constructor", etc. and it will "just work". It works for GitOid, all tests pass.
The new interface for the raw Oid is what I described:
var oid = git.raw.Oid.fromString("SHA1")
oid.sha() = ...
This API change has repercussions, changing some APIs to sync from async, as in Commit. ATM, the API is inconsistent, as Reference's sha() method is still async, because of indirect references. However, I propose to change the api to have have an IndirectReference class and a DirectReference class, with IndirectReference only having a resolve() method, and sha() being synchronous on DirectReference.
It is no longer possible to construct a raw Oid from scratch, as it would be in an invalid state; and further objects are now immutable.
Along the way I've identified what I believe to be memory leaks. I'm hoping to have the code-gen produce code without these leaks, if they are indeed real.
This is intended to generate both sync and async code -- the async isn't done yet, but hopefully it will be by friday.
A goal of my implementation though is to only make methods that do IO async. If they don't do IO, they are sync. The particular change mentioned here (Oid.fromStr() becoming sync) is due to the fact that the underlying libgit2 implementation does not do IO in these methods.
This looks wonderful! @tbranyen we could generate async code as well, or just update the use cases, as implied by @nkallen's suggestions here: #68 (comment)
I am now code-gening GitBlob. This is noteworthy since GitBlob has real async methods, like lookup(). While I expect further roadblocks, this seems to suggest that most, if not all, of the raw api can be code-gen'd. Over the next week I will try to convert more and more classes.
Note that the API continues to change, for two reasons.
As before, methods that don't perform IO no longer take callbacks. So content() (formerly rawcontent()) doesn't do IO, only lookup() does IO. lookup() remains async. This propagates through the convenience API. (Note also, that lookup() is now a method on the constructor: var blob = git.Blob.lookup(sha)).
The raw API matches more closely to libgit2. For example, content() doesn't return a buffer, as libgit2 returns a void * and you must also call git_blob_size() to figure out what to do with the void *. The raw api thus becomes: blob.content().toBuffer(blob.size()). The convenience API, however, is unaffected by this change.
At this point it's worth noting that the API has continued to drift a bit. In addition to the fake async methods become sync, putting factory methods on constructors, etc., i've also moved some of the lookup/factory methods to repo so repo doesn't have to be threaded through the code as much.
The next thing I plan to do may be controversial. DiffList, Index, Error, Odb, Revwalk, Tag, Threads, and Tree remain to be converted. Of these, all are trivial except DiffList and Tree, because both use the C callback methods. AFAICT, there is no particular reason to use these, and they complicate the implementation dramatically: E.g., in DiffList
static void WalkWorkSendFile(uv_async_t *handle, int status /*UNUSED*/);
static void WalkWorkSendHunk(uv_async_t *handle, int status /*UNUSED*/);
static void WalkWorkSendData(uv_async_t *handle, int status /*UNUSED*/);
static void WalkWorkSendEnd(uv_async_t *handle, int status /*UNUSED*/);
With these have to a worry about caching and what runs in what threads.
There is a simpler version of the interface, IIUC, better suited for cross-language bindings, namely you can call git_diff_num_deltas and git_diff_get_patch with an index. The only trade-off is explicit memory management, but that's fairly trivial.
The convenience API could preserve the event emitter style for Tree if you want, but why not ditch it for a simpler interface like this?
function dfs(tree, error) {
tree.entries().forEach(function (entry) {
if (entry.isDirectory()) entry.getTree(dfs)
else if (entry.isFile()) entry.getBlob(f)
});
}
It's a little weird because of the asynchronicity, though not that bad, and it does have the theoretical possibility of a stack overflow, but that's totally unrealistic given a real-world filesystem. In any case, you could build an event emitter on top of this fairly trivially if you wish.
In general I should warn you I'm not a good steward of open-source projects, but I anticipate being heavily involved with nodegit for the next month or so.
Now does Tree. I preserved the event emitter api on the convenience code, but you'll notice the C++ implementation no longer uses callback methods. This dramatically simplifies the C++ code. You may want to take a look at https://github.com/nkallen/nodegit/blob/codegen/lib/tree.js#L62 . I intend to perform this same transformation to DiffList and RevWalk.
Latest commit does Diff nkallen@d9ea5a6 . The convenience API around diff is basically gone, I intend to rebuild it. But all of the basic functionality works, if inconveniently.
Only class left is RevWalk, a fairly easy one. I will do that tomorrow hopefully, although I'm flying to Croatia so we'll see, could take till the weekend. After RevWalk I expect to make a pass through the raw and convenience API to make them both as nice as possible, with fairly conservative changes. It's possible I'll want to switch from using decorators to inheritance as I think I can make the raw API much nicer with very little work -- the codegen allows me to say which libgit methods are in which classes, so I can put branch.lookup(repo, branchname) on repo.lookupBranch(branchname) just by changing the json, which makes the the "raw" layer seem almost OO, and thus the convenience layer becomes very lightweight. If the raw api becomes nice enough, decorators are a pain because it's lots of boilerplate delegation, whereas inheritance would be preferable if the convenience layer is as thin as I hope it can be.
I need to make sure that raw API has decent documentation, I'm not yet familiar with how we do documentation in C++ bindings but I'll figure it out. After that, I'll rewrite the examples to reflect the changes in the API. Then we'll need to do some extensive testing of the code to make sure this shit actually works. The trickiest part is memory management, making sure 1) there are no memory leaks and 2) we aren't freeing memory prematurely, which leads to segfaults.
Once we're all satisfied that this works fairly robustly, I'll do a minor amount of refactoring, and then we can merge this to master and tick the version #.
Sorry I disappeared, I've had no internet for a week. It's actually quite difficult to program without being able to copy and paste from stackoverflow. I did get some work done, however.
Everything passes jslint etc., unit tests pass, etc. It's worthwhile to start reviewing code now. All that's left is stress testing, bug fixing, documentation, and incorporating your feedback.
Awesome man. Any thoughts on clone.h?
On Aug 11, 2013 1:12 PM, "Nick Kallen" notifications@github.com wrote:
I've pushed a few more changes today, dealing with support for treebuilder.
This code is messy, but fortunately it's in javascript. I think the API is
nice-enough, checkout examples/new-commit.js
—
Reply to this email directly or view it on GitHubhttps://github.com//issues/70#issuecomment-22461217
.
AFAICT, the main complexity of clone.h is handling progress callbacks ("75% done") without threading or memory corruption issues. I estimate worst case it's a week, best case 1 day.
My top priority is to get a new project of mine, gitdbhttps://github.com/nkallen/gitdb , to a stable release candidate. This is what's motivating any nodegit bug fixes and API changes ATM. I have about a full week of work to do to get it to this point. I'm still on vacation (in Leipzig ATM) so one week of work currently takes me 3 calendar weeks.
After this, though, I will have time to work on clone. But at the moment, I think the WIP is mostly blocked on: making sure it's stable and getting adequate documentation. If you could help with the latter I would appreciate it. We have to document every method. It's not a huge amount of work but we can't create a release candidate without it.
Absolutely man. Just started my sabbatical and this is a priority for me. Would like to refresh the site, get better up-to-date documentation, and ensure all reported issues are corrected.
It works AFAICT but -- I've not yet implemented the progress callbacks. These are the hard part. In node you are supposed to use uv_async_send to do stuff like this, but there are very few examples of how to use it http://nikhilm.github.io/uvbook/threads.html . I think I get the general idea but we'll see. It will take a couple of days.
I hope to get the documentation fairly polished this week. I'd like to merge WIP into master after this. AFAICT, the code is of equal or greater stability than the existing master, and with documentation we're ready for the next step, which is getting broader user feedback.
Hey @nkallen I have a few items on my plate before we merge as well. I need to finish the installer rewrite (about 50% there). This will include Windows support. I'll worry about the binary distribution after we merge into master since that will be more work.
I also need to integrate the new logo and do some housekeeping with the examples.
Sounds good.. but let's keep the blocking tasks to a minimum -- the sooner we merge though the sooner I can fix the most important bugs. I'd rather do them while I have some momentum with this codebase. We can always add more stuff later.
I was thinking that it might be beneficial for the community to merge the nodegit and node-gitteh projects. I know there are some differences in design philosophy, but the codegen provides a new opportunity to think through whether a compromise can be found. In particular I noticed that the maintainer of gitteh is stepping down: libgit2/node-gitteh#68 -- this might be a good opportunity to think this through. I'm chiming in on the discussion shortly.
@nkallen we were asked to join the libgit2 community about two years ago when things weren't all that stable, so I declined. I think after merging the wip branch and putting a little polish we should definitely move to the libgit2 organization. We don't really need this one.
@tbranyen what do you think of merging to master and improving the install script in another branch? i already have people using wip and it seems to be fairly stable.
Activity
tbranyen commentedon Jun 19, 2013
Oh super cool, nice work! I'm absolutely sure there are memory leaks as my early dive into Valgrind indicated.
A sync API does break a lot of the use cases provided by this library, but I'm sure its possible to generate async code as well.
nkallen commentedon Jun 19, 2013
This is intended to generate both sync and async code -- the async isn't done yet, but hopefully it will be by friday.
A goal of my implementation though is to only make methods that do IO async. If they don't do IO, they are sync. The particular change mentioned here (
Oid.fromStr()becoming sync) is due to the fact that the underlying libgit2 implementation does not do IO in these methods.faceleg commentedon Jun 20, 2013
This looks wonderful! @tbranyen we could generate async code as well, or just update the use cases, as implied by @nkallen's suggestions here: #68 (comment)
tbranyen commentedon Jun 20, 2013
That's fair and I agree with the changes 👍
nkallen commentedon Jun 20, 2013
With this commit:
nkallen@42c7fa7
I am now code-gening
GitBlob. This is noteworthy sinceGitBlobhas real async methods, likelookup(). While I expect further roadblocks, this seems to suggest that most, if not all, of the raw api can be code-gen'd. Over the next week I will try to convert more and more classes.Note that the API continues to change, for two reasons.
content()(formerlyrawcontent()) doesn't do IO, onlylookup()does IO.lookup()remains async. This propagates through the convenience API. (Note also, thatlookup()is now a method on the constructor:var blob = git.Blob.lookup(sha)).content()doesn't return a buffer, as libgit2 returns avoid *and you must also callgit_blob_size()to figure out what to do with thevoid *. The raw api thus becomes:blob.content().toBuffer(blob.size()). The convenience API, however, is unaffected by this change.nkallen commentedon Jun 22, 2013
I expect within a week I will be able to code-gen nearly everything. Two more things finished today.
Repo: nkallen@458d871
Reference: nkallen@707675a
tbranyen commentedon Jun 22, 2013
Awesome, can't wait for a pull request so we can review and version bump. Once we match the API 1:1 we should bump the version to a minor
0.1.0imo.nkallen commentedon Jun 23, 2013
This latest branch converts
TreeEntry, Commit, Signature, Time, and Object.nkallen@cf7d352
At this point it's worth noting that the API has continued to drift a bit. In addition to the fake async methods become sync, putting factory methods on constructors, etc., i've also moved some of the lookup/factory methods to repo so repo doesn't have to be threaded through the code as much.
The next thing I plan to do may be controversial.
DiffList, Index, Error, Odb, Revwalk, Tag, Threads, and Treeremain to be converted. Of these, all are trivial exceptDiffList and Tree, because both use the C callback methods. AFAICT, there is no particular reason to use these, and they complicate the implementation dramatically: E.g., in DiffListWith these have to a worry about caching and what runs in what threads.
There is a simpler version of the interface, IIUC, better suited for cross-language bindings, namely you can call
git_diff_num_deltasandgit_diff_get_patchwith an index. The only trade-off is explicit memory management, but that's fairly trivial.The convenience API could preserve the event emitter style for Tree if you want, but why not ditch it for a simpler interface like this?
It's a little weird because of the asynchronicity, though not that bad, and it does have the theoretical possibility of a stack overflow, but that's totally unrealistic given a real-world filesystem. In any case, you could build an event emitter on top of this fairly trivially if you wish.
nkallen commentedon Jun 24, 2013
Everything but DiffList and Tree is now done.
tbranyen commentedon Jun 24, 2013
Hey @nkallen since you're being such a good steward I added you as an owner to the project :) Really appreciate all the help.
nkallen commentedon Jun 24, 2013
Thanks @tbranyen !
In general I should warn you I'm not a good steward of open-source projects, but I anticipate being heavily involved with nodegit for the next month or so.
In any case,
https://github.com/nkallen/nodegit/tree/codegen
Now does Tree. I preserved the event emitter api on the convenience code, but you'll notice the C++ implementation no longer uses callback methods. This dramatically simplifies the C++ code. You may want to take a look at https://github.com/nkallen/nodegit/blob/codegen/lib/tree.js#L62 . I intend to perform this same transformation to DiffList and RevWalk.
faceleg commentedon Jun 26, 2013
Great job @nkallen, this project has sorely needed more contributions. I love all that you're doing.
nkallen commentedon Jun 26, 2013
Latest commit does Diff nkallen@d9ea5a6 . The convenience API around diff is basically gone, I intend to rebuild it. But all of the basic functionality works, if inconveniently.
nkallen commentedon Jun 26, 2013
Only class left is RevWalk, a fairly easy one. I will do that tomorrow hopefully, although I'm flying to Croatia so we'll see, could take till the weekend. After RevWalk I expect to make a pass through the raw and convenience API to make them both as nice as possible, with fairly conservative changes. It's possible I'll want to switch from using decorators to inheritance as I think I can make the raw API much nicer with very little work -- the codegen allows me to say which libgit methods are in which classes, so I can put branch.lookup(repo, branchname) on repo.lookupBranch(branchname) just by changing the json, which makes the the "raw" layer seem almost OO, and thus the convenience layer becomes very lightweight. If the raw api becomes nice enough, decorators are a pain because it's lots of boilerplate delegation, whereas inheritance would be preferable if the convenience layer is as thin as I hope it can be.
I need to make sure that raw API has decent documentation, I'm not yet familiar with how we do documentation in C++ bindings but I'll figure it out. After that, I'll rewrite the examples to reflect the changes in the API. Then we'll need to do some extensive testing of the code to make sure this shit actually works. The trickiest part is memory management, making sure 1) there are no memory leaks and 2) we aren't freeing memory prematurely, which leads to segfaults.
Once we're all satisfied that this works fairly robustly, I'll do a minor amount of refactoring, and then we can merge this to master and tick the version #.
nkallen commentedon Jul 6, 2013
Sorry I disappeared, I've had no internet for a week. It's actually quite difficult to program without being able to copy and paste from stackoverflow. I did get some work done, however.
I'm nearing a release candidate as most things seem to work. A bunch more of libgit is now supported. It's hard to tell, though, since I haven't yet figured out how to generate documentation. I've reworked all the examples in in the examples directory: https://github.com/nkallen/nodegit/tree/codegen/example. In particular take a look at https://github.com/nkallen/nodegit/blob/codegen/example/general.js which is a transliteration of the libigt2 version.
Everything passes jslint etc., unit tests pass, etc. It's worthwhile to start reviewing code now. All that's left is stress testing, bug fixing, documentation, and incorporating your feedback.
5 remaining items
tbranyen commentedon Aug 11, 2013
Awesome man. Any thoughts on clone.h?
On Aug 11, 2013 1:12 PM, "Nick Kallen" notifications@github.com wrote:
nkallen commentedon Aug 11, 2013
AFAICT, the main complexity of clone.h is handling progress callbacks ("75% done") without threading or memory corruption issues. I estimate worst case it's a week, best case 1 day.
My top priority is to get a new project of mine,
gitdbhttps://github.com/nkallen/gitdb , to a stable release candidate. This is what's motivating anynodegitbug fixes and API changes ATM. I have about a full week of work to do to get it to this point. I'm still on vacation (in Leipzig ATM) so one week of work currently takes me 3 calendar weeks.After this, though, I will have time to work on clone. But at the moment, I think the WIP is mostly blocked on: making sure it's stable and getting adequate documentation. If you could help with the latter I would appreciate it. We have to document every method. It's not a huge amount of work but we can't create a release candidate without it.
tbranyen commentedon Aug 14, 2013
Absolutely man. Just started my sabbatical and this is a priority for me. Would like to refresh the site, get better up-to-date documentation, and ensure all reported issues are corrected.
nkallen commentedon Aug 27, 2013
I implemented remote-fetch and clone in https://github.com/nodegit/nodegit/blob/wip/example/clone.js and https://github.com/nodegit/nodegit/blob/wip/example/fetch.js
It works AFAICT but -- I've not yet implemented the progress callbacks. These are the hard part. In node you are supposed to use
uv_async_sendto do stuff like this, but there are very few examples of how to use it http://nikhilm.github.io/uvbook/threads.html . I think I get the general idea but we'll see. It will take a couple of days.nkallen commentedon Aug 27, 2013
Alright -- I've started working on documentation. Some preliminary stuff is up here: http://www.nodegit.org/nodegit/
I hope to get the documentation fairly polished this week. I'd like to merge WIP into master after this. AFAICT, the code is of equal or greater stability than the existing master, and with documentation we're ready for the next step, which is getting broader user feedback.
tbranyen commentedon Aug 27, 2013
Hey @nkallen I have a few items on my plate before we merge as well. I need to finish the installer rewrite (about 50% there). This will include Windows support. I'll worry about the binary distribution after we merge into master since that will be more work.
I also need to integrate the new logo and do some housekeeping with the examples.
tbranyen commentedon Aug 27, 2013
Great job on the documentation by the way!
nkallen commentedon Aug 27, 2013
Sounds good.. but let's keep the blocking tasks to a minimum -- the sooner we merge though the sooner I can fix the most important bugs. I'd rather do them while I have some momentum with this codebase. We can always add more stuff later.
nkallen commentedon Sep 1, 2013
Hi Tim,
I was thinking that it might be beneficial for the community to merge the nodegit and node-gitteh projects. I know there are some differences in design philosophy, but the codegen provides a new opportunity to think through whether a compromise can be found. In particular I noticed that the maintainer of gitteh is stepping down: libgit2/node-gitteh#68 -- this might be a good opportunity to think this through. I'm chiming in on the discussion shortly.
faceleg commentedon Sep 2, 2013
:+1 so long as we don't take their name.
tbranyen commentedon Sep 2, 2013
@nkallen we were asked to join the libgit2 community about two years ago when things weren't all that stable, so I declined. I think after merging the wip branch and putting a little polish we should definitely move to the libgit2 organization. We don't really need this one.
nkallen commentedon Sep 5, 2013
@tbranyen what do you think of merging to master and improving the install script in another branch? i already have people using wip and it seems to be fairly stable.
tbranyen commentedon Sep 5, 2013
Sounds good to me. I've got it pretty much working in Windows; hopefully I'll have a pull request at the end of the week.
nkallen commentedon Sep 5, 2013
Merged to master. Will hold off on publishing a new package till your merge.