7
7
import { NavigatorContext , Repository , User , WorkspaceContext } from "@gitpod/gitpod-protocol" ;
8
8
import { log } from "@gitpod/gitpod-protocol/lib/util/logging" ;
9
9
import { TraceContext } from "@gitpod/gitpod-protocol/lib/util/tracing" ;
10
- import { Schema } from "bitbucket" ;
10
+ import { Schema } from "@atlassian/ bitbucket-server " ;
11
11
import { inject , injectable } from "inversify" ;
12
12
import { BitbucketTokenHelper } from "../bitbucket/bitbucket-token-handler" ;
13
13
import { NotFoundError } from "../errors" ;
14
- import { AbstractContextParser , IContextParser } from "../workspace/context-parser" ;
14
+ import { AbstractContextParser , IContextParser , URLParts } from "../workspace/context-parser" ;
15
15
import { BitbucketServerApiFactory } from "./bitbucket-api-factory" ;
16
+ import { URL } from "url" ;
16
17
17
18
const DEFAULT_BRANCH = "master" ;
18
19
@@ -43,38 +44,68 @@ export class BitbucketServerContextParser extends AbstractContextParser implemen
43
44
}
44
45
}
45
46
46
- public async fetchCommitHistory ( ctx : TraceContext , user : User , contextUrl : string , commit : string , maxDepth : number ) : Promise < string [ ] | undefined > {
47
- return undefined ;
48
- }
47
+ public async parseURL ( user : User , contextUrl : string ) : Promise < URLParts > {
48
+ const url = new URL ( contextUrl ) ;
49
+ const pathname = url . pathname . replace ( / ^ \/ / , "" ) . replace ( / \/ $ / , "" ) ; // pathname without leading and trailing slash
50
+ const segments = pathname . split ( '/' ) ;
49
51
50
- protected async isValidCommitHash ( user : User , owner : string , repoName : string , potentialCommitHash : string ) {
51
- if ( potentialCommitHash . length !== 40 ) {
52
- return false ;
52
+ const host = this . host ; // as per contract, cf. `canHandle(user, contextURL)`
53
+
54
+ const lenghtOfRelativePath = host . split ( "/" ) . length - 1 ; // e.g. "123.123.123.123/gitlab" => length of 1
55
+ if ( lenghtOfRelativePath > 0 ) {
56
+ // remove segments from the path to be consider further, which belong to the relative location of the host
57
+ // cf. https://github.com/gitpod-io/gitpod/issues/2637
58
+ segments . splice ( 0 , lenghtOfRelativePath ) ;
53
59
}
54
- try {
55
- const api = await this . api ( user ) ;
56
- const result = ( await api . repositories . getCommit ( { workspace : owner , repo_slug : repoName , commit : potentialCommitHash } ) ) ;
57
- return result . data . hash === potentialCommitHash ;
58
- } catch {
59
- return false ;
60
+
61
+ var owner : string = segments [ 1 ] ;
62
+ var repoName : string = segments [ 3 ] ;
63
+ var moreSegmentsStart : number = 4 ;
64
+ const endsWithRepoName = segments . length === moreSegmentsStart ;
65
+ const searchParams = url . searchParams ;
66
+ return {
67
+ host,
68
+ owner,
69
+ repoName : this . parseRepoName ( repoName , endsWithRepoName ) ,
70
+ moreSegments : endsWithRepoName ? [ ] : segments . slice ( moreSegmentsStart ) ,
71
+ searchParams
60
72
}
61
73
}
62
74
63
- protected async isTag ( user : User , owner : string , repoName : string , potentialTag : string ) {
64
- try {
65
- const api = await this . api ( user ) ;
66
- const result = ( await api . repositories . getTag ( { workspace : owner , repo_slug : repoName , name : potentialTag } ) ) ;
67
- return result . data . name === potentialTag ;
68
- } catch {
69
- return false ;
70
- }
75
+ public async fetchCommitHistory ( ctx : TraceContext , user : User , contextUrl : string , commit : string , maxDepth : number ) : Promise < string [ ] | undefined > {
76
+ return undefined ;
71
77
}
72
78
73
- protected async handleNavigatorContext ( ctx : TraceContext , user : User , host : string , owner : string , repoName : string , more : Partial < NavigatorContext > = { } , givenRepo ?: Schema . Repository ) : Promise < NavigatorContext > {
79
+ // protected async isValidCommitHash(user: User, owner: string, repoName: string, potentialCommitHash: string) {
80
+ // if (potentialCommitHash.length !== 40) {
81
+ // return false;
82
+ // }
83
+ // try {
84
+ // const api = await this.api(user);
85
+ // const result = (await api.repositories.getCommit({ workspace: owner, repo_slug: repoName, commit: potentialCommitHash }));
86
+ // return result.data.hash === potentialCommitHash;
87
+ // } catch {
88
+ // return false;
89
+ // }
90
+ // }
91
+
92
+ // protected async isTag(user: User, owner: string, repoName: string, potentialTag: string) {
93
+ // try {
94
+ // const api = await this.api(user);
95
+ // const result = (await api.repositories.getTag({ workspace: owner, repo_slug: repoName, name: potentialTag }));
96
+ // return result.data.name === potentialTag;
97
+ // } catch {
98
+ // return false;
99
+ // }
100
+ // }
101
+
102
+ protected async handleNavigatorContext ( ctx : TraceContext , user : User , host : string , owner : string , repoName : string , more : Partial < NavigatorContext > = { } ) : Promise < NavigatorContext > {
74
103
const span = TraceContext . startSpan ( "BitbucketServerContextParser.handleNavigatorContext" , ctx ) ;
75
104
try {
76
105
const api = await this . api ( user ) ;
77
- const repo = givenRepo || ( await api . repositories . get ( { workspace : owner , repo_slug : repoName } ) ) . data ;
106
+
107
+ const repo = ( await api . repos . getRepository ( { projectKey : owner , repositorySlug : repoName } ) ) . data ;
108
+
78
109
const repository = await this . toRepository ( user , host , repo ) ;
79
110
span . log ( { "request.finished" : "" } ) ;
80
111
@@ -88,23 +119,28 @@ export class BitbucketServerContextParser extends AbstractContextParser implemen
88
119
more . refType = more . refType || "branch" ;
89
120
90
121
if ( ! more . revision ) {
91
- const commits = ( await api . repositories . listCommitsAt ( { workspace : owner , repo_slug : repoName , revision : more . ref ! , pagelen : 1 } ) ) . data ;
92
- more . revision = commits . values && commits . values . length > 0 ? commits . values [ 0 ] . hash : "" ;
93
- if ( ( ! commits . values || commits . values . length === 0 ) && more . ref === repository . defaultBranch ) {
94
- // empty repo
95
- more . ref = undefined ;
96
- more . revision = "" ;
97
- more . refType = undefined ;
98
- }
122
+ const tipCommitOnDefaultBranch = await api . repos . getCommits ( { projectKey : owner , repositorySlug : repoName , q : { limit : 1 } } ) ;
123
+ more . revision = tipCommitOnDefaultBranch . data . values [ 0 ] ?. id || "" ;
99
124
}
100
125
101
- if ( ! more . path ) {
102
- more . isFile = false ;
103
- more . path = "" ;
104
- } else if ( more . isFile === undefined ) {
105
- const fileMeta = ( await api . repositories . readSrc ( { workspace : owner , repo_slug : repoName , format : "meta" , commit : more . revision ! , path : more . path ! , pagelen : 1 } ) ) . data ;
106
- more . isFile = ( fileMeta as any ) . type === "commit_file" ;
107
- }
126
+ // if (!more.revision) {
127
+ // const commits = (await api.repositories.listCommitsAt({ workspace: owner, repo_slug: repoName, revision: more.ref!, pagelen: 1 })).data;
128
+ // more.revision = commits.values && commits.values.length > 0 ? commits.values[0].hash : "";
129
+ // if ((!commits.values || commits.values.length === 0) && more.ref === repository.defaultBranch) {
130
+ // // empty repo
131
+ // more.ref = undefined;
132
+ // more.revision = "";
133
+ // more.refType = undefined;
134
+ // }
135
+ // }
136
+
137
+ // if (!more.path) {
138
+ // more.isFile = false;
139
+ // more.path = "";
140
+ // } else if (more.isFile === undefined) {
141
+ // const fileMeta = (await api.repositories.readSrc({ workspace: owner, repo_slug: repoName, format: "meta", commit: more.revision!, path: more.path!, pagelen: 1 })).data;
142
+ // more.isFile = (fileMeta as any).type === "commit_file";
143
+ // }
108
144
109
145
return {
110
146
...more ,
@@ -125,27 +161,26 @@ export class BitbucketServerContextParser extends AbstractContextParser implemen
125
161
if ( ! repo ) {
126
162
throw new Error ( 'Unknown repository.' ) ;
127
163
}
128
- // full_name: string
129
- // The concatenation of the repository owner's username and the slugified name, e.g. "evzijst/interruptingcow". This is the same string used in Bitbucket URLs.
130
- const fullName = repo . full_name ! . split ( "/" ) ;
131
- const owner = fullName [ 0 ] ;
132
- const name = fullName [ 1 ] ;
164
+
165
+ const owner = repo . project . key ;
166
+ const name = repo . name ;
167
+ const cloneUrl = repo . links . clone . find ( u => u . name === "http" ) ?. href ! ;
133
168
134
169
const result : Repository = {
135
- cloneUrl : `https:// ${ host } / ${ repo . full_name } .git` ,
170
+ cloneUrl,
136
171
host,
137
172
name,
138
173
owner,
139
- private : ! ! repo . isPrivate ,
140
- defaultBranch : repo . mainbranch ? repo . mainbranch . name : DEFAULT_BRANCH ,
141
- }
142
- if ( ! ! repo . parent && ! ! repo . parent . full_name ) {
143
- const api = await this . api ( user ) ;
144
- const parentRepo = ( await api . repositories . get ( { workspace : repo . parent ! . full_name ! . split ( "/" ) [ 0 ] , repo_slug : repo . parent ! . full_name ! . split ( "/" ) [ 1 ] } ) ) . data ;
145
- result . fork = {
146
- parent : await this . toRepository ( user , host , parentRepo )
147
- } ;
174
+ private : ! repo . public ,
175
+ defaultBranch : DEFAULT_BRANCH ,
148
176
}
177
+ // if (!!repo.parent && !!repo.parent.full_name) {
178
+ // const api = await this.api(user);
179
+ // const parentRepo = (await api.repositories.get({ workspace: repo.parent!.full_name!.split("/")[0], repo_slug: repo.parent!.full_name!.split("/")[1] })).data;
180
+ // result.fork = {
181
+ // parent: await this.toRepository(user, host, parentRepo)
182
+ // };
183
+ // }
149
184
150
185
return result ;
151
186
}
0 commit comments