@@ -4,6 +4,40 @@ import { AzurePipelinesDebugSession } from "./azure-pipelines-debug";
4
4
import { integer , Position } from "vscode-languageclient" ;
5
5
import jsYaml from "js-yaml" ;
6
6
import { applyEdits , modify } from "jsonc-parser" ;
7
+ import vsVars from "vscode-variables" ;
8
+
9
+ function joinPath ( l , r ) {
10
+ return l ? l + "/" + r : r ;
11
+ }
12
+
13
+ function cliQuote ( str ) {
14
+ if ( str . includes ( " " ) || str . includes ( "$" ) || str . includes ( "\t" ) || str . includes ( "\n" ) || str . includes ( "\r" ) || str . includes ( '"' ) ) {
15
+ return `'${ str . replace ( / ' / g, "'\\''" ) } '` ;
16
+ }
17
+ return str ;
18
+ }
19
+
20
+ async function locateExternalRepoUrl ( rawbase , filename ) {
21
+ try {
22
+ var base = vscode . Uri . parse ( rawbase , true ) ;
23
+ var stat = await vscode . workspace . fs . stat ( base ) ;
24
+ if ( stat . type === vscode . FileType . Directory ) {
25
+ return base . with ( { path : joinPath ( base . path , filename ) } ) ;
26
+ }
27
+ } catch {
28
+
29
+ }
30
+ try {
31
+ var base = vscode . Uri . file ( rawbase ) ;
32
+ var stat = await vscode . workspace . fs . stat ( base ) ;
33
+ if ( stat . type === vscode . FileType . Directory ) {
34
+ return base . with ( { path : joinPath ( base . path , filename ) } ) ;
35
+ }
36
+ } catch {
37
+
38
+ }
39
+ throw Error ( `Cannot locate: ${ rawbase } ` ) ;
40
+ }
7
41
8
42
/**
9
43
* @param {vscode.ExtensionContext } context
@@ -25,28 +59,6 @@ function activate(context) {
25
59
return virtualFiles [ uri . path ] ;
26
60
}
27
61
} ) ;
28
- var joinPath = ( l , r ) => l ? l + "/" + r : r ;
29
- var locateExternalRepoUrl = async ( rawbase , filename ) => {
30
- try {
31
- var base = vscode . Uri . parse ( rawbase , true ) ;
32
- var stat = await vscode . workspace . fs . stat ( base ) ;
33
- if ( stat . type === vscode . FileType . Directory ) {
34
- return base . with ( { path : joinPath ( base . path , filename ) } ) ;
35
- }
36
- } catch {
37
-
38
- }
39
- try {
40
- var base = vscode . Uri . file ( rawbase ) ;
41
- var stat = await vscode . workspace . fs . stat ( base ) ;
42
- if ( stat . type === vscode . FileType . Directory ) {
43
- return base . with ( { path : joinPath ( base . path , filename ) } ) ;
44
- }
45
- } catch {
46
-
47
- }
48
- throw Error ( `Cannot locate: ${ rawbase } ` ) ;
49
- } ;
50
62
var loadingPromise = null ;
51
63
var runtimePromise = ( ) => loadingPromise ??= vscode . window . withProgress ( {
52
64
location : vscode . ProgressLocation . Notification ,
@@ -326,69 +338,7 @@ function activate(context) {
326
338
}
327
339
328
340
var runtime = await runtimePromise ( ) ;
329
- var base = null ;
330
-
331
- var skipCurrentEditor = false ;
332
- var filename = null
333
- if ( fspathname ) {
334
- skipCurrentEditor = true ;
335
- var uris = [ vscode . Uri . parse ( fspathname ) , vscode . Uri . file ( fspathname ) ] ;
336
- for ( var current of uris ) {
337
- var rbase = vscode . workspace . getWorkspaceFolder ( current ) ;
338
- var name = vscode . workspace . asRelativePath ( current , false ) ;
339
- if ( rbase && name ) {
340
- base = rbase . uri ;
341
- filename = name ;
342
- break ;
343
- }
344
- }
345
- if ( filename == null ) {
346
- for ( var workspace of ( vscode . workspace . workspaceFolders || [ ] ) ) {
347
- // Normalize
348
- var nativepathname = vscode . Uri . file ( fspathname ) . fsPath ;
349
- if ( nativepathname . startsWith ( workspace . uri . fsPath ) ) {
350
- base = workspace . uri ;
351
- filename = vscode . workspace . asRelativePath ( workspace . uri . with ( { path : joinPath ( workspace . uri . path , nativepathname . substring ( workspace . uri . fsPath . length ) . replace ( / [ \\ \/ ] + / g, "/" ) ) } ) , false ) ;
352
- break ;
353
- }
354
- }
355
- }
356
- if ( filename == null ) {
357
- // untitled uris will land here
358
- var current = vscode . Uri . parse ( fspathname ) ;
359
- for ( var workspace of ( vscode . workspace . workspaceFolders || [ ] ) ) {
360
- var workspacePath = workspace . uri . path . replace ( / \/ * $ / , "/" ) ;
361
- if ( workspace . uri . scheme === current . scheme && workspace . uri . authority === current . authority && current . path . startsWith ( workspacePath ) ) {
362
- base = workspace . uri ;
363
- filename = current . path . substring ( workspacePath . length ) ;
364
- break ;
365
- }
366
- }
367
- var li = current . path . lastIndexOf ( "/" ) ;
368
- base ??= current . with ( { path : current . path . substring ( 0 , li ) } ) ;
369
- filename ??= current . path . substring ( li + 1 ) ;
370
- try {
371
- await vscode . workspace . fs . stat ( current ) ;
372
- } catch {
373
- // untitled uris cannot be read by readFile
374
- skipCurrentEditor = false ;
375
- }
376
- }
377
- } else {
378
- filename = null ;
379
- var current = textEditor . document . uri ;
380
- for ( var workspace of ( vscode . workspace . workspaceFolders || [ ] ) ) {
381
- var workspacePath = workspace . uri . path . replace ( / \/ * $ / , "/" ) ;
382
- if ( workspace . uri . scheme === current . scheme && workspace . uri . authority === current . authority && current . path . startsWith ( workspacePath ) ) {
383
- base = workspace . uri ;
384
- filename = current . path . substring ( workspacePath . length ) ;
385
- break ;
386
- }
387
- }
388
- var li = current . path . lastIndexOf ( "/" ) ;
389
- base ??= current . with ( { path : current . path . substring ( 0 , li ) } ) ;
390
- filename ??= current . path . substring ( li + 1 ) ;
391
- }
341
+ var { name, base, skipCurrentEditor, filename } = await locatePipeline ( fspathname , name , textEditor ) ;
392
342
var handle = { hasErrors : false , base : base , skipCurrentEditor : skipCurrentEditor , textEditor : textEditor , filename : filename , repositories : repositories , parameters : parameters , error : ( async jsonex => {
393
343
if ( autocompletelist ?. disableErrors ) {
394
344
return ;
@@ -689,6 +639,23 @@ function activate(context) {
689
639
690
640
context . subscriptions . push ( vscode . commands . registerCommand ( 'extension.validateAzurePipeline' , ( ) => validateAzurePipelineCommand ( ) ) ) ;
691
641
642
+ context . subscriptions . push ( vscode . commands . registerCommand ( 'azure-pipelines-vscode-ext.copyTaskAsCommand' , ( ) => {
643
+ vscode . tasks . fetchTasks ( { type : "azure-pipelines-vscode-ext" } ) . then ( tasks =>
644
+ vscode . window . showQuickPick ( tasks . filter ( t => t . definition . program ) . map ( t => t . name ) , { placeHolder : "Select Task to copy as Runner.Client Command" } ) . then ( async name => {
645
+ if ( name ) {
646
+ var task = tasks . find ( t => t . name === name ) ;
647
+ if ( task ) {
648
+ var { filename } = await locatePipeline ( vsVars ( task . definition . program ) , null , null ) ;
649
+ let quiet = task . definition . preview ? " -q" : "" ;
650
+ await vscode . env . clipboard . writeText ( `Runner.Client azexpand${ quiet } -W ${ cliQuote ( filename ) } ${ task . definition . parameters ? Object . entries ( task . definition . parameters ) . reduce ( ( p , c ) => `${ p } --input ${ cliQuote ( `${ c [ 0 ] } =${ typeof c [ 1 ] === 'object' ? JSON . stringify ( c [ 1 ] ) : c [ 1 ] } ` ) } ` , "" ) : "" } ${ task . definition . variables ? Object . entries ( task . definition . variables ) . reduce ( ( p , c ) => `${ p } --var ${ cliQuote ( `${ c [ 0 ] } =${ c [ 1 ] } '` ) } ` , "" ) : "" } ${ task . definition . repositories ? Object . entries ( task . definition . repositories ) . reduce ( ( p , c ) => `${ p } --local-repository ${ cliQuote ( `${ c [ 0 ] } =${ c [ 1 ] } ` ) } ` , "" ) : "" } ` ) ;
651
+ await vscode . window . showInformationMessage ( "Copied to clipboard" ) ;
652
+ return ;
653
+ }
654
+ }
655
+ await vscode . window . showErrorMessage ( "No Task selected" ) ;
656
+ } ) . catch ( err => vscode . window . showErrorMessage ( err . toString ( ) ) ) ) ;
657
+ } ) ) ;
658
+
692
659
var statusbar = vscode . window . createStatusBarItem ( vscode . StatusBarAlignment . Right ) ;
693
660
context . subscriptions . push ( statusbar ) ;
694
661
statusbar . tooltip = "Configure this Icon in Settings" ;
@@ -1026,6 +993,19 @@ function activate(context) {
1026
993
warn : message => writeEmitter . fire ( "\x1b[33m[warn]" + message . replace ( / \r ? \n / g, "\r\n" ) + "\x1b[0m\r\n" ) ,
1027
994
error : message => writeEmitter . fire ( "\x1b[31m[error]" + message . replace ( / \r ? \n / g, "\r\n" ) + "\x1b[0m\r\n" ) ,
1028
995
} ;
996
+ let config = vscode . workspace . getConfiguration ( "azure-pipelines-vscode-ext" ) ;
997
+ if ( config . get ( "create-task-log-files" ) ) {
998
+ let taskChannel = vscode . window . createOutputChannel ( self . name , { log : true } ) ;
999
+ self . disposables . push ( taskChannel ) ;
1000
+ for ( var t in task ) {
1001
+ let type = t ;
1002
+ let org = task [ type ] ;
1003
+ task [ type ] = message => {
1004
+ taskChannel [ type ] ( message ) ;
1005
+ org ( message ) ;
1006
+ }
1007
+ }
1008
+ }
1029
1009
var requestReOpen = true ;
1030
1010
var documentClosed = true ;
1031
1011
var doc = null ;
@@ -1207,6 +1187,73 @@ function activate(context) {
1207
1187
} ) ) ;
1208
1188
}
1209
1189
1190
+ async function locatePipeline ( fspathname , name , textEditor ) {
1191
+ var base = null ;
1192
+
1193
+ var skipCurrentEditor = false ;
1194
+ var filename = null ;
1195
+ if ( fspathname ) {
1196
+ skipCurrentEditor = true ;
1197
+ var uris = [ vscode . Uri . parse ( fspathname ) , vscode . Uri . file ( fspathname ) ] ;
1198
+ for ( var current of uris ) {
1199
+ var rbase = vscode . workspace . getWorkspaceFolder ( current ) ;
1200
+ var name = vscode . workspace . asRelativePath ( current , false ) ;
1201
+ if ( rbase && name ) {
1202
+ base = rbase . uri ;
1203
+ filename = name ;
1204
+ break ;
1205
+ }
1206
+ }
1207
+ if ( filename == null ) {
1208
+ for ( var workspace of ( vscode . workspace . workspaceFolders || [ ] ) ) {
1209
+ // Normalize
1210
+ var nativepathname = vscode . Uri . file ( fspathname ) . fsPath ;
1211
+ if ( nativepathname . startsWith ( workspace . uri . fsPath ) ) {
1212
+ base = workspace . uri ;
1213
+ filename = vscode . workspace . asRelativePath ( workspace . uri . with ( { path : joinPath ( workspace . uri . path , nativepathname . substring ( workspace . uri . fsPath . length ) . replace ( / [ \\ \/ ] + / g, "/" ) ) } ) , false ) ;
1214
+ break ;
1215
+ }
1216
+ }
1217
+ }
1218
+ if ( filename == null ) {
1219
+ // untitled uris will land here
1220
+ var current = vscode . Uri . parse ( fspathname ) ;
1221
+ for ( var workspace of ( vscode . workspace . workspaceFolders || [ ] ) ) {
1222
+ var workspacePath = workspace . uri . path . replace ( / \/ * $ / , "/" ) ;
1223
+ if ( workspace . uri . scheme === current . scheme && workspace . uri . authority === current . authority && current . path . startsWith ( workspacePath ) ) {
1224
+ base = workspace . uri ;
1225
+ filename = current . path . substring ( workspacePath . length ) ;
1226
+ break ;
1227
+ }
1228
+ }
1229
+ var li = current . path . lastIndexOf ( "/" ) ;
1230
+ base ??= current . with ( { path : current . path . substring ( 0 , li ) } ) ;
1231
+ filename ??= current . path . substring ( li + 1 ) ;
1232
+ try {
1233
+ await vscode . workspace . fs . stat ( current ) ;
1234
+ } catch {
1235
+ // untitled uris cannot be read by readFile
1236
+ skipCurrentEditor = false ;
1237
+ }
1238
+ }
1239
+ } else if ( textEditor !== null ) {
1240
+ filename = null ;
1241
+ var current = textEditor . document . uri ;
1242
+ for ( var workspace of ( vscode . workspace . workspaceFolders || [ ] ) ) {
1243
+ var workspacePath = workspace . uri . path . replace ( / \/ * $ / , "/" ) ;
1244
+ if ( workspace . uri . scheme === current . scheme && workspace . uri . authority === current . authority && current . path . startsWith ( workspacePath ) ) {
1245
+ base = workspace . uri ;
1246
+ filename = current . path . substring ( workspacePath . length ) ;
1247
+ break ;
1248
+ }
1249
+ }
1250
+ var li = current . path . lastIndexOf ( "/" ) ;
1251
+ base ??= current . with ( { path : current . path . substring ( 0 , li ) } ) ;
1252
+ filename ??= current . path . substring ( li + 1 ) ;
1253
+ }
1254
+ return { name, base, skipCurrentEditor, filename } ;
1255
+ }
1256
+
1210
1257
// this method is called when your extension is deactivated
1211
1258
function deactivate ( ) { }
1212
1259
0 commit comments