diff --git a/README.md b/README.md index 1678830..ab557af 100644 --- a/README.md +++ b/README.md @@ -270,13 +270,14 @@ If you are using this library in one of your projects, add it in this list. :spa - `@atomist/automation-client` - `@storybook/storybook-deployer` - `@kadira/storybook-deployer` + - `@backstage/backend-common` - `gatsby-source-git` - `umi-build-dev` - `@atomist/automation-client-ext-raven` - `git-source` - `@atomist/sdm-pack-analysis` - - `@git-stack/server-core` - `@qiwi/semantic-release-gh-pages-plugin` + - `@git-stack/server-core` - `@nuxt/telemetry` - `@lerna/github-client` - `@umijs/block-sdk` @@ -316,11 +317,11 @@ If you are using this library in one of your projects, add it in this list. :spa - `@koumoul/gh-pages-multi` - `@feizheng/next-git-url` - `@yarnpkg/plugin-git` - - `@git-stack/hemera-plugin` - - `@s-ui/mono` - `@adminide-stack/git-api-browser` - - `@xdn/cli` + - `@s-ui/mono` - `@atomist/skill` + - `@git-stack/hemera-plugin` + - `@xdn/cli` - `committing` - `gitbook-start-https-alex-moi` - `gitbook-start-iaas-ull-es-merquililycony` @@ -331,6 +332,7 @@ If you are using this library in one of your projects, add it in this list. :spa - `@axetroy/git-clone` - `generator-cleanphp` - `@axetroy/gpmx` + - `generator-ckeditor4` - `documentation-habitlab` - `nodeschool-admin` - `one-more-gitlab-cli` @@ -390,8 +392,8 @@ If you are using this library in one of your projects, add it in this list. :spa - `git-service-node` - `@infinitecsolutions/storybook-deployer` - `@1nd/documentation` - - `git-cherry-fix` - `branch-release` + - `git-cherry-fix` - `vuepress-plugin-remote-url` - `gatsby-source-github-raw` - `moto-connector` @@ -408,9 +410,9 @@ If you are using this library in one of your projects, add it in this list. :spa - `@epranka/create-tsx-package` - `flutter-boot` - `node-norman` + - `remote-commit-url` - `air-material_cli` - `@belt/repo` - - `remote-commit-url` - `@arcanis/sherlock` - `@dandean/storybook-deployer` - `git-upstream` @@ -419,11 +421,10 @@ If you are using this library in one of your projects, add it in this list. :spa - `@tagoro9/git` - `tldw` - `gatsby-theme-hansin` - - `@temporg/ui-scripts` - - `generate-preview` - `aral-vps-test` + - `generate-preview` + - `@temporg/ui-scripts` - `bitbucket-pullr` - - `@s-ui/changelog` - `@whey/gatsby-theme-whey` - `@docomodigital/pdor` - `auto-clone` @@ -431,11 +432,9 @@ If you are using this library in one of your projects, add it in this list. :spa - `create-n` - `aral-server` - `gatsby-source-git-remotes` - - `@pagedip/tool-autorelease` - - `@shopgate/pwa-releaser` - `@vicoders/cli2` - - `@stavalfi/ci` - `@amorist/gatsby-theme-antd` + - `@stavalfi/ci` - `cirodown` - `@apardellass/react-native-audio-stream` - `gatsby-theme-cone` @@ -447,7 +446,6 @@ If you are using this library in one of your projects, add it in this list. :spa - `@cilyn/bitbucket` - `react-native-plugpag-wrapper` - `meta-release` - - `@cyber-tools/lib-cli` - `@feizheng/git-url-cli` - `@hnp/package-scripts` - `git-csv` @@ -455,47 +453,55 @@ If you are using this library in one of your projects, add it in this list. :spa - `ssh-remote` - `@senti-techlabs/generator-senti-project-template` - `canarist` - - `mira` - `fotingo` - `react-native-pulsator-native` - `actions-package-update` - `@epranka/create-package` - - `@bcgov/gatsby-source-github-raw` - - `kit-command` - `@theowenyoung/gatsby-source-git` - `git-lab-cli` - `git-push-pr` - `@csmith/release-it` - `query-registry` - - `@git-stack/module-server` - `cetus-cli` - - `rollman` - `cc-flow` - `@s-ui/ssr` - `@gasket/plugin-metrics` - `react-native-kakao-maps` - `@elestu/actions-dependacop` - `generate-github-directory` - - `lage` - `@rescribe/cli` - `sinanews-flutter-boot` + - `configorama` - `@geeky-apo/react-native-advanced-clipboard` - - `dx-scanner` - - `native-kakao-login` - - `native-google-login` - `native-apple-login` - - `configorama` - - `@backstage/plugin-catalog-backend` - - `@s-ui/ci` + - `native-google-login` - `kaskadi-cli` - `documentation-markdown-themes` - - `@backstage/plugin-scaffolder-backend` - - `@backstage/plugin-techdocs-backend` - - `@pubcore/node-docker-build` - `@tahini/nc` + - `@shopgate/pwa-releaser` + - `native-kakao-login` + - `@pubcore/node-docker-build` + - `@s-ui/changelog` + - `rollman` + - `@reshiftsecurity/reshift-plugin-npm` - `@antv/gatsby-theme-antv` + - `@hemith/react-native-tnk` - `@myetherwallet/mew-components` - - `@datalogic/react-native-datalogic-module` + - `@cyber-tools/cyber-npm` + - `@bcgov/gatsby-source-github-raw` + - `dx-scanner` + - `lage` + - `@pagedip/tool-autorelease` + - `kit-command` + - `detect-node-support` + - `@s-ui/ci` + - `@backstage/plugin-catalog-backend` + - `@backstage/plugin-scaffolder-backend` + - `@backstage/plugin-techdocs-backend` + - `@tcorley/storybook-addon-material-ui` + - `@git-stack/module-server` + - `mira` + - `git-multi-profile` - `pr-log` - `git-issues` diff --git a/lib/index.js b/lib/index.js index c776928..db8ae29 100644 --- a/lib/index.js +++ b/lib/index.js @@ -148,10 +148,14 @@ function gitUrlParse(url) { const blobIndex = splits.indexOf("blob", 2); const treeIndex = splits.indexOf("tree", 2); const commitIndex = splits.indexOf("commit", 2); + const srcIndex = splits.indexOf("src", 2); + const rawIndex = splits.indexOf("raw", 2); nameIndex = dashIndex > 0 ? dashIndex - 1 : blobIndex > 0 ? blobIndex - 1 : treeIndex > 0 ? treeIndex - 1 : commitIndex > 0 ? commitIndex - 1 + : srcIndex > 0 ? srcIndex - 1 + : rawIndex > 0 ? rawIndex - 1 : nameIndex; urlInfo.owner = splits.slice(0, nameIndex).join('/'); @@ -165,7 +169,7 @@ function gitUrlParse(url) { urlInfo.filepathtype = ""; urlInfo.filepath = ""; const offsetNameIndex = splits.length > nameIndex && splits[nameIndex+1] === "-" ? nameIndex + 1 : nameIndex; - if ((splits.length > offsetNameIndex + 2) && (["blob", "tree"].indexOf(splits[offsetNameIndex + 1]) >= 0)) { + if ((splits.length > offsetNameIndex + 2) && (["raw","src","blob", "tree"].indexOf(splits[offsetNameIndex + 1]) >= 0)) { urlInfo.filepathtype = splits[offsetNameIndex + 1]; urlInfo.ref = splits[offsetNameIndex + 2]; if (splits.length > offsetNameIndex + 3) { @@ -183,7 +187,32 @@ function gitUrlParse(url) { urlInfo.full_name += urlInfo.name; } } + // Bitbucket Server + if(urlInfo.owner.startsWith("scm/")) { + urlInfo.owner = urlInfo.owner.replace("scm/",""); + urlInfo.organization = urlInfo.owner; + } + + const bitbucket = /(projects|users)\/(.*?)\/repos\/(.*?)\/(raw|browse)\/(.*?)$/ + const matches = bitbucket.exec(urlInfo.pathname) + if(matches != null) { + if (matches[1] === "users") { + urlInfo.owner = "~" + matches[2]; + } else { + urlInfo.owner = matches[2]; + } + + urlInfo.organization = urlInfo.owner; + urlInfo.name = matches[3]; + urlInfo.filepathtype = matches[4]; + urlInfo.filepath = matches[5]; + if(urlInfo.query.at) { + urlInfo.ref = urlInfo.query.at; + } else { + urlInfo.ref = ""; + } + } return urlInfo; } diff --git a/package.json b/package.json index 422634c..e801793 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "git-url-parse", - "version": "11.3.0", + "version": "11.4.0", "description": "A high level git url parser for common git providers.", "main": "lib/index.js", "scripts": { diff --git a/test/index.js b/test/index.js index 3d03dd7..5e5802e 100644 --- a/test/index.js +++ b/test/index.js @@ -133,6 +133,100 @@ tester.describe("parse urls", test => { test.expect(res.name).toBe("name"); }); + // bitbucket cloud src file + test.should("parse Bitbucket Cloud src file", () => { + var res = gitUrlParse("https://bitbucket.org/owner/name/src/master/README.md"); + test.expect(res.owner).toBe("owner"); + test.expect(res.name).toBe("name"); + test.expect(res.filepath).toBe("README.md"); + test.expect(res.ref).toBe("master"); + test.expect(res.filepathtype).toBe("src"); + }); + + // bitbucket cloud raw file + test.should("parse Bitbucket Cloud raw file", () => { + var res = gitUrlParse("https://bitbucket.org/owner/name/raw/master/README.md"); + test.expect(res.owner).toBe("owner"); + test.expect(res.name).toBe("name"); + test.expect(res.filepath).toBe("README.md"); + test.expect(res.ref).toBe("master"); + test.expect(res.filepathtype).toBe("raw"); + }); + + // https bitbucket server + test.should("parse Bitbucket Server clone over http", () => { + var res = gitUrlParse("https://user@bitbucket.companyname.com/scm/owner/name.git"); + test.expect(res.owner).toBe("owner"); + test.expect(res.name).toBe("name"); + }); + + // ssh bitbucket server + test.should("parse Bitbucket Server clone over ssh", () => { + var res = gitUrlParse("ssh://git@bitbucket.companyname.com/owner/name.git"); + test.expect(res.owner).toBe("owner"); + test.expect(res.name).toBe("name"); + }); + + // bitbucket server raw file + test.should("parse Bitbucket Server raw file", () => { + var res = gitUrlParse("https://bitbucket.mycompany.com/projects/owner/repos/name/raw/README.md?at=master"); + test.expect(res.owner).toBe("owner"); + test.expect(res.name).toBe("name"); + test.expect(res.filepath).toBe("README.md") + test.expect(res.ref).toBe("master"); + test.expect(res.filepathtype).toBe("raw"); + }); + + // bitbucket server raw file + test.should("parse Bitbucket Server raw file without ref", () => { + var res = gitUrlParse("https://bitbucket.mycompany.com/projects/owner/repos/name/raw/README.md"); + test.expect(res.owner).toBe("owner"); + test.expect(res.name).toBe("name"); + test.expect(res.filepath).toBe("README.md") + test.expect(res.ref).toBe(""); + test.expect(res.filepathtype).toBe("raw"); + }); + + test.should("parse Bitbucket server browse file", () => { + var res = gitUrlParse("https://bitbucket.mycompany.com/projects/owner/repos/name/browse/README.md?at=master"); + test.expect(res.owner).toBe("owner"); + test.expect(res.name).toBe("name"); + test.expect(res.filepath).toBe("README.md"); + test.expect(res.ref).toBe("master"); + test.expect(res.filepathtype).toBe("browse"); + }); + + test.should("parse Bitbucket Server personal repository browse url", () => { + var res = gitUrlParse("https://bitbucket.mycompany.com/users/owner/repos/name/browse/README.md?at=master"); + test.expect(res.owner).toBe("~owner"); + test.expect(res.name).toBe("name"); + test.expect(res.filepath).toBe("README.md"); + test.expect(res.ref).toBe("master"); + test.expect(res.filepathtype).toBe("browse"); + }); + + test.should("parse Bitbucket Server personal repository raw url", () => { + var res = gitUrlParse("https://bitbucket.mycompany.com/users/owner/repos/name/raw/README.md?at=master"); + test.expect(res.owner).toBe("~owner"); + test.expect(res.name).toBe("name"); + test.expect(res.filepath).toBe("README.md"); + test.expect(res.ref).toBe("master"); + test.expect(res.filepathtype).toBe("raw"); + }); + + test.should("parse Bitbucket Server personal repository clone over ssh", () => { + var res = gitUrlParse("ssh://git@bitbucket.mycompany.com/~owner/name.git"); + test.expect(res.owner).toBe("~owner"); + test.expect(res.name).toBe("name"); + }); + + test.should("parse Bitbucket Server personal repository clone over http", () => { + var res = gitUrlParse("https://bitbucket.mycompany.com/scm/~owner/name.git"); + test.expect(res.owner).toBe("~owner"); + test.expect(res.organization).toBe("~owner") + test.expect(res.name).toBe("name"); + }); + // https cloudforge test.should("parse CloudForge urls", () => { var res = gitUrlParse("https://owner@organization.git.cloudforge.com/name.git");