Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
yields committed Apr 27, 2014
0 parents commit 8316d9b
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

test:
@node_modules/.bin/mocha \
--reporter spec

.PHONY: test
22 changes: 22 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

## gh-resolve

Resolves a semver version / branch name to git ref.

## Example

```js
resolve('component/[email protected]', user, tok, function(err, ref){
if (err) return done(err);
assert('refs/tags/0.19.6' == ref.ref);
assert('https://api.github.com/repos/component/component/git/tags/6d6501d002aef91f1261f6ec98c6ed32046fe46a' == ref.object.url);
assert('https://api.github.com/repos/component/component/git/refs/tags/0.19.6' == ref.url);
assert('6d6501d002aef91f1261f6ec98c6ed32046fe46a' == ref.object.sha);
assert('tag' == ref.object.type);
done();
});
```

## License

(MIT)
138 changes: 138 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@

/**
* Module dependencies.
*/

var satisfies = require('semver').satisfies;
var request = require('request');

/**
* Expose `resolve`
*/

module.exports = resolve;

/**
* Resolve `repo@version` with `user`, `token` and `fn(err, res)`.
*
* @param {String} repo
* @param {String} user
* @param {String} token
* @param {Function} fn
* @api public
*/

function resolve(repo, user, token, fn){
var parts = repo.split('@');
var repo = parts.shift();
var version = parts.shift() || '*';

var headers = {
'User-Agent': 'gh-resolve',
Authorization: basic(user, token)
};

function next(url){
get(url, function(err, res, prev){
if (err) return fn(err);
var ref = satisfy(res, version);
if (ref) return fn(null, ref);
if (prev) return next(prev);
fn();
});
}

function get(url, fn){
request({
url: url,
json: true,
headers: headers,
}, function(err, res, body){
if (err) return fn(err);
var s = res.statusCode / 100 | 0;
if (4 <= s) return fn(error(res));
fn(null, body, parse(res.headers.link));
});
}

next('https://api.github.com/repos/' + repo + '/git/refs?per_page=100&last')
}

/**
* Parse the previous `link`.
*
* @param {String} link
* @return {String}
* @api private
*/

function parse(link){
return (link || '')
.split(',')
.reduce(function(_, link){
var parts = link.split(';');
var rel = parts[1];
if (!~rel.indexOf('last')) return;
return parts[0].trim().slice(1, -1);
});
}

/**
* Satisfy `version` with `refs`.
*
* @param {Array} refs
* @param {String} version
* @return {Object}
* @api privae
*/

function satisfy(refs, version){
for (var i = 0; i < refs.length; ++i) {
var name = refs[i].ref.split('/').pop();
if (equal(name, version)) return refs[i];
}
};

/**
* Check if the given `ref` is equal to `version`.
*
* @param {String} ref
* @param {String} version
* @return {Boolean}
* @api private
*/

function equal(ref, version){
try {
return satisfies(ref, version) || ref == version;
} catch (e) {
return ref == version;
}
}

/**
* Basic auth for `user`, `tok`.
*
* @param {String} user
* @param {String} tok
* @return {String}
* @api private
*/

function basic(user, tok){
return 'Basic ' + new Buffer(user + ':' + tok).toString('base64');
}

/**
* Error with `res`.
*
* @param {Response} res
* @return {Error}
* @api private
*/

function error(res){
var err = new Error(res.body.message || 'Unknown gh error');
err.res = res;
return err;
}
11 changes: 11 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "gh-resolve",
"version": "0.0.1",
"dependencies": {
"semver": "^2.2.1",
"request": "^2.34.0"
},
"devDependencies": {
"mocha": "~1.18.2"
}
}
28 changes: 28 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

var resolve = require('./');
var assert = require('assert');
var user = process.env.GITHUB_USER;
var tok = process.env.GITHUB_PASSWORD;

describe('resolve()', function(){
it('should resolve a semver version to gh ref', function(done){
resolve('component/[email protected]', user, tok, function(err, ref){
if (err) return done(err);
assert('refs/tags/0.19.6' == ref.ref);
assert('https://api.github.com/repos/component/component/git/tags/6d6501d002aef91f1261f6ec98c6ed32046fe46a' == ref.object.url);
assert('https://api.github.com/repos/component/component/git/refs/tags/0.19.6' == ref.url);
assert('6d6501d002aef91f1261f6ec98c6ed32046fe46a' == ref.object.sha);
assert('tag' == ref.object.type);
done();
});
});

it('should resolve a branch to gh ref', function(done){
resolve('component/component@master', user, tok, function(err, ref){
if (err) return done(err);
assert('refs/heads/master' == ref.ref);
assert('https://api.github.com/repos/component/component/git/refs/heads/master' == ref.url);
done();
});
})
});

0 comments on commit 8316d9b

Please sign in to comment.