Esempio n. 1
0
        public void TestMixedSlash()
        {
            var assetPath1 = new UFile("/a\\b/c\\d.txt");
            var assetPath2 = new UFile("/a/b/c/d.txt");

            Assert.Equal(assetPath1.ToString(), assetPath2.ToString());
        }
Esempio n. 2
0
        protected override bool Generate(SessionTemplateGeneratorParameters parameters)
        {
            if (parameters is null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            parameters.Validate();

            var description = (TemplateSampleDescription)parameters.Description;
            var log         = parameters.Logger;

            // The package might depend on other packages which need to be copied together when instanciating it.
            //  However some of these packages might be in a parent folder, which can result in undesired behavior when copied.
            //  Setting this to true will enforce all package dependencies to be moved to a folder local to the project
            bool doMoveParentDependencies = true;

            var regexes     = new List <Tuple <Regex, MatchEvaluator> >();
            var patternName = description.PatternName ?? description.DefaultOutputName;

            // Samples don't support spaces / dot in name (we would need to separate package name, package short name and namespace renaming for that)
            var parametersName = parameters.Name.Replace(" ", string.Empty)
                                 .Replace(".", string.Empty);

            if (patternName != parametersName)
            {
                // Make sure the target name is a safe for use everywhere, since both an asset or script might reference a filename
                //  in which case they should match and be valid in that context
                string validNamespaceName = Utilities.BuildValidNamespaceName(parametersName);

                // Rename for general occurences of template name
                regexes.Add(new Tuple <Regex, MatchEvaluator>(new Regex($@"\b{patternName}\b"), match => validNamespaceName));

                // Rename App as well (used in code) -- this is the only pattern of "package short name" that we have so far in Windows samples
                regexes.Add(new Tuple <Regex, MatchEvaluator>(new Regex($@"\b{patternName}App\b"), match => validNamespaceName));
            }

            var outputDirectory = parameters.OutputDirectory;

            if (!Directory.Exists(outputDirectory))
            {
                Directory.CreateDirectory(outputDirectory);
            }

            // Write .gitignore
            WriteGitIgnore(parameters);

            UFile projectOutputFile = null;
            UFile projectInputFile  = null;

            // Process files
            foreach (var directory in FileUtility.EnumerateDirectories(description.TemplateDirectory, SearchDirection.Down))
            {
                foreach (var file in directory.GetFiles())
                {
                    // If the file is ending with the Template extension or a directory with the sample extension, don;t copy it
                    if (file.FullName.EndsWith(TemplateDescription.FileExtension) ||
                        string.Compare(directory.Name, TemplateDescription.FileExtension, StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        continue;
                    }

                    var relativeFile = new UFile(file.FullName).MakeRelative(description.TemplateDirectory);

                    // Replace the name in the files if necessary
                    foreach (var nameRegex in regexes)
                    {
                        relativeFile = nameRegex.Item1.Replace(relativeFile, nameRegex.Item2);
                    }

                    // Create the output directory if needed
                    var outputFile          = UPath.Combine(outputDirectory, relativeFile);
                    var outputFileDirectory = outputFile.GetParent();

                    // Determine if we are processing the main game project
                    var isPackageFile = projectOutputFile is null &&
                                        Path.GetExtension(file.FullName).ToLowerInvariant() == ".csproj" &&
                                        !Path.GetFileNameWithoutExtension(file.FullName).EndsWith(".Windows");

                    if (isPackageFile)
                    {
                        projectInputFile  = file.FullName;
                        projectOutputFile = outputFile;
                    }

                    if (!Directory.Exists(outputFileDirectory))
                    {
                        Directory.CreateDirectory(outputFileDirectory);
                    }

                    if (IsBinaryFile(file.FullName))
                    {
                        File.Copy(file.FullName, outputFile, true);
                    }
                    else
                    {
                        ProcessTextFile(file.FullName, outputFile, regexes, (isPackageFile && doMoveParentDependencies));
                    }
                }
            }

            if (projectOutputFile != null)
            {
                var inputProject   = (SolutionProject)Package.LoadProject(log, projectInputFile);
                var outputProject  = (SolutionProject)Package.LoadProject(log, projectOutputFile);
                var msbuildProject = VSProjectHelper.LoadProject(outputProject.FullPath, platform: "NoPlatform");

                // If requested, add reference to Stride.Games.Testing
                if (parameters.TryGetTag(AddGamesTestingKey))
                {
                    var items = msbuildProject.AddItem("PackageReference", "Stride.Games.Testing", new[] { new KeyValuePair <string, string>("Version", StrideVersion.NuGetVersion), new KeyValuePair <string, string>("PrivateAssets", "contentfiles;analyzers") });
                    foreach (var item in items)
                    {
                        foreach (var metadata in item.Metadata)
                        {
                            metadata.Xml.ExpressedAsAttribute = true;
                        }
                    }
                }

                // Copy dependency files locally
                //  We only want to copy the asset files. The raw files are in Resources and the game assets are in Assets.
                //  If we copy each file locally they will be included in the package and we can then delete the dependency packages.
                foreach (var projectReference in msbuildProject.GetItems("ProjectReference").ToList())
                {
                    var packageDirectory = UPath.Combine(inputProject.FullPath.GetFullDirectory(), (UFile)projectReference.EvaluatedInclude).GetFullDirectory();
                    foreach (var directory in FileUtility.EnumerateDirectories(packageDirectory, SearchDirection.Down))
                    {
                        foreach (var file in directory.GetFiles())
                        {
                            // If the file is ending with the Template extension or a directory with the sample extension, don`t copy it
                            if (file.FullName.EndsWith(TemplateDescription.FileExtension) ||
                                string.Compare(directory.Name, TemplateDescription.FileExtension, StringComparison.OrdinalIgnoreCase) == 0)
                            {
                                continue;
                            }

                            var relativeFile     = new UFile(file.FullName).MakeRelative(packageDirectory);
                            var relativeFilename = relativeFile.ToString();

                            bool isAsset    = relativeFilename.Contains("Assets");
                            bool isResource = relativeFilename.Contains("Resources");

                            if (!isAsset && !isResource)
                            {
                                continue;
                            }

                            // Replace the name in the files if necessary
                            foreach (var nameRegex in regexes)
                            {
                                relativeFile = nameRegex.Item1.Replace(relativeFile, nameRegex.Item2);
                            }

                            var outputFile = UPath.Combine(outputDirectory, relativeFile);
                            {
                                // Create the output directory if needed
                                var outputFileDirectory = outputFile.GetParent();
                                if (!Directory.Exists(outputFileDirectory))
                                {
                                    Directory.CreateDirectory(outputFileDirectory);
                                }
                            }

                            if (IsBinaryFile(file.FullName))
                            {
                                File.Copy(file.FullName, outputFile, true);
                            }
                            else
                            {
                                ProcessTextFile(file.FullName, outputFile, regexes);
                            }
                        }
                    }

                    msbuildProject.RemoveItem(projectReference);
                }

                // Save csproj without ProjectReferences
                msbuildProject.Save();
                msbuildProject.ProjectCollection.UnloadAllProjects();
                msbuildProject.ProjectCollection.Dispose();

                // Add package to session
                var loadParams = PackageLoadParameters.Default();
                loadParams.GenerateNewAssetIds     = true;
                loadParams.LoadMissingDependencies = false;
                var session = parameters.Session;
                // We should switch to loading .csproj once all samples are upgraded
                var loadedProject = session.AddExistingProject(projectOutputFile, log, loadParams);

                RemoveUnusedAssets(loadedProject.Package, session);

                parameters.Tags.Add(GeneratedPackageKey, loadedProject.Package);
            }
            else
            {
                log.Error("Unable to find generated package for this template.");
            }

            // Make sure we transfer overrides, etc. from what we deserialized to the asset graphs that we are going to save right after
            ApplyMetadata(parameters);
            return(true);
        }
Esempio n. 3
0
 public void TestMixedSlash()
 {
     var assetPath1 = new UFile("/a\\b/c\\d.txt");
     var assetPath2 = new UFile("/a/b/c/d.txt");
     Assert.AreEqual(assetPath1.ToString(), assetPath2.ToString());
 }
Esempio n. 4
0
        private static Process FindVisualStudioInstance(UFile solutionPath)
        {
            // NOTE: this code is very hackish and does not 100% ensure that the correct instance of VS will be activated.
            var processes = Process.GetProcessesByName("devenv");

            foreach (var process in processes)
            {
                // Get instances that have a solution with the same name currently open (The solution name is displayed in the title bar).
                if (process.MainWindowTitle.ToLowerInvariant().StartsWith(solutionPath.GetFileNameWithoutExtension().ToLowerInvariant()))
                {
                    // If there is a matching instance, get its command line.
                    var query = $"SELECT CommandLine FROM Win32_Process WHERE ProcessId = {process.Id}";
                    using (var managementObjectSearcher = new ManagementObjectSearcher(query))
                    {
                        var managementObject = managementObjectSearcher.Get().Cast <ManagementObject>().First();
                        var commandLine      = managementObject["CommandLine"].ToString();
                        if (commandLine.ToLowerInvariant().Replace("/", "\\").Contains(solutionPath.ToString().ToLowerInvariant().Replace("/", "\\")))
                        {
                            return(process);
                        }
                    }
                }
            }

            return(null);
        }
Esempio n. 5
0
        protected override bool Generate(SessionTemplateGeneratorParameters parameters)
        {
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }
            parameters.Validate();

            var description = (TemplateSampleDescription)parameters.Description;
            var log         = parameters.Logger;

            // The package might depend on other packages which need to be copied together when instanciating it.
            //  However some of these packages might be in a parent folder, which can result in undesired behavior when copied.
            //  Setting this to true will enforce all package dependencies to be moved to a folder local to the project
            bool doMoveParentDependencies = true;

            var packageFile = Path.ChangeExtension(description.FullPath, Package.PackageFileExtension);

            if (!File.Exists(packageFile))
            {
                log.Error($"Unable to find package [{packageFile}]");
                return(false);
            }

            var packageLoadResult = new LoggerResult();
            var package           = Package.Load(packageLoadResult, packageFile, new PackageLoadParameters
            {
                AutoLoadTemporaryAssets = false,
                AutoCompileProjects     = false,
                LoadAssemblyReferences  = false,
            });

            packageLoadResult.CopyTo(log);
            if (packageLoadResult.HasErrors)
            {
                return(false);
            }

            // We are going to replace all projects id by new ids
            var idsToReplace = package.Profiles.SelectMany(profile => profile.ProjectReferences).Select(project => project.Id).Distinct().ToDictionary(guid => guid.ToString("D"), guid => Guid.NewGuid(), StringComparer.OrdinalIgnoreCase);

            idsToReplace.Add(package.Id.ToString("D"), Guid.NewGuid());

            // Add dependencies
            foreach (var packageReference in package.LocalDependencies)
            {
                description.FullPath.GetFullDirectory();

                var referencePath = UPath.Combine(description.FullPath.GetFullDirectory(), packageReference.Location);

                if (!File.Exists(referencePath))
                {
                    log.Error($"Unable to find dependency package [{referencePath}]");
                    return(false);
                }

                var referenceLoadResult = new LoggerResult();
                var reference           = Package.Load(referenceLoadResult, referencePath, new PackageLoadParameters
                {
                    AutoLoadTemporaryAssets = false,
                    AutoCompileProjects     = false,
                    LoadAssemblyReferences  = false,
                });
                referenceLoadResult.CopyTo(log);
                if (referenceLoadResult.HasErrors)
                {
                    return(false);
                }

                var extraIdsToReplace = reference.Profiles.SelectMany(profile => profile.ProjectReferences).Select(project => project.Id).Distinct().ToDictionary(guid => guid.ToString("D"), guid => Guid.NewGuid(), StringComparer.OrdinalIgnoreCase);

                idsToReplace.AddRange(extraIdsToReplace);
            }

            var guidRegexPattern = new StringBuilder();

            guidRegexPattern.Append("(");
            guidRegexPattern.Append(string.Join("|", idsToReplace.Keys));
            guidRegexPattern.Append(")");

            var regexes = new List <Tuple <Regex, MatchEvaluator> >();

            var guidRegex = new Tuple <Regex, MatchEvaluator>(new Regex(guidRegexPattern.ToString(), RegexOptions.IgnoreCase),
                                                              match => idsToReplace[match.Groups[1].Value].ToString("D"));

            regexes.Add(guidRegex);
            var patternName = description.PatternName ?? description.DefaultOutputName;

            // Samples don't support spaces and dot in name (we would need to separate package name, package short name and namespace renaming for that).
            var parametersName = parameters.Name.Replace(" ", string.Empty).Replace(".", string.Empty);

            if (patternName != parametersName)
            {
                // Make sure the target name is a safe for use everywhere, since both an asset or script might reference a filename
                //  in which case they should match and be valid in that context
                string validNamespaceName = Utilities.BuildValidNamespaceName(parametersName);

                // Rename for general occurences of template name
                regexes.Add(new Tuple <Regex, MatchEvaluator>(new Regex($@"\b{patternName}\b"), match => validNamespaceName));

                // Rename App as well (used in code) -- this is the only pattern of "package short name" that we have so far in Windows samples
                regexes.Add(new Tuple <Regex, MatchEvaluator>(new Regex($@"\b{patternName}App\b"), match => validNamespaceName));
            }

            var outputDirectory = parameters.OutputDirectory;

            if (!Directory.Exists(outputDirectory))
            {
                Directory.CreateDirectory(outputDirectory);
            }

            //write gitignore
            WriteGitIgnore(parameters);

            UFile packageOutputFile = null;

            // Process files
            foreach (var directory in FileUtility.EnumerateDirectories(description.TemplateDirectory, SearchDirection.Down))
            {
                foreach (var file in directory.GetFiles())
                {
                    // If the file is ending with the Template extension or a directory with the sample extension, don;t copy it
                    if (file.FullName.EndsWith(TemplateDescription.FileExtension) ||
                        string.Compare(directory.Name, TemplateDescription.FileExtension, StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        continue;
                    }

                    var relativeFile = new UFile(file.FullName).MakeRelative(description.TemplateDirectory);

                    // Replace the name in the files if necessary
                    foreach (var nameRegex in regexes)
                    {
                        relativeFile = nameRegex.Item1.Replace(relativeFile, nameRegex.Item2);
                    }

                    // Create the output directory if needed
                    var outputFile          = UPath.Combine(outputDirectory, relativeFile);
                    var outputFileDirectory = outputFile.GetParent();

                    // Grab the name of the output package file
                    var isPackageFile = (packageOutputFile == null && file.FullName.EndsWith(Package.PackageFileExtension));

                    if (isPackageFile)
                    {
                        packageOutputFile = outputFile;
                    }

                    if (!Directory.Exists(outputFileDirectory))
                    {
                        Directory.CreateDirectory(outputFileDirectory);
                    }

                    if (IsBinaryFile(file.FullName))
                    {
                        File.Copy(file.FullName, outputFile, true);
                    }
                    else
                    {
                        ProcessTextFile(file.FullName, outputFile, regexes, (isPackageFile && doMoveParentDependencies));
                    }
                }
            }

            // Copy dependency files locally
            //  We only want to copy the asset files. The raw files are in Resources and the game assets are in Assets.
            //  If we copy each file locally they will be included in the package and we can then delete the dependency packages.
            foreach (var packageReference in package.LocalDependencies)
            {
                var packageDirectory = packageReference.Location.GetFullDirectory();
                foreach (var directory in FileUtility.EnumerateDirectories(packageDirectory, SearchDirection.Down))
                {
                    foreach (var file in directory.GetFiles())
                    {
                        // If the file is ending with the Template extension or a directory with the sample extension, don`t copy it
                        if (file.FullName.EndsWith(TemplateDescription.FileExtension) ||
                            string.Compare(directory.Name, TemplateDescription.FileExtension, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            continue;
                        }

                        var relativeFile     = new UFile(file.FullName).MakeRelative(packageDirectory);
                        var relativeFilename = relativeFile.ToString();

                        bool isAsset    = relativeFilename.Contains("Assets");
                        bool isResource = relativeFilename.Contains("Resources");

                        if (!isAsset && !isResource)
                        {
                            continue;
                        }

                        // Replace the name in the files if necessary
                        foreach (var nameRegex in regexes)
                        {
                            relativeFile = nameRegex.Item1.Replace(relativeFile, nameRegex.Item2);
                        }

                        var outputFile = UPath.Combine(outputDirectory, relativeFile);
                        {   // Create the output directory if needed
                            var outputFileDirectory = outputFile.GetParent();
                            if (!Directory.Exists(outputFileDirectory))
                            {
                                Directory.CreateDirectory(outputFileDirectory);
                            }
                        }

                        if (IsBinaryFile(file.FullName))
                        {
                            File.Copy(file.FullName, outputFile, true);
                        }
                        else
                        {
                            ProcessTextFile(file.FullName, outputFile, regexes);
                        }
                    }
                }
            }

            if (packageOutputFile != null)
            {
                // Add package to session
                var loadParams = PackageLoadParameters.Default();
                loadParams.ForceNugetRestore       = true;
                loadParams.GenerateNewAssetIds     = true;
                loadParams.LoadMissingDependencies = false;
                var session       = parameters.Session;
                var loadedPackage = session.AddExistingPackage(packageOutputFile, log, loadParams);

                RemoveUnusedAssets(loadedPackage, session);

                parameters.Tags.Add(GeneratedPackageKey, loadedPackage);
            }
            else
            {
                log.Error("Unable to find generated package for this template");
            }

            // Make sure we transfer overrides, etc. from what we deserialized to the asset graphs that we are going to save right after.
            ApplyMetadata(parameters);
            return(true);
        }