Initial commit
[yaffs-website] / node_modules / hosted-git-info / index.js
1 'use strict'
2 var url = require('url')
3 var gitHosts = require('./git-host-info.js')
4 var GitHost = module.exports = require('./git-host.js')
5
6 var protocolToRepresentationMap = {
7   'git+ssh': 'sshurl',
8   'git+https': 'https',
9   'ssh': 'sshurl',
10   'git': 'git'
11 }
12
13 function protocolToRepresentation (protocol) {
14   if (protocol.substr(-1) === ':') protocol = protocol.slice(0, -1)
15   return protocolToRepresentationMap[protocol] || protocol
16 }
17
18 var authProtocols = {
19   'git:': true,
20   'https:': true,
21   'git+https:': true,
22   'http:': true,
23   'git+http:': true
24 }
25
26 module.exports.fromUrl = function (giturl) {
27   if (giturl == null || giturl === '') return
28   var url = fixupUnqualifiedGist(
29     isGitHubShorthand(giturl) ? 'github:' + giturl : giturl
30   )
31   var parsed = parseGitUrl(url)
32   var matches = Object.keys(gitHosts).map(function (gitHostName) {
33     var gitHostInfo = gitHosts[gitHostName]
34     var auth = null
35     if (parsed.auth && authProtocols[parsed.protocol]) {
36       auth = decodeURIComponent(parsed.auth)
37     }
38     var committish = parsed.hash ? decodeURIComponent(parsed.hash.substr(1)) : null
39     var user = null
40     var project = null
41     var defaultRepresentation = null
42     if (parsed.protocol === gitHostName + ':') {
43       user = decodeURIComponent(parsed.host)
44       project = parsed.path && decodeURIComponent(parsed.path.replace(/^[/](.*?)(?:[.]git)?$/, '$1'))
45       defaultRepresentation = 'shortcut'
46     } else {
47       if (parsed.host !== gitHostInfo.domain) return
48       if (!gitHostInfo.protocols_re.test(parsed.protocol)) return
49       var pathmatch = gitHostInfo.pathmatch
50       var matched = parsed.path.match(pathmatch)
51       if (!matched) return
52       if (matched[1] != null) user = decodeURIComponent(matched[1])
53       if (matched[2] != null) project = decodeURIComponent(matched[2])
54       defaultRepresentation = protocolToRepresentation(parsed.protocol)
55     }
56     return new GitHost(gitHostName, user, auth, project, committish, defaultRepresentation)
57   }).filter(function (gitHostInfo) { return gitHostInfo })
58   if (matches.length !== 1) return
59   return matches[0]
60 }
61
62 function isGitHubShorthand (arg) {
63   // Note: This does not fully test the git ref format.
64   // See https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html
65   //
66   // The only way to do this properly would be to shell out to
67   // git-check-ref-format, and as this is a fast sync function,
68   // we don't want to do that.  Just let git fail if it turns
69   // out that the commit-ish is invalid.
70   // GH usernames cannot start with . or -
71   return /^[^:@%/\s.-][^:@%/\s]*[/][^:@\s/%]+(?:#.*)?$/.test(arg)
72 }
73
74 function fixupUnqualifiedGist (giturl) {
75   // necessary for round-tripping gists
76   var parsed = url.parse(giturl)
77   if (parsed.protocol === 'gist:' && parsed.host && !parsed.path) {
78     return parsed.protocol + '/' + parsed.host
79   } else {
80     return giturl
81   }
82 }
83
84 function parseGitUrl (giturl) {
85   if (typeof giturl !== 'string') giturl = '' + giturl
86   var matched = giturl.match(/^([^@]+)@([^:]+):[/]?((?:[^/]+[/])?[^/]+?)(?:[.]git)?(#.*)?$/)
87   if (!matched) return url.parse(giturl)
88   return {
89     protocol: 'git+ssh:',
90     slashes: true,
91     auth: matched[1],
92     host: matched[2],
93     port: null,
94     hostname: matched[2],
95     hash: matched[4],
96     search: null,
97     query: null,
98     pathname: '/' + matched[3],
99     path: '/' + matched[3],
100     href: 'git+ssh://' + matched[1] + '@' + matched[2] +
101           '/' + matched[3] + (matched[4] || '')
102   }
103 }