UNPKG

bitbucket-repository-provider

Version:
252 lines (212 loc) 6.02 kB
import { Provider } from "repository-provider"; import { BitbucketBranch } from "./bitbucket-branch"; import { BitbucketRepository } from "./bitbucket-repository"; import { BitbucketProject } from "./bitbucket-project"; import request from "request-promise"; export { BitbucketBranch, BitbucketRepository, BitbucketProject }; /** * Provider for bitbucket repositories * @param {Object} config * @param {string} config.url provider scm base * @param {string} config.api provider api base * @param {Object} config.auth authentication * @param {string} config.auth.type * @param {string} config.auth.username * @param {string} config.auth.password */ export class BitbucketProvider extends Provider { /** * Default configuration as given for the cloud privider * @return {Object} */ static get defaultOptions() { return { url: "https://bitbucket.org", api: { "2.0": "https://api.bitbucket.org/2.0" } }; } /** * provide auth info from environment variables * either from * __BITBUCKET_USERNAME__ and * __BITBUCKET_PASSWORD__ * or * __BITBUCKET_TOKEN__ or __BB_TOKEN__ * @param {Object} env as provided by process.env * @return {Object} undefined if no bitbucket related entries where found */ static optionsFromEnvironment(env) { if (env !== undefined) { const token = env.BB_TOKEN || env.BITBUCKET_TOKEN; if (token !== undefined) { return { auth: { type: "token", token } }; } if (env.BITBUCKET_USERNAME && env.BITBUCKET_PASSWORD) { return { auth: { type: "basic", username: env.BITBUCKET_USERNAME, password: env.BITBUCKET_PASSWORD } }; } } return undefined; } /** * @return {Class} BitbucketRepository */ get repositoryClass() { return BitbucketRepository; } /** * @return {Class} BitbucketBranch */ get branchClass() { return BitbucketBranch; } /** * @return {Class} BitbucketProject */ get repositoryGroupClass() { return BitbucketProject; } /** * decode URL for a given repo url * provide version 1.0 for stash hosts names and 2.0 for all other * @param {string} url bitbucket (repo) * @param {Object} options api version * @return {Object} bitbucket api urls by version */ analyseURL(url, options = { version: "2.0" }) { if (url === undefined) { return undefined; } if (url.match(/^(\w+)$/)) { switch (options.part) { case "project": return { project: url }; break; case "repository": return { repository: url }; break; } return { project: url }; } let version = options.version; if (url.startsWith("git@") || url.startsWith("git+ssh@")) { url = url.replace(/^\w+@/, ""); url = url.replace(/:/, "/"); url = "https://" + url; } else if (url.startsWith("git+https:")) { url = url.replace(/^git\+/, ""); } if (!url.match(/^[\w\+]+:/)) { // TODO default url url = "https://bitbucket.org/" + url; } const apiURL = new URL(url); const branch = apiURL.hash.substring(1); apiURL.hash = ""; const parts = apiURL.pathname.split(/\//); const project = parts[parts.length - 2]; let repository = parts[parts.length - 1]; repository = repository.replace(/\.git$/, ""); if (apiURL.host.match(/stash\./)) { version = "1.0"; apiURL.pathname = `rest/api/${version}`; } else { apiURL.host = "api." + apiURL.host; apiURL.pathname = `${version}`; } apiURL.username = ""; apiURL.password = ""; return { api: { [version]: apiURL.href }, repository, project, branch }; } /** * Supported name schemes are * - https://user:aSecret@bitbucket.org/owner/repo-name.git * - git+https://user:aSecret@bitbucket.org/owner/repo-name.git * - git@bitbucket.org:owner/repo-name.git * - owner/repo-name * @param {string} name * @return {Repository} */ async repository(name, options) { const analysed = this.analyseURL(name, { part: "repository" }); if (analysed === undefined) { return undefined; } let repository = this.repositories.get(analysed.repository); if (repository === undefined) { const project = await this.project(analysed.project, { api: analysed.api }); console.log(project); console.log(analysed.repository); repository = new this.repositoryClass( project, analysed.repository, options ); project.repositories.set(repository.name, repository); } return repository; } /** * @param {string} name * @param {Object} options */ async project(name, options) { if (name === undefined) { return name; } let project = this.repositoryGroups.get(name); if (project !== undefined) { return project; } project = new this.repositoryGroupClass(this, name, options); this.repositoryGroups.set(project.name, project); return project; } get(path) { const params = { uri: path.match(/^https?:/) ? path : this.api["2.0"] + "/" + path, auth: this.auth, json: true }; console.log(`GET ${params.uri}`); return request.get(params); } put(path) { const params = { uri: this.api["2.0"] + "/" + path, auth: this.auth }; return request.put(params); } delete(path, data) { const params = { uri: path.match(/^https?:/) ? path : this.api["2.0"] + "/" + path, auth: this.auth, form: data }; console.log(`DELETE ${params.uri}`); return request.delete(params); } post(path, data) { const params = { uri: path.match(/^https?:/) ? path : this.api["2.0"] + "/" + path, auth: this.auth, form: data }; return request.post(params); } }