Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: npm/hosted-git-info
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: afeaefdd86ba9bb5044be3c1554a666d007cf19a
Choose a base ref
...
head repository: npm/hosted-git-info
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: a810463604a54af041223a1f69c80622b85fac90
Choose a head ref

Commits on Aug 12, 2019

  1. fix(cache): Switch to lru-cache to save ourselves from unlimited memo…

    …ry consumption
    
    PR-URL: #38
    Credit: @iarna
    Close: #38
    Reviewed-by: @isaacs
    
    BREAKING CHANGE: Drop support for node 0.x
    iarna authored and isaacs committed Aug 12, 2019
    1
    Copy the full SHA
    37c2891 View commit details
  2. chore(release): 3.0.0

    isaacs committed Aug 12, 2019
    Copy the full SHA
    64f0b64 View commit details

Commits on Sep 28, 2019

  1. test: added default fixtures and github specific fixtures

    Michael Perrotte committed Sep 28, 2019
    Copy the full SHA
    145b0c9 View commit details
  2. test: added refactered tests for gists

    Michael Perrotte committed Sep 28, 2019
    Copy the full SHA
    305939f View commit details
  3. fix: updated pathmatch for gitlab

    Michael Perrotte committed Sep 28, 2019
    Copy the full SHA
    fa87af7 View commit details
  4. test: added basic test for ._fill() method

    Michael Perrotte committed Sep 28, 2019
    Copy the full SHA
    b473c55 View commit details
  5. test: added ignore; for 100% testing (this seems wonky)

    Michael Perrotte committed Sep 28, 2019
    Copy the full SHA
    0aea712 View commit details
  6. test: added refactered tests for bitbucket

    Michael Perrotte committed Sep 28, 2019
    Copy the full SHA
    a03d51e View commit details
  7. test: moved all github url tests together

    Michael Perrotte committed Sep 28, 2019
    Copy the full SHA
    4693b9c View commit details
  8. test: removed unused testing structure

    Michael Perrotte committed Sep 28, 2019
    Copy the full SHA
    d04239b View commit details
  9. test: added script to get coverage report

    Michael Perrotte committed Sep 28, 2019
    Copy the full SHA
    af4835c View commit details

Commits on Oct 7, 2019

  1. fix: update pathmatch for gitlab

    PR-URL: #52
    Credit: @mikemimik
    Close: #52
    Reviewed-by: @isaacs
    claudiahdz authored and isaacs committed Oct 7, 2019
    Copy the full SHA
    e3e3054 View commit details
  2. chore(release): 3.0.1

    isaacs committed Oct 7, 2019
    Copy the full SHA
    97c8caa View commit details

Commits on Oct 8, 2019

  1. fix: do not encodeURIComponent the domain

    I ran into a situation where I have to test how Pacote handles git
    shorthands from hosted-git-info, but I didn't want to ping GitHub to run
    my tests.
    
    I set up a git daemon and http server on localhost easily enough, but it
    was still necessary to make it a 'real' HostedGit for the purposes of
    npm-package-arg, and the : with port number was getting URL encoded.
    
    This shows an example of doing this hack/test workaround, and fixes the
    encoding issue.
    
    It would be interesting to perhaps support GitHub Enterprise or on-prem
    GitLab by letting users specify a prefix and format for hosted git info
    in their npm configs, and then clone the definition with a different
    domain name.
    
    PR-URL: #53
    Credit: @isaacs
    Close: #53
    Reviewed-by: @isaacs
    isaacs committed Oct 8, 2019
    Copy the full SHA
    3e5fbec View commit details
  2. chore(release): 3.0.2

    isaacs committed Oct 8, 2019
    Copy the full SHA
    4636ac9 View commit details

Commits on Feb 25, 2020

  1. Ensure passwords in hosted Git URLs are correctly escaped

    PR-URL: #58
    Credit: @stevenhilder
    Close: #58
    Reviewed-by: @darcyclarke
    stevenhilder authored and darcyclarke committed Feb 25, 2020
    Copy the full SHA
    31140a7 View commit details
  2. chore(release): 3.0.3

    darcyclarke committed Feb 25, 2020
    Copy the full SHA
    6f39e93 View commit details

Commits on Feb 26, 2020

  1. fix: Do not pass scp-style URLs to the WhatWG url.URL

    Fix #60
    
    PR-URL: #63
    Credit: @isaacs
    Close: #63
    Reviewed-by: @isaacs
    isaacs committed Feb 26, 2020
    Copy the full SHA
    0835306 View commit details
  2. chore(release): 3.0.4

    isaacs committed Feb 26, 2020
    1
    Copy the full SHA
    8e0b0ec View commit details

Commits on Jul 11, 2020

  1. update lru-cache to latest

    isaacs committed Jul 11, 2020
    Copy the full SHA
    47c931e View commit details
  2. chore: properly advertise version support

    We dropped support for node 6 and 8 with version 3, but didn't update
    the package.json file.  This corrects that oversight.
    isaacs committed Jul 11, 2020
    Copy the full SHA
    167cef2 View commit details
  3. chore(release): 3.0.5

    isaacs committed Jul 11, 2020
    Copy the full SHA
    c53c6ab View commit details

Commits on Oct 12, 2020

  1. fix: support to github gist legacy hash length

    In a previous refactor we add a length count to strict a little bit more
    the regex that identifies gists, unfortunately it drops support to
    legacy gists that had less than 32 characters hashes,
    ref: d5cf830
    
    This changeset fixes it by reducing that count to 7 (which is the
    smallest hash length found in tests from our package ecosystem) that
    seems to have been in use until at least late-2012.
    
    PR-URL: #68
    Credit: @ruyadorno
    Close: #68
    Reviewed-by: @darcyclarke
    ruyadorno authored and darcyclarke committed Oct 12, 2020
    Copy the full SHA
    c067102 View commit details
  2. chore(release): 3.0.6

    darcyclarke committed Oct 12, 2020
    Copy the full SHA
    d30f96e View commit details

Commits on Oct 15, 2020

  1. fix: correctly filter out urls for tarballs in gitlab

    PR-URL: #69
    Credit: @nlf
    Close: #69
    Reviewed-by: @isaacs
    nlf authored and isaacs committed Oct 15, 2020
    Copy the full SHA
    eb5bd5a View commit details
  2. chore(release): 3.0.7

    isaacs committed Oct 15, 2020
    Copy the full SHA
    afe2808 View commit details

Commits on Jan 28, 2021

  1. fix: simplify the regular expression for shortcut matching

    PR-URL: #76
    Credit: @nlf
    Close: #76
    Reviewed-by: @isaacs
    nlf committed Jan 28, 2021
    Copy the full SHA
    bede0dc View commit details
  2. chore(release): 3.0.8

    nlf committed Jan 28, 2021
    Copy the full SHA
    a810463 View commit details
2 changes: 0 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -3,5 +3,3 @@ sudo: false
node_js:
- "12"
- "10"
- "8"
- "6"
86 changes: 86 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -2,6 +2,92 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

<a name="3.0.8"></a>
## [3.0.8](https://github.com/npm/hosted-git-info/compare/v3.0.7...v3.0.8) (2021-01-28)


### Bug Fixes

* simplify the regular expression for shortcut matching ([bede0dc](https://github.com/npm/hosted-git-info/commit/bede0dc)), closes [#76](https://github.com/npm/hosted-git-info/issues/76)



<a name="3.0.7"></a>
## [3.0.7](https://github.com/npm/hosted-git-info/compare/v3.0.6...v3.0.7) (2020-10-15)


### Bug Fixes

* correctly filter out urls for tarballs in gitlab ([eb5bd5a](https://github.com/npm/hosted-git-info/commit/eb5bd5a)), closes [#69](https://github.com/npm/hosted-git-info/issues/69)



<a name="3.0.6"></a>
## [3.0.6](https://github.com/npm/hosted-git-info/compare/v3.0.5...v3.0.6) (2020-10-12)


### Bug Fixes

* support to github gist legacy hash length ([c067102](https://github.com/npm/hosted-git-info/commit/c067102)), closes [#68](https://github.com/npm/hosted-git-info/issues/68)



<a name="3.0.5"></a>
## [3.0.5](https://github.com/npm/hosted-git-info/compare/v3.0.4...v3.0.5) (2020-07-11)



<a name="3.0.4"></a>
## [3.0.4](https://github.com/npm/hosted-git-info/compare/v3.0.3...v3.0.4) (2020-02-26)


### Bug Fixes

* Do not pass scp-style URLs to the WhatWG url.URL ([0835306](https://github.com/npm/hosted-git-info/commit/0835306)), closes [#60](https://github.com/npm/hosted-git-info/issues/60) [#63](https://github.com/npm/hosted-git-info/issues/63)



<a name="3.0.3"></a>
## [3.0.3](https://github.com/npm/hosted-git-info/compare/v3.0.2...v3.0.3) (2020-02-25)



<a name="3.0.2"></a>
## [3.0.2](https://github.com/npm/hosted-git-info/compare/v3.0.1...v3.0.2) (2019-10-08)


### Bug Fixes

* do not encodeURIComponent the domain ([3e5fbec](https://github.com/npm/hosted-git-info/commit/3e5fbec)), closes [#53](https://github.com/npm/hosted-git-info/issues/53)



<a name="3.0.1"></a>
## [3.0.1](https://github.com/npm/hosted-git-info/compare/v3.0.0...v3.0.1) (2019-10-07)


### Bug Fixes

* update pathmatch for gitlab ([e3e3054](https://github.com/npm/hosted-git-info/commit/e3e3054)), closes [#52](https://github.com/npm/hosted-git-info/issues/52)
* updated pathmatch for gitlab ([fa87af7](https://github.com/npm/hosted-git-info/commit/fa87af7))



<a name="3.0.0"></a>
# [3.0.0](https://github.com/npm/hosted-git-info/compare/v2.8.3...v3.0.0) (2019-08-12)


### Bug Fixes

* **cache:** Switch to lru-cache to save ourselves from unlimited memory consumption ([37c2891](https://github.com/npm/hosted-git-info/commit/37c2891)), closes [#38](https://github.com/npm/hosted-git-info/issues/38)


### BREAKING CHANGES

* **cache:** Drop support for node 0.x



<a name="2.8.3"></a>
## [2.8.3](https://github.com/npm/hosted-git-info/compare/v2.8.2...v2.8.3) (2019-08-12)

4 changes: 2 additions & 2 deletions git-host-info.js
Original file line number Diff line number Diff line change
@@ -25,12 +25,12 @@ var gitHosts = module.exports = {
'bugstemplate': 'https://{domain}/{user}/{project}/issues',
'httpstemplate': 'git+https://{auth@}{domain}/{user}/{projectPath}.git{#committish}',
'tarballtemplate': 'https://{domain}/{user}/{project}/repository/archive.tar.gz?ref={committish}',
'pathmatch': /^[/]([^/]+)[/](.+?)(?:[.]git|[/])?$/
'pathmatch': /^\/([^/]+)\/((?!.*(\/-\/|\/repository(\/[^/]+)?\/archive\.tar\.gz)).*?)(?:\.git|\/)?$/
},
gist: {
'protocols': [ 'git', 'git+ssh', 'git+https', 'ssh', 'https' ],
'domain': 'gist.github.com',
'pathmatch': /^[/](?:([^/]+)[/])?([a-z0-9]{32,})(?:[.]git)?$/,
'pathmatch': /^[/](?:([^/]+)[/])?([a-z0-9]{7,})(?:[.]git)?$/,
'filetemplate': 'https://gist.githubusercontent.com/{user}/{project}/raw{/committish}/{path}',
'bugstemplate': 'https://{domain}/{project}',
'gittemplate': 'git://{domain}/{project}.git{#committish}',
2 changes: 1 addition & 1 deletion git-host.js
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@ GitHost.prototype._fill = function (template, opts) {
vars[key] = value.split('/').map(function (pathComponent) {
return encodeURIComponent(pathComponent)
}).join('/')
} else {
} else if (key !== 'domain') {
vars[key] = encodeURIComponent(value)
}
})
40 changes: 31 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
@@ -2,6 +2,8 @@
var url = require('url')
var gitHosts = require('./git-host-info.js')
var GitHost = module.exports = require('./git-host.js')
var LRU = require('lru-cache')
var cache = new LRU({max: 1000})

var protocolToRepresentationMap = {
'git+ssh:': 'sshurl',
@@ -22,17 +24,15 @@ var authProtocols = {
'git+http:': true
}

var cache = {}

module.exports.fromUrl = function (giturl, opts) {
if (typeof giturl !== 'string') return
var key = giturl + JSON.stringify(opts || {})

if (!(key in cache)) {
cache[key] = fromUrl(giturl, opts)
if (!cache.has(key)) {
cache.set(key, fromUrl(giturl, opts))
}

return cache[key]
return cache.get(key)
}

function fromUrl (giturl, opts) {
@@ -41,21 +41,21 @@ function fromUrl (giturl, opts) {
isGitHubShorthand(giturl) ? 'github:' + giturl : giturl
)
var parsed = parseGitUrl(url)
var shortcutMatch = url.match(new RegExp('^([^:]+):(?:(?:[^@:]+(?:[^@]+)?@)?([^/]*))[/](.+?)(?:[.]git)?($|#)'))
var shortcutMatch = url.match(/^([^:]+):(?:[^@]+@)?(?:([^/]*)\/)?([^#]+)/)
var matches = Object.keys(gitHosts).map(function (gitHostName) {
try {
var gitHostInfo = gitHosts[gitHostName]
var auth = null
if (parsed.auth && authProtocols[parsed.protocol]) {
auth = decodeURIComponent(parsed.auth)
auth = parsed.auth
}
var committish = parsed.hash ? decodeURIComponent(parsed.hash.substr(1)) : null
var user = null
var project = null
var defaultRepresentation = null
if (shortcutMatch && shortcutMatch[1] === gitHostName) {
user = shortcutMatch[2] && decodeURIComponent(shortcutMatch[2])
project = decodeURIComponent(shortcutMatch[3])
project = decodeURIComponent(shortcutMatch[3].replace(/\.git$/, ''))
defaultRepresentation = 'shortcut'
} else {
if (parsed.host && parsed.host !== gitHostInfo.domain && parsed.host.replace(/^www[.]/, '') !== gitHostInfo.domain) return
@@ -64,6 +64,7 @@ function fromUrl (giturl, opts) {
var pathmatch = gitHostInfo.pathmatch
var matched = parsed.path.match(pathmatch)
if (!matched) return
/* istanbul ignore else */
if (matched[1] !== null && matched[1] !== undefined) {
user = decodeURIComponent(matched[1].replace(/^:/, ''))
}
@@ -105,7 +106,28 @@ function fixupUnqualifiedGist (giturl) {

function parseGitUrl (giturl) {
var matched = giturl.match(/^([^@]+)@([^:/]+):[/]?((?:[^/]+[/])?[^/]+?)(?:[.]git)?(#.*)?$/)
if (!matched) return url.parse(giturl)
if (!matched) {
var legacy = url.parse(giturl)
if (legacy.auth) {
// git urls can be in the form of scp-style/ssh-connect strings, like
// git+ssh://user@host.com:some/path, which the legacy url parser
// supports, but WhatWG url.URL class does not. However, the legacy
// parser de-urlencodes the username and password, so something like
// https://user%3An%40me:p%40ss%3Aword@x.com/ becomes
// https://user:n@me:p@ss:word@x.com/ which is all kinds of wrong.
// Pull off just the auth and host, so we dont' get the confusing
// scp-style URL, then pass that to the WhatWG parser to get the
// auth properly escaped.
const authmatch = giturl.match(/[^@]+@[^:/]+/)
/* istanbul ignore else - this should be impossible */
if (authmatch) {
var whatwg = new url.URL(authmatch[0])
legacy.auth = whatwg.username || ''
if (whatwg.password) legacy.auth += ':' + whatwg.password
}
}
return legacy
}
return {
protocol: 'git+ssh:',
slashes: true,
1,801 changes: 784 additions & 1,017 deletions package-lock.json

Large diffs are not rendered by default.

13 changes: 10 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hosted-git-info",
"version": "2.8.3",
"version": "3.0.8",
"description": "Provides metadata and conversions from repository urls for Github, Bitbucket and Gitlab",
"main": "index.js",
"repository": {
@@ -22,10 +22,14 @@
"scripts": {
"prerelease": "npm t",
"postrelease": "npm publish && git push --follow-tags",
"pretest": "standard",
"posttest": "standard",
"release": "standard-version -s",
"test:coverage": "tap --coverage-report=html -J --100 --no-esm test/*.js",
"test": "tap -J --100 --no-esm test/*.js"
},
"dependencies": {
"lru-cache": "^6.0.0"
},
"devDependencies": {
"standard": "^11.0.1",
"standard-version": "^4.4.0",
@@ -35,5 +39,8 @@
"index.js",
"git-host.js",
"git-host-info.js"
]
],
"engines": {
"node": ">=10"
}
}
18 changes: 18 additions & 0 deletions test/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
var HostedGitInfo = require('../')

var tap = require('tap')
var url = require('url')

// Auth credentials with special characters (colon and/or at-sign) should remain correctly escaped
var parsedInfo = HostedGitInfo.fromUrl('https://user%3An%40me:p%40ss%3Aword@github.com/npm/hosted-git-info.git')
tap.equal(parsedInfo.auth, 'user%3An%40me:p%40ss%3Aword')

// Node.js' built-in `url` module should be able to parse the resulting url
var parsedUrl = new url.URL(parsedInfo.toString())
tap.equal(parsedUrl.username, 'user%3An%40me')
tap.equal(parsedUrl.password, 'p%40ss%3Aword')
tap.equal(parsedUrl.hostname, 'github.com')

// For full backwards-compatibility; support auth where only username or only password is provided
tap.equal(HostedGitInfo.fromUrl('https://user%3An%40me@github.com/npm/hosted-git-info.git').auth, 'user%3An%40me')
tap.equal(HostedGitInfo.fromUrl('https://:p%40ss%3Aword@github.com/npm/hosted-git-info.git').auth, ':p%40ss%3Aword')
3 changes: 3 additions & 0 deletions test/basic.js
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ var test = require('tap').test

test('basic', function (t) {
const h = HostedGit.fromUrl('github:user/project')
t.equal(h._fill(), undefined)
t.is(h.constructor, HostedGit)
t.is(h.constructor.name, 'GitHost')
t.is(HostedGit.fromUrl('https://google.com'), undefined, 'null on failure')
@@ -36,6 +37,8 @@ test('basic', function (t) {
t.is(HostedGit.fromUrl('github.com/abc/def/'), undefined, 'forgot the protocol')
t.is(HostedGit.fromUrl('completely-invalid'), undefined, 'not a url is not hosted')

t.is(HostedGit.fromUrl('git+ssh://git@git.unlucky.com:RND/electron-tools/some-tool#2.0.1'), undefined, 'properly ignores non-hosted scp style urls')

t.is(HostedGit.fromUrl('http://github.com/foo/bar').toString(), 'git+ssh://git@github.com/foo/bar.git', 'github http protocol use git+ssh urls')
t.end()
})
27 changes: 0 additions & 27 deletions test/bitbucket-https-with-embedded-auth.js

This file was deleted.

306 changes: 283 additions & 23 deletions test/bitbucket.js
Original file line number Diff line number Diff line change
@@ -2,32 +2,292 @@
var HostedGit = require('../index')
var test = require('tap').test

test('fromUrl(bitbucket url)', function (t) {
function verify (host, label, branch) {
var showLabel = function (label, fn) { return label + ' -> ' + fn }

var testFixtures = function (t, params, fixtures) {
for (var i = 0; i < fixtures.length; ++i) {
var fixture = fixtures[i]

var host = fixture.host(params)
var hostinfo = HostedGit.fromUrl(host)
var hash = branch ? '#' + branch : ''
t.ok(hostinfo, label)
if (!hostinfo) return
t.is(hostinfo.https(), 'git+https://bitbucket.org/111/222.git' + hash, label + ' -> https')
t.is(hostinfo.browse(), 'https://bitbucket.org/111/222' + (branch ? '/src/' + branch : ''), label + ' -> browse')
t.is(hostinfo.browse(''), 'https://bitbucket.org/111/222/src/' + (branch || 'master') + '/', label + ' -> browse(path)')
t.is(hostinfo.browse('C'), 'https://bitbucket.org/111/222/src/' + (branch || 'master') + '/C', label + ' -> browse(path)')
t.is(hostinfo.browse('C/D'), 'https://bitbucket.org/111/222/src/' + (branch || 'master') + '/C/D', label + ' -> browse(path)')
t.is(hostinfo.browse('C', 'A'), 'https://bitbucket.org/111/222/src/' + (branch || 'master') + '/C#a', label + ' -> browse(path, fragment)')
t.is(hostinfo.browse('C/D', 'A'), 'https://bitbucket.org/111/222/src/' + (branch || 'master') + '/C/D#a', label + ' -> browse(path, fragment)')
t.is(hostinfo.docs(), 'https://bitbucket.org/111/222' + (branch ? '/src/' + branch : '') + '#readme', label + ' -> docs')
t.is(hostinfo.ssh(), 'git@bitbucket.org:111/222.git' + hash, label + ' -> ssh')
t.is(hostinfo.sshurl(), 'git+ssh://git@bitbucket.org/111/222.git' + hash, label + ' -> sshurl')
t.is(hostinfo.shortcut(), 'bitbucket:111/222' + hash, label + ' -> shortcut')
t.is(hostinfo.file(''), 'https://bitbucket.org/111/222/raw/' + (branch || 'master') + '/', label + ' -> file')
t.is(hostinfo.file('C'), 'https://bitbucket.org/111/222/raw/' + (branch || 'master') + '/C', label + ' -> file')
t.is(hostinfo.file('C/D'), 'https://bitbucket.org/111/222/raw/' + (branch || 'master') + '/C/D', label + ' -> file')
t.is(hostinfo.tarball(), 'https://bitbucket.org/111/222/get/' + (branch || 'master') + '.tar.gz', label + ' -> tarball')
t.is(hostinfo.tarball({ noCommittish: true }), 'https://bitbucket.org/111/222/get/' + (branch || 'master') + '.tar.gz', label + ' -> tarball')

// INFO: fromUrl should return `undefined` from fixture input
if (fixture.isUndefined) {
t.test('input results in undefined', function (tt) {
tt.is(hostinfo, undefined)
tt.end()
})
break
}

t.test('hostinfo.https', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url + '#' + params.branch
: url
}
tt.is(
hostinfo.https(),
expected('git+https://bitbucket.org/some-owner/some-repo.git', fixture.hasBranch, fixture.hasGroup),
showLabel(fixture.label, 'https')
)
// INFO: not using `expected` because with `{noCommittish: true}` the output is always the same
tt.is(
hostinfo.https({ noCommittish: true }),
'git+https://bitbucket.org/some-owner/some-repo.git',
showLabel(fixture.label, 'https({ noCommittish: true })')
)
tt.is(
hostinfo.https({ noGitPlus: true }),
expected('https://bitbucket.org/some-owner/some-repo.git', fixture.hasBranch),
showLabel(fixture.label, 'https({ noGitPlus: true })')
)
tt.end()
})
t.test('hostinfo.browse', function (tt) {
var expected = function (url, hasBranch) {
if (hasBranch) {
if (url.indexOf('master') === -1) {
return url + '/src/' + params.branch
} else {
return url.replace(/master/gi, params.branch)
}
}
return url
}
tt.is(
hostinfo.browse(),
expected('https://bitbucket.org/some-owner/some-repo', fixture.hasBranch),
showLabel(fixture.label, 'browse')
)
tt.is(
hostinfo.browse(''),
expected('https://bitbucket.org/some-owner/some-repo/src/master/', fixture.hasBranch),
showLabel(fixture.label, "browse('')")
)
tt.is(
hostinfo.browse('C'),
expected('https://bitbucket.org/some-owner/some-repo/src/master/C', fixture.hasBranch),
showLabel(fixture.label, "browse('C')")
)
tt.is(
hostinfo.browse('C/D'),
expected('https://bitbucket.org/some-owner/some-repo/src/master/C/D', fixture.hasBranch),
showLabel(fixture.label, "browse('C/D')")
)
tt.is(
hostinfo.browse('C', 'A'),
expected('https://bitbucket.org/some-owner/some-repo/src/master/C#a', fixture.hasBranch),
showLabel(fixture.label, "browse('C', 'A')")
)
tt.is(
hostinfo.browse('C/D', 'A'),
expected('https://bitbucket.org/some-owner/some-repo/src/master/C/D#a', fixture.hasBranch),
showLabel(fixture.label, "browse('C/D', 'A')")
)
tt.end()
})
t.test('hostinfo.docs', function (tt) {
var expected = function (url, hasBranch) {
if (hasBranch) {
var splitUrl = url.split('#')
return splitUrl[0] + '/src/' + params.branch + '#' + splitUrl[1]
}
return url
}
tt.is(
hostinfo.docs(),
expected('https://bitbucket.org/some-owner/some-repo#readme', fixture.hasBranch),
showLabel(fixture.label, 'docs')
)
tt.is(
hostinfo.docs({ noCommittish: true }),
// INFO: not using `expected` because with `{noCommittish: true}` the output is always the same
'https://bitbucket.org/some-owner/some-repo#readme',
showLabel(fixture.label, 'docs({ noCommittish: true })')
)
tt.is(
hostinfo.docs({ noGitPlus: true }),
expected('https://bitbucket.org/some-owner/some-repo#readme', fixture.hasBranch),
showLabel(fixture.label, 'docs({ noGitPlus: true })')
)
tt.end()
})
t.test('hostinfo.ssh', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url + '#' + params.branch
: url
}
tt.is(
hostinfo.ssh(),
expected('git@bitbucket.org:some-owner/some-repo.git', fixture.hasBranch),
showLabel(fixture.label, 'ssh')
)
tt.is(
hostinfo.ssh({ noCommittish: true }),
// INFO: not using `expected` because with `{noCommittish: true}` the output is always the same
'git@bitbucket.org:some-owner/some-repo.git',
showLabel(fixture.label, 'ssh({ noCommittish: true })')
)
tt.is(
hostinfo.ssh({ noGitPlus: true }),
expected('git@bitbucket.org:some-owner/some-repo.git', fixture.hasBranch),
showLabel(fixture.label, 'ssh({ noGitPlus: true })')
)
tt.end()
})
t.test('hostinfo.sshurl', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url + '#' + params.branch
: url
}
tt.is(
hostinfo.sshurl(),
expected('git+ssh://git@bitbucket.org/some-owner/some-repo.git', fixture.hasBranch),
showLabel(fixture.label, 'sshurl')
)
tt.is(
hostinfo.sshurl({ noCommittish: true }),
// INFO: not using `expected` because with `{noCommittish: true}` the output is always the same
'git+ssh://git@bitbucket.org/some-owner/some-repo.git',
showLabel(fixture.label, 'sshurl({ noCommittish: true })')
)
tt.is(
hostinfo.sshurl({ noGitPlus: true }),
expected('ssh://git@bitbucket.org/some-owner/some-repo.git', fixture.hasBranch),
showLabel(fixture.label, 'sshurl({ noGitPlus: true })')
)
tt.end()
})
t.test('hostinfo.shortcut', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url + '#' + params.branch
: url
}
tt.is(
hostinfo.shortcut(),
expected('bitbucket:some-owner/some-repo', fixture.hasBranch),
showLabel(fixture.label, 'shortcut')
)
tt.is(
hostinfo.shortcut({ noCommittish: true }),
// INFO: not using `expected` because with `{noCommittish: true}` the output is always the same
'bitbucket:some-owner/some-repo',
showLabel(fixture.label, 'shortcut({ noCommittish: true })')
)
tt.is(
hostinfo.shortcut({ noGitPlus: true }),
expected('bitbucket:some-owner/some-repo', fixture.hasBranch),
showLabel(fixture.label, 'shortcut({ noGitPlus: true })')
)
tt.end()
})
t.test('hostinfo.file', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url.replace(/master/gi, params.branch)
: url
}
tt.is(
hostinfo.file(),
expected('https://bitbucket.org/some-owner/some-repo/raw/master/', fixture.hasBranch),
showLabel(fixture.label, 'file')
)
tt.is(
hostinfo.file('C'),
expected('https://bitbucket.org/some-owner/some-repo/raw/master/C', fixture.hasBranch),
showLabel(fixture.label, "file('C')")
)
tt.is(
hostinfo.file('C/D'),
expected('https://bitbucket.org/some-owner/some-repo/raw/master/C/D', fixture.hasBranch),
showLabel(fixture.label, "file('C/D')")
)
tt.end()
})
t.test('hostinfo.tarball', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url.replace(/master/gi, params.branch)
: url
}
tt.is(
hostinfo.tarball(),
expected('https://bitbucket.org/some-owner/some-repo/get/master.tar.gz', fixture.hasBranch),
showLabel(fixture.label, 'tarball')
)
tt.is(
hostinfo.tarball({ noCommittish: true }),
expected('https://bitbucket.org/some-owner/some-repo/get/master.tar.gz', fixture.hasBranch),
showLabel(fixture.label, 'tarball({ noCommittish: true })')
)
tt.is(
hostinfo.tarball({ noGitPlus: true }),
expected('https://bitbucket.org/some-owner/some-repo/get/master.tar.gz', fixture.hasBranch),
showLabel(fixture.label, 'tarball({ noGitPlus: true })')
)
tt.end()
})
}
}

test('fromUrl(bitbucket url)', function (t) {
var fixtures = require('./fixtures/bitbucket')
// var gitlabFixtures = require('./fixtures/bitbucket')
// var collectedFixtures = [].concat(fixtures, gitlabFixtures)

t.test('domain: bitbucket.org', function (tt) {
var params = {
domain: 'bitbucket.org',
shortname: 'bitbucket',
label: 'bitbucket',
owner: 'some-owner',
project: 'some-repo',
branch: 'feature-branch'
}
testFixtures(tt, params, fixtures)
tt.end()
})

t.test('domain: www.bitbucket.org', function (tt) {
var params = {
domain: 'www.bitbucket.org',
shortname: 'bitbucket',
label: 'bitbucket',
owner: 'some-owner',
project: 'some-repo',
branch: 'feature-branch'
}
testFixtures(tt, params, fixtures)
tt.end()
})

require('./lib/standard-tests')(verify, 'bitbucket.org', 'bitbucket')
require('./lib/standard-tests')(verify, 'www.bitbucket.org', 'bitbucket')
t.test('Bitbucket HTTPS URLs with embedded auth', function (tt) {
tt.is(
HostedGit.fromUrl('https://user:pass@bitbucket.org/user/repo.git').toString(),
'git+https://user:pass@bitbucket.org/user/repo.git',
'credentials were included in URL'
)
tt.is(
HostedGit.fromUrl('https://user:pass@bitbucket.org/user/repo').toString(),
'git+https://user:pass@bitbucket.org/user/repo.git',
'credentials were included in URL'
)
tt.is(
HostedGit.fromUrl('git+https://user:pass@bitbucket.org/user/repo.git').toString(),
'git+https://user:pass@bitbucket.org/user/repo.git',
'credentials were included in URL'
)
tt.is(
HostedGit.fromUrl('git+https://user:pass@bitbucket.org/user/repo').toString(),
'git+https://user:pass@bitbucket.org/user/repo.git',
'credentials were included in URL'
)
tt.end()
})

t.end()
})
99 changes: 99 additions & 0 deletions test/fixtures/bitbucket.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
'use strcit'

module.exports = [
{
host: function (p) { return 'https://' + p.domain + '/' + p.owner + '/' + p.project },
label: 'https'
},
{
host: function (p) { return 'https://' + p.domain + '/' + p.owner + '/' + p.project + '.git' },
label: 'https.git'
},
{
host: function (p) { return 'https://' + p.domain + '/' + p.owner + '/' + p.project + '#' + p.branch },
label: 'https#branch',
hasBranch: true
},
{
host: function (p) { return 'https://' + p.domain + '/' + p.owner + '/' + p.project + '.git#' + p.branch },
label: 'https.git#branch',
hasBranch: true
},
{
host: function (p) { return 'https://' + p.domain + '/' + p.owner + '/' + p.project + '/-/' + 'archive' + '/3.3.2' + '/ws-3.3.2.tar.gz' },
label: 'https.tar',
isUndefined: true
},
{
host: function (p) { return 'git+https://' + p.domain + '/' + p.owner + '/' + p.project },
label: 'git+https'
},
{
host: function (p) { return 'git+https://' + p.domain + '/' + p.owner + '/' + p.project + '.git' },
label: 'git+https.git'
},
{
host: function (p) { return 'git+https://' + p.domain + '/' + p.owner + '/' + p.project + '#' + p.branch },
label: 'git+https#branch',
hasBranch: true
},
{
host: function (p) { return 'git+https://' + p.domain + '/' + p.owner + '/' + p.project + '.git#' + p.branch },
label: 'git+https.git#branch',
hasBranch: true
},
{
host: function (p) { return 'git@' + p.domain + ':' + p.owner + '/' + p.project },
label: 'ssh'
},
{
host: function (p) { return 'git@' + p.domain + ':' + p.owner + '/' + p.project + '.git' },
label: 'ssh.git'
},
{
host: function (p) { return 'git@' + p.domain + ':' + p.owner + '/' + p.project + '#' + p.branch },
label: 'ssh#branch',
hasBranch: true
},
{
host: function (p) { return 'git@' + p.domain + ':' + p.owner + '/' + p.project + '.git#' + p.branch },
label: 'ssh.git#branch',
hasBranch: true
},
{
host: function (p) { return 'git+ssh://git@' + p.domain + '/' + p.owner + '/' + p.project },
label: 'ssh-url'
},
{
host: function (p) { return 'git+ssh://git@' + p.domain + '/' + p.owner + '/' + p.project + '.git' },
label: 'ssh-url.git'
},
{
host: function (p) { return 'git+ssh://git@' + p.domain + '/' + p.owner + '/' + p.project + '#' + p.branch },
label: 'ssh-url#branch',
hasBranch: true
},
{
host: function (p) { return 'git+ssh://git@' + p.domain + '/' + p.owner + '/' + p.project + '.git#' + p.branch },
label: 'ssh-url.git#branch',
hasBranch: true
},
{
host: function (p) { return p.shortname + ':' + p.owner + '/' + p.project },
label: 'shortcut'
},
{
host: function (p) { return p.shortname + ':' + p.owner + '/' + p.project + '.git' },
label: 'shortcut.git'
},
{
host: function (p) { return p.shortname + ':' + p.owner + '/' + p.project + '#' + p.branch },
label: 'shortcut#branch',
hasBranch: true
},
{
host: function (p) { return p.shortname + ':' + p.owner + '/' + p.project + '.git#' + p.branch },
label: 'shortcut.git#branch',
hasBranch: true
}
]
60 changes: 60 additions & 0 deletions test/fixtures/gist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
'use strict'

module.exports = [
{
host: function (p) { return 'gist:' + p.owner + '/' + p.project },
label: 'gist'
},
{
host: function (p) { return 'git@' + p.domain + ':/' + p.project },
label: 'git@:/'
},
{
host: function (p) { return 'git@' + p.domain + ':/' + p.project + '.git' },
label: 'git@:/.git'
},
{
host: function (p) { return 'git@' + p.domain + ':' + p.project + '.git' },
label: 'git@'
},
{
host: function (p) { return 'git@' + p.domain + ':/' + p.project + '.git' },
label: 'git@/'
},
{
host: function (p) { return 'git://' + p.domain + '/' + p.project },
label: 'git'
},
{
host: function (p) { return 'git://' + p.domain + '/' + p.project + '.git' },
label: 'git.git'
},
{
host: function (p) { return 'git://' + p.domain + '/' + p.project + '#' + p.branch },
label: 'git#branch',
hasBranch: true
},
{
host: function (p) { return 'git://' + p.domain + '/' + p.project + '.git#' + p.branch },
label: 'git.git#branch',
hasBranch: true
},
{
host: function (p) { return 'git://' + p.domain + ':/' + p.project },
label: 'git:/'
},
{
host: function (p) { return 'git://' + p.domain + ':/' + p.project + '.git' },
label: 'git:/.git'
},
{
host: function (p) { return 'git://' + p.domain + ':/' + p.project + '#' + p.branch },
label: 'git:/#branch',
hasBranch: true
},
{
host: function (p) { return 'git://' + p.domain + ':/' + p.project + '.git#' + p.branch },
label: 'git:/.git#branch',
hasBranch: true
}
]
38 changes: 38 additions & 0 deletions test/fixtures/github.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
'use strict'

module.exports = [
// Github Shorturls
{
host: function (p) { return p.owner + '/' + p.project },
label: 'github-short'
},
{
host: function (p) { return p.owner + '/' + p.project + '#' + p.branch },
label: 'github-short#branch',
hasBranch: true
},
{
host: function (p) { return p.owner + '/' + p.project + '#' + p.branch },
label: 'github-short#branch',
hasBranch: true
},
// Insecure Protocols
{
host: function (p) { return 'git://' + p.domain + '/' + p.owner + '/' + p.project },
label: 'git'
},
{
host: function (p) { return 'git://' + p.domain + '/' + p.owner + '/' + p.project + '.git' },
label: 'git.git'
},
{
host: function (p) { return 'git://' + p.domain + '/' + p.owner + '/' + p.project + '#' + p.branch },
label: 'git#branch',
hasBranch: true
},
{
host: function (p) { return 'git://' + p.domain + '/' + p.owner + '/' + p.project + '.git#' + p.branch },
label: 'git.git#branch',
hasBranch: true
}
]
22 changes: 22 additions & 0 deletions test/fixtures/gitlab-subgroups.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use strict'

module.exports = [
{
host: function (p) { return p.shortname + ':' + p.owner + '/' + p.group + '/' + p.project },
label: 'shortname'
},
{
host: function (p) { return p.shortname + ':' + p.owner + '/' + p.group + '/' + p.project },
label: 'shortname.git'
},
{
host: function (p) { return p.shortname + ':' + p.owner + '/' + p.group + '/' + p.project + '#' + p.branch },
label: 'shortname#branch',
hasBranch: true
},
{
host: function (p) { return p.shortname + ':' + p.owner + '/' + p.group + '/' + p.project + '#' + p.branch },
label: 'shortname.git#branch',
hasBranch: true
}
]
109 changes: 109 additions & 0 deletions test/fixtures/gitlab.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
'use strcit'

module.exports = [
{
host: function (p) { return 'https://' + p.domain + '/' + p.owner + '/' + p.project },
label: 'https'
},
{
host: function (p) { return 'https://' + p.domain + '/' + p.owner + '/' + p.project + '.git' },
label: 'https.git'
},
{
host: function (p) { return 'https://' + p.domain + '/' + p.owner + '/' + p.project + '#' + p.branch },
label: 'https#branch',
hasBranch: true
},
{
host: function (p) { return 'https://' + p.domain + '/' + p.owner + '/' + p.project + '.git#' + p.branch },
label: 'https.git#branch',
hasBranch: true
},
{
host: function (p) { return 'https://' + p.domain + '/' + p.owner + '/' + p.project + '/-/' + 'archive' + '/3.3.2' + '/ws-3.3.2.tar.gz' },
label: 'https.tar',
isUndefined: true
},
{
host: function (p) { return 'https://' + p.domain + '/' + p.owner + '/' + p.project + '/repository/archive.tar.gz?ref=' + p.branch },
label: 'https.tar',
isUndefined: true
},
{
host: function (p) { return 'https://' + p.domain + '/' + p.owner + '/' + p.project + '/repository/archive.tar.gz' },
label: 'https.tar',
isUndefined: true
},
{
host: function (p) { return 'git+https://' + p.domain + '/' + p.owner + '/' + p.project },
label: 'git+https'
},
{
host: function (p) { return 'git+https://' + p.domain + '/' + p.owner + '/' + p.project + '.git' },
label: 'git+https.git'
},
{
host: function (p) { return 'git+https://' + p.domain + '/' + p.owner + '/' + p.project + '#' + p.branch },
label: 'git+https#branch',
hasBranch: true
},
{
host: function (p) { return 'git+https://' + p.domain + '/' + p.owner + '/' + p.project + '.git#' + p.branch },
label: 'git+https.git#branch',
hasBranch: true
},
{
host: function (p) { return 'git@' + p.domain + ':' + p.owner + '/' + p.project },
label: 'ssh'
},
{
host: function (p) { return 'git@' + p.domain + ':' + p.owner + '/' + p.project + '.git' },
label: 'ssh.git'
},
{
host: function (p) { return 'git@' + p.domain + ':' + p.owner + '/' + p.project + '#' + p.branch },
label: 'ssh#branch',
hasBranch: true
},
{
host: function (p) { return 'git@' + p.domain + ':' + p.owner + '/' + p.project + '.git#' + p.branch },
label: 'ssh.git#branch',
hasBranch: true
},
{
host: function (p) { return 'git+ssh://git@' + p.domain + '/' + p.owner + '/' + p.project },
label: 'ssh-url'
},
{
host: function (p) { return 'git+ssh://git@' + p.domain + '/' + p.owner + '/' + p.project + '.git' },
label: 'ssh-url.git'
},
{
host: function (p) { return 'git+ssh://git@' + p.domain + '/' + p.owner + '/' + p.project + '#' + p.branch },
label: 'ssh-url#branch',
hasBranch: true
},
{
host: function (p) { return 'git+ssh://git@' + p.domain + '/' + p.owner + '/' + p.project + '.git#' + p.branch },
label: 'ssh-url.git#branch',
hasBranch: true
},
{
host: function (p) { return p.shortname + ':' + p.owner + '/' + p.project },
label: 'shortcut'
},
{
host: function (p) { return p.shortname + ':' + p.owner + '/' + p.project + '.git' },
label: 'shortcut.git'
},
{
host: function (p) { return p.shortname + ':' + p.owner + '/' + p.project + '#' + p.branch },
label: 'shortcut#branch',
hasBranch: true
},
{
host: function (p) { return p.shortname + ':' + p.owner + '/' + p.project + '.git#' + p.branch },
label: 'shortcut.git#branch',
hasBranch: true
}
]
99 changes: 99 additions & 0 deletions test/fixtures/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
'use strcit'

module.exports = [
{
host: function (p) { return 'https://' + p.domain + '/' + p.owner + '/' + p.project },
label: 'https'
},
{
host: function (p) { return 'https://' + p.domain + '/' + p.owner + '/' + p.project + '.git' },
label: 'https.git'
},
{
host: function (p) { return 'https://' + p.domain + '/' + p.owner + '/' + p.project + '#' + p.branch },
label: 'https#branch',
hasBranch: true
},
{
host: function (p) { return 'https://' + p.domain + '/' + p.owner + '/' + p.project + '.git#' + p.branch },
label: 'https.git#branch',
hasBranch: true
},
{
host: function (p) { return 'https://' + p.domain + '/' + p.owner + '/' + p.project + '/-/' + 'archive' + '/3.3.2' + '/ws-3.3.2.tar.gz' },
label: 'https.tar',
isUndefined: true
},
{
host: function (p) { return 'git+https://' + p.domain + '/' + p.owner + '/' + p.project },
label: 'git+https'
},
{
host: function (p) { return 'git+https://' + p.domain + '/' + p.owner + '/' + p.project + '.git' },
label: 'git+https.git'
},
{
host: function (p) { return 'git+https://' + p.domain + '/' + p.owner + '/' + p.project + '#' + p.branch },
label: 'git+https#branch',
hasBranch: true
},
{
host: function (p) { return 'git+https://' + p.domain + '/' + p.owner + '/' + p.project + '.git#' + p.branch },
label: 'git+https.git#branch',
hasBranch: true
},
{
host: function (p) { return 'git@' + p.domain + ':' + p.owner + '/' + p.project },
label: 'ssh'
},
{
host: function (p) { return 'git@' + p.domain + ':' + p.owner + '/' + p.project + '.git' },
label: 'ssh.git'
},
{
host: function (p) { return 'git@' + p.domain + ':' + p.owner + '/' + p.project + '#' + p.branch },
label: 'ssh#branch',
hasBranch: true
},
{
host: function (p) { return 'git@' + p.domain + ':' + p.owner + '/' + p.project + '.git#' + p.branch },
label: 'ssh.git#branch',
hasBranch: true
},
{
host: function (p) { return 'git+ssh://git@' + p.domain + '/' + p.owner + '/' + p.project },
label: 'ssh-url'
},
{
host: function (p) { return 'git+ssh://git@' + p.domain + '/' + p.owner + '/' + p.project + '.git' },
label: 'ssh-url.git'
},
{
host: function (p) { return 'git+ssh://git@' + p.domain + '/' + p.owner + '/' + p.project + '#' + p.branch },
label: 'ssh-url#branch',
hasBranch: true
},
{
host: function (p) { return 'git+ssh://git@' + p.domain + '/' + p.owner + '/' + p.project + '.git#' + p.branch },
label: 'ssh-url.git#branch',
hasBranch: true
},
{
host: function (p) { return p.shortname + ':' + p.owner + '/' + p.project },
label: 'shortcut'
},
{
host: function (p) { return p.shortname + ':' + p.owner + '/' + p.project + '.git' },
label: 'shortcut.git'
},
{
host: function (p) { return p.shortname + ':' + p.owner + '/' + p.project + '#' + p.branch },
label: 'shortcut#branch',
hasBranch: true
},
{
host: function (p) { return p.shortname + ':' + p.owner + '/' + p.project + '.git#' + p.branch },
label: 'shortcut.git#branch',
hasBranch: true
}
]
290 changes: 254 additions & 36 deletions test/gist.js
Original file line number Diff line number Diff line change
@@ -2,49 +2,267 @@
var HostedGit = require('../index')
var test = require('tap').test

test('fromUrl(gist url)', function (t) {
var proj = new Array(33).join('2')
function verify (host, label, branch) {
var showLabel = function (label, fn) { return label + ' -> ' + fn }

var testFixtures = function (t, params, fixtures) {
for (var i = 0; i < fixtures.length; ++i) {
var fixture = fixtures[i]
var host = fixture.host(params)
var hostinfo = HostedGit.fromUrl(host)
var hash = branch ? '#' + branch : ''
t.ok(hostinfo, label)
if (!hostinfo) return
t.is(hostinfo.https(), 'git+https://gist.github.com/' + proj + '.git' + hash, label + ' -> https')
t.is(hostinfo.git(), 'git://gist.github.com/' + proj + '.git' + hash, label + ' -> git')
t.is(hostinfo.browse(), 'https://gist.github.com/' + proj + (branch ? '/' + branch : ''), label + ' -> browse')
t.is(hostinfo.browse('C'), 'https://gist.github.com/' + proj + (branch ? '/' + branch : '') + '#file-c', label + ' -> browse(path)')
t.is(hostinfo.browse('C/D'), 'https://gist.github.com/' + proj + (branch ? '/' + branch : '') + '#file-cd', label + ' -> browse(path)')
t.is(hostinfo.browse('C', 'A'), 'https://gist.github.com/' + proj + (branch ? '/' + branch : '') + '#file-c', label + ' -> browse(path, fragment)')
t.is(hostinfo.browse('C/D', 'A'), 'https://gist.github.com/' + proj + (branch ? '/' + branch : '') + '#file-cd', label + ' -> browse(path)')
t.is(hostinfo.bugs(), 'https://gist.github.com/' + proj, label + ' -> bugs')
t.is(hostinfo.docs(), 'https://gist.github.com/' + proj + (branch ? '/' + branch : ''), label + ' -> docs')
t.is(hostinfo.ssh(), 'git@gist.github.com:/' + proj + '.git' + hash, label + ' -> ssh')
t.is(hostinfo.sshurl(), 'git+ssh://git@gist.github.com/' + proj + '.git' + hash, label + ' -> sshurl')
t.is(hostinfo.shortcut(), 'gist:' + proj + hash, label + ' -> shortcut')
var expectedHash = params.project

// INFO: from Url should return `undefined` from fixture input
if (fixture.isUndefined) {
t.test('input results in undefined', function (tt) {
tt.is(hostinfo, undefined)
tt.end()
})
break
}

t.test('hostinfo.https', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url + '#' + params.branch
: url
}
tt.is(
hostinfo.https(),
expected(`git+https://gist.github.com/${expectedHash}.git`, fixture.hasBranch),
showLabel(fixture.label, 'https')
)
tt.is(
hostinfo.https({ noCommittish: true }),
// INFO: not using `expected` because with `{noCommittish: true}` the output is always the same
`git+https://gist.github.com/${expectedHash}.git`,
showLabel(fixture.label, 'https({ noCommittish: true })')
)
tt.is(
hostinfo.https({ noGitPlus: true }),
expected(`https://gist.github.com/${expectedHash}.git`, fixture.hasBranch),
showLabel(fixture.label, 'https({ noGitPlus: true })')
)
tt.end()
})
t.test('hostinfo.git', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url + '#' + params.branch
: url
}
tt.is(
hostinfo.git(),
expected(`git://gist.github.com/${expectedHash}.git`, fixture.hasBranch),
showLabel(fixture.label, 'git')
)
tt.is(
hostinfo.git({ noCommittish: true }),
// INFO: not using `expected` because with `{noCommittish: true}` the output is always the same
`git://gist.github.com/${expectedHash}.git`,
showLabel(fixture.label, 'git({ noCommittish: true })')
)
tt.is(
hostinfo.git({ noGitPlus: true }),
expected(`git://gist.github.com/${expectedHash}.git`, fixture.hasBranch),
showLabel(fixture.label, 'git({ noGitPlus: true })')
)
tt.end()
})
t.test('hostinfo.browse', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url + '/' + params.branch
: url
}
tt.is(
hostinfo.browse(),
expected(`https://gist.github.com/${expectedHash}`, fixture.hasBranch),
showLabel(fixture.label, 'browse')
)
tt.is(
hostinfo.browse('C'),
expected(`https://gist.github.com/${expectedHash}`, fixture.hasBranch) + '#file-c',
showLabel(fixture.label, "browse('C')")
)
tt.is(
hostinfo.browse('C/D'),
expected(`https://gist.github.com/${expectedHash}`, fixture.hasBranch) + '#file-cd',
showLabel(fixture.label, "browse('C/D')")
)
tt.is(
hostinfo.browse('C', 'A'),
expected(`https://gist.github.com/${expectedHash}`, fixture.hasBranch) + '#file-c',
showLabel(fixture.label, "browse('C', 'A')")
)
tt.is(
hostinfo.browse('C/D', 'A'),
expected(`https://gist.github.com/${expectedHash}`, fixture.hasBranch) + '#file-cd',
showLabel(fixture.label, "browse('C/D', 'A')")
)
tt.end()
})
t.test('hostinfo.bugs', function (tt) {
tt.is(
hostinfo.bugs(),
`https://gist.github.com/${expectedHash}`,
showLabel(fixture.label, 'bugs')
)
tt.end()
})
t.test('hostinfo.docs', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url + '/' + params.branch
: url
}
tt.is(
hostinfo.docs(),
expected(`https://gist.github.com/${expectedHash}`, fixture.hasBranch),
showLabel(fixture.label, 'docs')
)
tt.end()
})
t.test('hostinfo.ssh', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url + '#' + params.branch
: url
}
tt.is(
hostinfo.ssh(),
expected(`git@gist.github.com:/${expectedHash}.git`, fixture.hasBranch),
showLabel(fixture.label, 'ssh')
)
tt.end()
})
t.test('hostinfo.sshurl', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url + '#' + params.branch
: url
}
tt.is(
hostinfo.sshurl(),
expected(`git+ssh://git@gist.github.com/${expectedHash}.git`, fixture.hasBranch),
showLabel(fixture.label, 'sshurl')
)
tt.end()
})
t.test('hostinfo.shortcut', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url + '#' + params.branch
: url
}
tt.is(
hostinfo.shortcut(),
expected(`gist:${expectedHash}`, fixture.hasBranch),
showLabel(fixture.label, 'shortcut')
)
tt.end()
})
if (hostinfo.user) {
t.is(hostinfo.file(''), 'https://gist.githubusercontent.com/111/' + proj + '/raw/' + (branch ? branch + '/' : ''), label + ' -> file')
t.is(hostinfo.file('C'), 'https://gist.githubusercontent.com/111/' + proj + '/raw/' + (branch ? branch + '/' : '') + 'C', label + ' -> file')
t.is(hostinfo.file('C/D'), 'https://gist.githubusercontent.com/111/' + proj + '/raw/' + (branch ? branch + '/' : '') + 'C/D', label + ' -> file')
t.is(hostinfo.tarball(), 'https://codeload.github.com/gist/' + proj + '/tar.gz/' + (branch || 'master'), label + ' -> tarball')
t.is(hostinfo.tarball({ noCommittish: true }), 'https://codeload.github.com/gist/' + proj + '/tar.gz/' + (branch || 'master'), label + ' -> tarball')
t.test('hostinfo.file', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url + params.branch + '/'
: url
}
tt.is(
hostinfo.file(),
expected(`https://gist.githubusercontent.com/some-owner/${expectedHash}/raw/`, fixture.hasBranch),
showLabel(fixture.label, 'file')
)
tt.is(
hostinfo.file(''),
expected(`https://gist.githubusercontent.com/some-owner/${expectedHash}/raw/`, fixture.hasBranch),
showLabel(fixture.label, "file('')")
)
tt.is(
hostinfo.file('C'),
expected(`https://gist.githubusercontent.com/some-owner/${expectedHash}/raw/`, fixture.hasBranch) + 'C',
showLabel(fixture.label, "file('C')")
)
tt.is(
hostinfo.file('C/D'),
expected(`https://gist.githubusercontent.com/some-owner/${expectedHash}/raw/`, fixture.hasBranch) + 'C/D',
showLabel(fixture.label, "file('C/D')")
)
tt.is(
hostinfo.file('C', 'A'),
expected(`https://gist.githubusercontent.com/some-owner/${expectedHash}/raw/`, fixture.hasBranch) + 'C',
showLabel(fixture.label, "file('C', 'A')")
)
tt.end()
})
t.test('hostinfo.tarball', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url.replace(/master/gi, params.branch)
: url
}
tt.is(
hostinfo.tarball(),
expected(`https://codeload.github.com/gist/${expectedHash}/tar.gz/master`, fixture.hasBranch),
showLabel(fixture.label, 'tarball')
)
tt.is(
hostinfo.tarball({ noCommittish: true }),
expected(`https://codeload.github.com/gist/${expectedHash}/tar.gz/master`, fixture.hasBranch),
showLabel(fixture.label, 'tarball({ noCommittish: true })')
)
tt.end()
})
}
}

verify('git@gist.github.com:' + proj + '.git', 'git@')
var hostinfo = HostedGit.fromUrl('git@gist.github.com:/c2b12db30a49324325a3781302668408.git')
if (t.ok(hostinfo, 'git@hex')) {
t.is(hostinfo.https(), 'git+https://gist.github.com/c2b12db30a49324325a3781302668408.git', 'git@hex -> https')
t.test('hostinfo.toString', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url + '#' + params.branch
: url
}
tt.is(
hostinfo.toString(),
expected(`git+https://gist.github.com/${expectedHash}.git`, fixture.hasBranch),
showLabel(fixture.label, 'toString')
)
tt.end()
})
}
verify('git@gist.github.com:/' + proj + '.git', 'git@/')
verify('git://gist.github.com/' + proj, 'git')
verify('git://gist.github.com/' + proj + '.git', 'git.git')
verify('git://gist.github.com/' + proj + '#branch', 'git#branch', 'branch')
verify('git://gist.github.com/' + proj + '.git#branch', 'git.git#branch', 'branch')
}

require('./lib/standard-tests')(verify, 'gist.github.com', 'gist', proj)
test('fromUrl(gist url)', function (t) {
var fixtures = require('./fixtures')
var gistFixtures = require('./fixtures/gist')
var collectedFixtures = [].concat(fixtures, gistFixtures)

t.test('main fixtures', function (tt) {
var params = {
domain: 'gist.github.com',
shortname: 'github',
label: 'github',
owner: 'some-owner',
project: new Array(17).join('a2'),
branch: 'feature-branch'
}

testFixtures(tt, params, collectedFixtures)
tt.end()
})

t.test('legacy gist hash length', function (tt) {
var params = {
domain: 'gist.github.com',
shortname: 'github',
label: 'github',
owner: 'some-owner',
project: '3135914',
branch: 'feature-branch'
}

verify(HostedGit.fromUrl('gist:111/' + proj).toString(), 'round-tripped shortcut')
verify('gist:' + proj, 'shortened shortcut')
testFixtures(tt, params, collectedFixtures)
tt.end()
})

t.end()
})
366 changes: 322 additions & 44 deletions test/github.js

Large diffs are not rendered by default.

306 changes: 268 additions & 38 deletions test/gitlab.js
Original file line number Diff line number Diff line change
@@ -2,47 +2,277 @@
var HostedGit = require('../index')
var test = require('tap').test

test('fromUrl(gitlab url)', function (t) {
function verify (host, label, branch) {
var showLabel = function (label, fn) { return label + ' -> ' + fn }

var testFixtures = function (t, params, fixtures) {
for (var i = 0; i < fixtures.length; ++i) {
var fixture = fixtures[i]

var host = fixture.host(params)
var hostinfo = HostedGit.fromUrl(host)
var hash = branch ? '#' + branch : ''
t.ok(hostinfo, label)
if (!hostinfo) return
t.is(hostinfo.https(), 'git+https://gitlab.com/111/222.git' + hash, label + ' -> https')
t.is(hostinfo.browse(), 'https://gitlab.com/111/222' + (branch ? '/tree/' + branch : ''), label + ' -> browse')
t.is(hostinfo.browse(''), 'https://gitlab.com/111/222/tree/' + (branch || 'master') + '/', label + ' -> browse(path)')
t.is(hostinfo.browse('C'), 'https://gitlab.com/111/222/tree/' + (branch || 'master') + '/C', label + ' -> browse(path)')
t.is(hostinfo.browse('C/D'), 'https://gitlab.com/111/222/tree/' + (branch || 'master') + '/C/D', label + ' -> browse(path)')
t.is(hostinfo.browse('C', 'A'), 'https://gitlab.com/111/222/tree/' + (branch || 'master') + '/C#a', label + ' -> browse(path, fragment)')
t.is(hostinfo.browse('C/D', 'A'), 'https://gitlab.com/111/222/tree/' + (branch || 'master') + '/C/D#a', label + ' -> browse(path, fragment)')
t.is(hostinfo.docs(), 'https://gitlab.com/111/222' + (branch ? '/tree/' + branch : '') + '#readme', label + ' -> docs')
t.is(hostinfo.ssh(), 'git@gitlab.com:111/222.git' + hash, label + ' -> ssh')
t.is(hostinfo.sshurl(), 'git+ssh://git@gitlab.com/111/222.git' + hash, label + ' -> sshurl')
t.is(hostinfo.shortcut(), 'gitlab:111/222' + hash, label + ' -> shortcut')
t.is(hostinfo.file(''), 'https://gitlab.com/111/222/raw/' + (branch || 'master') + '/', label + ' -> file')
t.is(hostinfo.file('C'), 'https://gitlab.com/111/222/raw/' + (branch || 'master') + '/C', label + ' -> file')
t.is(hostinfo.file('C/D'), 'https://gitlab.com/111/222/raw/' + (branch || 'master') + '/C/D', label + ' -> file')
t.is(hostinfo.tarball(), 'https://gitlab.com/111/222/repository/archive.tar.gz?ref=' + (branch || 'master'), label + ' -> tarball')
t.is(hostinfo.tarball({ noCommittish: true }), 'https://gitlab.com/111/222/repository/archive.tar.gz?ref=' + (branch || 'master'), label + ' -> tarball')

// INFO: fromUrl should return `undefined` from fixture input
if (fixture.isUndefined) {
t.test('input results in undefined', function (tt) {
tt.is(hostinfo, undefined)
tt.end()
})
continue
}

t.test('hostinfo.https', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url + '#' + params.branch
: url
}
tt.is(
hostinfo.https(),
expected('git+https://gitlab.com/some-owner/some-repo.git', fixture.hasBranch, fixture.hasGroup),
showLabel(fixture.label, 'https')
)
tt.is(
hostinfo.https({ noCommittish: true }),
// INFO: not using `expected` because with `{noCommittish: true}` the output is always the same
'git+https://gitlab.com/some-owner/some-repo.git',
showLabel(fixture.label, 'https({ noCommittish: true })')
)
tt.is(
hostinfo.https({ noGitPlus: true }),
expected('https://gitlab.com/some-owner/some-repo.git', fixture.hasBranch),
showLabel(fixture.label, 'https({ noGitPlus: true })')
)
tt.end()
})
t.test('hostinfo.browse', function (tt) {
var expected = function (url, hasBranch) {
if (hasBranch) {
if (url.indexOf('master') === -1) {
return url + '/tree/' + params.branch
} else {
return url.replace(/master/gi, params.branch)
}
}
return url
}
tt.is(
hostinfo.browse(),
expected('https://gitlab.com/some-owner/some-repo', fixture.hasBranch),
showLabel(fixture.label, 'browse')
)
tt.is(
hostinfo.browse(''),
expected('https://gitlab.com/some-owner/some-repo/tree/master/', fixture.hasBranch),
showLabel(fixture.label, "browse('')")
)
tt.is(
hostinfo.browse('C'),
expected('https://gitlab.com/some-owner/some-repo/tree/master/C', fixture.hasBranch),
showLabel(fixture.label, "browse('C')")
)
tt.is(
hostinfo.browse('C/D'),
expected('https://gitlab.com/some-owner/some-repo/tree/master/C/D', fixture.hasBranch),
showLabel(fixture.label, "browse('C/D')")
)
tt.is(
hostinfo.browse('C', 'A'),
expected('https://gitlab.com/some-owner/some-repo/tree/master/C#a', fixture.hasBranch),
showLabel(fixture.label, "browse('C', 'A')")
)
tt.is(
hostinfo.browse('C/D', 'A'),
expected('https://gitlab.com/some-owner/some-repo/tree/master/C/D#a', fixture.hasBranch),
showLabel(fixture.label, "browse('C/D', 'A')")
)
tt.end()
})
t.test('hostinfo.docs', function (tt) {
var expected = function (url, hasBranch) {
if (hasBranch) {
var splitUrl = url.split('#')
return splitUrl[0] + '/tree/' + params.branch + '#' + splitUrl[1]
}
return url
}
tt.is(
hostinfo.docs(),
expected('https://gitlab.com/some-owner/some-repo#readme', fixture.hasBranch),
showLabel(fixture.label, 'docs')
)
tt.is(
hostinfo.docs({ noCommittish: true }),
// INFO: not using `expected` because with `{noCommittish: true}` the output is always the same
'https://gitlab.com/some-owner/some-repo#readme',
showLabel(fixture.label, 'docs({ noCommittish: true })')
)
tt.is(
hostinfo.docs({ noGitPlus: true }),
expected('https://gitlab.com/some-owner/some-repo#readme', fixture.hasBranch),
showLabel(fixture.label, 'docs({ noGitPlus: true })')
)
tt.end()
})
t.test('hostinfo.ssh', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url + '#' + params.branch
: url
}
tt.is(
hostinfo.ssh(),
expected('git@gitlab.com:some-owner/some-repo.git', fixture.hasBranch),
showLabel(fixture.label, 'ssh')
)
tt.end()
})
t.test('hostinfo.sshurl', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url + '#' + params.branch
: url
}
tt.is(
hostinfo.sshurl(),
expected('git+ssh://git@gitlab.com/some-owner/some-repo.git', fixture.hasBranch),
showLabel(fixture.label, 'sshurl')
)
tt.end()
})
t.test('hostinfo.shortcut', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url + '#' + params.branch
: url
}
tt.is(
hostinfo.shortcut(),
expected('gitlab:some-owner/some-repo', fixture.hasBranch),
showLabel(fixture.label, 'shortcut')
)
tt.end()
})
t.test('hostinfo.file', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url.replace(/master/gi, params.branch)
: url
}
tt.is(
hostinfo.file(),
expected('https://gitlab.com/some-owner/some-repo/raw/master/', fixture.hasBranch),
showLabel(fixture.label, 'file')
)
tt.is(
hostinfo.file('C'),
expected('https://gitlab.com/some-owner/some-repo/raw/master/C', fixture.hasBranch),
showLabel(fixture.label, "file('C')")
)
tt.is(
hostinfo.file('C/D'),
expected('https://gitlab.com/some-owner/some-repo/raw/master/C/D', fixture.hasBranch),
showLabel(fixture.label, "file('C/D')")
)
tt.end()
})
t.test('hostinfo.tarball', function (tt) {
var expected = function (url, hasBranch) {
return (hasBranch)
? url.replace(/master/gi, params.branch)
: url
}
tt.is(
hostinfo.tarball(),
expected('https://gitlab.com/some-owner/some-repo/repository/archive.tar.gz?ref=master', fixture.hasBranch),
showLabel(fixture.label, 'tarball')
)
tt.is(
hostinfo.tarball({ noCommittish: true }),
expected('https://gitlab.com/some-owner/some-repo/repository/archive.tar.gz?ref=master', fixture.hasBranch),
showLabel(fixture.label, 'tarball({ noCommittish: true })')
)
tt.end()
})
}
}
test('fromUrl(gitlab url)', function (t) {
var fixtures = require('./fixtures')
var gitlabFixtures = require('./fixtures/gitlab')
var collectedFixtures = [].concat(fixtures, gitlabFixtures)

t.test('domain: gitlab.com', function (tt) {
var params = {
domain: 'gitlab.com',
shortname: 'gitlab',
label: 'gitlab',
owner: 'some-owner',
project: 'some-repo',
branch: 'feature-branch'
}
testFixtures(tt, params, collectedFixtures)
tt.end()
})

t.test('domain: www.gitlab.com', function (tt) {
var params = {
domain: 'www.gitlab.com',
shortname: 'gitlab',
label: 'gitlab',
owner: 'some-owner',
project: 'some-repo',
branch: 'feature-branch'
}
testFixtures(tt, params, collectedFixtures)
tt.end()
})

t.test('subgroups', function (tt) {
var groupFixtures = require('./fixtures/gitlab-subgroups')

var params = {
domain: 'gitlab.com',
shortname: 'gitlab',
label: 'gitlab',
owner: 'some-owner',
project: 'some-repo',
group: 'group/sub-group1',
branch: 'feature-branch'
}
for (var g = 0; g < groupFixtures.length; ++g) {
var fixture = groupFixtures[g]
var host = fixture.host(params)
var hostinfo = HostedGit.fromUrl(host)

var expected = function (url, hasBranch) {
return (hasBranch)
? url + '#' + params.branch
: url
}
tt.is(
hostinfo.https(),
expected('git+https://gitlab.com/some-owner/group/sub-group1/some-repo.git', fixture.hasBranch),
showLabel(fixture.label, 'https')
)
tt.is(
hostinfo.https({ noCommittish: true }),
// INFO: not using `expected` because with `{noCommittish: true}` the output is always the same
'git+https://gitlab.com/some-owner/group/sub-group1/some-repo.git',
showLabel(fixture.label, 'https({ noCommittish: true })')
)
tt.is(
hostinfo.https({ noGitPlus: true }),
expected('https://gitlab.com/some-owner/group/sub-group1/some-repo.git', fixture.hasBranch),
showLabel(fixture.label, 'https({ noGitPlus: true })')
)
}

require('./lib/standard-tests')(verify, 'gitlab.com', 'gitlab')
require('./lib/standard-tests')(verify, 'www.gitlab.com', 'gitlab')

const subsShort = HostedGit.fromUrl('gitlab:adpt/starters/hello-node')
const subsFull = HostedGit.fromUrl('git+https://gitlab.com/adpt/starters/hello-node.git')
t.ok(subsShort)
t.equal(subsShort.https(), 'git+https://gitlab.com/adpt/starters/hello-node.git')
t.equal(subsShort.ssh(), 'git@gitlab.com:adpt/starters/hello-node.git')
t.ok(subsFull)
t.equal(subsFull.https(), 'git+https://gitlab.com/adpt/starters/hello-node.git')
t.equal(subsFull.ssh(), 'git@gitlab.com:adpt/starters/hello-node.git')

t.is(
HostedGit.fromUrl('gitlab:group/sub group1/subgroup2/repo').https(),
'git+https://gitlab.com/group/sub%20group1/subgroup2/repo.git',
'subgroups are delimited with slashes and url encoded (shortcut -> https)'
)
tt.is(
HostedGit.fromUrl('gitlab:group/sub group1/subgroup2/repo').https(),
'git+https://gitlab.com/group/sub%20group1/subgroup2/repo.git',
'subgroups are delimited with slashes and url encoded (shortcut -> https)'
)
tt.end()
})

t.end()
})
44 changes: 0 additions & 44 deletions test/https-with-inline-auth.js

This file was deleted.

28 changes: 0 additions & 28 deletions test/lib/standard-tests.js

This file was deleted.

29 changes: 29 additions & 0 deletions test/localhost.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// An example of a custom setup, useful when testing modules like pacote,
// which do various things with these git shortcuts.
const t = require('tap')
const ghi = require('../git-host-info.js')
ghi.localhost = {
protocols: [ 'git' ],
domain: 'localhost:12345',
gittemplate: 'git://{domain}/{user}{#committish}',
treepath: 'not-implemented',
tarballtemplate: 'http://localhost:18000/repo-HEAD.tgz',
shortcuttemplate: '{type}:{user}/x{#committish}',
pathtemplate: '/{user}{#committish}',
pathmatch: /^\/(repo|submodule-repo)/,
hashformat: h => h,
protocols_re: /^(git):$/
}

const gh = require('../')
const f = gh.fromUrl('git://localhost:12345/repo')

t.ok(f, 'got a localhost "hosted" repo')
t.equal(f.git(), 'git://localhost:12345/repo')
t.equal(f.tarball(), 'http://localhost:18000/repo-HEAD.tgz')
t.equal(f.shortcut(), 'localhost:repo/x')

const g = gh.fromUrl('localhost:repo/x')
t.ok(g, 'got a localhost repo from shortcut')
t.equal(g.git(), f.git(), 'resolves to the same repo')
t.equal(g.tarball(), f.tarball(), 'resolves to same tarball')