Beispiel #1
0
        /// <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, PackageSaveParameters saveParameters = null)
        {
            bool packagesSaved = false;

            //var clock = Stopwatch.StartNew();
            using (var profile = Profiler.Begin(PackageSessionProfilingKeys.Saving))
            {
                try
                {
                    saveParameters = saveParameters ?? PackageSaveParameters.Default();
                    var assetsOrPackagesToRemove = BuildAssetsOrPackagesToRemove();

                    // 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;
                    //    }
                    //}

                    // Depending on saveParameters, select the list of source file operations to do
                    List<SourceFileOperation> sourceFileOperations;
                    switch (saveParameters.SaveSourceFileOperations)
                    {
                        case PackageSaveSourceFileOperations.All:
                            sourceFileOperations = BuildSourceFileOperations(assetsOrPackagesToRemove);
                            break;
                        case PackageSaveSourceFileOperations.ReversibleOnly:
                            sourceFileOperations = BuildSourceFileOperations(assetsOrPackagesToRemove).Where(x => !x.Irreversible).ToList();
                            break;
                        case PackageSaveSourceFileOperations.None:
                            sourceFileOperations = new List<SourceFileOperation>();
                            break;
                        default:
                            throw new ArgumentOutOfRangeException();
                    }

                    // If package are not modified, return immediately
                    if (!CheckModifiedPackages() && assetsOrPackagesToRemove.Count == 0 && sourceFileOperations.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;
                    }

                    // Perform source file operations
                    foreach (var sourceFileOperation in sourceFileOperations)
                    {
                        switch (sourceFileOperation.Type)
                        {
                            case SourceFileOperationType.Move:
                                try
                                {
                                    // Move target already exists: try to copy and then delete
                                    if (File.Exists(sourceFileOperation.Destination))
                                    {
                                        // Use upper try/catch
                                        File.Copy(sourceFileOperation.Source, sourceFileOperation.Destination, true);

                                        // Try to delete source
                                        try
                                        {
                                            File.Delete(sourceFileOperation.Source);
                                        }
                                        catch (Exception ex)
                                        {
                                            // File locked?
                                            log.Warning(sourceFileOperation.AssetItem.Package, sourceFileOperation.AssetItem.ToReference(), AssetMessageCode.AssetCannotDelete, ex, sourceFileOperation.Source);
                                        }
                                    }
                                    else
                                    {
                                        try
                                        {
                                            File.Move(sourceFileOperation.Source, sourceFileOperation.Destination);
                                        }
                                        catch (Exception ex)
                                        {
                                            // Could not Move, revert back to a Copy instead
                                            // Use upper try/catch
                                            File.Copy(sourceFileOperation.Source, sourceFileOperation.Destination, true);
                                            log.Warning(sourceFileOperation.AssetItem.Package, sourceFileOperation.AssetItem.ToReference(), AssetMessageCode.AssetCannotDelete, ex,
                                                sourceFileOperation.Source);
                                        }
                                    }

                                    // Update AssetItem
                                    var assetItem = sourceFileOperation.AssetItem;
                                    ((AssetImport)assetItem.Asset).Source = sourceFileOperation.Destination;
                                    assetItem.IsDirty = true;
                                }
                                catch (Exception ex)
                                {
                                    log.Error(sourceFileOperation.AssetItem.Package, sourceFileOperation.AssetItem.ToReference(), AssetMessageCode.AssetCannotSave, ex, sourceFileOperation.Destination);
                                }
                                break;
                            case SourceFileOperationType.Copy:
                                try
                                {
                                    File.Copy(sourceFileOperation.Source, sourceFileOperation.Destination, true);

                                    // Update AssetItem
                                    var assetItem = sourceFileOperation.AssetItem;
                                    ((AssetImport)assetItem.Asset).Source = sourceFileOperation.Destination;
                                    assetItem.IsDirty = true;
                                }
                                catch (Exception ex)
                                {
                                    log.Error(sourceFileOperation.AssetItem.Package, sourceFileOperation.AssetItem.ToReference(), AssetMessageCode.AssetCannotSave, ex, sourceFileOperation.Destination);
                                }
                                break;
                            case SourceFileOperationType.Delete:
                                try
                                {
                                    File.Delete(sourceFileOperation.Source);
                                }
                                catch (Exception ex)
                                {
                                    // File locked?
                                    log.Warning(sourceFileOperation.AssetItem.Package, sourceFileOperation.AssetItem.ToReference(), AssetMessageCode.AssetCannotDelete, ex, sourceFileOperation.Source);
                                }
                                break;
                            default:
                                throw new ArgumentOutOfRangeException();
                        }
                    }

                    //batch projects
                    var vsProjs = new Dictionary<string, Project>();

                    // Delete previous files
                    foreach (var fileIt in assetsOrPackagesToRemove)
                    {
                        var assetPath = fileIt.Key;
                        var assetItemOrPackage = fileIt.Value;

                        var assetItem = assetItemOrPackage as AssetItem;

                        if (File.Exists(assetPath))
                        {
                            try
                            {
                                //If we are within a csproj we need to remove the file from there as well
                                if (assetItem?.SourceProject != null)
                                {
                                    var projectAsset = assetItem.Asset as ProjectSourceCodeAsset;
                                    if (projectAsset != null)
                                    {
                                        Project project;
                                        if (!vsProjs.TryGetValue(assetItem.SourceProject, out project))
                                        {
                                            project = VSProjectHelper.LoadProject(assetItem.SourceProject);
                                            vsProjs.Add(assetItem.SourceProject, project);
                                        }
                                        var include = (new UFile(projectAsset.ProjectInclude)).ToWindowsPath();
                                        var item = project.Items.FirstOrDefault(x => (x.ItemType == "Compile" || x.ItemType == "None") && x.EvaluatedInclude == include);
                                        if (item != null)
                                        {
                                            project.RemoveItem(item);
                                        }
                                    }
                                }

                                File.Delete(assetPath);
                            }
                            catch (Exception ex)
                            {
                                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);
                                    }
                                }
                            }
                        }
                    }

                    foreach (var project in vsProjs.Values)
                    {
                        project.Save();
                        project.ProjectCollection.UnloadAllProjects();
                        project.ProjectCollection.Dispose();
                    }

                    // 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;
            }
        }
Beispiel #2
0
 /// <summary>
 /// Saves this package and all dirty assets. See remarks.
 /// </summary>
 /// <param name="saveAllAssets">if set to <c>true</c> [save all assets].</param>
 /// <returns>LoggerResult.</returns>
 /// <remarks>When calling this method directly, it does not handle moving assets between packages. 
 /// Call <see cref="PackageSession.Save"/> instead.
 /// </remarks>
 public LoggerResult Save(PackageSaveParameters saveParameters = null)
 {
     var result = new LoggerResult();
     Save(result, saveParameters);
     return result;
 }
Beispiel #3
0
        /// <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, PackageSaveParameters saveParameters = null)
        {
            if (log == null) throw new ArgumentNullException(nameof(log));

            if (FullPath == null)
            {
                log.Error(this, null, AssetMessageCode.PackageCannotSave, "null");
                return;
            }

            saveParameters = saveParameters ?? PackageSaveParameters.Default();

            // Use relative paths when saving
            var analysis = new PackageAnalysis(this, new PackageAnalysisParameters()
            {
                SetDirtyFlagOnAssetWhenFixingUFile = false,
                ConvertUPathTo = UPathType.Relative,
                IsProcessingUPaths = true,
            });
            analysis.Run(log);

            var assetsFiltered = false;
            try
            {
                // Update source folders
                UpdateSourceFolders(Assets);

                if (IsDirty)
                {
                    List<UFile> filesToDeleteLocal;
                    lock (filesToDelete)
                    {
                        filesToDeleteLocal = filesToDelete.ToList();
                        filesToDelete.Clear();
                    }

                    try
                    {
                        AssetFileSerializer.Save(FullPath, this);

                        // Move the package if the path has changed
                        if (previousPackagePath != null && previousPackagePath != packagePath)
                        {
                            filesToDeleteLocal.Add(previousPackagePath);
                        }
                        previousPackagePath = packagePath;

                        IsDirty = false;
                    }
                    catch (Exception ex)
                    {
                        log.Error(this, null, AssetMessageCode.PackageCannotSave, ex, FullPath);
                        return;
                    }
                    
                    // Delete obsolete files
                    foreach (var file in filesToDeleteLocal)
                    {
                        if (File.Exists(file.FullPath))
                        {
                            try
                            {
                                File.Delete(file.FullPath);
                            }
                            catch (Exception ex)
                            {
                                log.Error(this, null, AssetMessageCode.AssetCannotDelete, ex, file.FullPath);
                            }
                        }
                    }
                }

                //batch projects
                var vsProjs = new Dictionary<string, Project>();

                foreach (var asset in Assets)
                {
                    var assetSaved = false;
                    if (asset.IsDirty)
                    {
                        if (saveParameters.AssetFilter?.Invoke(asset) ?? true)
                        {
                            SaveSingleAsset_NoUpdateSourceFolder(asset, log);
                        }
                        else
                        {
                            assetsFiltered = true;
                        }
                    }

                    // Add new files to .csproj
                    var projectAsset = asset.Asset as IProjectAsset;
                    if (projectAsset != null)
                    {
                        var projectFullPath = asset.SourceProject;
                        var projectInclude = asset.GetProjectInclude();

                        Project project;
                        if (!vsProjs.TryGetValue(projectFullPath, out project))
                        {
                            project = VSProjectHelper.LoadProject(projectFullPath);
                            vsProjs.Add(projectFullPath, project);
                        }

                        //check if the item is already there, this is possible when saving the first time when creating from a template
                        if (project.Items.All(x => x.EvaluatedInclude != projectInclude))
                        {
                            var generatorAsset = projectAsset as IProjectFileGeneratorAsset;
                            if (generatorAsset != null)
                            {
                                var generatedInclude = asset.GetGeneratedInclude();

                                project.AddItem("None", projectInclude,
                                    new List<KeyValuePair<string, string>>
                                    {
                                    new KeyValuePair<string, string>("Generator", generatorAsset.Generator),
                                    new KeyValuePair<string, string>("LastGenOutput", new UFile(generatedInclude).GetFileNameWithExtension())
                                    });

                                project.AddItem("Compile", generatedInclude,
                                    new List<KeyValuePair<string, string>>
                                    {
                                    new KeyValuePair<string, string>("AutoGen", "True"),
                                    new KeyValuePair<string, string>("DesignTime", "True"),
                                    new KeyValuePair<string, string>("DesignTimeSharedInput", "True"),
                                    new KeyValuePair<string, string>("DependentUpon", new UFile(projectInclude).GetFileNameWithExtension())
                                    });
                            }
                            else
                            {
                                project.AddItem("Compile", projectInclude);
                            }
                        }
                    }
                }

                foreach (var project in vsProjs.Values)
                {
                    project.Save();
                    project.ProjectCollection.UnloadAllProjects();
                    project.ProjectCollection.Dispose();
                }

                // If some assets were filtered out, Assets is still dirty
                Assets.IsDirty = assetsFiltered;

                // Save properties like the Xenko 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>
        /// <param name="saveParameters">The parameters for the save operation.</param>
        public void Save(LoggerResult log, PackageSaveParameters saveParameters = null)
        {
            bool packagesSaved = false;

            //var clock = Stopwatch.StartNew();
            using (var profile = Profiler.Begin(PackageSessionProfilingKeys.Saving))
            {
                var packagesDirty = false;
                try
                {
                    saveParameters = saveParameters ?? PackageSaveParameters.Default();
                    var assetsOrPackagesToRemove = BuildAssetsOrPackagesToRemove();

                    // 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
                    dependencies?.BeginSavingSession();
                    sourceTracker?.BeginSavingSession();

                    // Return immediately if there is any error
                    if (log.HasErrors)
                        return;
       
                    //batch projects
                    var vsProjs = new Dictionary<string, Project>();

                    // Delete previous files
                    foreach (var fileIt in assetsOrPackagesToRemove)
                    {
                        var assetPath = fileIt.Key;
                        var assetItemOrPackage = fileIt.Value;

                        var assetItem = assetItemOrPackage as AssetItem;

                        if (File.Exists(assetPath))
                        {
                            try
                            {
                                //If we are within a csproj we need to remove the file from there as well
                                if (assetItem?.SourceProject != null)
                                {
                                    var projectAsset = assetItem.Asset as IProjectAsset;
                                    if (projectAsset != null)
                                    {
                                        var projectInclude = assetItem.GetProjectInclude();

                                        Project project;
                                        if (!vsProjs.TryGetValue(assetItem.SourceProject, out project))
                                        {
                                            project = VSProjectHelper.LoadProject(assetItem.SourceProject);
                                            vsProjs.Add(assetItem.SourceProject, project);
                                        }
                                        var projectItem = project.Items.FirstOrDefault(x => (x.ItemType == "Compile" || x.ItemType == "None") && x.EvaluatedInclude == projectInclude);
                                        if (projectItem != null)
                                        {
                                            project.RemoveItem(projectItem);
                                        }

                                        //delete any generated file as well
                                        var generatorAsset = assetItem.Asset as IProjectFileGeneratorAsset;
                                        if (generatorAsset != null)
                                        {
                                            var generatedAbsolutePath = assetItem.GetGeneratedAbsolutePath().ToWindowsPath();

                                            File.Delete(generatedAbsolutePath);

                                            var generatedInclude = assetItem.GetGeneratedInclude();
                                            var generatedItem = project.Items.FirstOrDefault(x => (x.ItemType == "Compile" || x.ItemType == "None") && x.EvaluatedInclude == generatedInclude);
                                            if (generatedItem != null)
                                            {
                                                project.RemoveItem(generatedItem);
                                            }
                                        }
                                    }
                                }

                                File.Delete(assetPath);
                            }
                            catch (Exception ex)
                            {
                                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);
                                    }
                                }
                            }
                        }
                    }

                    foreach (var project in vsProjs.Values)
                    {
                        project.Save();
                        project.ProjectCollection.UnloadAllProjects();
                        project.ProjectCollection.Dispose();
                    }

                    // Save all dirty assets
                    packagesCopy.Clear();
                    foreach (var package in LocalPackages)
                    {
                        // Save the package to disk and all its assets
                        package.Save(log, saveParameters);

                        // Check if everything was saved (might not be the case if things are filtered out)
                        if (package.IsDirty || package.Assets.IsDirty)
                            packagesDirty = true;

                        // Clone the package (but not all assets inside, just the structure)
                        var packageClone = package.Clone();
                        packagesCopy.Add(packageClone);
                    }

                    packagesSaved = true;
                }
                finally
                {
                    sourceTracker?.EndSavingSession();
                    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 = packagesDirty;
            }
        }