New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Automatically detecting smart Git hosts #1628
Conversation
var stderrString; | ||
var isSmartServer; | ||
|
||
stderrString = stderr.toString(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moot as stderr is already a string
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you're right, of course. I copied this from here: https://github.com/bower/bower/blob/master/lib/core/resolvers/GitRemoteResolver.js#L180 - toString()
is used on stdout.
|
Sure - I'll take a look. |
2118d82
to
3452dce
Compare
Btw. there |
Do you have an example for using I checked the existing test cases, but I couldn't find any instance where |
Something like this should work: var gitRemoteResolverFactory = function (handler) {
return helpers.require('lib/core/resolvers/GitRemoteResolver', {
'../../util/cmd': handler
});
};
var gitRemoteResolver = gitRemoteResolverFactory(function (cmd) {
return Q.all(["stdout", "stderr"]);
}); EDIT: fixed few things |
Thanks - this looks helpful indeed! I'll give it a try. |
3452dce
to
6f0028b
Compare
@sheerun Thanks a lot! Your code example was really helpful.
Please let me know what you think. |
Sorry for being such a nuisance, but is there anything I can do to get this moving? |
@nwinkler After I rebase it on master, the tests are failing :( Could you look at it? |
Sure, I'll take a look at it either tonight or tomorrow morning. |
// negotiation that needs to take place. | ||
// | ||
// The above should cover most cases, including BitBucket. | ||
GitRemoteResolver.prototype._supportsShallowCloning = function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wow this is so excellent!
Almost seems like this method deserves its own npm lib
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks - appreciate the feedback!
Also, sometimes parsing url fails, and |
Also, probably result of this should be cached between class instances (as far as I see GitRemoteResolver is instantiated for each source in bower.json; instead there should be only one remote call per host). |
Yes, I'm aware that the result should probably be cached per host. I wanted to add that once I'm sure that the approach taken is acceptable. Can you give me an example under which circumstances you see the remote parsing fails? And I'm not sure I'm following with regards to eager/lazy promises - can you give an example? |
I think I've found the culprit with regards to the failing test cases. It's in It looks like the way to solve this would be to mock the This test (and the one after it) is essentially "spamming" the cmd throttle queue with calls to |
I feel the tests should pass even before you implement mocks. That's why I suggested lazy promise (i.e. check shallow cloning support only when
After that you'd need to properly handle failure case of shallow clone checking, and default it to false. So for example if After that point probably mocks are OK, but I'm not sure how to handle it. Probably we'd need to use https://github.com/mfncooper/mockery and intercept cmd calls selectively (or even introduce new abstraction layer on commands, so we can mock them more easily). |
Yes, that makes sense. The lazy promise should be easy to add. Thanks for the hint! |
Added logic to automatically detect smart Git hosts that allow shallow cloning. This is done by sending an `ls-remote` request to the server and then evaluating the returned HTTP header fields. For this, Curl verbose logging is enabled for the `ls-remote` request, since Curl verbose logging sends the returned HTTP headers to `stderr`. If the `stderr` output contains the desired header Content-Type: application/x-git-upload-pack-advertisement then the server supports shallow cloning. This approach uses Git and Curl for the heavy lifting. Instead of implementing the request to the server using a simple HTTP client, Git is used, since it takes care of authentication using stored credentials. The used approach should also work for BitBucket, which only sends the Content-Type header when a specific user agent is used. Using Git to make the request enables this behavior. The function to detect the smart Git host (`GitRemoteResolver.prototype._supportsShallowCloning`) returns a promise that is resolved when the server's request is evaluated. The promise handling required an addition to `GitHubResolver.js` - to always resolve the promise to `true`, since GitHub supports shallow cloning. Added test cases to verify the new functionality.
6f0028b
to
a352d51
Compare
I've changed the implementation to only call The tests run fine for me locally now - everything rebased on master. Let me know - I can spend some more time on this tonight/tomorrow if required. |
Put some more work into this and added the following:
Added several unit tests to verify the above. |
Let me know if I should squash commits at one point... |
We probably need to add caching, as without it this feature can slow down things instead ;/ We can probably extract this functionality it as util. Maybe even npm module. I can squash commits for you when merging. You'll still be present as an author. |
I've added caching in my last commit, it will only try once per host. Looking forward to seeing this merged! And thanks for all the help! |
Just a note to show how significant change is. For one of our typical projects, the time for Really looking forward to having this in the official version. |
Looks good to me now :) Thank you for this amazing work! I'll release it as soon as I finish tests for the |
Automatically detecting smart Git hosts
@nwinkler For some reason few tests are failing on master after merging (only on travis). Could you look at it? |
I'm taking a look now. It's strange, since in the PR Travis build, everything was fine: https://travis-ci.org/bower/bower/builds/55695755 |
I don't think it's my code that caused the unit test issue. I created a new branch off master before you merged in my PR, and the same error happens there: https://travis-ci.org/nwinkler/bower/jobs/55915627 It looks like something changed in the environment or dependencies between yesterday and today. |
@sheerun I found the culprit for the failing tests: The If you set the version of |
Added logic to automatically detect smart Git hosts that allow shallow cloning. This is done by sending an
ls-remote
request to the server and then evaluating the returned HTTP header fields. For this, Curlverbose logging is enabled for the
ls-remote
request, since Curl verbose logging sends the returned HTTP headers tostderr
.If the
stderr
output contains the desired headerthen the server supports shallow cloning.
This approach uses Git and Curl for the heavy lifting. Instead of implementing the request to the server using a simple HTTP client, Git is used, since it takes care of authentication using stored credentials.
The used approach should also work for BitBucket, which only sends the Content-Type header when a specific user agent is used. Using Git to make the request enables this behavior.
The function to detect the smart Git host (
GitRemoteResolver.prototype._supportsShallowCloning
) returns a promise that is resolved when the server's request is evaluated. The promise handling required an addition toGitHubResolver.js
- to always resolve the promise totrue
, since GitHub supports shallow cloning.This should fix the issues #1558, #1559 and #1568 - and provide a better solution than #1393, which disabled shallow cloning for everyone.
I don't have an instance of GitHub Enterprise that I could test this with - but I'm pretty confident that it is working. It would be great if someone with access to a GitHub Enterprise instance could verify this.
If you run Bower with
-V
(for verbose logging), you should see a message indicating whether the host in question (for non-GitHub hosts) supports shallow cloning, i.e. is a smart host.The code could be optimized to cache information about the hosts - I haven't added this yet since I wanted to get feedback on whether the approach I've taken is sensible/acceptable.