private static IEnumerable <string> EnumeratePackageFullPaths(string fullPath) { if (PackageSessionHelper.IsSolutionFile(fullPath)) { // Solution file: extract projects var solutionDirectory = Path.GetDirectoryName(fullPath) ?? ""; var solution = SiliconStudio.Core.VisualStudio.Solution.FromFile(fullPath); foreach (var project in solution.Projects) { string packagePath; if (PackageSessionHelper.IsPackage(project, out packagePath)) { var packageFullPath = Path.Combine(solutionDirectory, packagePath); yield return(packageFullPath); } } } else { // Otherwise, let's assume it was a package yield return(fullPath); } }
/// <summary> /// Saves this package and all dirty assets. See remarks. /// </summary> /// <param name="log">The log.</param> /// <exception cref="System.ArgumentNullException">log</exception> /// <remarks>When calling this method directly, it does not handle moving assets between packages. /// Call <see cref="PackageSession.Save" /> instead.</remarks> public void Save(ILogger log) { if (log == null) { throw new ArgumentNullException("log"); } if (FullPath == null) { log.Error(this, null, AssetMessageCode.PackageCannotSave, "null"); return; } // Use relative paths when saving var analysis = new PackageAnalysis(this, new PackageAnalysisParameters() { SetDirtyFlagOnAssetWhenFixingUFile = false, ConvertUPathTo = UPathType.Relative, IsProcessingUPaths = true }); analysis.Run(log); try { // Update source folders UpdateSourceFolders(); if (IsDirty) { try { // Notifies the dependency manager that a package with the specified path is being saved if (session != null && session.HasDependencyManager) { session.DependencyManager.AddFileBeingSaveDuringSessionSave(FullPath); } AssetSerializer.Save(FullPath, this); IsDirty = false; } catch (Exception ex) { log.Error(this, null, AssetMessageCode.PackageCannotSave, ex, FullPath); return; } } foreach (var asset in Assets) { if (asset.IsDirty) { var assetPath = asset.FullPath; try { // Notifies the dependency manager that an asset with the specified path is being saved if (session != null && session.HasDependencyManager) { session.DependencyManager.AddFileBeingSaveDuringSessionSave(assetPath); } // Incject a copy of the base into the current asset when saving var assetBase = asset.Asset.Base; if (assetBase != null && !assetBase.IsRootImport) { var assetBaseItem = session != null?session.FindAsset(assetBase.Id) : Assets.Find(assetBase.Id); if (assetBaseItem != null) { var newBase = (Asset)AssetCloner.Clone(assetBaseItem.Asset); newBase.Base = null; asset.Asset.Base = new AssetBase(asset.Asset.Base.Location, newBase); } } AssetSerializer.Save(assetPath, asset.Asset); asset.IsDirty = false; } catch (Exception ex) { log.Error(this, asset.ToReference(), AssetMessageCode.AssetCannotSave, ex, assetPath); } } } Assets.IsDirty = false; // Save properties like the Paradox version used PackageSessionHelper.SaveProperties(this); } finally { // Rollback all relative UFile to absolute paths analysis.Parameters.ConvertUPathTo = UPathType.Absolute; analysis.Run(); } }
/// <summary> /// Saves all packages and assets. /// </summary> /// <param name="log">The <see cref="LoggerResult"/> in which to report result.</param> public void Save(LoggerResult log) { bool packagesSaved = false; //var clock = Stopwatch.StartNew(); using (var profile = Profiler.Begin(PackageSessionProfilingKeys.Saving)) { try { // Grab all previous assets var previousAssets = new Dictionary <Guid, AssetItem>(); foreach (var assetItem in packagesCopy.SelectMany(package => package.Assets)) { previousAssets[assetItem.Id] = assetItem; } // Grab all new assets var newAssets = new Dictionary <Guid, AssetItem>(); foreach (var assetItem in LocalPackages.SelectMany(package => package.Assets)) { newAssets[assetItem.Id] = assetItem; } // Compute all assets that were removed var assetsOrPackagesToRemove = new Dictionary <UFile, object>(); foreach (var assetIt in previousAssets) { var asset = assetIt.Value; AssetItem newAsset; if (!newAssets.TryGetValue(assetIt.Key, out newAsset) || newAsset.Location != asset.Location) { assetsOrPackagesToRemove[asset.FullPath] = asset; } } // Compute packages that have been renamed // TODO: Disable for now, as not sure if we want to delete a previous package //foreach (var package in packagesCopy) //{ // var newPackage = packages.Find(package.Id); // if (newPackage != null && package.PackagePath != null && newPackage.PackagePath != package.PackagePath) // { // assetsOrPackagesToRemove[package.PackagePath] = package; // } //} // If package are not modified, return immediately if (!CheckModifiedPackages() && assetsOrPackagesToRemove.Count == 0) { return; } // Suspend tracking when saving as we don't want to receive // all notification events if (dependencies != null) { dependencies.BeginSavingSession(); } // Return immediately if there is any error if (log.HasErrors) { return; } // Delete previous files foreach (var fileIt in assetsOrPackagesToRemove) { var assetPath = fileIt.Key; var assetItemOrPackage = fileIt.Value; if (File.Exists(assetPath)) { try { File.Delete(assetPath); } catch (Exception ex) { var assetItem = assetItemOrPackage as AssetItem; if (assetItem != null) { log.Error(assetItem.Package, assetItem.ToReference(), AssetMessageCode.AssetCannotDelete, ex, assetPath); } else { var package = assetItemOrPackage as Package; if (package != null) { log.Error(package, null, AssetMessageCode.AssetCannotDelete, ex, assetPath); } } } } } // Save all dirty assets packagesCopy.Clear(); foreach (var package in LocalPackages) { // Save the package to disk and all its assets package.Save(log); // Clone the package (but not all assets inside, just the structure) var packageClone = package.Clone(false); packagesCopy.Add(packageClone); } packagesSaved = true; } finally { if (dependencies != null) { dependencies.EndSavingSession(); } // Once all packages and assets have been saved, we can save the solution (as we need to have fullpath to // be setup for the packages) if (packagesSaved) { PackageSessionHelper.SaveSolution(this, log); } } //System.Diagnostics.Trace.WriteLine("Elapsed saved: " + clock.ElapsedMilliseconds); IsDirty = false; } }
/// <summary> /// Loads a package from specified file path. /// </summary> /// <param name="filePath">The file path to a package file.</param> /// <param name="sessionResult">The session result.</param> /// <param name="loadParameters">The load parameters.</param> /// <returns>A package.</returns> /// <exception cref="System.ArgumentNullException">filePath</exception> /// <exception cref="System.ArgumentException">File [{0}] must exist.ToFormat(filePath);filePath</exception> public static void Load(string filePath, PackageSessionResult sessionResult, PackageLoadParameters loadParameters = null) { if (filePath == null) { throw new ArgumentNullException("filePath"); } if (sessionResult == null) { throw new ArgumentNullException("sessionResult"); } // Make sure with have valid parameters loadParameters = loadParameters ?? PackageLoadParameters.Default(); // Make sure to use a full path. filePath = FileUtility.GetAbsolutePath(filePath); if (!File.Exists(filePath)) { throw new ArgumentException("File [{0}] must exist".ToFormat(filePath), "filePath"); } try { // Enable reference analysis caching during loading AssetReferenceAnalysis.EnableCaching = true; using (var profile = Profiler.Begin(PackageSessionProfilingKeys.Loading)) { sessionResult.Clear(); sessionResult.Progress("Loading..", 0, 1); var session = new PackageSession(); var packagePaths = new List <string>(); // If we have a solution, load all packages if (PackageSessionHelper.IsSolutionFile(filePath)) { PackageSessionHelper.LoadSolution(session, filePath, packagePaths, sessionResult); } else if (PackageSessionHelper.IsPackageFile(filePath)) { packagePaths.Add(filePath); } else { sessionResult.Error("Unsupported file extension (only .sln or {0} are supported)", Package.PackageFileExtension); return; } var cancelToken = loadParameters.CancelToken; // Load all packages var packagesLoaded = new PackageCollection(); foreach (var packageFilePath in packagePaths) { PreLoadPackage(session, sessionResult, packageFilePath, false, packagesLoaded, loadParameters); // Output the session only if there is no cancellation if (cancelToken.HasValue && cancelToken.Value.IsCancellationRequested) { return; } } // Load all missing references/dependencies session.LoadMissingReferences(sessionResult, loadParameters); // Fix relative references var analysis = new PackageSessionAnalysis(session, GetPackageAnalysisParametersForLoad()); var analysisResults = analysis.Run(); analysisResults.CopyTo(sessionResult); // Run custom package session analysis foreach (var type in AssetRegistry.GetPackageSessionAnalysisTypes()) { var pkgAnalysis = (PackageSessionAnalysisBase)Activator.CreateInstance(type); pkgAnalysis.Session = session; var results = pkgAnalysis.Run(); results.CopyTo(sessionResult); } // Output the session only if there is no cancellation if (!cancelToken.HasValue || !cancelToken.Value.IsCancellationRequested) { sessionResult.Session = session; // Defer the initialization of the dependency manager //session.DependencyManager.InitializeDeferred(); } // The session is not dirty when loading it session.IsDirty = false; } } finally { // Disable reference analysis caching after loading AssetReferenceAnalysis.EnableCaching = false; } }