File Explorer

/var/lang/lib/node_modules/npm/node_modules/hosted-git-info/lib

This explorer reads the filesystem of the server it runs on, so /workspace/user isn't present here. Browsing and the terminal still work against this server's own disk from /.

0 dirs
4 files
index.js5.3 KB · 228 lines
'use strict' const { LRUCache } = require('lru-cache')const hosts = require('./hosts.js')const fromUrl = require('./from-url.js')const parseUrl = require('./parse-url.js') const cache = new LRUCache({ max: 1000 }) function unknownHostedUrl (url) {  try {    const {      protocol,      hostname,      pathname,    } = new URL(url)     if (!hostname) {      return null    }     const proto = /(?:git\+)http:$/.test(protocol) ? 'http:' : 'https:'    const path = pathname.replace(/\.git$/, '')    return `${proto}//${hostname}${path}`  } catch {    return null  }} class GitHost {  constructor (type, user, auth, project, committish, defaultRepresentation, opts = {}) {    Object.assign(this, GitHost.#gitHosts[type], {      type,      user,      auth,      project,      committish,      default: defaultRepresentation,      opts,    })  }   static #gitHosts = { byShortcut: {}, byDomain: {} }  static #protocols = {    'git+ssh:': { name: 'sshurl' },    'ssh:': { name: 'sshurl' },    'git+https:': { name: 'https', auth: true },    'git:': { auth: true },    'http:': { auth: true },    'https:': { auth: true },    'git+http:': { auth: true },  }   static addHost (name, host) {    GitHost.#gitHosts[name] = host    GitHost.#gitHosts.byDomain[host.domain] = name    GitHost.#gitHosts.byShortcut[`${name}:`] = name    GitHost.#protocols[`${name}:`] = { name }  }   static fromUrl (giturl, opts) {    if (typeof giturl !== 'string') {      return    }     const key = giturl + JSON.stringify(opts || {})     if (!cache.has(key)) {      const hostArgs = fromUrl(giturl, opts, {        gitHosts: GitHost.#gitHosts,        protocols: GitHost.#protocols,      })      cache.set(key, hostArgs ? new GitHost(...hostArgs) : undefined)    }     return cache.get(key)  }   static fromManifest (manifest, opts = {}) {    if (!manifest || typeof manifest !== 'object') {      return    }     const r = manifest.repository    // TODO: look into also checking the `bugs`/`homepage` URLs     const rurl = r && (      typeof r === 'string'        ? r        : typeof r === 'object' && typeof r.url === 'string'          ? r.url          : null    )     if (!rurl) {      throw new Error('no repository')    }     const info = (rurl && GitHost.fromUrl(rurl.replace(/^git\+/, ''), opts)) || null    if (info) {      return info    }    const unk = unknownHostedUrl(rurl)    return GitHost.fromUrl(unk, opts) || unk  }   static parseUrl (url) {    return parseUrl(url)  }   #fill (template, opts) {    if (typeof template !== 'function') {      return null    }     const options = { ...this, ...this.opts, ...opts }     // the path should always be set so we don't end up with 'undefined' in urls    if (!options.path) {      options.path = ''    }     // template functions will insert the leading slash themselves    if (options.path.startsWith('/')) {      options.path = options.path.slice(1)    }     if (options.noCommittish) {      options.committish = null    }     const result = template(options)    return options.noGitPlus && result.startsWith('git+') ? result.slice(4) : result  }   hash () {    return this.committish ? `#${this.committish}` : ''  }   ssh (opts) {    return this.#fill(this.sshtemplate, opts)  }   sshurl (opts) {    return this.#fill(this.sshurltemplate, opts)  }   browse (path, ...args) {    // not a string, treat path as opts    if (typeof path !== 'string') {      return this.#fill(this.browsetemplate, path)    }     if (typeof args[0] !== 'string') {      return this.#fill(this.browsetreetemplate, { ...args[0], path })    }     return this.#fill(this.browsetreetemplate, { ...args[1], fragment: args[0], path })  }   // If the path is known to be a file, then browseFile should be used. For some hosts  // the url is the same as browse, but for others like GitHub a file can use both `/tree/`  // and `/blob/` in the path. When using a default committish of `HEAD` then the `/tree/`  // path will redirect to a specific commit. Using the `/blob/` path avoids this and  // does not redirect to a different commit.  browseFile (path, ...args) {    if (typeof args[0] !== 'string') {      return this.#fill(this.browseblobtemplate, { ...args[0], path })    }     return this.#fill(this.browseblobtemplate, { ...args[1], fragment: args[0], path })  }   docs (opts) {    return this.#fill(this.docstemplate, opts)  }   bugs (opts) {    return this.#fill(this.bugstemplate, opts)  }   https (opts) {    return this.#fill(this.httpstemplate, opts)  }   git (opts) {    return this.#fill(this.gittemplate, opts)  }   shortcut (opts) {    return this.#fill(this.shortcuttemplate, opts)  }   path (opts) {    return this.#fill(this.pathtemplate, opts)  }   tarball (opts) {    return this.#fill(this.tarballtemplate, { ...opts, noCommittish: false })  }   file (path, opts) {    return this.#fill(this.filetemplate, { ...opts, path })  }   edit (path, opts) {    return this.#fill(this.edittemplate, { ...opts, path })  }   getDefaultRepresentation () {    return this.default  }   toString (opts) {    if (this.default && typeof this[this.default] === 'function') {      return this[this.default](opts)    }     return this.sshurl(opts)  }} for (const [name, host] of Object.entries(hosts)) {  GitHost.addHost(name, host)} module.exports = GitHost