Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
PackageSession.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 using System.Collections.Specialized;
6 using System.Diagnostics;
7 using System.IO;
8 using System.Linq;
9 using System.Threading;
10 using Microsoft.Build.Execution;
11 using SharpYaml;
12 using SiliconStudio.Assets.Analysis;
13 using SiliconStudio.Core;
14 using SiliconStudio.Core.Collections;
15 using SiliconStudio.Core.Diagnostics;
16 using SiliconStudio.Core.IO;
17 using SiliconStudio.Assets.Diagnostics;
18 using SiliconStudio.Core.Reflection;
19 using SiliconStudio.Core.Storage;
20 using SiliconStudio.Core.VisualStudio;
21 
22 namespace SiliconStudio.Assets
23 {
24  /// <summary>
25  /// A session for editing a package.
26  /// </summary>
27  public sealed class PackageSession : IDisposable, IDirtyable
28  {
29  private readonly PackageCollection packagesCopy;
30  private readonly PackageCollection packages;
31  private readonly AssemblyContainer assemblyContainer;
32  private readonly object dependenciesLock = new object();
33  private Package currentPackage;
34  private AssetDependencyManager dependencies;
35 
36  public event Action<Asset> AssetDirtyChanged;
37 
38  /// <summary>
39  /// Initializes a new instance of the <see cref="PackageSession"/> class.
40  /// </summary>
41  public PackageSession() : this(null)
42  {
43  }
44 
45  /// <summary>
46  /// Initializes a new instance of the <see cref="PackageSession"/> class.
47  /// </summary>
48  public PackageSession(Package package)
49  {
50  packages = new PackageCollection();
51  packagesCopy = new PackageCollection();
52  assemblyContainer = new AssemblyContainer();
53  packages.CollectionChanged += PackagesCollectionChanged;
54  if (package != null)
55  {
56  Packages.Add(package);
57  }
58  }
59 
60  /// <inheritdoc/>
61  public bool IsDirty { get; set; }
62 
63  /// <summary>
64  /// Gets the packages.
65  /// </summary>
66  /// <value>The packages.</value>
67  public PackageCollection Packages
68  {
69  get
70  {
71  return packages;
72  }
73  }
74 
75  /// <summary>
76  /// Gets the user packages (excluding system packages).
77  /// </summary>
78  /// <value>The user packages.</value>
79  public IEnumerable<Package> LocalPackages
80  {
81  get
82  {
83  return packages.Where(package => !package.IsSystem);
84  }
85  }
86 
87  /// <summary>
88  /// Gets or sets the solution path (sln) in case the session was loaded from a solution.
89  /// </summary>
90  /// <value>The solution path.</value>
91  public UFile SolutionPath { get; set; }
92 
93  /// <summary>
94  /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
95  /// </summary>
96  public void Dispose()
97  {
98  if (dependencies != null)
99  {
100  dependencies.Dispose();
101  }
102  }
103 
104  /// <summary>
105  /// Gets a value indicating whether this instance has dependency manager.
106  /// </summary>
107  /// <value><c>true</c> if this instance has dependency manager; otherwise, <c>false</c>.</value>
108  public bool HasDependencyManager
109  {
110  get
111  {
112  lock (dependenciesLock)
113  {
114  return dependencies != null;
115  }
116  }
117  }
118 
119  /// <summary>
120  /// Gets or sets the selected current package.
121  /// </summary>
122  /// <value>The selected current package.</value>
123  /// <exception cref="System.InvalidOperationException">Expecting a package that is already registered in this session</exception>
124  public Package CurrentPackage
125  {
126  get
127  {
128  return currentPackage;
129  }
130  set
131  {
132  if (value != null)
133  {
134  if (!Packages.Contains(value))
135  {
136  throw new InvalidOperationException("Expecting a package that is already registered in this session");
137  }
138  }
139  currentPackage = value;
140  }
141  }
142 
143  /// <summary>
144  /// Gets the packages referenced by the current package.
145  /// </summary>
146  /// <returns>IEnumerable&lt;Package&gt;.</returns>
148  {
149  if (CurrentPackage == null)
150  {
151  yield break;
152  }
153 
154  yield return CurrentPackage;
155 
156  foreach (var storeDep in CurrentPackage.Meta.Dependencies)
157  {
158  var package = Packages.Find(storeDep);
159  // In case the package is not found (when working with session not fully loaded/resolved with all deps)
160  if (package != null)
161  {
162  yield return package;
163  }
164  }
165 
166  foreach (var localDep in CurrentPackage.LocalDependencies)
167  {
168  var package = Packages.Find(localDep.Id);
169  // In case the package is not found (when working with session not fully loaded/resolved with all deps)
170  if (package != null)
171  {
172  yield return package;
173  }
174  }
175  }
176 
177  /// <summary>
178  /// Gets the dependency manager.
179  /// </summary>
180  /// <value>AssetDependencyManager.</value>
181  public AssetDependencyManager DependencyManager
182  {
183  get
184  {
185  lock (dependenciesLock)
186  {
187  return dependencies ?? (dependencies = new AssetDependencyManager(this));
188  }
189  }
190  }
191 
192  /// <summary>
193  /// Adds an existing package to the current session.
194  /// </summary>
195  /// <param name="packagePath">The package path.</param>
196  /// <param name="loadParameters">The load parameters.</param>
197  /// <exception cref="System.ArgumentNullException">packagePath</exception>
198  /// <exception cref="System.IO.FileNotFoundException">Unable to find package</exception>
199  public LoggerResult AddExistingPackage(UFile packagePath, PackageLoadParameters loadParameters = null)
200  {
201  var loggerResult = new LoggerResult();
202  AddExistingPackage(packagePath, loggerResult, loadParameters);
203  return loggerResult;
204  }
205 
206  /// <summary>
207  /// Adds an existing package to the current session.
208  /// </summary>
209  /// <param name="packagePath">The package path.</param>
210  /// <param name="logger">The session result.</param>
211  /// <param name="loadParametersArg">The load parameters argument.</param>
212  /// <exception cref="System.ArgumentNullException">packagePath</exception>
213  /// <exception cref="System.ArgumentException">Invalid relative path. Expecting an absolute package path;packagePath</exception>
214  /// <exception cref="System.IO.FileNotFoundException">Unable to find package</exception>
215  public Package AddExistingPackage(UFile packagePath, ILogger logger, PackageLoadParameters loadParametersArg = null)
216  {
217  if (packagePath == null) throw new ArgumentNullException("packagePath");
218  if (logger == null) throw new ArgumentNullException("logger");
219  if (!packagePath.IsAbsolute) throw new ArgumentException("Invalid relative path. Expecting an absolute package path", "packagePath");
220  if (!File.Exists(packagePath)) throw new FileNotFoundException("Unable to find package", packagePath);
221 
222  var loadParameters = loadParametersArg ?? PackageLoadParameters.Default();
223 
224  Package package;
225  try
226  {
227  // Enable reference analysis caching during loading
228  AssetReferenceAnalysis.EnableCaching = true;
229 
230  var packagesLoaded = new PackageCollection();
231 
232  package = PreLoadPackage(this, logger, packagePath, false, packagesLoaded, loadParameters);
233 
234  // Run analysis after
235  foreach (var packageToAdd in packagesLoaded)
236  {
237  var analysis = new PackageAnalysis(packageToAdd, GetPackageAnalysisParametersForLoad());
238  analysis.Run(logger);
239  }
240  }
241  finally
242  {
243  // Disable reference analysis caching after loading
244  AssetReferenceAnalysis.EnableCaching = false;
245  }
246  return package;
247  }
248 
249  /// <summary>
250  /// Loads a package from specified file path.
251  /// </summary>
252  /// <param name="filePath">The file path to a package file.</param>
253  /// <param name="sessionResult">The session result.</param>
254  /// <param name="loadParameters">The load parameters.</param>
255  /// <returns>A package.</returns>
256  /// <exception cref="System.ArgumentNullException">filePath</exception>
257  /// <exception cref="System.ArgumentException">File [{0}] must exist.ToFormat(filePath);filePath</exception>
258  public static void Load(string filePath, PackageSessionResult sessionResult, PackageLoadParameters loadParameters = null)
259  {
260  if (filePath == null) throw new ArgumentNullException("filePath");
261  if (sessionResult == null) throw new ArgumentNullException("sessionResult");
262 
263  // Make sure with have valid parameters
264  loadParameters = loadParameters ?? PackageLoadParameters.Default();
265 
266  // Make sure to use a full path.
267  filePath = FileUtility.GetAbsolutePath(filePath);
268 
269  if (!File.Exists(filePath)) throw new ArgumentException("File [{0}] must exist".ToFormat(filePath), "filePath");
270 
271  try
272  {
273  // Enable reference analysis caching during loading
274  AssetReferenceAnalysis.EnableCaching = true;
275 
276  using (var profile = Profiler.Begin(PackageSessionProfilingKeys.Loading))
277  {
278  sessionResult.Clear();
279  sessionResult.Progress("Loading..", 0, 1);
280 
281  var session = new PackageSession();
282 
283  var packagePaths = new List<string>();
284 
285  // If we have a solution, load all packages
286  if (PackageSessionHelper.IsSolutionFile(filePath))
287  {
288  PackageSessionHelper.LoadSolution(session, filePath, packagePaths, sessionResult);
289  }
290  else if (PackageSessionHelper.IsPackageFile(filePath))
291  {
292  packagePaths.Add(filePath);
293  }
294  else
295  {
296  sessionResult.Error("Unsupported file extension (only .sln or {0} are supported)", Package.PackageFileExtension);
297  return;
298  }
299 
300  var cancelToken = loadParameters.CancelToken;
301 
302  // Load all packages
303  var packagesLoaded = new PackageCollection();
304  foreach (var packageFilePath in packagePaths)
305  {
306  PreLoadPackage(session, sessionResult, packageFilePath, false, packagesLoaded, loadParameters);
307 
308  // Output the session only if there is no cancellation
309  if (cancelToken.HasValue && cancelToken.Value.IsCancellationRequested)
310  {
311  return;
312  }
313  }
314 
315  // Load all missing references/dependencies
316  session.LoadMissingReferences(sessionResult, loadParameters);
317 
318  // Fix relative references
319  var analysis = new PackageSessionAnalysis(session, GetPackageAnalysisParametersForLoad());
320  var analysisResults = analysis.Run();
321  analysisResults.CopyTo(sessionResult);
322 
323  // Output the session only if there is no cancellation
324  if (!cancelToken.HasValue || !cancelToken.Value.IsCancellationRequested)
325  {
326  sessionResult.Session = session;
327 
328  // Defer the initialization of the dependency manager
329  //session.DependencyManager.InitializeDeferred();
330  }
331 
332  // The session is not dirty when loading it
333  session.IsDirty = false;
334  }
335  }
336  finally
337  {
338  // Disable reference analysis caching after loading
339  AssetReferenceAnalysis.EnableCaching = false;
340  }
341  }
342 
343  /// <summary>
344  /// Loads a package from specified file path.
345  /// </summary>
346  /// <param name="filePath">The file path to a package file.</param>
347  /// <param name="loadParameters">The load parameters.</param>
348  /// <returns>A package.</returns>
349  /// <exception cref="System.ArgumentNullException">filePath</exception>
350  public static PackageSessionResult Load(string filePath, PackageLoadParameters loadParameters = null)
351  {
352  var result = new PackageSessionResult();
353  Load(filePath, result, loadParameters);
354  return result;
355  }
356 
357  /// <summary>
358  /// Loads the missing references
359  /// </summary>
360  /// <param name="log">The log.</param>
361  /// <param name="loadParametersArg">The load parameters argument.</param>
362  public void LoadMissingReferences(ILogger log, PackageLoadParameters loadParametersArg = null)
363  {
364  var loadParameters = loadParametersArg ?? PackageLoadParameters.Default();
365 
366  var cancelToken = loadParameters.CancelToken;
367 
368  var packagesLoaded = new PackageCollection();
369 
370  // Make a copy of Packages as it can be modified by PreLoadPackageDependencies
371  var previousPackages = Packages.ToList();
372  foreach (var package in previousPackages)
373  {
374  // Output the session only if there is no cancellation
375  if (cancelToken.HasValue && cancelToken.Value.IsCancellationRequested)
376  {
377  return;
378  }
379 
380  PreLoadPackageDependencies(this, log, package, packagesLoaded, loadParameters);
381  }
382  }
383 
384  /// <summary>
385  /// Saves all packages and assets.
386  /// </summary>
387  /// <returns>Result of saving.</returns>
389  {
390  var log = new LoggerResult();
391 
392  bool packagesSaved = false;
393 
394  //var clock = Stopwatch.StartNew();
395  using (var profile = Profiler.Begin(PackageSessionProfilingKeys.Saving))
396  {
397  try
398  {
399  // Grab all previous assets
400  var previousAssets = new Dictionary<Guid, AssetItem>();
401  foreach (var assetItem in packagesCopy.SelectMany(package => package.Assets))
402  {
403  previousAssets[assetItem.Id] = assetItem;
404  }
405 
406  // Grab all new assets
407  var newAssets = new Dictionary<Guid, AssetItem>();
408  foreach (var assetItem in LocalPackages.SelectMany(package => package.Assets))
409  {
410  newAssets[assetItem.Id] = assetItem;
411  }
412 
413  // Compute all assets that were removed
414  var assetsOrPackagesToRemove = new Dictionary<UFile, object>();
415  foreach (var assetIt in previousAssets)
416  {
417  var asset = assetIt.Value;
418 
419  AssetItem newAsset;
420  if (!newAssets.TryGetValue(assetIt.Key, out newAsset) || newAsset.Location != asset.Location)
421  {
422  assetsOrPackagesToRemove[asset.FullPath] = asset;
423  }
424  }
425 
426  // Compute packages that have been renamed
427  // TODO: Disable for now, as not sure if we want to delete a previous package
428  //foreach (var package in packagesCopy)
429  //{
430  // var newPackage = packages.Find(package.Id);
431  // if (newPackage != null && package.PackagePath != null && newPackage.PackagePath != package.PackagePath)
432  // {
433  // assetsOrPackagesToRemove[package.PackagePath] = package;
434  // }
435  //}
436 
437  // If package are not modified, return immediately
438  if (!CheckModifiedPackages() && assetsOrPackagesToRemove.Count == 0)
439  {
440  return log;
441  }
442 
443  // Suspend tracking when saving as we don't want to receive
444  // all notification events
445  if (dependencies != null)
446  {
447  dependencies.BeginSavingSession();
448  }
449 
450  // Return immediately if there is any error
451  if (log.HasErrors)
452  {
453  return log;
454  }
455 
456  // Delete previous files
457  foreach (var fileIt in assetsOrPackagesToRemove)
458  {
459  var assetPath = fileIt.Key;
460  var assetItemOrPackage = fileIt.Value;
461 
462  if (File.Exists(assetPath))
463  {
464  try
465  {
466  File.Delete(assetPath);
467  }
468  catch (Exception ex)
469  {
470  var assetItem = assetItemOrPackage as AssetItem;
471  if (assetItem != null)
472  {
473  log.Error(assetItem.Package, assetItem.ToReference(), AssetMessageCode.AssetCannotDelete, ex, assetPath);
474  }
475  else
476  {
477  var package = assetItemOrPackage as Package;
478  if (package != null)
479  {
480  log.Error(package, null, AssetMessageCode.AssetCannotDelete, ex, assetPath);
481  }
482  }
483  }
484  }
485  }
486 
487  // Save all dirty assets
488  packagesCopy.Clear();
489  foreach (var package in LocalPackages)
490  {
491  // Save the package to disk and all its assets
492  package.Save(log);
493 
494  // Clone the package (but not all assets inside, just the structure)
495  var packageClone = package.Clone(false);
496  packagesCopy.Add(packageClone);
497  }
498 
499  packagesSaved = true;
500  }
501  finally
502  {
503  if (dependencies != null)
504  {
505  dependencies.EndSavingSession();
506  }
507 
508  // Once all packages and assets have been saved, we can save the solution (as we need to have fullpath to
509  // be setup for the packages)
510  if (packagesSaved)
511  {
512  PackageSessionHelper.SaveSolution(this, log);
513  }
514  }
515 
516  //System.Diagnostics.Trace.WriteLine("Elapsed saved: " + clock.ElapsedMilliseconds);
517  IsDirty = false;
518 
519  return log;
520  }
521  }
522 
523  private bool CheckModifiedPackages()
524  {
525  if (IsDirty)
526  {
527  return true;
528  }
529 
530  foreach (var package in LocalPackages)
531  {
532  if (package.IsDirty || package.Assets.IsDirty)
533  {
534  return true;
535  }
536  if (package.Assets.Any(item => item.IsDirty))
537  {
538  return true;
539  }
540  }
541  return false;
542  }
543 
544  private void PackagesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
545  {
546  switch (e.Action)
547  {
548  case NotifyCollectionChangedAction.Add:
549  RegisterPackage((Package)e.NewItems[0]);
550  break;
551  case NotifyCollectionChangedAction.Remove:
552  UnRegisterPackage((Package)e.OldItems[0]);
553  break;
554 
555  case NotifyCollectionChangedAction.Replace:
556  packagesCopy.Clear();
557 
558  foreach (var oldPackage in e.OldItems.OfType<Package>())
559  {
560  UnRegisterPackage(oldPackage);
561  }
562 
563  foreach (var packageToCopy in packages)
564  {
565  RegisterPackage(packageToCopy);
566  }
567  break;
568  }
569  }
570 
571  private void RegisterPackage(Package package)
572  {
573  package.Session = this;
574  if (package.IsSystem)
575  return;
576  package.AssetDirtyChanged += OnAssetDirtyChanged;
577 
578  // If the package doesn't have any temporary assets, we can freeze it
579  if (package.TemporaryAssets.Count == 0)
580  {
581  FreezePackage(package);
582  }
583 
584  IsDirty = true;
585  }
586 
587  /// <summary>
588  /// Freeze a package once it is loaded with all its assets
589  /// </summary>
590  /// <param name="package"></param>
591  private void FreezePackage(Package package)
592  {
593  if (package.IsSystem)
594  return;
595 
596  packagesCopy.Add(package.Clone(false));
597  }
598 
599  private void UnRegisterPackage(Package package)
600  {
601  package.Session = null;
602  if (package.IsSystem)
603  return;
604  package.AssetDirtyChanged -= OnAssetDirtyChanged;
605 
606  packagesCopy.RemoveById(package.Id);
607 
608  IsDirty = true;
609  }
610 
611  private void OnAssetDirtyChanged(Asset asset)
612  {
613  Action<Asset> handler = AssetDirtyChanged;
614  if (handler != null) handler(asset);
615  }
616 
617  private static Package PreLoadPackage(PackageSession session, ILogger log, string filePath, bool isSystemPackage, PackageCollection loadedPackages, PackageLoadParameters loadParameters)
618  {
619  if (session == null) throw new ArgumentNullException("session");
620  if (log == null) throw new ArgumentNullException("log");
621  if (filePath == null) throw new ArgumentNullException("filePath");
622  if (loadedPackages == null) throw new ArgumentNullException("loadedPackages");
623  if (loadParameters == null) throw new ArgumentNullException("loadParameters");
624 
625  try
626  {
627  var packageId = Package.GetPackageIdFromFile(filePath);
628 
629  // Check that the package was not already loaded, otherwise return the same instance
630  if (session.Packages.ContainsById(packageId))
631  {
632  return session.Packages.Find(packageId);
633  }
634 
635  // Package is already loaded, use the instance
636  if (loadedPackages.ContainsById(packageId))
637  {
638  return loadedPackages.Find(packageId);
639  }
640 
641  // Load the package without loading assets
642  var newLoadParameters = loadParameters.Clone();
643  newLoadParameters.AssemblyContainer = session.assemblyContainer;
644 
645  // Load the package
646  var package = Package.Load(log, filePath, newLoadParameters);
647  package.IsSystem = isSystemPackage;
648 
649  // Add the package has loaded before loading dependencies
650  loadedPackages.Add(package);
651 
652  // Load package dependencies
653  PreLoadPackageDependencies(session, log, package, loadedPackages, loadParameters);
654 
655  // Add the package to the session but don't freeze it yet
656  session.Packages.Add(package);
657 
658  // Validate assets from package
659  package.ValidateAssets(loadParameters.GenerateNewAssetIds);
660 
661  // Freeze the package after loading the assets
662  session.FreezePackage(package);
663 
664  return package;
665  }
666  catch (Exception ex)
667  {
668  log.Error("Error while pre-loading package [{0}]", ex, filePath);
669  }
670 
671  return null;
672  }
673 
674  private static void PreLoadPackageDependencies(PackageSession session, ILogger log, Package package, PackageCollection loadedPackages, PackageLoadParameters loadParameters)
675  {
676  if (session == null) throw new ArgumentNullException("session");
677  if (log == null) throw new ArgumentNullException("log");
678  if (package == null) throw new ArgumentNullException("package");
679  if (loadParameters == null) throw new ArgumentNullException("loadParameters");
680 
681  // 1. Load store package
682  foreach (var packageDependency in package.Meta.Dependencies)
683  {
684  var loadedPackage = session.Packages.Find(packageDependency);
685  if (loadedPackage != null)
686  {
687  continue;
688  }
689 
690  var file = PackageStore.Instance.GetPackageFileName(packageDependency.Name, packageDependency.Version);
691 
692  if (file == null)
693  {
694  // TODO: We need to support automatic download of packages. This is not supported yet when only Paradox
695  // package is supposed to be installed, but It will be required for full store
696  log.Error("Unable to find package {0} not installed", packageDependency);
697  continue;
698  }
699 
700  // Recursive load of the system package
701  PreLoadPackage(session, log, file, true, loadedPackages, loadParameters);
702  }
703 
704  // 2. Load local packages
705  foreach (var packageReference in package.LocalDependencies)
706  {
707  // Check that the package was not already loaded, otherwise return the same instance
708  if (session.Packages.ContainsById(packageReference.Id))
709  {
710  continue;
711  }
712 
713  // Expand the string of the location
714  var newLocation = (UFile)AssetRegistry.ExpandString(session, packageReference.Location);
715 
716  var subPackageFilePath = package.RootDirectory != null ? UPath.Combine(package.RootDirectory, newLocation) : newLocation;
717 
718  // Recursive load
719  PreLoadPackage(session, log, subPackageFilePath.FullPath, false, loadedPackages, loadParameters);
720  }
721  }
722 
723  private static PackageAnalysisParameters GetPackageAnalysisParametersForLoad()
724  {
725  return new PackageAnalysisParameters()
726  {
727  IsPackageCheckDependencies = true,
728  IsProcessingAssetReferences = true,
729  IsLoggingAssetNotFoundAsError = true,
730  };
731  }
732 
733  }
734 }
PackageDependencyCollection Dependencies
Gets the package dependencies.
Definition: PackageMeta.cs:158
bool IsSystem
Gets or sets a value indicating whether this package is a system package.
Definition: Package.cs:75
AssetItemCollection TemporaryAssets
Gets the temporary assets list loaded from disk before they are going into Assets.
Definition: Package.cs:157
PackageSession(Package package)
Initializes a new instance of the PackageSession class.
Base class for Asset.
Definition: Asset.cs:14
static PackageSessionResult Load(string filePath, PackageLoadParameters loadParameters=null)
Loads a package from specified file path.
SiliconStudio.Core.Diagnostics.LoggerResult LoggerResult
A logger that stores messages locally useful for internal log scenarios.
Definition: LoggerResult.cs:14
PackageCollection Packages
Gets the packages.
A registry for file extensions, IAssetImporter, IAssetFactory and aliases associated with assets...
Package AddExistingPackage(UFile packagePath, ILogger logger, PackageLoadParameters loadParametersArg=null)
Adds an existing package to the current session.
AssetMessageCode
A message code used by AssetLogMessage to identify an error/warning.
void Dispose()
Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resourc...
Class PackageAnalysisParameters. This class cannot be inherited.
bool ContainsById(Guid packageGuid)
Determines whether this collection contains a package with the specified package unique identifier...
An analysis to check the validity of a Package, convert UFile or UDirectory references to absolute/re...
An asset item part of a Package accessible through SiliconStudio.Assets.Package.Assets.
Definition: AssetItem.cs:17
A session for editing a package.
static void Load(string filePath, PackageSessionResult sessionResult, PackageLoadParameters loadParameters=null)
Loads a package from specified file path.
PackageSession()
Initializes a new instance of the PackageSession class.
bool IsAbsolute
Determines whether this instance is absolute.
Definition: UPath.cs:269
A package analysis provides methods to validate the integrity of a whole package. ...
System.IO.File File
LoggerResult AddExistingPackage(UFile packagePath, PackageLoadParameters loadParameters=null)
Adds an existing package to the current session.
A class responsible for providing asset dependencies for a PackageSession and file tracking dependenc...
Result returned when loading a session using PackageSession.Load(string,PackageSessionResult,System.Nullable{System.Threading.CancellationToken},bool)
List< PackageReference > LocalDependencies
Gets the local package dependencies used by this package (only valid for local references). Global dependencies are defined through the Meta property in PackageMeta.Dependencies
Definition: Package.cs:91
IEnumerable< Package > GetPackagesFromCurrent()
Gets the packages referenced by the current package.
A package managing assets.
Definition: Package.cs:28
void LoadMissingReferences(ILogger log, PackageLoadParameters loadParametersArg=null)
Loads the missing references
static string ExpandString(object context, string stringToExpand)
Expands a string using the registered string expander (RegisterStringExpander)
Parameters used for loading a package.
An interface that tags if an object is dirty.
Definition: IDirtyable.cs:8
LoggerResult Save()
Saves all packages and assets.
Interface for logging.
Definition: ILogger.cs:8
PackageMeta Meta
Gets or sets the metadata associated with this package.
Definition: Package.cs:82
Defines a normalized file path. See UPath for details. This class cannot be inherited.
Definition: UFile.cs:13