private async Task UpgradeProject(MSBuildWorkspace workspace, UFile projectPath)
        {
            // Upgrade .csproj file
            // TODO: Use parsed file?
            var fileContents = File.ReadAllText(projectPath);

            // Rename referenced to the package, shaders and effects
            var newFileContents = fileContents.Replace(".pdx", ".xk");

            // Rename variables
            newFileContents = newFileContents.Replace("Paradox", "Xenko");

            // Save file if there were any changes
            if (newFileContents != fileContents)
            {
                File.WriteAllText(projectPath, newFileContents);
            }

            // Upgrade source code
            var project = await workspace.OpenProjectAsync(projectPath.ToWindowsPath());
            var compilation = await project.GetCompilationAsync();
            var tasks = compilation.SyntaxTrees.Select(syntaxTree => Task.Run(() => UpgradeSourceFile(syntaxTree))).ToList();

            await Task.WhenAll(tasks);
        }
Beispiel #2
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)
        {
            if (log == null) throw new ArgumentNullException(nameof(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);

                        // Move the package if the path has changed
                        if (previousPackagePath != null && previousPackagePath != packagePath)
                        {
                            filesToDelete.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 filesToDelete)
                    {
                        if (File.Exists(file.FullPath))
                        {
                            try
                            {
                                File.Delete(file.FullPath);
                            }
                            catch (Exception ex)
                            {
                                log.Error(this, null, AssetMessageCode.AssetCannotDelete, ex, file.FullPath);
                            }
                        }
                    }
                    filesToDelete.Clear();
                }

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

                foreach (var asset in Assets)
                {
                    if (asset.IsDirty)
                    {
                        var assetPath = asset.FullPath;

                        try
                        {
                            //Handle the ProjectSourceCodeAsset differently then regular assets in regards of Path
                            var sourceCodeAsset = asset.Asset as ProjectSourceCodeAsset;
                            if (sourceCodeAsset != null)
                            {
                                var profile = Profiles.FindSharedProfile();

                                var lib = profile?.ProjectReferences.FirstOrDefault(x => x.Type == ProjectType.Library && asset.Location.FullPath.StartsWith(x.Location.GetFileName()));
                                if (lib == null) continue;

                                var projectFullPath = UPath.Combine(RootDirectory, lib.Location);
                                var fileFullPath = UPath.Combine(RootDirectory, asset.Location);
                                var filePath = fileFullPath.MakeRelative(projectFullPath.GetFullDirectory());
                                var codeFile = new UFile(filePath + AssetRegistry.GetDefaultExtension(sourceCodeAsset.GetType()));

                                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 != codeFile.ToWindowsPath()))
                                {
                                    project.AddItem(AssetRegistry.GetDefaultExtension(sourceCodeAsset.GetType()) == ".cs" ? "Compile" : "None", codeFile.ToWindowsPath());
                                    //todo None case needs Generator and LastGenOutput properties support! (eg xksl)
                                }

                                asset.SourceProject = projectFullPath;
                                asset.SourceFolder = RootDirectory.GetFullDirectory();
                                sourceCodeAsset.ProjectInclude = codeFile;
                                sourceCodeAsset.ProjectName = Path.GetFileNameWithoutExtension(projectFullPath.ToWindowsPath());
                                sourceCodeAsset.AbsoluteSourceLocation = UPath.Combine(projectFullPath.GetFullDirectory(), codeFile);
                                sourceCodeAsset.AbsoluteProjectLocation = projectFullPath;

                                assetPath = sourceCodeAsset.AbsoluteSourceLocation;
                            }

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

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

                Assets.IsDirty = false;

                // 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();
            }
        }
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)
        {
            if (log == null) throw new ArgumentNullException(nameof(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,
                AssetTemplatingRemoveUnusedBaseParts = true,
            });
            analysis.Run(log);

            try
            {
                // Update source folders
                UpdateSourceFolders();

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

                    try
                    {
                        AssetSerializer.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)
                {
                    if (asset.IsDirty)
                    {
                        var assetPath = asset.FullPath;

                        try
                        {
                            //Handle the ProjectSourceCodeAsset differently then regular assets in regards of Path
                            var sourceCodeAsset = asset.Asset as ProjectSourceCodeAsset;
                            if (sourceCodeAsset != null)
                            {
                                var profile = Profiles.FindSharedProfile();

                                var lib = profile?.ProjectReferences.FirstOrDefault(x => x.Type == ProjectType.Library && asset.Location.FullPath.StartsWith(x.Location.GetFileName()));
                                if (lib == null) continue;

                                var projectFullPath = UPath.Combine(RootDirectory, lib.Location);
                                var fileFullPath = UPath.Combine(RootDirectory, asset.Location);
                                var filePath = fileFullPath.MakeRelative(projectFullPath.GetFullDirectory());
                                var codeFile = new UFile(filePath + AssetRegistry.GetDefaultExtension(sourceCodeAsset.GetType()));

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

                                asset.SourceProject = projectFullPath;
                                asset.SourceFolder = RootDirectory.GetFullDirectory();
                                sourceCodeAsset.ProjectInclude = codeFile;
                                sourceCodeAsset.ProjectName = Path.GetFileNameWithoutExtension(projectFullPath.ToWindowsPath());
                                sourceCodeAsset.AbsoluteSourceLocation = UPath.Combine(projectFullPath.GetFullDirectory(), codeFile);
                                sourceCodeAsset.AbsoluteProjectLocation = projectFullPath;
                                assetPath = sourceCodeAsset.AbsoluteSourceLocation;

                                //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 != codeFile.ToWindowsPath()))
                                {
                                    var generatorAsset = sourceCodeAsset as ProjectCodeGeneratorAsset;
                                    if (generatorAsset != null)
                                    {
                                        generatorAsset.GeneratedAbsolutePath = new UFile(generatorAsset.AbsoluteSourceLocation).GetFullPathWithoutExtension() + ".cs";
                                        generatorAsset.GeneratedInclude = new UFile(generatorAsset.ProjectInclude).GetFullPathWithoutExtension() + ".cs";

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

                                        project.AddItem("Compile", new UFile(generatorAsset.GeneratedInclude).ToWindowsPath(),
                                            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(generatorAsset.ProjectInclude).GetFileNameWithExtension())
                                            });
                                    }
                                    else
                                    {
                                        project.AddItem("Compile", codeFile.ToWindowsPath());
                                    }                                
                                }
                            }

                            // Inject a copy of the base into the current asset when saving
                            var assetBase = asset.Asset.Base;
                            if (assetBase != null && !assetBase.IsRootImport)
                            {
                                asset.Asset.Base = UpdateAssetBase(assetBase);
                            }

                            // Update base for BaseParts
                            if (asset.Asset.BaseParts != null)
                            {
                                var baseParts = asset.Asset.BaseParts;
                                for (int i = 0; i < baseParts.Count; i++)
                                {
                                    var basePart = baseParts[i];
                                    baseParts[i] = UpdateAssetBase(basePart);
                                }
                            }

                            AssetSerializer.Save(assetPath, asset.Asset);
                            asset.IsDirty = false;
                        }
                        catch (Exception ex)
                        {
                            log.Error(this, asset.ToReference(), AssetMessageCode.AssetCannotSave, ex, assetPath);
                        }
                    }
                }

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

                Assets.IsDirty = false;

                // 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();
            }
        }
Beispiel #4
0
        private async Task UpgradeProject(MSBuildWorkspace workspace, UFile projectPath)
        {
            // Upgrade .csproj file
            // TODO: Use parsed file?
            var fileContents = File.ReadAllText(projectPath);

            // Rename referenced to the package, shaders and effects
            var newFileContents = fileContents.Replace(".pdx", ".xk");

            // Rename variables
            newFileContents = newFileContents.Replace("Paradox", "Xenko");

            // Create fallback for old environment variable
            var index = newFileContents.IndexOf("<SiliconStudioCurrentPackagePath>", StringComparison.InvariantCulture);
            if (index >= 0)
            {
                newFileContents = newFileContents.Insert(index, "<SiliconStudioXenkoDir Condition=\"'$(SiliconStudioXenkoDir)' == ''\">$(SiliconStudioParadoxDir)</SiliconStudioXenkoDir>\n    ");
            }

            // Save file if there were any changes
            if (newFileContents != fileContents)
            {
                File.WriteAllText(projectPath, newFileContents);
            }

            // Upgrade source code
            var project = await workspace.OpenProjectAsync(projectPath.ToWindowsPath());
            var compilation = await project.GetCompilationAsync();
            var tasks = compilation.SyntaxTrees.Select(syntaxTree => Task.Run(() => UpgradeSourceFile(syntaxTree))).ToList();

            await Task.WhenAll(tasks);
        }