Exemplo n.º 1
0
        static void InitializePlatformSpecificTools()
        {
            Alt.Sketch.Config.Font_NoAntiAliasMaxSize = 5;

#if UNITY_5
            Alt.Backend.BackendManager.Clipboard = new UnityClipboard();

            UnityEngine.TextAsset bindata = UnityEngine.Resources.Load("AltData.zip", typeof(UnityEngine.TextAsset)) as UnityEngine.TextAsset;
            if (bindata != null)
            {
                System.IO.MemoryStream stream = new System.IO.MemoryStream(bindata.bytes);

                VirtualFileSystem.AddZipStorage(
                    "AltData.zip",
                    stream);
            }
#else
            VirtualFileSystem.AddZipStorage(
                "AltData.zip",
                VirtualFile.OpenRead("Assets/AltData.zip"));
#endif

            Alt.Sketch.Config.AppendLogo(Bitmap.FromFile("AltData/Logo/Unity.jpg"));

            UnityApplication.GetOrCreateInstance();
        }
Exemplo n.º 2
0
        public ParserResult Parse(VirtualFile file)
        {
            log.LogVerbose($"Parse file {file.FullName}.");
            List <CodeSpecificException> codeSpecificExceptions = new();
            List <ParserMessage>         messages = new();
            CppStreamParser parser = new();
            ParseNode       root   = parser.Parse(file.OpenRead());

            if (!parser.Succeeded)
            {
                messages.Add(parser.Exception == null
                                 ? new ParserMessage("CPP0004", 1, 1)
                                 : new ParserMessage("CPP0005", parser.Exception.Row, parser.Exception.Col,
                                                     $"{Environment.NewLine}{parser.Exception.Message}"));
                codeSpecificExceptions.AddRange(messages.Select(m => m.ToException(file)));
                return(new ParserResult(codeSpecificExceptions));
            }

            string[] usings = GetUsing(root);
            IDictionary <IType, CodePosition> types = GetTypes(root, usings, messages);

            string[] includes = GetIncludes(root);
            Dictionary <string, string> defineStatements = GetDefineStatements(root);
            IEnumerable <IConstant>     constants        = GetConstants(root, usings);

            codeSpecificExceptions.AddRange(messages.Select(m => m.ToException(file)));

            return(new ParserResult(codeSpecificExceptions, types, includes, defineStatements, constants));
        }
Exemplo n.º 3
0
        public static IntPtr fs_open(string path)
        {
            IntPtr fid = IntPtr.Zero;

            //if (mode == "r")
            {
                string fn = "Data/" + path;
                if (VirtualFile.Exists(fn))
                {
                    System.IO.Stream fs = VirtualFile.OpenRead(fn);
                    if (fs != null)
                    {
                        fid = new IntPtr(m_LastFileID++);

                        byte[] buffer = new byte[fs.Length];
                        fs.Read(buffer, 0, (int)fs.Length);
                        fs.Close();

                        fs = new System.IO.MemoryStream(buffer, false);

                        m_Files.Add(fid, new FileDescription(fs));

                        return(fid);
                    }
                }
            }

            return(fid);
        }
Exemplo n.º 4
0
 public void LoadCache(VirtualFile cacheFile)
 {
     try
     {
         Stopwatch loadWatch = new Stopwatch();
         loadWatch.Start();
         using (Stream fileStream = cacheFile.OpenRead())
             using (TextReader reader = new StreamReader(fileStream))
                 using (JsonReader jsonReader = new JsonTextReader(reader))
                 {
                     JsonSerializer      serializer = CreateSerializer();
                     IncludeCacheEntry[] result     = serializer.Deserialize <IncludeCacheEntry[]>(jsonReader);
                     cache          = result?.ToDictionary(r => r.File, r => r) ?? new Dictionary <string, IncludeCacheEntry>();
                     this.cacheFile = cacheFile;
                 }
         loadWatch.Stop();
         log.LogInformation($"Successfully loaded the include cache in {loadWatch.ElapsedMilliseconds} ms.");
     }
     catch (Exception e)
     {
         log.LogError($"Error while parsing include cache file, using empty cache.{Environment.NewLine}{e}");
         cache          = new Dictionary <string, IncludeCacheEntry>();
         this.cacheFile = cacheFile;
     }
 }
Exemplo n.º 5
0
 public void LoadCache(VirtualFile cacheFile)
 {
     using (Stream fileStream = cacheFile.OpenRead())
     {
         LoadFrom(fileStream);
     }
     this.cacheFile = cacheFile;
 }
Exemplo n.º 6
0
        public async Task <VirtualFile> DownloadVersion(string version, VirtualDirectory downloadDirectory,
                                                        IProgressNotifier parentProgress = null,
                                                        string proxy = "")
        {
            await EnsureRepository(proxy).ConfigureAwait(false);

            string actualVersion = await CheckVersion(version, proxy).ConfigureAwait(false);

            CliVersionDefinition versionDefinition = repository.Version.FirstOrDefault(v => v.GetInformalVersion() == actualVersion);

            if (versionDefinition == null)
            {
                throw new UnkownVersionException(actualVersion);
            }

            FileDefinition downloadFile = GetCorrectVersion();

            if (downloadFile == null)
            {
                throw new UnsupportedSystemException(environmentService.PlatformName, environmentService.Architecture);
            }

            Uri downloadUri = InvalidUriFormatException.TryCreateUri(downloadFile.relPath,
                                                                     InvalidUriFormatException.TryCreateUri(settingsProvider.Settings.CliRepositoryRoot));
            VirtualFile result = downloadDirectory.File(downloadFile.name);

            using (Stream fileStream = result.OpenWrite())
            {
                await Download(downloadUri, fileStream, proxy, parentProgress).ConfigureAwait(false);
            }

            using (Stream fileStream = result.OpenRead())
            {
                try
                {
                    securityValidator.ValidateHash(fileStream, downloadFile.Fingerprint.hash, downloadFile.Fingerprint.algorithm);
                }
                catch (HashValidationException e)
                {
                    e.ValidationFileName = downloadUri.AbsolutePath;
                    throw;
                }
            }

            return(result);

            FileDefinition GetCorrectVersion()
            {
                FileDefinition[] correctArchitecture = versionDefinition.File
                                                       .Where(f => f.Architecture.ToString().Equals(environmentService.Architecture,
                                                                                                    StringComparison.OrdinalIgnoreCase))
                                                       .ToArray();
                return(correctArchitecture.FirstOrDefault(f => f.OS.ToString().Equals(environmentService.PlatformName,
                                                                                      StringComparison.OrdinalIgnoreCase)) ??
                       correctArchitecture.FirstOrDefault(f => f.OS == OSDefinition.unbound));
            }
        }
        public string MoveApplicationFile(string fileName, string newLocation)
        {
            VirtualFile oldFile = FileSystem.GetFile(Path.Combine(AssemblyDirectory, fileName));
            VirtualFile newFile = FileSystem.GetFile(Path.Combine(AssemblyDirectory, newLocation));

            using (Stream source = oldFile.OpenRead())
                using (Stream destination = newFile.OpenWrite())
                {
                    source.CopyTo(destination);
                }

            return(newFile.FullName);
        }
        private Settings LoadSettings()
        {
            string path = SettingsPath;

            if (!fileSystem.FileExists(path))
            {
                log.LogInformation("No settings file found. Use default settings:");
                Settings result = new Settings();
                log.LogInformation(JsonConvert.SerializeObject(result, Formatting.Indented));
                return(result);
            }
            VirtualFile file = fileSystem.GetFile(path);

            using (Stream stream = file.OpenRead())
            {
                XDocument            document = XDocument.Load(stream);
                IEnumerable <string> paths    = document.Descendants("SDKS").Any()
                                                ? document.Descendants("SDK").Select(d => d.Value)
                                                : Settings.SdkPathsDefault;
                IEnumerable <string> templates = document.Descendants("Templates").Any()
                                                    ? document.Descendants("Template").Select(d => d.Value)
                                                    : Settings.TemplateLocationsDefault;
                string attributePrefix = document.Descendants("Settings").FirstOrDefault()?
                                         .Attribute("AttributePrefix")?.Value
                                         ?? Settings.AttributePrefixDefault;
                string cliRpositoryRoot = document.Descendants("Settings").FirstOrDefault()?
                                          .Element("CliRepositoryRoot")?.Value
                                          ?? Settings.CliRepositoryRootDefault;
                string cliRpositoryFileName = document.Descendants("Settings").FirstOrDefault()?
                                              .Element("CliRepositoryFileName")?.Value
                                              ?? Settings.CliRepositoryFileNameDefault;
                string cliRpositorySignatureFileName = document.Descendants("Settings").FirstOrDefault()?
                                                       .Element("CliRepositorySignatureFileName")?.Value
                                                       ?? Settings.CliRepositorySignatureFileNameDefault;
                string httpProxy = document.Descendants("Settings").FirstOrDefault()?
                                   .Element("HttpProxy")?.Value
                                   ?? Settings.HttpProxyDefault;
                string logFilePath = document.Descendants("Settings").FirstOrDefault()?
                                     .Element("LogFilePath")?.Value
                                     ?? Settings.LogFilePathDefault;
                bool systemCommands = bool.TryParse(document.Descendants("Settings").FirstOrDefault()?
                                                    .Element("SystemCommands")?.Value, out bool parsed)
                                          ? parsed
                                          : Settings.UseSystemCommandsDefault;

                log.LogInformation($"Used settings {file.FullName}:");
                Settings result = new Settings(attributePrefix, paths.ToArray(), cliRpositoryRoot, cliRpositoryFileName, cliRpositorySignatureFileName, httpProxy, logFilePath, templates.ToArray(), systemCommands);
                log.LogInformation(JsonConvert.SerializeObject(result, Formatting.Indented));
                return(result);
            }
        }
        public override Entity Resolve(Entity owner, string key, bool fallback = false)
        {
            switch (key)
            {
            case EntityKeys.BuildTypeKey:
                string buildType = GetBuildType(owner);
                return(owner.Create(key, buildType));

            case EntityKeys.InternalBuildSystemDirectoryKey:
                VirtualDirectory directory = GetBuildSystemDirectory(owner, false);
                return(owner.Create(key, directory));

            case EntityKeys.InternalBuildSystemKey:
                VirtualDirectory buildSystemDirectory = GetBuildSystemDirectory(owner);
                JArray           codeModel            = GetCodeModel(owner, buildSystemDirectory);
                return(owner.Create(key, codeModel, buildSystemDirectory));

            case EntityKeys.InternalExternalLibrariesKey:
                IEnumerable <string> externalLibraries = FindExternalLibrariesInCodeModel(owner.Value <JArray>(),
                                                                                          owner.Root.Name,
                                                                                          owner.Value <VirtualDirectory>());
                return(owner.Create(key, externalLibraries.Select(l => owner.Create(key, l))));

            case EntityKeys.InternalInstallationPathsKey:
                IEnumerable <string> installationPaths = FindInstallationPaths(owner.Value <JArray>(),
                                                                               owner.Root.Name);
                return(owner.Create(key, installationPaths.Select(p => owner.Create(key, p))));

            default:
                VirtualFile cmakeFile = GetCMakeFile(owner);
                using (Stream fileStream = cmakeFile.OpenRead())
                    using (StreamReader reader = new StreamReader(fileStream))
                    {
                        while (!reader.EndOfStream)
                        {
                            string line = reader.ReadLine();
                            if (string.IsNullOrEmpty(line))
                            {
                                continue;
                            }
                            Match projectNameMatch = projectNameFinder.Match(line);
                            if (projectNameMatch.Success)
                            {
                                return(owner.Create(key, projectNameMatch.Groups["name"].Value));
                            }
                        }
                    }

                return(owner.Create(key, Path.GetFileName(owner.Path)));
            }
        }
Exemplo n.º 10
0
 public static T Load <T>(this VirtualFile file)
     where T : class
 {
     try
     {
         using (Stream stream = file.OpenRead())
         {
             XmlSerializer xs = XmlSerializer(typeof(T));
             return(xs.Deserialize(stream) as T);
         }
     }
     catch (Exception ex)
     {
         // do nothing
     }
     return(default(T));
 }
Exemplo n.º 11
0
        private BinaryLocator GetLocator(string baseDirectory)
        {
            if (locators.ContainsKey(baseDirectory))
            {
                return(locators[baseDirectory]);
            }
            if (fileSystem.FileExists(Path.Combine(baseDirectory, Constants.FileNamesFile)))
            {
                VirtualFile fileNamesFile = fileSystem.GetFile(Path.Combine(baseDirectory, Constants.FileNamesFile));
                using (Stream stream = fileNamesFile.OpenRead())
                {
                    XDocument document = XDocument.Load(stream);
                    Dictionary <string, VirtualFile> executables = new Dictionary <string, VirtualFile>();
                    foreach (XElement element in document.Element("names")?.Elements() ??
                             Enumerable.Empty <XElement>())
                    {
                        string name     = element.Name.LocalName;
                        string partPath = element.Attribute("path")?.Value ?? string.Empty;
                        string path     = Path.Combine(baseDirectory,
                                                       partPath.Replace("/", $"{Path.DirectorySeparatorChar}"));
                        if (environmentService.Platform == OSPlatform.Windows)
                        {
                            path = path + ".exe";
                        }

                        if (fileSystem.FileExists(path))
                        {
                            executables.Add(name, fileSystem.GetFile(path));
                        }
                        else
                        {
                            userInterface.WriteVerbose($"While locating binaries the following file was not found {path}.");
                        }
                    }

                    locators.Add(baseDirectory, new BinaryLocator(executables));
                }
            }
            else
            {
                locators.Add(baseDirectory, new BinaryLocator(new Dictionary <string, VirtualFile>()));
            }

            return(locators[baseDirectory]);
        }
Exemplo n.º 12
0
        public IEnumerable <Entity> FindAllEntities(string entityName, Entity owner)
        {
            if (!owner.HasPathCommandArgument())
            {
                executionContext.WriteVerbose("The executed command lacks the path argument, no project file can be loaded.");
                return(Enumerable.Empty <Entity>());
            }

            string rootFilePath = fileSystem.GetDirectory(owner.GetPathCommandArgument(), createNew: false)
                                  .FullName;

            VirtualFile file = fileSystem.FileExists(rootFilePath)
                                   ? fileSystem.GetFile(rootFilePath)
                                   : fileSystem.FileExists(Constants.ProjectFileName, rootFilePath)
                                       ? fileSystem.GetFile(Constants.ProjectFileName, rootFilePath)
                                       : null;

            if (file == null)
            {
                executionContext.WriteVerbose($"No project file found in {rootFilePath}.");
                return(Enumerable.Empty <Entity>());
            }

            try
            {
                using (Stream fileStream = file.OpenRead())
                    using (XmlReader reader = XmlReader.Create(fileStream))
                    {
                        XmlSerializer   serializer = new XmlSerializer(typeof(ProjectSettings));
                        ProjectSettings settings   = (ProjectSettings)serializer.Deserialize(reader);
                        if (settings.Type != null && settings.Type.Equals(entityName, StringComparison.Ordinal))
                        {
                            return new[] { owner.Create(entityName, new ProjectDescription(settings, file.Parent, file)) }
                        }
                        ;
                    }
            }
            catch (Exception e)
            {
                executionContext.WriteVerbose($"Error while trying to parse project settings {file.FullName}." +
                                              $"{Environment.NewLine}{e}");
            }

            return(Enumerable.Empty <Entity>());
        }
Exemplo n.º 13
0
 public static T LoadJson <T>(this VirtualFile file)
     where T : class
 {
     try
     {
         using (Stream stream = file.OpenRead())
             using (StreamReader sr = new StreamReader(stream))
             {
                 JsonSerializer xs = new JsonSerializer();
                 return(xs.Deserialize(sr, typeof(T)) as T);
             }
     }
     catch (Exception ex)
     {
         // do nothing
     }
     return(default(T));
 }
Exemplo n.º 14
0
        public void DeployFiles(Entity dataModel)
        {
            IEnumerable <Entity> deployableEntities = dataModel.Root.Hierarchy();
            ProjectEntity        project            = ProjectEntity.Decorate(dataModel.Root);

            // get targets to deploy for
            IEnumerable <Target> targets = null;

            CommandEntity command = CommandEntity.Decorate(dataModel);

            if (command.IsCommandArgumentSpecified(Constants.TargetArgumentName))
            {
                IEnumerable <string> rawTargets = command.GetMultiValueArgument(Constants.TargetArgumentName);

                if (rawTargets.Any())
                {
                    targets = targetParser.GetSpecificTargets(rawTargets, false).Select(t => t.Item1);
                }
                else
                {
                    targets = targetParser.Targets(project, false).ValidTargets;
                }
            }
            else
            {
                targets = targetParser.Targets(project, false).ValidTargets;
            }
            if (!targets.Any())
            {
                throw new NoTargetSpecifiedException();
            }


            foreach (Entity deployableEntity in deployableEntities)
            {
                DeployFilesFromTemplate(deployableEntity);
            }

            if (command.IsCommandArgumentSpecified(Constants.FilesArgumentName))
            {
                IEnumerable <string> files = command.GetMultiValueArgument(Constants.FilesArgumentName);

                foreach (string file in files)
                {
                    DeployFileFromArgument(file);
                }
            }

            void DeployFileFromArgument(string file)
            {
                Match match = FilesDecoder.Match(file);

                if (!match.Success)
                {
                    throw new FormattableException($"The input {file} could not be parsed. Expected pattern is <fileLocation>|<destination>[|<target>]");
                }

                string from      = match.Groups["from"].Value;
                string to        = match.Groups["destination"].Value;
                string rawTarget = match.Groups["target"].Value;

                VirtualDirectory baseDirectory     = null;
                string           relativePath      = null;
                bool             recreateStructure = false;

                string[] path          = fileSystem.GetPath(from);
                int      firstWildCard = path.TakeWhile(p => !p.Contains('*') && !p.Contains('?')).Count();

                if (firstWildCard != path.Length)
                {
                    baseDirectory     = fileSystem.GetDirectory(Path.Combine(path.Take(firstWildCard).ToArray()), project.Path, false);
                    relativePath      = Path.Combine(path.Skip(firstWildCard).ToArray());
                    recreateStructure = true;
                }

                if (recreateStructure)
                {
                    IEnumerable <VirtualFile> deployFiles = baseDirectory.Files(relativePath, true).ToArray();
                    if (!deployFiles.Any())
                    {
                        throw new DeployFileNotFoundException(@from);
                    }
                    foreach (VirtualFile deployFile in deployFiles)
                    {
                        string structure       = Path.GetDirectoryName(deployFile.GetRelativePath(baseDirectory));
                        string fileDestination = string.IsNullOrEmpty(structure) ? to : Path.Combine(to, structure);
                        DeployFile(deployFile.FullName, fileDestination);
                    }
                }
                else if (fileSystem.FileExists(from, project.Path))
                {
                    DeployFile(from, to);
                }
                else
                {
                    throw new DeployFileNotFoundException(@from);
                }

                void DeployFile(string sourceFile, string destinationDirectory)
                {
                    if (!string.IsNullOrEmpty(rawTarget))
                    {
                        DeployFileForRawTarget(rawTarget, sourceFile, destinationDirectory);
                    }
                    else
                    {
                        foreach (Target target in targets)
                        {
                            DeployFileForTarget(target, sourceFile, destinationDirectory);
                        }
                    }
                }

                void DeployFileForRawTarget(string target, string sourceFile, string destinationDirectory)
                {
                    Target parsedTarget = targetParser.ParseTarget(target, null, targets);

                    DeployFileForTarget(parsedTarget, sourceFile, destinationDirectory);
                }

                void DeployFileForTarget(Target target, string sourceFile, string destinationDirectory)
                {
                    VirtualFile fileToCopy = fileSystem.GetFile(sourceFile, project.Path);
                    VirtualFile copiedFile = fileSystem.GetDirectory(destinationDirectory, GetOutputDirectory(target).FullName).File(fileToCopy.Name);

                    using (Stream source = fileToCopy.OpenRead(true))
                        using (Stream destination = copiedFile.OpenWrite())
                        {
                            destination.SetLength(0);
                            source.CopyTo(destination);

                            executionContext.WriteVerbose($"Deployed file {fileToCopy.FullName} to {copiedFile.FullName}.");
                        }
                }
            }

            void DeployFilesFromTemplate(Entity deployableEntity)
            {
                TemplateDescription template = deployableEntity.Template();

                if (template == null)
                {
                    return;
                }

                foreach (templateFile file in template.File)
                {
                    if (!file.deployPathSpecified)
                    {
                        continue;
                    }

                    VirtualFile deployableFile = GetFile(file, dataModel.Root.Path, false, out string path);

                    DeployFile(file, deployableFile, path);
                }

                foreach (templateGeneratedFile generatedFile in template.GeneratedFile ?? Enumerable.Empty <templateGeneratedFile>())
                {
                    if (!generatedFile.deployPathSpecified)
                    {
                        continue;
                    }

                    VirtualFile deployableFile = GetFile(generatedFile, dataModel.Root.Path, true, out string path);

                    DeployFile(generatedFile, deployableFile, path);
                }

                VirtualFile GetDestination(templateFile file, Target target, string name)
                {
                    string basePath = GetOutputDirectory(target).FullName;
                    string path     = resolver.Resolve(file.deployPath ?? string.Empty, deployableEntity);

                    VirtualFile destination = fileSystem.GetFile(Path.Combine(path, name), basePath);

                    return(destination);
                }

                void DeployFile(templateFile file, VirtualFile deployableFile, string filePath)
                {
                    if (deployableFile == null)
                    {
                        executionContext.WriteVerbose($"Could not find file {filePath} in {dataModel.Root.Path}, the file will not be deployed.");
                        return;
                    }
                    foreach (Target target in targets)
                    {
                        VirtualFile destination = GetDestination(file, target, deployableFile.Name);

                        using (Stream source = deployableFile.OpenRead(true))
                            using (Stream dest = destination.OpenWrite())
                            {
                                dest.SetLength(0);
                                source.CopyTo(dest);
                            }

                        executionContext.WriteVerbose($"Deployed file {deployableFile.FullName} to {destination.FullName}.");
                    }
                }

                VirtualFile GetFile(templateFile file, string basePath, bool isGeneratedFile, out string realFilePath)
                {
                    string path = resolver.Resolve(file.path ?? string.Empty, deployableEntity);
                    string name = resolver.Resolve(file.name, deployableEntity);

                    if (isGeneratedFile && file is templateGeneratedFile generatedFile)
                    {
                        realFilePath = Path.Combine(path, name);
                        if (!Path.IsPathRooted(realFilePath))
                        {
                            realFilePath = Path.Combine(Constants.IntermediateFolderName, generatedFile.generator?.ToLowerInvariant() ?? string.Empty, realFilePath);
                        }
                    }
                    else
                    {
                        realFilePath = Path.Combine(path, name);
                    }

                    VirtualFile destination = fileSystem.FileExists(realFilePath, basePath)
                                                  ? fileSystem.GetFile(realFilePath, basePath)
                                                  : null;

                    return(destination);
                }
            }

            VirtualDirectory GetOutputDirectory(Target target)
            {
                string buildTypeFolder = command.IsCommandArgumentSpecified(Constants.BuildTypeArgumentName)
                                             ? FormatBuildType(command.GetSingleValueArgument(Constants.BuildTypeArgumentName))
                                             : Constants.ReleaseFolderName;
                string basePath = project.Path;

                if (!command.IsCommandArgumentSpecified(Constants.OutputArgumentName))
                {
                    return(fileSystem.GetDirectory(Path.Combine(basePath, Constants.LibraryFolderName, target.GetFullName().Replace(',', '_'),
                                                                buildTypeFolder)));
                }

                basePath = fileSystem.GetDirectory(command.GetSingleValueArgument(Constants.OutputArgumentName), basePath).FullName;
                basePath = Path.Combine(basePath, target.GetFullName().Replace(',', '_'), buildTypeFolder);

                return(fileSystem.GetDirectory(basePath));

                string FormatBuildType(string buildType)
                {
                    if (string.IsNullOrEmpty(buildType))
                    {
                        return(Constants.ReleaseFolderName);
                    }

                    return(buildType.Substring(0, 1).ToUpperInvariant() +
                           buildType.Substring(1).ToLowerInvariant());
                }
            }
        }
Exemplo n.º 15
0
        public override Entity Resolve(Entity owner, string key, bool fallback = false)
        {
            switch (key)
            {
            case EntityKeys.ProjectConfigurationsKey:
                return(GetProjectConfiguration());

            case EntityKeys.EngineerVersionKey:
                return(GetEngineerVersion());

            case EntityKeys.SolutionVersionKey:
                return(GetSolutionVersion());

            case EntityKeys.LibraryDescriptionKey:
                return(GetLibraryDescription());

            case EntityKeys.LibraryVersionKey:
                return(GetLibraryVersion());

            default:
                throw new ContentProviderException(key, owner);
            }

            Entity GetProjectConfiguration()
            {
                if (!owner.HasPath)
                {
                    executionContext.WriteVerbose("The executed command lacks the path argument, no project configuration can be loaded.");
                    return(owner.Create(key, new ProjectConfigurations()));
                }

                string rootFilePath = fileSystem.GetDirectory(owner.Path, createNew: false)
                                      .FullName;

                string projectDirectory = fileSystem.FileExists(rootFilePath)
                                            ? Path.GetDirectoryName(rootFilePath)
                                            : rootFilePath;

                VirtualFile file = fileSystem.DirectoryExists(projectDirectory) &&
                                   fileSystem.FileExists(Path.Combine(projectDirectory, Constants.ConfigFileName))
                                           ? fileSystem.GetFile(Path.Combine(projectDirectory, Constants.ConfigFileName))
                                           : null;

                if (file == null)
                {
                    executionContext.WriteVerbose($"No config file found in {projectDirectory}.");
                    return(owner.Create(key, new ProjectConfigurations()));
                }

                try
                {
                    using (Stream fileStream = file.OpenRead())
                        using (XmlReader reader = XmlReader.Create(fileStream))
                        {
                            XmlSerializer        serializer    = new XmlSerializer(typeof(ProjectConfiguration));
                            ProjectConfiguration configuration = (ProjectConfiguration)serializer.Deserialize(reader);
                            if (configuration != null)
                            {
                                return(owner.Create(key, new ProjectConfigurations(configuration, file)));
                            }
                        }
                }
                catch (DeployArgumentsException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    executionContext.WriteVerbose($"Error while trying to parse project configuration {file.FullName}." +
                                                  $"{Environment.NewLine}{e}");
                }

                return(owner.Create(key, new ProjectConfigurations()));
            }

            Entity GetEngineerVersion()
            {
                CommandEntity command = CommandEntity.Decorate(owner.Origin);
                ProjectEntity project = ProjectEntity.Decorate(owner);

                if (command.CommandName.Equals("deploy", StringComparison.OrdinalIgnoreCase) &&
                    command.IsCommandArgumentSpecified(Constants.EngineerVersionArgumentKey))
                {
                    if (command.IsCommandArgumentSpecified(Constants.SolutionVersionArgumentKey))
                    {
                        throw new DeployArgumentsException();
                    }
                    string value = command.GetSingleValueArgument(Constants.EngineerVersionArgumentKey);
                    project.Configuration.EngineerVersion = value;
                    return(owner.Create(key, value));
                }

                return(owner.Create(key, project.Configuration.EngineerVersion));
            }

            Entity GetSolutionVersion()
            {
                CommandEntity command = CommandEntity.Decorate(owner.Origin);
                ProjectEntity project = ProjectEntity.Decorate(owner);

                if (command.CommandName.Equals("deploy", StringComparison.OrdinalIgnoreCase) &&
                    command.IsCommandArgumentSpecified(Constants.SolutionVersionArgumentKey))
                {
                    if (command.IsCommandArgumentSpecified(Constants.EngineerVersionArgumentKey))
                    {
                        throw new DeployArgumentsException();
                    }
                    string value = command.GetSingleValueArgument(Constants.SolutionVersionArgumentKey);
                    project.Configuration.SolutionVersion = value;
                    return(owner.Create(key, value));
                }

                return(owner.Create(key, project.Configuration.SolutionVersion));
            }

            Entity GetLibraryDescription()
            {
                CommandEntity command = CommandEntity.Decorate(owner.Origin);
                ProjectEntity project = ProjectEntity.Decorate(owner);

                if (command.CommandName.Equals("deploy", StringComparison.OrdinalIgnoreCase) &&
                    command.IsCommandArgumentSpecified(Constants.DescriptionArgumentKey))
                {
                    string value = command.GetSingleValueArgument(Constants.DescriptionArgumentKey);
                    project.Configuration.LibraryDescription = value;
                    return(owner.Create(key, value));
                }

                return(owner.Create(key, project.Configuration.LibraryDescription));
            }

            Entity GetLibraryVersion()
            {
                CommandEntity command = CommandEntity.Decorate(owner.Origin);
                ProjectEntity project = ProjectEntity.Decorate(owner);

                if (command.CommandName.Equals("deploy", StringComparison.OrdinalIgnoreCase) &&
                    command.IsCommandArgumentSpecified(Constants.VersionArgumentKey))
                {
                    string value = command.GetSingleValueArgument(Constants.VersionArgumentKey);
                    project.Configuration.LibraryVersion = value;
                    return(owner.Create(key, value));
                }

                return(owner.Create(key, project.Configuration.LibraryVersion));
            }
        }
Exemplo n.º 16
0
        public ParserResult Parse(VirtualFile file)
        {
            log.LogVerbose($"Parse file {file.FullName}.");
            List <CodeSpecificException>      codeSpecificExceptions = new List <CodeSpecificException>();
            List <ParserMessage>              messages = new List <ParserMessage>();
            IDictionary <IType, CodePosition> types    = new Dictionary <IType, CodePosition>();
            CppStreamParser parser = new CppStreamParser();
            ParseNode       root   = parser.Parse(file.OpenRead());

            if (!parser.Succeeded)
            {
                messages.Add(parser.Exception == null
                                 ? new ParserMessage("CPP0004", 1, 1)
                                 : new ParserMessage("CPP0005", parser.Exception.Row, parser.Exception.Col,
                                                     $"{Environment.NewLine}{parser.Exception.Message}"));
                codeSpecificExceptions.AddRange(messages.Select(m => m.ToException(file)));
                return(new ParserResult(codeSpecificExceptions));
            }

            string[] usings = GetUsings();
            foreach (ParseNode typeDeclaration in GetTypeDeclarations(root))
            {
                ParseNode content = GetDeclarationContentParent(typeDeclaration);
                if (content != null && IsValidDecalration(content, typeDeclaration))
                {
                    string name = GetName(typeDeclaration);
                    string ns   = GetNamespace(typeDeclaration);
                    switch (typeDeclaration[1].RuleName)
                    {
                    case "struct_decl":
                        CppStructure structure = new CppStructure(ns, name, usings, content, messages, typeDeclaration,
                                                                  settingsProvider.Settings.AttributePrefix);
                        types.Add(structure, new CodePosition(typeDeclaration.Position.line, typeDeclaration.Position.column));

                        break;

                    case "class_decl":
                        CppClass cppClass = new CppClass(ns, name, usings, content, typeDeclaration[1], messages,
                                                         settingsProvider.Settings.AttributePrefix);
                        types.Add(cppClass, new CodePosition(typeDeclaration.Position.line, typeDeclaration.Position.column));

                        break;

                    case "enum_decl":
                        CppEnum cppEnum = new CppEnum(ns, name, usings, content, messages, typeDeclaration[1],
                                                      settingsProvider.Settings.AttributePrefix);
                        types.Add(cppEnum, new CodePosition(typeDeclaration.Position.line, typeDeclaration.Position.column));

                        break;

                    default:
                        //do nothing
                        break;
                    }
                }
            }

            codeSpecificExceptions.AddRange(messages.Select(m => m.ToException(file)));
            string[] includes = GetIncludes();
            return(new ParserResult(codeSpecificExceptions, types, includes));

            bool IsValidDecalration(ParseNode content, ParseNode typeDeclaration)
            {
                return(content.Count >= 2 &&
                       content.Any(c => c.GetHierarchy().Contains(typeDeclaration)) &&
                       content.SkipWhile(c => !c.GetHierarchy().Contains(typeDeclaration))
                       .Skip(1).Any(c => c.GetHierarchy().Any(n => n.RuleName == "brace_group")));
            }

            string GetName(ParseNode typeDeclaration)
            {
                ParseNode leaf = typeDeclaration.GetHierarchy()
                                 .FirstOrDefault(n => n.RuleName == "identifier" ||
                                                 n.RuleName == "generic");

                if (leaf == null)
                {
                    return(Guid.NewGuid().ToByteString());
                }

                return(leaf.ToString());
            }

            ParseNode GetDeclarationContentParent(ParseNode current)
            {
                while (current != null &&
                       current.RuleType != "plus" &&
                       current.RuleName != "declaration_content")
                {
                    current = current.GetParent();
                }

                return(current);
            }

            IEnumerable <ParseNode> GetTypeDeclarations(ParseNode current)
            {
                foreach (ParseNode node in current)
                {
                    if (node.RuleType == "sequence" && node.RuleName == "type_decl")
                    {
                        yield return(node);
                    }
                    else
                    {
                        foreach (ParseNode child in GetTypeDeclarations(node))
                        {
                            yield return(child);
                        }
                    }
                }
            }

            string[] GetIncludes()
            {
                List <string> result = new List <string>();

                foreach (ParseNode includeNode in root.GetHierarchy().Where(n => n.RuleType == "sequence" &&
                                                                            n.RuleName == "pp_directive" &&
                                                                            n.Any(c => c.ToString().Equals("include", StringComparison.OrdinalIgnoreCase))))
                {
                    ParseNode include = includeNode.FirstOrDefault(n => n.RuleName == "until_eol");
                    if (include != null)
                    {
                        result.Add(include.ToString().Trim('\"'));
                    }
                }

                return(result.ToArray());
            }

            string[] GetUsings()
            {
                List <string> result = new List <string>();

                foreach (ParseNode usingNode in root.GetHierarchy().Where(n => n.RuleType == "leaf" &&
                                                                          n.RuleName == "identifier" &&
                                                                          n.ToString() == "using"))
                {
                    ParseNode declarationParent = GetDeclarationContentParent(usingNode);
                    string[]  identifier        = declarationParent.ChildrenSkipUnnamed()
                                                  .Select(Identifier)
                                                  .Where(i => i != null)
                                                  .Select(i => i.ToString())
                                                  .ToArray();
                    if (identifier.Length > 2 && identifier[0] == "using" && identifier[1] == "namespace")
                    {
                        result.Add(identifier.Skip(2).Aggregate(string.Empty, (s, s1) => s + s1));
                    }
                }

                return(result.ToArray());
            }

            ParseNode Identifier(ParseNode parent)
            {
                if (parent.RuleType == "choice" && parent.RuleName == "node")
                {
                    ParseNode result = parent.FirstOrDefault();
                    if (result?.RuleType == "leaf" && result.RuleName == "identifier")
                    {
                        return(result);
                    }
                }

                return(null);
            }

            string GetNamespace(ParseNode typeDeclaration)
            {
                ParseNode declarationParent;

                typeDeclaration = GetDeclarationContentParent(typeDeclaration).GetParent();
                string result = string.Empty;

                while ((declarationParent = GetDeclarationContentParent(typeDeclaration)) != null)
                {
                    string[] identifier = declarationParent.ChildrenSkipUnnamed()
                                          .Where(r => r.RuleName != "comment_set")
                                          .Select(Identifier)
                                          .TakeWhile(i => i != null)
                                          .Select(i => i.ToString())
                                          .ToArray();
                    if (identifier.Length > 1 && identifier[0] == "namespace")
                    {
                        result = $"{identifier.Skip(1).Aggregate(string.Empty, (s, s1) => s + s1)}::{result}";
                    }
                    else if (identifier.Length == 0)
                    {
                        ParseNode parentTypeDeclaration = declarationParent.ChildrenSkipUnnamed()
                                                          .Where(c => c.RuleType == "choice" &&
                                                                 c.RuleName == "node")
                                                          .SelectMany(c => c.ChildrenSkipUnnamed())
                                                          .FirstOrDefault(
                            c => c.RuleType == "sequence" &&
                            c.RuleName == "type_decl");
                        ParseNode name = parentTypeDeclaration?.GetHierarchy()
                                         .FirstOrDefault(n => n.RuleType == "leaf" &&
                                                         n.RuleName == "identifier");
                        if (name != null)
                        {
                            result = $"{name}::{result}";
                        }
                    }

                    typeDeclaration = declarationParent.GetParent();
                }

                if (!string.IsNullOrEmpty(result))
                {
                    result = result.Substring(0, result.Length - 2);
                }

                return(result);
            }
        }
        public IReadOnlyCollection <TemplateLoaderResult> LoadTemplates()
        {
            List <TemplateLoaderResult> result          = new List <TemplateLoaderResult>();
            XmlSerializer templatesSerializer           = new XmlSerializer(typeof(Templates.Templates));
            XmlSerializer templateDescriptionSerializer = new XmlSerializer(typeof(TemplateDescription));
            XmlSerializer fieldTemplateSerializer       = new XmlSerializer(typeof(FieldTemplates));
            XmlSerializer typeTemplateSerializer        = new XmlSerializer(typeof(TypeTemplates));
            XmlSerializer formatTemplateSerializer      = new XmlSerializer(typeof(FormatTemplates));

            foreach (string templateLocation in settingsProvider.Settings.TemplateLocations)
            {
                try
                {
                    if (!fileSystem.FileExists(templateLocation, environmentService.AssemblyDirectory))
                    {
                        executionContext.WriteWarning($"The template location {templateLocation} does not point to an existing file." +
                                                      " Fix problems with template or remove the location from the settings.");
                        continue;
                    }

                    VirtualFile         baseFile = fileSystem.GetFile(templateLocation, environmentService.AssemblyDirectory);
                    Templates.Templates templates;
                    using (Stream fileStream = baseFile.OpenRead())
                        using (XmlReader reader = XmlReader.Create(fileStream))
                        {
                            templates = (Templates.Templates)templatesSerializer.Deserialize(reader);
                        }

                    foreach (include include in templates.Include)
                    {
                        string path = include.Value.Replace('\\', Path.DirectorySeparatorChar)
                                      .Replace('/', Path.DirectorySeparatorChar);
                        path = Path.Combine(baseFile.Parent.FullName, path);
                        using (Stream includeStream = fileSystem.GetFile(path).OpenRead())
                            using (XmlReader reader = XmlReader.Create(includeStream))
                            {
                                switch (include.type)
                                {
                                case includeType.Template:
                                    result.Add(new TemplateLoaderResult(
                                                   templateDescriptionSerializer.Deserialize(reader),
                                                   Path.GetDirectoryName(path)));
                                    break;

                                case includeType.Fields:
                                    result.Add(new TemplateLoaderResult(
                                                   fieldTemplateSerializer.Deserialize(reader),
                                                   Path.GetDirectoryName(path)));
                                    break;

                                case includeType.Types:
                                    result.Add(new TemplateLoaderResult(
                                                   typeTemplateSerializer.Deserialize(reader),
                                                   Path.GetDirectoryName(path)));
                                    break;

                                case includeType.Format:
                                    result.Add(new TemplateLoaderResult(
                                                   formatTemplateSerializer.Deserialize(reader),
                                                   Path.GetDirectoryName(path)));
                                    break;

                                default:
                                    throw new InvalidOperationException();
                                }
                            }
                    }
                }
                catch (InvalidOperationException e)
                {
                    executionContext.WriteWarning($"The template {templateLocation} could not be loaded. See log for details.");
                    executionContext.WriteWarning($"Fix problems with template or remove template {templateLocation} from the settings", false);
                    executionContext.WriteError(e.ToString(), false);
                }
            }

            MergeTemplates(result.Select(r => r.Template)
                           .OfType <TemplateDescription>()
                           .ToArray());

            return(result);

            void MergeTemplates(TemplateDescription[] descriptions)
            {
                List <TemplateDescription> merged = new List <TemplateDescription>();

                foreach (TemplateDescription templateDescription in descriptions)
                {
                    MergeTemplate(templateDescription);
                }

                void MergeTemplate(TemplateDescription templateDescription)
                {
                    TemplateDescription baseDescription = GetBaseDescription();

                    if (baseDescription != null)
                    {
                        if (!merged.Contains(baseDescription))
                        {
                            MergeTemplate(baseDescription);
                        }
                        templateDescription.Merge(baseDescription);
                    }
                    merged.Add(templateDescription);

                    TemplateDescription GetBaseDescription()
                    {
                        return(descriptions.FirstOrDefault(d => d.name.Equals(templateDescription.basedOn,
                                                                              StringComparison.OrdinalIgnoreCase)));
                    }
                }
            }
        }
Exemplo n.º 18
0
        public async Task Unpack(VirtualFile file, VirtualDirectory destination,
                                 IProgressNotifier parentProgress = null, ChangeObservable observable = null)
        {
            if (Path.GetExtension(file.Name)?.Equals(".zip", StringComparison.OrdinalIgnoreCase) == true)
            {
                await UnpackZipFile().ConfigureAwait(false);
            }
            else if (file.Name.EndsWith(".tar.xz", StringComparison.OrdinalIgnoreCase))
            {
                UnpackTarXzFile(file);
            }
            else if (Path.GetExtension(file.Name)?.Equals(".xz", StringComparison.OrdinalIgnoreCase) == true)
            {
                UnpackXzFile(file);
            }
            else if (Path.GetExtension(file.Name)?.Equals(".tar", StringComparison.OrdinalIgnoreCase) == true)
            {
                UnpackTarFile(file);
            }
            else if (Path.GetExtension(file.Name)?.Equals(".sh", StringComparison.OrdinalIgnoreCase) == true &&
                     environmentService.Platform != OSPlatform.Windows)
            {
                await UnpackSelfExtractingShellScript().ConfigureAwait(false);
            }
            else
            {
                throw new UnsupportedArchiveFormatException(file.FullName);
            }

            async Task UnpackSelfExtractingShellScript()
            {
                ValidateShellScript();
                StringBuilderUserInterface userInterface = new StringBuilderUserInterface(log, writeInformation: true, writeError: true);

                try
                {
                    using (parentProgress?.SpawnInfiniteProgress("Executing the shell script."))
                        using (IProcess process = processManager.StartProcess(file.FullName, $"-y -d \"{destination.FullName}\"", userInterface))
                        {
                            await process.WaitForExitAsync().ConfigureAwait(false);

                            if (process.ExitCode != 0)
                            {
                                throw new UnsupportedArchiveFormatException(file.FullName,
                                                                            new FormattableException(
                                                                                $"An error occured while executing the script.{Environment.NewLine}" +
                                                                                $"{userInterface.Error}"));
                            }
                        }
                }
                catch (Exception e)
                {
                    if (e is FormattableException)
                    {
                        throw;
                    }
                    throw new UnsupportedArchiveFormatException(file.FullName,
                                                                new FormattableException(
                                                                    $"An exception occured while executing the script.{Environment.NewLine}" +
                                                                    $"{e.Message}", e));
                }

                void ValidateShellScript()
                {
                    StringBuilderUserInterface validationUserInterface = new StringBuilderUserInterface(log, writeInformation: true, writeError: true);

                    try
                    {
                        using (IProcess process = processManager.StartProcess(file.FullName, "--help", validationUserInterface))
                        {
                            process.WaitForExit();
                        }
                    }
                    catch (UnauthorizedAccessException e)
                    {
                        throw new UnsupportedArchiveFormatException(file.FullName,
                                                                    new FormattableException(
                                                                        $"An exception occured while inspecting the script.{Environment.NewLine}" +
                                                                        $"This excpetion can occur when the file is not marked as executable.{Environment.NewLine}" +
                                                                        $"{e.Message}", e));
                    }
                    catch (Exception e)
                    {
                        if (e is FormattableException)
                        {
                            throw;
                        }
                        throw new UnsupportedArchiveFormatException(file.FullName,
                                                                    new FormattableException(
                                                                        $"An exception occured while inspecting the script.{Environment.NewLine}" +
                                                                        $"{e.Message}", e));
                    }

                    if (!Regex.IsMatch(validationUserInterface.Information,
                                       @"(?=.*(?:usage|Usage)).*(?=.*-y)(?=.*-d)"))
                    {
                        throw new UnsupportedArchiveFormatException(file.FullName,
                                                                    new FormattableException($"Did not find the expected usage information.{Environment.NewLine}" +
                                                                                             $"The expected information need to include the options '-y' and '-d'.{Environment.NewLine}" +
                                                                                             $"The following usage information was given:{Environment.NewLine}" +
                                                                                             $"{validationUserInterface.Information}"));
                    }
                }
            }

            async Task UnpackZipFile()
            {
                using (Stream fileStream = file.OpenRead())
                    using (ZipFile zipFile = new ZipFile(fileStream))
                        using (IProgressNotifier mainProgress = parentProgress?.Spawn(2, $"Extracting {file.FullName} to {destination.FullName}."))
                        {
                            archiveResultBuilder.Clear();
                            using (mainProgress?.SpawnInfiniteProgress("Test archive integrity."))
                            {
                                ZipFile copy = zipFile;
                                await Task.Run(() =>
                                {
                                    if (!copy.TestArchive(true, TestStrategy.FindAllErrors, ResultHandler))
                                    {
                                        throw new UnsupportedArchiveFormatException(
                                            file.FullName, new FormattableException(archiveResultBuilder.ToString()));
                                    }
                                }).ConfigureAwait(false);
                            }

                            double increment = (double)Constants.ProgressMaxResolution / zipFile.Count + 1;
                            using (IProgressNotifier extractProgress = mainProgress?.Spawn(Constants.ProgressMaxResolution, "Extract files"))
                            {
                                foreach (ZipEntry zipEntry in zipFile)
                                {
                                    extractProgress?.TickIncrement(increment);
                                    if (!zipEntry.IsFile)
                                    {
                                        continue;   // Ignore directories
                                    }

                                    byte[] buffer = new byte[Constants.StreamCopyBufferSize]; // 4K is optimum

                                    using (Stream zipStream = zipFile.GetInputStream(zipEntry))
                                    {
                                        string[]         path            = fileSystem.GetPath(zipEntry.Name);
                                        VirtualDirectory fileDestination = destination.Directory(path.Take(path.Length - 1).ToArray());
                                        VirtualFile      entryFile       = fileDestination.File(path.Last());

                                        // Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
                                        // of the file, but does not waste memory.
                                        using (Stream streamWriter = entryFile.OpenWrite())
                                        {
                                            StreamUtils.Copy(zipStream, streamWriter, buffer);
                                        }
                                    }
                                }
                            }
                        }
            }

            VirtualFile UnpackXzFile(VirtualFile packedFile)
            {
                using (Stream fileStream = packedFile.OpenRead())
                    using (XZStream xzStream = new XZStream(fileStream))
                        using (parentProgress?.SpawnInfiniteProgress($"Extracting {packedFile.Name}..."))
                        {
                            string[] path             = fileSystem.GetPath(packedFile.FullName);
                            string   relativeFilePath = path.Last().Substring(0, path.Last().LastIndexOf(".xz", StringComparison.OrdinalIgnoreCase));
                            if (destination.FileExists(relativeFilePath))
                            {
                                destination.File(relativeFilePath).Delete();
                            }
                            VirtualFile destinationFile = destination.File(relativeFilePath);
                            observable?.OnNext(new Change(() => destinationFile.Restore()));

                            byte[] buffer = new byte[Constants.StreamCopyBufferSize]; // 4K is optimum

                            using (Stream streamWriter = destinationFile.OpenWrite())
                            {
                                StreamUtils.Copy(xzStream, streamWriter, buffer);
                                return(destinationFile);
                            }
                        }
            }

            void UnpackTarFile(VirtualFile packedFile)
            {
                //sharpcompress
                using (Stream fileStream = packedFile.OpenRead())
                    using (TarArchive tarArchive = TarArchive.Open(fileStream))
                    {
                        double increment = (double)Constants.ProgressMaxResolution / tarArchive.Entries.Count;
                        using (IProgressNotifier extractProgress = parentProgress?.Spawn(Constants.ProgressMaxResolution, "Extracting .tar archive"))
                        {
                            foreach (TarArchiveEntry tarEntry in tarArchive.Entries)
                            {
                                extractProgress?.TickIncrement(increment);
                                if (tarEntry.IsDirectory)
                                {
                                    continue;       // Ignore directories
                                }

                                byte[] buffer = new byte[Constants.StreamCopyBufferSize]; // 4K is optimum

                                using (Stream tarStream = tarEntry.OpenEntryStream())
                                {
                                    string[]         path            = fileSystem.GetPath(tarEntry.Key);
                                    VirtualDirectory fileDestination = destination.Directory(path.Take(path.Length - 1).ToArray());
                                    if (fileDestination.FileExists(path.Last()))
                                    {
                                        fileDestination.File(path.Last()).Delete();
                                    }
                                    VirtualFile entryFile = fileDestination.File(path.Last());
                                    observable?.OnNext(new Change(() => entryFile.Restore()
                                                                  //, $"Unpack {tarEntry.Key}."
                                                                  ));

                                    //Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
                                    // of the file, but does not waste memory.
                                    using (Stream streamWriter = entryFile.OpenWrite())
                                    {
                                        StreamUtils.Copy(tarStream, streamWriter, buffer);
                                    }
                                }
                            }
                        }
                    }
            }

            void UnpackTarXzFile(VirtualFile packedFile)
            {
                using (IProgressNotifier subProgress = parentProgress?.Spawn(2))
                {
                    parentProgress = subProgress;
                    VirtualFile tarFile = UnpackXzFile(packedFile);
                    UnpackTarFile(tarFile);
                    tarFile.Delete();
                }
            }
        }
Exemplo n.º 19
0
        public (bool, VirtualDirectory) EnsureConfigured(BuildInformation buildInformation, bool showWarningsToUser, ChangeObservable observable = null,
                                                         bool throwOnError = false, bool showMessagesToUser = true)
        {
            if (!CmakeFileExists())
            {
                GenerateCmakeFile();
            }

            VirtualDirectory cmakeFolder = CreateCmakeFolder();

            LoadCmakeOptions();

            bool success = ConfigureCMake();

            return(success, cmakeFolder);

            void GenerateCmakeFile()
            {
                //It is important to get the name first before the cmake file is created in the next line.
                string      name      = buildInformation.RootEntity.Name;
                VirtualFile cMakeFile = buildInformation.RootFileEntity.Directory.File(Constants.CMakeFileName);

                //TODO Generate cmakefile with template system
                //TODO Set src folders in cmake file (consider foreign project structure)
                CMakeFileGenerator.WriteCMakeFile(cMakeFile, name);
                observable?.OnNext(new Change(() => { /*Do not delete, because user need to make changes perhaps*/ }, $"Generated cmake file {cMakeFile.FullName}"));
            }

            bool CmakeFileExists()
            {
                return(buildInformation.RootFileEntity.Directory.FileExists(Constants.CMakeFileName));
            }

            VirtualDirectory CreateCmakeFolder()
            {
                VirtualDirectory result = buildInformation.BuildEntity.BuildSystemDirectory;

                if (buildInformation.Configure && !buildInformation.NoConfigure)
                {
                    result.Clear();
                    observable?.OnNext(new Change(() => result.UnClear(), $"Cleared cmake directory."));
                }
                return(result);
            }

            string GetRealBuildType()
            {
                string buildType = !string.IsNullOrEmpty(buildInformation.BuildType)
                                       ? buildInformation.BuildType
                                       : Constants.ReleaseFolderName;

                return(buildType);
            }

            void LoadCmakeOptions()
            {
                if (!string.IsNullOrEmpty(buildInformation.BuildProperties))
                {
                    return;
                }

                if (buildInformation.RootFileEntity?.Directory?.FileExists(Constants.CMakeCommandArgsFileName) == true)
                {
                    string      cmakeArgs       = string.Empty;
                    VirtualFile commandArgsFile = buildInformation.RootFileEntity.Directory.File(Constants.CMakeCommandArgsFileName);
                    using (Stream fileStream = commandArgsFile.OpenRead())
                        using (StreamReader streamReader = new StreamReader(fileStream))
                        {
                            while (!streamReader.EndOfStream)
                            {
                                string line = streamReader.ReadLine();
                                if (string.IsNullOrEmpty(line))
                                {
                                    continue;
                                }
                                cmakeArgs = string.Join(" ", cmakeArgs, line);
                            }
                        }
                    buildInformation.BuildProperties          = cmakeArgs;
                    buildInformation.BuildPropertiesSetByFile = true;
                }
            }

            bool ConfigureCMake()
            {
                executionContext.WriteInformation("Checking if CMake needs to be reconfigured...", showMessagesToUser);
                if ((!cmakeFolder.FileExists("CMakeCache.txt") ||
                     buildInformation.Configure ||
                     !CacheHasValidTimestamp() ||
                     !IsCorrectlyConfigured() ||
                     OutputOptionDiffersFromStagingPrefix()) &&
                    !buildInformation.NoConfigure)
                {
                    string cmakeCommand = GenerateCmakeCommand(buildInformation.Target.Name,
                                                               buildInformation.Target.LongVersion);

                    executionContext.WriteInformation("Configuring CMake...", showMessagesToUser);

                    bool result = CallCmake(cmakeFolder, cmakeCommand, showMessagesToUser, throwOnError, showWarningsToUser);

                    AddTimestamp();

                    return(result);
                }

                if (!string.IsNullOrEmpty(buildInformation.BuildProperties) && !buildInformation.BuildPropertiesSetByFile)
                {
                    executionContext.WriteWarning($"The specified build options will not be used, " +
                                                  $"because no reconfiguration is necessary. " +
                                                  $"To force a reconfiguration please use the '--configure' command option.",
                                                  showMessagesToUser);
                }

                return(true);

                string GenerateCmakeCommand(string target, string version)
                {
                    List <string> commandParts = new List <string>();
                    string        sdkRoot      = buildInformation.SdkInformation.Root.FullName.Replace("\\", "/");

                    if (!buildInformation.BuildProperties.Contains("-DCMAKE_TOOLCHAIN_FILE="))
                    {
                        commandParts.Add(ToolchainFileOption.Replace("%SDK_ROOT%", sdkRoot));
                    }
                    if (!buildInformation.BuildProperties.Contains("-DARP_TOOLCHAIN_ROOT="))
                    {
                        commandParts.Add(ToolchainRootOption.Replace("%SDK_ROOT%", sdkRoot));
                    }
                    if (!buildInformation.BuildProperties.Contains("-DCMAKE_BUILD_TYPE="))
                    {
                        commandParts.Add(BuildTypeOption.Replace("%BUILD_TYPE%", GetRealBuildType()));
                    }
                    if (!buildInformation.BuildProperties.Contains("-DARP_DEVICE="))
                    {
                        commandParts.Add(DeviceOption.Replace("%TARGET%", $"\"{target}\""));
                    }
                    if (!buildInformation.BuildProperties.Contains("-DARP_DEVICE_VERSION="))
                    {
                        commandParts.Add(DeviceVersionOption.Replace("%VERSION%", $"\"{version}\""));
                    }
                    if (!buildInformation.BuildProperties.Contains("-DCMAKE_STAGING_PREFIX="))
                    {
                        commandParts.Add(StagingPrefixOption.Replace("%STAGING_PREFIX%", GenerateStagingPrefixForTarget()));
                    }
                    if (!buildInformation.BuildProperties.Contains("-DCMAKE_PREFIX_PATH=") &&
                        IsIncludePathAvailable(out string includePath))
                    {
                        commandParts.Add(PrefixPathOption.Replace("%PREFIX_PATH%", includePath));
                    }
                    if (!buildInformation.BuildProperties.Contains("-G "))
                    {
                        commandParts.Add(GeneratorOption);
                        if (buildInformation.SdkInformation.MakeFile != null && !buildInformation.BuildProperties.Contains("-DCMAKE_MAKE_PROGRAM "))
                        {
                            commandParts.Add(MakeFileOption.Replace("%MAKE_EXE%", $"\"{buildInformation.SdkInformation.MakeFile.FullName.Replace("\\", "/")}\""));
                        }
                    }
                    if (!string.IsNullOrEmpty(buildInformation.BuildProperties))
                    {
                        commandParts.Add(buildInformation.BuildProperties);
                    }
                    commandParts.Add($"\"{buildInformation.RootFileEntity.Directory.FullName.Replace("\\", "/")}\"");
                    return(string.Join(" ", commandParts));

                    string GenerateStagingPrefixForTarget()
                    {
                        string basePath = buildInformation.RootFileEntity.Directory.FullName;

                        return(buildInformation.Output != null
                                   ? OutputOptionFullPath()
                                   : Path.Combine(basePath, Constants.LibraryFolderName)
                               .Replace(Path.DirectorySeparatorChar, '/'));
                    }

                    bool IsIncludePathAvailable(out string path)
                    {
                        path = null;
                        if (!buildInformation.RootFileEntity.Directory.DirectoryExists("external"))
                        {
                            return(false);
                        }

                        Dictionary <Version, VirtualDirectory> versions = new Dictionary <Version, VirtualDirectory>();
                        VirtualDirectory externalDirectory = buildInformation.RootFileEntity.Directory.Directory("external");

                        foreach (VirtualDirectory directory in externalDirectory.Directories)
                        {
                            Match patternMatch = IncludeDirectoryPattern.Match(directory.Name);
                            if (!patternMatch.Success ||
                                !Version.TryParse(patternMatch.Groups["version"].Value, out Version includeVersion) ||
                                target != patternMatch.Groups["name"].Value)
                            {
                                continue;
                            }

                            versions.Add(includeVersion, directory);
                        }

                        Version actualVersion = Version.Parse(buildInformation.Target.Version);
                        Version bestMatch     = versions.Keys.Where(v => v <= actualVersion)
                                                .OrderByDescending(v => v)
                                                .FirstOrDefault();

                        if (bestMatch != null)
                        {
                            VirtualDirectory directory = versions[bestMatch];
                            if (directory.DirectoryExists(buildInformation.BuildType))
                            {
                                path = directory.Directory(buildInformation.BuildType).FullName;
                            }
                            else if (directory.DirectoryExists(Constants.ReleaseFolderName))
                            {
                                path = directory.Directory(Constants.ReleaseFolderName).FullName;
                            }
                            else
                            {
                                path = directory.FullName;
                            }
                        }
                        else
                        {
                            path = externalDirectory.FullName;
                        }

                        return(true);
                    }
                }

                string OutputOptionFullPath()
                {
                    return(fileSystem.GetDirectory(buildInformation.Output,
                                                   buildInformation.RootFileEntity.Directory.FullName)
                           .FullName.Replace(Path.DirectorySeparatorChar, '/'));
                }

                bool OutputOptionDiffersFromStagingPrefix()
                {
                    return(buildInformation.Output != null &&
                           !buildInformation.BuildEntity.BuildSystem.InstallationPaths.Any(p => p.StartsWith(OutputOptionFullPath(), StringComparison.Ordinal)));
                }

                bool IsCorrectlyConfigured()
                {
                    try
                    {
                        return(buildInformation.BuildEntity.HasBuildSystem &&
                               buildInformation.BuildEntity.BuildSystem != null);
                    }
                    catch (Exception e)
                    {
                        if (!IsTimeout(e))
                        {
                            executionContext.WriteVerbose($"The project is not correctly configured:{Environment.NewLine}{e}");
                            return(false);
                        }
                    }

                    return(true); //this is a timeout so we dont know if it is correctly configured

                    bool IsTimeout(Exception exception)
                    {
                        return(exception is TimeoutException ||
                               exception is AggregateException aggregate &&
                               aggregate.InnerExceptions.Any(e => e is TimeoutException));
                    }
                }

                void AddTimestamp()
                {
                    if (buildInformation.RootFileEntity?.Directory?.FileExists(Constants.CMakeCommandArgsFileName) == true)
                    {
                        VirtualFile commandArgsFile = buildInformation.RootFileEntity.Directory.File(Constants.CMakeCommandArgsFileName);
                        VirtualFile timestampFile   = cmakeFolder.File(Constants.CMakeTimestampFileName);

                        JObject timestamp = new JObject
                        {
                            new JProperty("FlagsWriteTime", new JValue(commandArgsFile.LastWriteTime))
                        };

                        using (Stream fileStream = timestampFile.OpenWrite())
                            using (StreamWriter streamWriter = new StreamWriter(fileStream, Encoding.UTF8))
                                using (JsonWriter jsonWriter = new JsonTextWriter(streamWriter))
                                {
                                    fileStream.SetLength(0);
                                    jsonWriter.Formatting = Formatting.Indented;
                                    timestamp.WriteTo(jsonWriter);
                                }
                    }
                    else
                    {
                        if (cmakeFolder.FileExists(Constants.CMakeTimestampFileName))
                        {
                            cmakeFolder.File(Constants.CMakeTimestampFileName).Delete();
                        }
                    }
                }

                bool CacheHasValidTimestamp()
                {
                    if (buildInformation.RootFileEntity?.Directory?.FileExists(Constants.CMakeCommandArgsFileName) == true)
                    {
                        DateTime commandArgsLastWriteTime = buildInformation.RootFileEntity
                                                            .Directory
                                                            .File(Constants.CMakeCommandArgsFileName)
                                                            .LastWriteTime;
                        if (cmakeFolder.FileExists(Constants.CMakeTimestampFileName))
                        {
                            VirtualFile timestampFile = cmakeFolder.File(Constants.CMakeTimestampFileName);
                            try
                            {
                                using (Stream fileStream = timestampFile.OpenRead())
                                    using (StreamReader reader = new StreamReader(fileStream))
                                        using (JsonReader jsonReader = new JsonTextReader(reader))
                                        {
                                            JObject fileContent = JObject.Load(jsonReader);
                                            if (fileContent.ContainsKey("FlagsWriteTime") &&
                                                fileContent["FlagsWriteTime"].Type == JTokenType.Date)
                                            {
                                                DateTime savedTimeStamp = fileContent["FlagsWriteTime"].Value <DateTime>();
                                                if (savedTimeStamp.CompareTo(commandArgsLastWriteTime) == 0)
                                                {
                                                    return(true);
                                                }
                                            }
                                        }
                            }
                            catch (JsonReaderException)
                            {
                                return(false);
                            }
                        }
                    }
                    else
                    {
                        if (!cmakeFolder.FileExists(Constants.CMakeTimestampFileName))
                        {
                            return(true);
                        }
                    }
                    return(false);
                }
            }
        }