@@ -4,6 +4,38 @@ import { env } from './env.js';
44
55type onProgressFn = ( event : SimpleGitProgressEvent ) => void ;
66
7+ // Helper function to prepare Azure DevOps authentication
8+ const prepareAzureDevOpsAuth = ( cloneUrl : string ) => {
9+ // Check if this is an Azure DevOps URL
10+ const isAzureDevOps = cloneUrl . includes ( 'dev.azure.com' ) || cloneUrl . includes ( 'devops' ) ;
11+
12+ if ( ! isAzureDevOps ) {
13+ return { url : cloneUrl , authHeader : null } ;
14+ }
15+
16+ let token = '' ;
17+ try {
18+ const url = new ( globalThis as any ) . URL ( cloneUrl ) ;
19+ token = url . password ;
20+ } catch ( e ) {
21+ return { url : cloneUrl , authHeader : null } ;
22+ }
23+
24+ if ( ! token ) {
25+ return { url : cloneUrl , authHeader : null } ;
26+ }
27+
28+ // For Azure DevOps, we need to remove the token from the URL and pass it as a header
29+ const url = new ( globalThis as any ) . URL ( cloneUrl ) ;
30+ url . password = '' ;
31+ const cleanUrl = url . toString ( ) ;
32+
33+ // Create the authorization header
34+ const authHeader = `Authorization: Basic ${ ( globalThis as any ) . Buffer . from ( `:${ token } ` ) . toString ( 'base64' ) } ` ;
35+
36+ return { url : cleanUrl , authHeader } ;
37+ } ;
38+
739export const cloneRepository = async (
840 {
941 cloneUrl,
@@ -18,20 +50,34 @@ export const cloneRepository = async (
1850 try {
1951 await mkdir ( path , { recursive : true } ) ;
2052
53+
2154 const git = simpleGit ( {
2255 progress : onProgress ,
2356 } ) . cwd ( {
2457 path,
2558 } )
2659
27- await git . clone (
28- cloneUrl ,
29- path ,
30- [
31- "--bare" ,
32- ]
33- ) ;
60+ const { url : cleanUrl , authHeader } = prepareAzureDevOpsAuth ( cloneUrl ) ;
3461
62+ if ( authHeader ) {
63+ await git . clone (
64+ cleanUrl ,
65+ path ,
66+ [
67+ "--bare" ,
68+ "-c" ,
69+ `http.extraHeader=${ authHeader } `
70+ ]
71+ ) ;
72+ } else {
73+ await git . clone (
74+ cloneUrl ,
75+ path ,
76+ [
77+ "--bare" ,
78+ ]
79+ ) ;
80+ }
3581 await unsetGitConfig ( path , [ "remote.origin.url" ] ) ;
3682 } catch ( error : unknown ) {
3783 const baseLog = `Failed to clone repository: ${ path } ` ;
@@ -65,12 +111,26 @@ export const fetchRepository = async (
65111 path : path ,
66112 } )
67113
68- await git . fetch ( [
69- cloneUrl ,
70- "+refs/heads/*:refs/heads/*" ,
71- "--prune" ,
72- "--progress"
73- ] ) ;
114+ const { url : cleanUrl , authHeader } = prepareAzureDevOpsAuth ( cloneUrl ) ;
115+
116+ if ( authHeader ) {
117+ // Temporarily set git configuration
118+ await git . addConfig ( 'http.extraHeader' , authHeader ) ;
119+
120+ await git . fetch ( [
121+ cleanUrl ,
122+ "+refs/heads/*:refs/heads/*" ,
123+ "--prune" ,
124+ "--progress"
125+ ] ) ;
126+ } else {
127+ await git . fetch ( [
128+ cloneUrl ,
129+ "+refs/heads/*:refs/heads/*" ,
130+ "--prune" ,
131+ "--progress"
132+ ] ) ;
133+ }
74134 } catch ( error : unknown ) {
75135 const baseLog = `Failed to fetch repository: ${ path } ` ;
76136 if ( env . SOURCEBOT_LOG_LEVEL !== "debug" ) {
0 commit comments