9
9
using System . Collections . Generic ;
10
10
using System . IO ;
11
11
using System . Linq ;
12
+ using System . Text . RegularExpressions ;
12
13
using System . Management . Automation ;
13
14
using System . Net ;
14
15
using System . Net . Http ;
@@ -440,12 +441,28 @@ internal void PushResource(string Repository, string modulePrefix, bool SkipDepe
440
441
{
441
442
ContainerRegistryServerAPICalls containerRegistryServer = new ContainerRegistryServerAPICalls ( repository , _cmdletPassedIn , _networkCredential , userAgentString ) ;
442
443
443
- var pkgMetadataFile = ( resourceType == ResourceType . Script ) ? pathToScriptFileToPublish : pathToModuleManifestToPublish ;
444
+ if ( _isNupkgPathSpecified )
445
+ {
446
+ // copy the .nupkg to a temp path (outputNupkgDir field) as we don't want to tamper with the original, possibly signed, .nupkg file
447
+ string copiedNupkgFilePath = CopyNupkgFileToTempPath ( nupkgFilePath : Path , errRecord : out ErrorRecord copyErrRecord ) ;
448
+ if ( copyErrRecord != null )
449
+ {
450
+ _cmdletPassedIn . WriteError ( copyErrRecord ) ;
451
+ return ;
452
+ }
453
+
454
+ // get package info (name, version, metadata hashtable) from the copied .nupkg package and then populate appropriate fields (_pkgName, _pkgVersion, parsedMetadata)
455
+ GetPackageInfoFromNupkg ( nupkgFilePath : copiedNupkgFilePath , errRecord : out ErrorRecord pkgInfoErrRecord ) ;
456
+ if ( pkgInfoErrRecord != null )
457
+ {
458
+ _cmdletPassedIn . WriteError ( pkgInfoErrRecord ) ;
459
+ return ;
460
+ }
461
+ }
444
462
445
- if ( ! containerRegistryServer . PushNupkgContainerRegistry ( pkgMetadataFile , outputNupkgDir , _pkgName , modulePrefix , _pkgVersion , resourceType , parsedMetadata , dependencies , out ErrorRecord pushNupkgContainerRegistryError ) )
463
+ if ( ! containerRegistryServer . PushNupkgContainerRegistry ( outputNupkgDir , _pkgName , modulePrefix , _pkgVersion , resourceType , parsedMetadata , dependencies , _isNupkgPathSpecified , Path , out ErrorRecord pushNupkgContainerRegistryError ) )
446
464
{
447
465
_cmdletPassedIn . WriteError ( pushNupkgContainerRegistryError ) ;
448
- // exit out of processing
449
466
return ;
450
467
}
451
468
}
@@ -455,6 +472,7 @@ internal void PushResource(string Repository, string modulePrefix, bool SkipDepe
455
472
{
456
473
outputNupkgDir = pathToNupkgToPublish ;
457
474
}
475
+
458
476
// This call does not throw any exceptions, but it will write unsuccessful responses to the console
459
477
if ( ! PushNupkg ( outputNupkgDir , repository . Name , repository . Uri . ToString ( ) , out ErrorRecord pushNupkgError ) )
460
478
{
@@ -474,7 +492,8 @@ internal void PushResource(string Repository, string modulePrefix, bool SkipDepe
474
492
}
475
493
finally
476
494
{
477
- if ( ! _isNupkgPathSpecified )
495
+ // For scenarios such as Publish-PSResource -NupkgPath -Repository <non-container registry repository>, the outputNupkgDir will be set to NupkgPath path, and a temp outputDir folder will not have been created and thus doesn't need to attempt to be deleted
496
+ if ( Directory . Exists ( outputDir ) )
478
497
{
479
498
_cmdletPassedIn . WriteVerbose ( string . Format ( "Deleting temporary directory '{0}'" , outputDir ) ) ;
480
499
Utils . DeleteDirectory ( outputDir ) ;
@@ -1243,6 +1262,191 @@ private bool CheckDependenciesExist(Hashtable dependencies, string repositoryNam
1243
1262
return true ;
1244
1263
}
1245
1264
1265
+ /// <summary>
1266
+ /// This method is called by Publish-PSResource when the -NupkgPath parameter is specified
1267
+ /// The method copies the .nupkg file to a temp path (populated at outputNupkgDir field) as we dont' want to extract and read original .nupkg file
1268
+ /// </summary>
1269
+ private string CopyNupkgFileToTempPath ( string nupkgFilePath , out ErrorRecord errRecord )
1270
+ {
1271
+ errRecord = null ;
1272
+ string destinationFilePath = String . Empty ;
1273
+ var packageFullName = System . IO . Path . GetFileName ( nupkgFilePath ) ;
1274
+ try
1275
+ {
1276
+ if ( ! Directory . Exists ( outputDir ) )
1277
+ {
1278
+ Directory . CreateDirectory ( outputDir ) ;
1279
+ if ( ! Directory . Exists ( outputNupkgDir ) )
1280
+ {
1281
+ Directory . CreateDirectory ( outputNupkgDir ) ;
1282
+ }
1283
+ }
1284
+
1285
+ destinationFilePath = System . IO . Path . Combine ( outputNupkgDir , packageFullName ) ;
1286
+ File . Copy ( Path , destinationFilePath ) ;
1287
+ }
1288
+ catch ( Exception e )
1289
+ {
1290
+ errRecord = new ErrorRecord (
1291
+ new ArgumentException ( $ "Error moving .nupkg at -NupkgPath to temp nupkg dir path '{ outputNupkgDir } ' due to: '{ e . Message } '.") ,
1292
+ "ErrorMovingNupkg" ,
1293
+ ErrorCategory . NotSpecified ,
1294
+ this ) ;
1295
+
1296
+ // exit process record
1297
+ return destinationFilePath ;
1298
+ }
1299
+
1300
+ return destinationFilePath ;
1301
+ }
1302
+
1303
+ /// <summary>
1304
+ /// Get package info from the .nupkg file provided, inluding package name (_pkgName), package version (_pkgVersion), and metadata parsed into a hashtable (parsedMetadata)
1305
+ /// </summary>
1306
+ private void GetPackageInfoFromNupkg ( string nupkgFilePath , out ErrorRecord errRecord )
1307
+ {
1308
+ errRecord = null ;
1309
+ Regex rx = new Regex ( @"\.\d+\." , RegexOptions . Compiled | RegexOptions . IgnoreCase ) ;
1310
+ var packageFullName = System . IO . Path . GetFileName ( nupkgFilePath ) ;
1311
+ MatchCollection matches = rx . Matches ( packageFullName ) ;
1312
+ if ( matches . Count == 0 )
1313
+ {
1314
+ return ;
1315
+ }
1316
+
1317
+ Match match = matches [ 0 ] ;
1318
+
1319
+ GroupCollection groups = match . Groups ;
1320
+ if ( groups . Count == 0 )
1321
+ {
1322
+ return ;
1323
+ }
1324
+
1325
+ Capture group = groups [ 0 ] ;
1326
+
1327
+ string pkgFoundName = packageFullName . Substring ( 0 , group . Index ) ;
1328
+
1329
+ string version = packageFullName . Substring ( group . Index + 1 , packageFullName . LastIndexOf ( '.' ) - group . Index - 1 ) ;
1330
+ _cmdletPassedIn . WriteDebug ( $ "Found package '{ pkgFoundName } ', version '{ version } ', from packageFullName '{ packageFullName } ' at path '{ Path } '") ;
1331
+
1332
+ if ( ! NuGetVersion . TryParse ( version , out NuGetVersion nugetVersion ) )
1333
+ {
1334
+ errRecord = new ErrorRecord (
1335
+ new ArgumentException ( $ "Error parsing version '{ version } ' into NuGetVersion instance.") ,
1336
+ "ErrorParsingNuGetVersion" ,
1337
+ ErrorCategory . NotSpecified ,
1338
+ this ) ;
1339
+
1340
+ return ;
1341
+ }
1342
+
1343
+ _pkgName = pkgFoundName ;
1344
+ _pkgVersion = nugetVersion ;
1345
+ parsedMetadata = GetMetadataFromNupkg ( nupkgFilePath , _pkgName , out errRecord ) ;
1346
+ }
1347
+
1348
+ /// <summary>
1349
+ /// Extract copied .nupkg, find metadata file (either .ps1, .psd1, or .nuspec) and read metadata into a hashtable
1350
+ /// </summary>
1351
+ internal Hashtable GetMetadataFromNupkg ( string copiedNupkgPath , string packageName , out ErrorRecord errRecord )
1352
+ {
1353
+ Hashtable pkgMetadata = new Hashtable ( StringComparer . OrdinalIgnoreCase ) ;
1354
+ errRecord = null ;
1355
+
1356
+ // in temp directory create an "extract" folder to which we'll copy .nupkg to, extract contents, etc.
1357
+ string nupkgDirPath = Directory . GetParent ( copiedNupkgPath ) . FullName ; //someGuid/nupkg/myPkg.nupkg -> /someGuid/nupkg
1358
+ string tempPath = Directory . GetParent ( nupkgDirPath ) . FullName ; // someGuid
1359
+ var extractPath = System . IO . Path . Combine ( tempPath , "extract" ) ; // someGuid/extract
1360
+
1361
+ try
1362
+ {
1363
+ var dir = Directory . CreateDirectory ( extractPath ) ;
1364
+ dir . Attributes &= ~ FileAttributes . ReadOnly ;
1365
+
1366
+ // change extension to .zip
1367
+ string zipFilePath = System . IO . Path . ChangeExtension ( copiedNupkgPath , ".zip" ) ;
1368
+ File . Move ( copiedNupkgPath , zipFilePath ) ;
1369
+
1370
+ // extract from .zip
1371
+ _cmdletPassedIn . WriteDebug ( $ "Extracting '{ zipFilePath } ' to '{ extractPath } '") ;
1372
+ System . IO . Compression . ZipFile . ExtractToDirectory ( zipFilePath , extractPath ) ;
1373
+
1374
+ string psd1FilePath = String . Empty ;
1375
+ string ps1FilePath = String . Empty ;
1376
+ string nuspecFilePath = String . Empty ;
1377
+ Utils . GetMetadataFilesFromPath ( extractPath , packageName , out psd1FilePath , out ps1FilePath , out nuspecFilePath , out string properCasingPkgName ) ;
1378
+
1379
+ List < string > pkgTags = new List < string > ( ) ;
1380
+
1381
+ if ( File . Exists ( psd1FilePath ) )
1382
+ {
1383
+ _cmdletPassedIn . WriteDebug ( $ "Attempting to read module manifest file '{ psd1FilePath } '") ;
1384
+ if ( ! Utils . TryReadManifestFile ( psd1FilePath , out pkgMetadata , out Exception readManifestError ) )
1385
+ {
1386
+ errRecord = new ErrorRecord (
1387
+ readManifestError ,
1388
+ "GetMetadataFromNupkgFailure" ,
1389
+ ErrorCategory . ParserError ,
1390
+ this ) ;
1391
+
1392
+ return pkgMetadata ;
1393
+ }
1394
+ }
1395
+ else if ( File . Exists ( ps1FilePath ) )
1396
+ {
1397
+ _cmdletPassedIn . WriteDebug ( $ "Attempting to read script file '{ ps1FilePath } '") ;
1398
+ if ( ! PSScriptFileInfo . TryTestPSScriptFileInfo ( ps1FilePath , out PSScriptFileInfo parsedScript , out ErrorRecord [ ] errors , out string [ ] verboseMsgs ) )
1399
+ {
1400
+ errRecord = new ErrorRecord (
1401
+ new InvalidDataException ( $ "PSScriptFile could not be read properly") ,
1402
+ "GetMetadataFromNupkgFailure" ,
1403
+ ErrorCategory . ParserError ,
1404
+ this ) ;
1405
+
1406
+ return pkgMetadata ;
1407
+ }
1408
+
1409
+ pkgMetadata = parsedScript . ToHashtable ( ) ;
1410
+ }
1411
+ else if ( File . Exists ( nuspecFilePath ) )
1412
+ {
1413
+ _cmdletPassedIn . WriteDebug ( $ "Attempting to read nuspec file '{ nuspecFilePath } '") ;
1414
+ pkgMetadata = Utils . GetMetadataFromNuspec ( nuspecFilePath , _cmdletPassedIn , out errRecord ) ;
1415
+ if ( errRecord != null )
1416
+ {
1417
+ return pkgMetadata ;
1418
+ }
1419
+ }
1420
+ else
1421
+ {
1422
+ errRecord = new ErrorRecord (
1423
+ new InvalidDataException ( $ ".nupkg package must contain either .psd1, .ps1, or .nuspec file and none were found") ,
1424
+ "GetMetadataFromNupkgFailure" ,
1425
+ ErrorCategory . InvalidData ,
1426
+ this ) ;
1427
+
1428
+ return pkgMetadata ;
1429
+ }
1430
+ }
1431
+ catch ( Exception e )
1432
+ {
1433
+ errRecord = new ErrorRecord (
1434
+ new InvalidOperationException ( $ "Temporary folder for installation could not be created or set due to: { e . Message } ") ,
1435
+ "GetMetadataFromNupkgFailure" ,
1436
+ ErrorCategory . InvalidOperation ,
1437
+ this ) ;
1438
+ }
1439
+ finally
1440
+ {
1441
+ if ( Directory . Exists ( extractPath ) )
1442
+ {
1443
+ Utils . DeleteDirectory ( extractPath ) ;
1444
+ }
1445
+ }
1446
+
1447
+ return pkgMetadata ;
1448
+ }
1449
+
1246
1450
#endregion
1247
1451
}
1248
1452
}
0 commit comments