11import type { Range , Uri } from 'vscode' ;
22import type { AutolinkReference , DynamicAutolinkReference } from '../../autolinks/models/autolinks' ;
3+ import type { Container } from '../../container' ;
4+ import { HostingIntegration } from '../../plus/integrations/integration' ;
5+ import { remoteProviderIdToIntegrationId } from '../../plus/integrations/integrationService' ;
36import type { Brand , Unbrand } from '../../system/brand' ;
47import type { Repository } from '../models/repository' ;
58import type { GkProviderId } from '../models/repositoryIdentities' ;
@@ -11,7 +14,14 @@ const fileRegex = /^\/([^/]+)\/([^/]+?)\/src(.+)$/i;
1114const rangeRegex = / ^ l i n e s - ( \d + ) (?: : ( \d + ) ) ? $ / ;
1215
1316export class BitbucketServerRemote extends RemoteProvider {
14- constructor ( domain : string , path : string , protocol ?: string , name ?: string , custom : boolean = false ) {
17+ constructor (
18+ private readonly container : Container ,
19+ domain : string ,
20+ path : string ,
21+ protocol ?: string ,
22+ name ?: string ,
23+ custom : boolean = false ,
24+ ) {
1525 super ( domain , path , protocol , name , custom ) ;
1626 }
1727
@@ -54,14 +64,12 @@ export class BitbucketServerRemote extends RemoteProvider {
5464 return `${ this . protocol } ://${ this . domain } /projects/${ project } /repos/${ repo } ` ;
5565 }
5666
57- protected override splitPath ( ) : [ string , string ] {
58- if ( this . path . startsWith ( 'scm/' ) && this . path . indexOf ( '/' ) !== this . path . lastIndexOf ( '/' ) ) {
59- const path = this . path . replace ( 'scm/' , '' ) ;
60- const index = path . indexOf ( '/' ) ;
61- return [ path . substring ( 0 , index ) , path . substring ( index + 1 ) ] ;
67+ protected override splitArgPath ( argPath : string ) : [ string , string ] {
68+ if ( argPath . startsWith ( 'scm/' ) && argPath . indexOf ( '/' ) !== argPath . lastIndexOf ( '/' ) ) {
69+ return super . splitArgPath ( argPath . replace ( 'scm/' , '' ) ) ;
6270 }
6371
64- return super . splitPath ( ) ;
72+ return super . splitArgPath ( argPath ) ;
6573 }
6674
6775 override get icon ( ) : string {
@@ -158,25 +166,48 @@ export class BitbucketServerRemote extends RemoteProvider {
158166 }
159167
160168 protected override getUrlForComparison ( base : string , head : string , _notation : '..' | '...' ) : string {
161- return this . encodeUrl ( `${ this . baseUrl } /branches/compare/${ base } %0D ${ head } ` ) . replaceAll ( '%250D' , '%0D' ) ;
169+ return this . encodeUrl ( `${ this . baseUrl } /branches/compare/${ head } \r ${ base } ` ) ;
162170 }
163171
164- protected override getUrlForCreatePullRequest (
172+ override async isReadyForForCrossForkPullRequestUrls ( ) : Promise < boolean > {
173+ const integrationId = remoteProviderIdToIntegrationId ( this . id ) ;
174+ const integration = integrationId && ( await this . container . integrations . get ( integrationId ) ) ;
175+ return integration ?. maybeConnected ?? integration ?. isConnected ( ) ?? false ;
176+ }
177+
178+ protected override async getUrlForCreatePullRequest (
165179 base : { branch ?: string ; remote : { path : string ; url : string } } ,
166180 head : { branch : string ; remote : { path : string ; url : string } } ,
167181 options ?: { title ?: string ; description ?: string } ,
168- ) : string | undefined {
182+ ) : Promise < string | undefined > {
169183 const query = new URLSearchParams ( { sourceBranch : head . branch , targetBranch : base . branch ?? '' } ) ;
170- // TODO: figure this out
171- // query.set('targetRepoId', base.repoId);
184+ const [ baseOwner , baseName ] = this . splitArgPath ( base . remote . path ) ;
185+ if ( base . remote . url !== head . remote . url ) {
186+ const targetDesc = {
187+ owner : baseOwner ,
188+ name : baseName ,
189+ } ;
190+ const integrationId = remoteProviderIdToIntegrationId ( this . id ) ;
191+ const integration = integrationId && ( await this . container . integrations . get ( integrationId ) ) ;
192+ let targetRepoId = undefined ;
193+ if ( integration ?. isConnected && integration instanceof HostingIntegration ) {
194+ targetRepoId = ( await integration . getRepoInfo ?.( targetDesc ) ) ?. id ;
195+ }
196+ if ( ! targetRepoId ) {
197+ return undefined ;
198+ }
199+ query . set ( 'targetRepoId' , targetRepoId ) ;
200+ }
172201 if ( options ?. title ) {
173202 query . set ( 'title' , options . title ) ;
174203 }
175204 if ( options ?. description ) {
176205 query . set ( 'description' , options . description ) ;
177206 }
178-
179- return `${ this . encodeUrl ( `${ this . baseUrl } /pull-requests?create` ) } &${ query . toString ( ) } ` ;
207+ const [ headOwner , headName ] = this . splitArgPath ( head . remote . path ) ;
208+ return `${ this . encodeUrl (
209+ `${ this . protocol } ://${ this . domain } /projects/${ headOwner } /repos/${ headName } /pull-requests?create` ,
210+ ) } &${ query . toString ( ) } `;
180211 }
181212
182213 protected getUrlForFile ( fileName : string , branch ?: string , sha ?: string , range ?: Range ) : string {
0 commit comments