static public WebHostTestSetup Setup( WebAppConfiguration webAppConfig, Func <IWebHostBuilder, IWebHostBuilder> webHostBuilderMap) { var testDirectory = Filesystem.CreateRandomDirectoryInTempDirectory(); var setup = new WebHostTestSetup(testDirectory, webHostBuilderMap); var webAppConfigFilePath = setup.WebAppConfigFilePath; Directory.CreateDirectory(Path.GetDirectoryName(webAppConfigFilePath)); File.WriteAllBytes(webAppConfigFilePath, ZipArchive.ZipArchiveFromEntries(webAppConfig.AsFiles())); return(setup); }
static public WebHostAdminInterfaceTestSetup Setup( Func <IWebHostBuilder, IWebHostBuilder> webHostBuilderMap, string adminRootPassword = null, Composition.Component deployAppConfigAndInitElmState = null, string adminWebHostUrlOverride = null, string publicWebHostUrlOverride = null) { var testDirectory = Filesystem.CreateRandomDirectoryInTempDirectory(); var setup = new WebHostAdminInterfaceTestSetup( testDirectory, adminRootPassword: adminRootPassword, deployAppConfigAndInitElmState: deployAppConfigAndInitElmState, webHostBuilderMap: webHostBuilderMap, adminWebHostUrlOverride: adminWebHostUrlOverride, publicWebHostUrlOverride: publicWebHostUrlOverride); return(setup); }
static public WebHostAdminInterfaceTestSetup Setup( Func <IWebHostBuilder, IWebHostBuilder>?webHostBuilderMap, string?adminPassword = null, IFileStore?fileStore = null, Composition.Component?deployAppConfigAndInitElmState = null, string?adminWebHostUrlOverride = null, string?publicWebHostUrlOverride = null, Func <DateTimeOffset>?persistentProcessHostDateTime = null) { var testDirectory = Filesystem.CreateRandomDirectoryInTempDirectory(); var setup = new WebHostAdminInterfaceTestSetup( testDirectory, adminPassword: adminPassword, fileStore: fileStore, deployAppConfigAndInitElmState: deployAppConfigAndInitElmState, webHostBuilderMap: webHostBuilderMap, adminWebHostUrlOverride: adminWebHostUrlOverride, publicWebHostUrlOverride: publicWebHostUrlOverride, persistentProcessHostDateTime: persistentProcessHostDateTime); return(setup); }
static public (ProcessOutput processOutput, IReadOnlyCollection <(IImmutableList <string> path, IReadOnlyList <byte> content)> resultingFiles) ExecuteFileWithArguments( IReadOnlyDictionary <IImmutableList <string>, IReadOnlyList <byte> > environmentFilesNotExecutable, byte[] executableFile, string arguments, IDictionary <string, string>?environmentStrings, IImmutableList <string>?workingDirectory = null, IReadOnlyDictionary <IImmutableList <string>, IReadOnlyList <byte> >?environmentFilesExecutable = null, IReadOnlyDictionary <string, IReadOnlyList <byte> >?environmentPathExecutableFiles = null) { var environmentStringsDict = environmentStrings?.ToImmutableDictionary() ?? ImmutableDictionary <string, string> .Empty; var environmentPathContainerDirectoryName = "environment-path-cont"; var containerDirectory = Filesystem.CreateRandomDirectoryInTempDirectory(); string writeEnvironmentFile(KeyValuePair <IImmutableList <string>, IReadOnlyList <byte> > environmentFile) { var environmentFilePath = Path.Combine(containerDirectory, Filesystem.MakePlatformSpecificPath(environmentFile.Key)); var environmentFileDirectory = Path.GetDirectoryName(environmentFilePath) !; Directory.CreateDirectory(environmentFileDirectory); File.WriteAllBytes(environmentFilePath, (environmentFile.Value as byte[]) ?? environmentFile.Value.ToArray()); return(environmentFilePath); } foreach (var environmentFile in environmentFilesNotExecutable) { writeEnvironmentFile(environmentFile); } var mainExecutableFileName = "name-used-to-execute-file.exe"; var mainExecutableFilePathRelative = ImmutableList.Create(mainExecutableFileName); var executableFileNameAppendix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : ""; var allExecutableFiles = (environmentFilesExecutable ?? ImmutableDictionary <IImmutableList <string>, IReadOnlyList <byte> > .Empty) .ToImmutableDictionary() .SetItems( (environmentPathExecutableFiles ?? ImmutableDictionary <string, IReadOnlyList <byte> > .Empty) .Select(execFile => new KeyValuePair <IImmutableList <string>, IReadOnlyList <byte> >( ImmutableList.Create(environmentPathContainerDirectoryName, execFile.Key + executableFileNameAppendix), execFile.Value))) .SetItem(mainExecutableFilePathRelative, executableFile); foreach (var environmentFile in allExecutableFiles) { var fileAbsolutePath = writeEnvironmentFile(environmentFile); if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { var unixFileInfo = new UnixFileInfo(fileAbsolutePath); unixFileInfo.FileAccessPermissions |= FileAccessPermissions.GroupExecute | FileAccessPermissions.UserExecute | FileAccessPermissions.OtherExecute | FileAccessPermissions.GroupRead | FileAccessPermissions.UserRead | FileAccessPermissions.OtherRead; } } var workingDirectoryAbsolute = Path.Combine( containerDirectory, Filesystem.MakePlatformSpecificPath(workingDirectory ?? ImmutableList <string> .Empty)); var mainExecutableFilePathAbsolute = Path.Combine(containerDirectory, mainExecutableFileName); var environmentPathExecutableFilesPathAbsolute = Path.Combine(containerDirectory, environmentPathContainerDirectoryName); var pathEnvironmentVarSeparator = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ";" : ":"; var environmentPathEntryBefore = environmentStringsDict.FirstOrDefault(c => c.Key.Equals("PATH", StringComparison.InvariantCultureIgnoreCase)); var environmentPath = environmentPathExecutableFilesPathAbsolute + pathEnvironmentVarSeparator + environmentPathEntryBefore.Value; var environmentStringsWithExecutableFiles = environmentStringsDict .SetItem(environmentPathEntryBefore.Key ?? "PATH", environmentPath); var process = new Process { StartInfo = new ProcessStartInfo { WorkingDirectory = workingDirectoryAbsolute, FileName = mainExecutableFilePathAbsolute, Arguments = arguments, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true, }, }; foreach (var envString in environmentStringsWithExecutableFiles.EmptyIfNull()) { process.StartInfo.Environment[envString.Key] = envString.Value; } process.Start(); var standardOutput = process.StandardOutput.ReadToEnd(); var standardError = process.StandardError.ReadToEnd(); process.WaitForExit(); var exitCode = process.ExitCode; process.Close(); var createdFiles = Filesystem.GetFilesFromDirectory( directoryPath: containerDirectory, filterByRelativeName: path => !path.SequenceEqual(mainExecutableFilePathRelative)); try { Directory.Delete(path: containerDirectory, recursive: true); } // Avoid crash in scenario like https://forum.botlab.org/t/farm-manager-tribal-wars-2-farmbot/3038/170 catch (UnauthorizedAccessException) { } return(new ProcessOutput { ExitCode = exitCode, StandardError = standardError, StandardOutput = standardOutput, }, createdFiles); }
static public Result <string, LoadFromUrlSuccess> LoadFromUrl( string sourceUrl, Func <GetRepositoryFilesPartialForCommitRequest, IImmutableDictionary <IImmutableList <string>, IReadOnlyList <byte> > > getRepositoryFilesPartialForCommit) { var parsedUrl = ParseUrl(sourceUrl); if (parsedUrl == null) { return(Result <string, LoadFromUrlSuccess> .err( "Failed to parse string '" + sourceUrl + "' as GitHub or GitLab URL.")); } string?branchName = null; bool refLooksLikeCommit = false; if (parsedUrl.inRepository != null) { refLooksLikeCommit = Regex.IsMatch(parsedUrl.inRepository.@ref, "[A-Fa-f0-9]{40}"); branchName = refLooksLikeCommit ? null : parsedUrl.inRepository.@ref; } var cloneUrl = parsedUrl.repository.TrimEnd('/') + ".git"; if (getRepositoryFilesPartialForCommit == null) { getRepositoryFilesPartialForCommit = req => GetRepositoryFilesPartialForCommitViaLibGitSharpCheckout( cloneUrl: req.cloneUrlCandidates[0], commit: req.commit); } var repositoryFilesPartial = refLooksLikeCommit ? getRepositoryFilesPartialForCommit( new GetRepositoryFilesPartialForCommitRequest( commit: parsedUrl.inRepository !.@ref, cloneUrlCandidates: ImmutableList.Create(cloneUrl))) : GetRepositoryFilesPartialForBranchViaLibGitSharpCheckout(cloneUrl, branchName); var tempWorkingDirectory = Filesystem.CreateRandomDirectoryInTempDirectory(); var gitRepositoryLocalDirectory = Path.Combine(tempWorkingDirectory, "git-repository"); try { foreach (var fileWithPath in repositoryFilesPartial) { var absoluteFilePath = Path.Combine(new[] { gitRepositoryLocalDirectory }.Concat(fileWithPath.Key).ToArray()); var absoluteDirectoryPath = Path.GetDirectoryName(absoluteFilePath) !; Directory.CreateDirectory(absoluteDirectoryPath); File.WriteAllBytes(absoluteFilePath, fileWithPath.Value.ToArray()); } (string hash, CommitContent content)? rootCommit = null; using var gitRepository = new Repository(gitRepositoryLocalDirectory); Commit?startCommit = null; if (parsedUrl.inRepository == null) { startCommit = gitRepository.Head.Commits.FirstOrDefault(); if (startCommit == null) { return(Result <string, LoadFromUrlSuccess> .err( "Failed to get the first commit from HEAD")); } } else { startCommit = gitRepository.Lookup(parsedUrl.inRepository.@ref) as Commit; if (startCommit == null) { return(Result <string, LoadFromUrlSuccess> .err( "I did not find the commit for ref '" + parsedUrl.inRepository.@ref + "'.")); } } ParsedUrlInRepository partInRepositoryWithCommit(Commit replacementCommit) => parsedUrl.inRepository == null ? new ParsedUrlInRepository(GitObjectType.tree, @ref: replacementCommit.Sha, path: "") : parsedUrl.inRepository with { @ref = replacementCommit.Sha }; var urlInCommit = BackToUrl(parsedUrl with { inRepository = partInRepositoryWithCommit(startCommit) }); rootCommit = GetCommitHashAndContent(startCommit); var parsedUrlPath = parsedUrl.inRepository == null ? "" : parsedUrl.inRepository.path; var pathNodesNames = parsedUrlPath.Split('/', StringSplitOptions.RemoveEmptyEntries); var findGitObjectResult = FindGitObjectAtPath(startCommit.Tree, pathNodesNames); var linkedObject = findGitObjectResult?.Ok; if (linkedObject == null) { return(Result <string, LoadFromUrlSuccess> .err( "I did not find an object at path '" + parsedUrlPath + "' in " + startCommit.Sha)); } IEnumerable <Commit> traceBackTreeParents() { var queue = new Queue <Commit>(); queue.Enqueue(startCommit); while (queue.TryDequeue(out var currentCommit)) { yield return(currentCommit); foreach (var parent in currentCommit.Parents) { if (FindGitObjectAtPath(parent.Tree, pathNodesNames)?.Ok?.Sha != linkedObject?.Sha) { continue; } queue.Enqueue(parent); } } } var firstParentCommitWithSameTreeRef = traceBackTreeParents().OrderBy(commit => commit.Author.When).First(); var firstParentCommitWithSameTree = GetCommitHashAndContent(firstParentCommitWithSameTreeRef); var urlInFirstParentCommitWithSameValueAtThisPath = BackToUrl(parsedUrl with { inRepository = partInRepositoryWithCommit(firstParentCommitWithSameTreeRef) });