@@ -18,6 +18,7 @@ namespace Google {
18
18
using System ;
19
19
using System . IO ;
20
20
using System . Collections . Generic ;
21
+ using System . Text . RegularExpressions ;
21
22
using UnityEditor ;
22
23
23
24
/// <summary>
@@ -37,7 +38,19 @@ internal class FileUtils {
37
38
/// <summary>
38
39
/// The name of Packages folder
39
40
/// </summary>
40
- public readonly static string PACKAGES_FOLDER = "Packages" ;
41
+ private readonly static string PACKAGES_FOLDER = "Packages" ;
42
+
43
+ /// <summary>
44
+ /// Regex to match packages folder like "Packages/com.company.pkg"
45
+ /// </summary>
46
+ private static Regex PACKAGES_ASSETDB_PATH_REGEX =
47
+ new Regex ( @"^(Packages[/\\][^/\\]+)([/\\].*)?$" ) ;
48
+
49
+ /// <summary>
50
+ /// Regex to match packages folder like "Library/PackageCache/com.company.pkg"
51
+ /// </summary>
52
+ private static Regex PACKAGES_PHYSICAL_PATH_REGEX =
53
+ new Regex ( @"^(Library[/\\]PackageCache[/\\])([^/\\]+)(@[^/\\]+)([/\\].*)?$" ) ;
41
54
42
55
/// <summary>
43
56
/// Returns the project directory (e.g contains the Assets folder).
@@ -352,42 +365,99 @@ public static bool CheckoutFile(string path, Logger logger) {
352
365
/// <param name="directory">Directory to check whether the path is under.</param>
353
366
/// <returns>True if the path is under the directory.</returns>
354
367
public static bool IsUnderDirectory ( string path , string directory ) {
368
+ if ( String . IsNullOrEmpty ( directory ) ) {
369
+ return false ;
370
+ }
355
371
if ( ! directory . EndsWith ( Path . DirectorySeparatorChar . ToString ( ) ) ) {
356
372
directory = directory + Path . DirectorySeparatorChar ;
357
373
}
358
374
return NormalizePathSeparators ( path . ToLower ( ) ) . StartsWith ( directory . ToLower ( ) ) ;
359
375
}
360
376
377
+ /// <summary>
378
+ /// Enum of different types of package directory.
379
+ /// </summary>
380
+ public enum PackageDirectoryType {
381
+ None = 0 ,
382
+ // Package path like "Packages/package-id", which is logical path only AssetDatabase
383
+ // can recognize.
384
+ AssetDatabasePath = 1 ,
385
+ // Package path like "Library/PackageCache/package-id@version", which is the physical
386
+ // path on the disk.
387
+ PhysicalPath = 2
388
+ }
389
+
390
+ /// <summary>
391
+ /// Checks if the given path is under the Package directory.
392
+ /// </summary>
393
+ /// <param name="path">Path to the file/directory.</param>
394
+ /// <returns>
395
+ /// PackageDirectoryType.None if the path is not under Package directory.
396
+ /// PackageDirectoryType.AssetDatabasePath if path matches "Packages/package-id".
397
+ /// PackageDirectoryType.PhysicalPath if path matches "Library/PackageCache/package-id".
398
+ /// </returns>
399
+ public static PackageDirectoryType GetPackageDirectoryType ( string path ) {
400
+ if ( PACKAGES_ASSETDB_PATH_REGEX . IsMatch ( path ) ) {
401
+ return PackageDirectoryType . AssetDatabasePath ;
402
+ }
403
+ if ( PACKAGES_PHYSICAL_PATH_REGEX . IsMatch ( path ) ) {
404
+ return PackageDirectoryType . PhysicalPath ;
405
+ }
406
+ return PackageDirectoryType . None ;
407
+ }
408
+
409
+ /// <summary>
410
+ /// Checks if the given path is under the Package directory.
411
+ /// </summary>
412
+ /// <param name="path">Path to the file/directory.</param>
413
+ /// <returns> True if the path is under package directory.</returns>
414
+ public static bool IsUnderPackageDirectory ( string path ) {
415
+ return GetPackageDirectoryType ( path ) != PackageDirectoryType . None ;
416
+ }
417
+
361
418
/// <summary>
362
419
/// Get the package directory from the path.
363
420
/// The package directory should look like "Packages/package-id", where package id is
364
421
/// the Unity Package Manager package name.
365
- /// Ex. "Packages/com.google.unity-jar-resolver" if actualPath is false, or
366
- /// "Library/PackageCache/[email protected] /" if true.
367
- /// Logical path is
368
422
/// Note that there is no way to get physical path if the package is installed from disk.
369
423
/// </summary>
370
424
/// <param name="path">Path to the file/directory.</param>
371
- /// <param name="actualPath">If false, return logical path only recognizable by
372
- /// AssetDatabase. Otherwise, return physical path of the package.</param>
373
- /// <returns>Package directory part of the given path. Empty string if the path is not valid
374
- /// .</returns>
375
- public static string GetPackageDirectory ( string path , bool actualPath ) {
376
- if ( ! IsUnderDirectory ( path , PACKAGES_FOLDER ) ) {
377
- return "" ;
378
- }
379
-
380
- string [ ] components = SplitPathIntoComponents ( path ) ;
381
- if ( components . Length < 2 ) {
382
- return "" ;
383
- }
384
-
385
- string packageDir = components [ 0 ] + Path . DirectorySeparatorChar + components [ 1 ] ;
386
- if ( actualPath ) {
387
- // This only works if the package is NOT installed from disk. That is, it should
388
- // work if the package is installed from a local tarball or from a registry server.
389
- string absolutePath = Path . GetFullPath ( packageDir ) ;
390
- packageDir = absolutePath . Substring ( ProjectDirectory . Length + 1 ) ;
425
+ /// <param name="directoryType">
426
+ /// If PackageDirectoryType.None, return package directoy as it is in the path.
427
+ /// If PackageDirectoryType.AssetDatabasePath, return package directory like
428
+ /// "Packages/package-id".
429
+ /// If PackageDirectoryType.PhysicalPath, return package directory like
430
+ /// "Library/PackageCache/package-id@version".
431
+ /// </param>
432
+ /// <returns>Package directory part of the given path. Empty string if the path is not under
433
+ /// package directory.</returns>
434
+ public static string GetPackageDirectory (
435
+ string path ,
436
+ PackageDirectoryType directoryType = PackageDirectoryType . None ) {
437
+ string packageDir = null ;
438
+ var nameMatch = PACKAGES_ASSETDB_PATH_REGEX . Match ( path ) ;
439
+ if ( nameMatch . Success ) {
440
+ packageDir = nameMatch . Groups [ 1 ] . Value ;
441
+ if ( directoryType == PackageDirectoryType . PhysicalPath ) {
442
+ // This only works if the package is NOT installed from disk. That is, it should
443
+ // work if the package is installed from a local tarball or from a registry
444
+ // server.
445
+ string absolutePath = Path . GetFullPath ( packageDir ) ;
446
+ packageDir = absolutePath . Substring ( ProjectDirectory . Length + 1 ) ;
447
+ }
448
+ } else {
449
+ nameMatch = PACKAGES_PHYSICAL_PATH_REGEX . Match ( path ) ;
450
+ if ( nameMatch . Success ) {
451
+ if ( directoryType == PackageDirectoryType . AssetDatabasePath ) {
452
+ packageDir = Path . Combine ( PACKAGES_FOLDER , nameMatch . Groups [ 2 ] . Value ) ;
453
+ } else {
454
+ packageDir = nameMatch . Groups [ 1 ] . Value +
455
+ nameMatch . Groups [ 2 ] . Value +
456
+ nameMatch . Groups [ 3 ] . Value ;
457
+ }
458
+ } else {
459
+ packageDir = "" ;
460
+ }
391
461
}
392
462
393
463
return packageDir ;
0 commit comments