Skip to content

Add support for bitbucket/stash instances hosted in a subpath #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 32 additions & 23 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,43 +37,52 @@ function parse(str) {

// Stash, aka Bitbucket Server. https://www.atlassian.com/software/bitbucket/server
// We look for a git@ URL not pointing at bitbucket.org/bitbucket.com, or for a HTTP/HTTPS URL that isn't pointing to
// bitbucket.com/bitbucket.org and that has a path that starts with /projects/
// bitbucket.com/bitbucket.org and that has a path that contains /projects/ or /scm/
var stashDetected =
(str.indexOf('git@') !== -1 && str.indexOf('[email protected]') === -1 && str.indexOf('[email protected]') === -1)
||
pathSegments.length === 3 && pathSegments[0] === 'scm'
||
(obj.hostname &&
!(obj.hostname.endsWith('bitbucket.org') || obj.hostname.endsWith('bitbucket.com')) &&
pathSegments[0] === 'projects');
(pathSegments.includes('projects') || pathSegments.includes('scm')));

var stashPathOffset = 0;
if (stashDetected) {
stashPathOffset = pathSegments.indexOf('projects');
if (stashPathOffset == -1) {
stashPathOffset = pathSegments.indexOf('scm');
}
stashPathOffset = stashPathOffset > 0 ? stashPathOffset : 0;
}

// TODO: This is too spaghetti.. rewrite this to be understandable, separate Bitbucket Server/Bitbucket Cloud paths,
// SSH/git paths, etc
if (stashDetected) {
// Stash mode
if (str.indexOf('git@') === -1 && pathSegments[0] !== 'scm') {
if (str.indexOf('git@') === -1 && pathSegments[0 + stashPathOffset] !== 'scm') {

if (pathSegments.length > 1) {
obj.owner = owner(pathSegments[1]);
obj.owner = owner(pathSegments[1 + stashPathOffset]);
} else {
obj.owner = null;
}

if (pathSegments.length > 3 && pathSegments[2] === 'repos') {
obj.name = name(pathSegments[3]);
if (pathSegments.length > 3 && pathSegments[2 + stashPathOffset] === 'repos') {
obj.name = name(pathSegments[3 + stashPathOffset]);
} else {
obj.name = null;
}
} else {
if (pathSegments.length === 3) {
if (pathSegments[0] !== 'scm') {
obj.host = pathSegments[0].replace('git@', '');
if (pathSegments.length - stashPathOffset === 3) {
if (pathSegments[0 + stashPathOffset] !== 'scm') {
obj.host = pathSegments[0 + stashPathOffset].replace('git@', '');
}
obj.owner = owner(pathSegments[1]);
obj.name = name(pathSegments[2]);
obj.owner = owner(pathSegments[1 + stashPathOffset]);
obj.name = name(pathSegments[2 + stashPathOffset]);
} else {
obj.owner = owner(pathSegments[0]);
obj.name = name(pathSegments[1]);
obj.owner = owner(pathSegments[0 + stashPathOffset]);
obj.name = name(pathSegments[1 + stashPathOffset]);
}
}
} else {
Expand All @@ -82,7 +91,7 @@ function parse(str) {
obj.name = name(pathSegments[1]);
}

if (pathSegments.length > 1 && obj.owner && obj.name) {
if (pathSegments.length > 1 + stashPathOffset && obj.owner && obj.name) {
obj.repo = obj.owner + '/' + obj.name;
} else {
var href = obj.href.split(':');
Expand All @@ -109,21 +118,21 @@ function parse(str) {
}
}

if (pathSegments.length >= 3) {
if (pathSegments.length >= 3 + stashPathOffset) {
switch(pathSegments[2]){
case 'get':
// Look at seg[3] for a file name, which will be the branch/tag name
// NOTE: tags and branches are treated alike in Bitbucket and cannot be distinguished by URL.
// We'll treat everything like branches.
var fileName = null;
if (pathSegments[3].endsWith('.tar.gz')) {
fileName = pathSegments[3].replace('.tar.gz', '');
if (pathSegments[3 + stashPathOffset].endsWith('.tar.gz')) {
fileName = pathSegments[3+ stashPathOffset].replace('.tar.gz', '');
}
if (pathSegments[3].endsWith('.tar.bz2')) {
fileName = pathSegments[3].replace('.tar.bz2', '');
if (pathSegments[3+ stashPathOffset].endsWith('.tar.bz2')) {
fileName = pathSegments[3+ stashPathOffset].replace('.tar.bz2', '');
}
if (pathSegments[3].endsWith('.zip')) {
fileName = pathSegments[3].replace('.zip', '');
if (pathSegments[3+ stashPathOffset].endsWith('.zip')) {
fileName = pathSegments[3+ stashPathOffset].replace('.zip', '');
}
obj.branch = fileName;

Expand All @@ -134,11 +143,11 @@ function parse(str) {
break;
case 'raw':// support file location. Bitbucket support two file modes:raw and src. This is only for bitbuket and not Bitbucket Server
case 'src':// todo: support bitbucket server file location
if(pathSegments.length < 5){
if(pathSegments.length < 5 + stashPathOffset){
// no file location
break;
}
var filepath = pathSegments.slice(4);
var filepath = pathSegments.slice(4 + stashPathOffset);
if(filepath.length){
var file = filepath[filepath.length - 1];
file = file.split('?')[0]; //remove the query params
Expand Down
26 changes: 26 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,4 +274,30 @@ describe('parse-bitbucket-url', function() {
assert.equal(bb('https://[email protected]/scm/cod/more-proj.git').host, 'stash-internal.codefresh.io');
assert.equal(bb('https://[email protected]/scm/cod/more-proj.git').repo, 'cod/more-proj');
});

it('should work with sub path Bitbucket Server URLs:', function() {
assert.equal(bb('https://stash.one.two/stashinstance/projects/KEY/repos/name1/browse').owner, 'KEY');
assert.equal(bb('https://stash.one.two/stashinstance/projects/ONE/repos/name2/browse').owner, 'ONE');
assert.equal(bb('https://stash.one.two/stashinstance/projects/ABC/repos/name3/commits/a1aa8e5c5b99002396d449c1bdd4d6946303bbc3').name, 'name3');
assert.equal(bb('https://stash.one.two/stashinstance/projects/DEF/repos/na-me4/commits').name, 'na-me4');
assert.equal(bb('https://bitbucketserver.one.two/stashinstance/projects/GHI/repos/name5/compare/commits?sourceBranch=refs%2Fheads%2Fmaster&targetBranch=refs%2Fheads%2Fbugfix%2Fdevelop').repo, 'GHI/name5');
assert.equal(bb('https://stash.one.two/stashinstance/projects/JKL/repos/nam-e6/branches').repo, 'JKL/nam-e6');
assert.equal(bb('https://internal.one.two:2034/stashinstance/projects/MNOPQ/repos/name7/pull-requests').host, 'internal.one.two:2034');
assert.equal(bb('https://stash-internal.my.company:3333/stashinstance/projects/KEY/repos/name1/browse/README.md?at=refs%2Fheads%2Fbranch333').host, 'stash-internal.my.company:3333');
assert.equal(bb('https://[email protected]/stashinstance/scm/a-key/a-project.git').branch, 'master');
assert.equal(bb('https://stash-internal.my.company:3333/stashinstance/projects/KEY/repos/name1/browse/README.md?at=refs%2Fheads%2Fbranch333').branch, 'branch333');
assert.equal(bb('https://stash.one.two/stashinstance/projects/KEY').owner, 'KEY');
assert.equal(bb('https://stash.one.two/stashinstance/projects/KEY').name, null);
assert.equal(bb('https://stash.one.two/stashinstance/projects/KEY').repo, null);
assert.equal(bb('https://stash.one.two/stashinstance/projects/KEY/repos').owner, 'KEY');
assert.equal(bb('https://stash.one.two/stashinstance/projects/KEY/repos/').name, null);
assert.equal(bb('https://stash.one.two/stashinstance/projects/KEY/repos/').repo, null);


assert.equal(bb('https://[email protected]/stashinstance/scm/cod/more-proj.git').owner, 'cod');
assert.equal(bb('https://[email protected]/stashinstance/scm/cod/more-proj.git').name, 'more-proj');
assert.equal(bb('https://[email protected]/stashinstance/scm/cod/more-proj.git').host, 'stash-internal.codefresh.io');
assert.equal(bb('https://[email protected]/stashinstance/scm/cod/more-proj.git').repo, 'cod/more-proj');

});
});