massive update, probably broken
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / 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   return protocolToRepresentationMap[protocol] || protocol.slice(0, -1)
15 }
16
17 var authProtocols = {
18   'git:': true,
19   'https:': true,
20   'git+https:': true,
21   'http:': true,
22   'git+http:': true
23 }
24
25 var cache = {}
26
27 module.exports.fromUrl = function (giturl, opts) {
28   if (typeof giturl !== 'string') return
29   var key = giturl + JSON.stringify(opts || {})
30
31   if (!(key in cache)) {
32     cache[key] = fromUrl(giturl, opts)
33   }
34
35   return cache[key]
36 }
37
38 function fromUrl (giturl, opts) {
39   if (giturl == null || giturl === '') return
40   var url = fixupUnqualifiedGist(
41     isGitHubShorthand(giturl) ? 'github:' + giturl : giturl
42   )
43   var parsed = parseGitUrl(url)
44   var shortcutMatch = url.match(/^([^:]+):(?:[^@]+@)?(?:([^/]*)\/)?([^#]+)/)
45   var matches = Object.keys(gitHosts).map(function (gitHostName) {
46     try {
47       var gitHostInfo = gitHosts[gitHostName]
48       var auth = null
49       if (parsed.auth && authProtocols[parsed.protocol]) {
50         auth = parsed.auth
51       }
52       var committish = parsed.hash ? decodeURIComponent(parsed.hash.substr(1)) : null
53       var user = null
54       var project = null
55       var defaultRepresentation = null
56       if (shortcutMatch && shortcutMatch[1] === gitHostName) {
57         user = shortcutMatch[2] && decodeURIComponent(shortcutMatch[2])
58         project = decodeURIComponent(shortcutMatch[3].replace(/\.git$/, ''))
59         defaultRepresentation = 'shortcut'
60       } else {
61         if (parsed.host && parsed.host !== gitHostInfo.domain && parsed.host.replace(/^www[.]/, '') !== gitHostInfo.domain) return
62         if (!gitHostInfo.protocols_re.test(parsed.protocol)) return
63         if (!parsed.path) return
64         var pathmatch = gitHostInfo.pathmatch
65         var matched = parsed.path.match(pathmatch)
66         if (!matched) return
67         /* istanbul ignore else */
68         if (matched[1] !== null && matched[1] !== undefined) {
69           user = decodeURIComponent(matched[1].replace(/^:/, ''))
70         }
71         project = decodeURIComponent(matched[2])
72         defaultRepresentation = protocolToRepresentation(parsed.protocol)
73       }
74       return new GitHost(gitHostName, user, auth, project, committish, defaultRepresentation, opts)
75     } catch (ex) {
76       /* istanbul ignore else */
77       if (ex instanceof URIError) {
78       } else throw ex
79     }
80   }).filter(function (gitHostInfo) { return gitHostInfo })
81   if (matches.length !== 1) return
82   return matches[0]
83 }
84
85 function isGitHubShorthand (arg) {
86   // Note: This does not fully test the git ref format.
87   // See https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html
88   //
89   // The only way to do this properly would be to shell out to
90   // git-check-ref-format, and as this is a fast sync function,
91   // we don't want to do that.  Just let git fail if it turns
92   // out that the commit-ish is invalid.
93   // GH usernames cannot start with . or -
94   return /^[^:@%/\s.-][^:@%/\s]*[/][^:@\s/%]+(?:#.*)?$/.test(arg)
95 }
96
97 function fixupUnqualifiedGist (giturl) {
98   // necessary for round-tripping gists
99   var parsed = url.parse(giturl)
100   if (parsed.protocol === 'gist:' && parsed.host && !parsed.path) {
101     return parsed.protocol + '/' + parsed.host
102   } else {
103     return giturl
104   }
105 }
106
107 function parseGitUrl (giturl) {
108   var matched = giturl.match(/^([^@]+)@([^:/]+):[/]?((?:[^/]+[/])?[^/]+?)(?:[.]git)?(#.*)?$/)
109   if (!matched) {
110     var legacy = url.parse(giturl)
111     // If we don't have url.URL, then sorry, this is just not fixable.
112     // This affects Node <= 6.12.
113     if (legacy.auth && typeof url.URL === 'function') {
114       // git urls can be in the form of scp-style/ssh-connect strings, like
115       // git+ssh://user@host.com:some/path, which the legacy url parser
116       // supports, but WhatWG url.URL class does not.  However, the legacy
117       // parser de-urlencodes the username and password, so something like
118       // https://user%3An%40me:p%40ss%3Aword@x.com/ becomes
119       // https://user:n@me:p@ss:word@x.com/ which is all kinds of wrong.
120       // Pull off just the auth and host, so we dont' get the confusing
121       // scp-style URL, then pass that to the WhatWG parser to get the
122       // auth properly escaped.
123       var authmatch = giturl.match(/[^@]+@[^:/]+/)
124       /* istanbul ignore else - this should be impossible */
125       if (authmatch) {
126         var whatwg = new url.URL(authmatch[0])
127         legacy.auth = whatwg.username || ''
128         if (whatwg.password) legacy.auth += ':' + whatwg.password
129       }
130     }
131     return legacy
132   }
133   return {
134     protocol: 'git+ssh:',
135     slashes: true,
136     auth: matched[1],
137     host: matched[2],
138     port: null,
139     hostname: matched[2],
140     hash: matched[4],
141     search: null,
142     query: null,
143     pathname: '/' + matched[3],
144     path: '/' + matched[3],
145     href: 'git+ssh://' + matched[1] + '@' + matched[2] +
146           '/' + matched[3] + (matched[4] || '')
147   }
148 }