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 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 | return /^[^:@%/\s.-][^:@%/\s]*[/][^:@\s/%]+(?:#.*)?$/.test(arg)
|
72 | }
|
73 |
|
74 | function fixupUnqualifiedGist (giturl) {
|
75 |
|
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 | }
|