private void TestGetExtension(string path, string expected) { Assert.Equal(expected, PathUtilities.GetExtension(path)); Assert.Equal(expected, Path.GetExtension(path)); }
internal static string?GetDesktopFrameworkDirectory() => GacFileResolver.IsAvailable ? PathUtilities.GetDirectoryName( typeof(object).GetTypeInfo().Assembly.ManifestModule.FullyQualifiedName ) : null;
internal void FlattenArgs( IEnumerable <string> rawArguments, IList <Diagnostic> diagnostics, List <string> processedArgs, List <string> scriptArgs, string baseDirectory, List <string> responsePaths = null) { bool parsingScriptArgs = false; Stack <string> args = new Stack <string>(rawArguments.Reverse()); while (args.Count > 0) { //EDMAURER trim off whitespace. Otherwise behavioral differences arise //when the strings which represent args are constructed by cmd or users. //cmd won't produce args with whitespace at the end. string arg = args.Pop().TrimEnd(); if (parsingScriptArgs) { scriptArgs.Add(arg); continue; } if (arg.StartsWith("@", StringComparison.Ordinal)) { // response file: string path = RemoveAllQuotes(arg.Substring(1)).TrimEnd(); string resolvedPath = FileUtilities.ResolveRelativePath(path, baseDirectory); if (resolvedPath != null) { foreach (string newArg in ParseResponseFile(resolvedPath, diagnostics).Reverse()) { // Ignores /noconfig option specified in a response file if (!string.Equals(newArg, "/noconfig", StringComparison.OrdinalIgnoreCase) && !string.Equals(newArg, "-noconfig", StringComparison.OrdinalIgnoreCase)) { args.Push(newArg); } else { diagnostics.Add(Diagnostic.Create(messageProvider, messageProvider.WRN_NoConfigNotOnCommandLine)); } } if (responsePaths != null) { responsePaths.Add(FileUtilities.NormalizeAbsolutePath(PathUtilities.GetDirectoryName(resolvedPath))); } } else { diagnostics.Add(Diagnostic.Create(messageProvider, messageProvider.FTL_InputFileNameTooLong, path)); } } else if (arg == "--" && scriptArgs != null) { parsingScriptArgs = true; } else { processedArgs.Add(arg); } } }
/// <summary>Run the install or uninstall script.</summary> /// <param name="args">The command line arguments.</param> /// <remarks> /// Initialization flow: /// 1. Collect information (mainly OS and install path) and validate it. /// 2. Ask the user whether to install or uninstall. /// /// Uninstall logic: /// 1. On Linux/Mac: if a backup of the launcher exists, delete the launcher and restore the backup. /// 2. Delete all files and folders in the game directory matching one of the values returned by <see cref="GetUninstallPaths"/>. /// /// Install flow: /// 1. Run the uninstall flow. /// 2. Copy the SMAPI files from package/Windows or package/Mono into the game directory. /// 3. On Linux/Mac: back up the game launcher and replace it with the SMAPI launcher. (This isn't possible on Windows, so the user needs to configure it manually.) /// 4. Create the 'Mods' directory. /// 5. Copy the bundled mods into the 'Mods' directory (deleting any existing versions). /// 6. Move any mods from app data into game's mods directory. /// </remarks> public void Run(string[] args) { /********* ** Step 1: initial setup *********/ /**** ** Get basic info & set window title ****/ ModToolkit toolkit = new ModToolkit(); Platform platform = EnvironmentUtility.DetectPlatform(); Console.Title = $"SMAPI {this.GetDisplayVersion(this.GetType().Assembly.GetName().Version)} installer on {platform} {EnvironmentUtility.GetFriendlyPlatformName(platform)}"; Console.WriteLine(); /**** ** Check if correct installer ****/ #if SMAPI_FOR_WINDOWS if (platform == Platform.Linux || platform == Platform.Mac) { this.PrintError($"This is the installer for Windows. Run the 'install on {platform}.{(platform == Platform.Linux ? "sh" : "command")}' file instead."); Console.ReadLine(); return; } #else if (platform == Platform.Windows) { this.PrintError($"This is the installer for Linux/Mac. Run the 'install on Windows.exe' file instead."); Console.ReadLine(); return; } #endif /**** ** Check Windows dependencies ****/ if (platform == Platform.Windows) { // .NET Framework 4.5+ if (!this.HasNetFramework45(platform)) { this.PrintError(Environment.OSVersion.Version >= this.Windows7Version ? "Please install the latest version of .NET Framework before installing SMAPI." // Windows 7+ : "Please install .NET Framework 4.5 before installing SMAPI." // Windows Vista or earlier ); this.PrintError("See the download page at https://www.microsoft.com/net/download/framework for details."); Console.ReadLine(); return; } if (!this.HasXna(platform)) { this.PrintError("You don't seem to have XNA Framework installed. Please run the game at least once before installing SMAPI, so it can perform its first-time setup."); Console.ReadLine(); return; } } /**** ** read command-line arguments ****/ // get action from CLI bool installArg = args.Contains("--install"); bool uninstallArg = args.Contains("--uninstall"); if (installArg && uninstallArg) { this.PrintError("You can't specify both --install and --uninstall command-line flags."); Console.ReadLine(); return; } // get game path from CLI string gamePathArg = null; { int pathIndex = Array.LastIndexOf(args, "--game-path") + 1; if (pathIndex >= 1 && args.Length >= pathIndex) { gamePathArg = args[pathIndex]; } } /********* ** Step 2: choose a theme (can't auto-detect on Linux/Mac) *********/ MonitorColorScheme scheme = MonitorColorScheme.AutoDetect; if (platform == Platform.Linux || platform == Platform.Mac) { /**** ** print header ****/ this.PrintPlain("Hi there! I'll help you install or remove SMAPI. Just a few questions first."); this.PrintPlain("----------------------------------------------------------------------------"); Console.WriteLine(); /**** ** show theme selector ****/ // get theme writers var lightBackgroundWriter = new ColorfulConsoleWriter(platform, ColorfulConsoleWriter.GetDefaultColorSchemeConfig(MonitorColorScheme.LightBackground)); var darkBackgroundWriter = new ColorfulConsoleWriter(platform, ColorfulConsoleWriter.GetDefaultColorSchemeConfig(MonitorColorScheme.DarkBackground)); // print question this.PrintPlain("Which text looks more readable?"); Console.WriteLine(); Console.Write(" [1] "); lightBackgroundWriter.WriteLine("Dark text on light background", ConsoleLogLevel.Info); Console.Write(" [2] "); darkBackgroundWriter.WriteLine("Light text on dark background", ConsoleLogLevel.Info); Console.WriteLine(); // handle choice string choice = this.InteractivelyChoose("Type 1 or 2, then press enter.", new[] { "1", "2" }); switch (choice) { case "1": scheme = MonitorColorScheme.LightBackground; this.ConsoleWriter = lightBackgroundWriter; break; case "2": scheme = MonitorColorScheme.DarkBackground; this.ConsoleWriter = darkBackgroundWriter; break; default: throw new InvalidOperationException($"Unexpected action key '{choice}'."); } } Console.Clear(); /********* ** Step 3: find game folder *********/ InstallerPaths paths; { /**** ** print header ****/ this.PrintInfo("Hi there! I'll help you install or remove SMAPI. Just a few questions first."); this.PrintDebug($"Color scheme: {this.GetDisplayText(scheme)}"); this.PrintDebug("----------------------------------------------------------------------------"); Console.WriteLine(); /**** ** collect details ****/ // get game path this.PrintInfo("Where is your game folder?"); DirectoryInfo installDir = this.InteractivelyGetInstallPath(platform, toolkit, gamePathArg); if (installDir == null) { this.PrintError("Failed finding your game path."); Console.ReadLine(); return; } // get folders DirectoryInfo bundleDir = new DirectoryInfo(this.BundlePath); paths = new InstallerPaths(bundleDir, installDir, EnvironmentUtility.GetExecutableName(platform)); } Console.Clear(); /********* ** Step 4: validate assumptions *********/ if (!File.Exists(paths.ExecutablePath)) { this.PrintError("The detected game install path doesn't contain a Stardew Valley executable."); Console.ReadLine(); return; } /********* ** Step 5: ask what to do *********/ ScriptAction action; { /**** ** print header ****/ this.PrintInfo("Hi there! I'll help you install or remove SMAPI. Just one question first."); this.PrintDebug($"Game path: {paths.GamePath}"); this.PrintDebug($"Color scheme: {this.GetDisplayText(scheme)}"); this.PrintDebug("----------------------------------------------------------------------------"); Console.WriteLine(); /**** ** ask what to do ****/ if (installArg) { action = ScriptAction.Install; } else if (uninstallArg) { action = ScriptAction.Uninstall; } else { this.PrintInfo("What do you want to do?"); Console.WriteLine(); this.PrintInfo("[1] Install SMAPI."); this.PrintInfo("[2] Uninstall SMAPI."); Console.WriteLine(); string choice = this.InteractivelyChoose("Type 1 or 2, then press enter.", new[] { "1", "2" }); switch (choice) { case "1": action = ScriptAction.Install; break; case "2": action = ScriptAction.Uninstall; break; default: throw new InvalidOperationException($"Unexpected action key '{choice}'."); } } } Console.Clear(); /********* ** Step 6: apply *********/ { /**** ** print header ****/ this.PrintInfo($"That's all I need! I'll {action.ToString().ToLower()} SMAPI now."); this.PrintDebug($"Game path: {paths.GamePath}"); this.PrintDebug($"Color scheme: {this.GetDisplayText(scheme)}"); this.PrintDebug("----------------------------------------------------------------------------"); Console.WriteLine(); /**** ** Back up user settings ****/ if (File.Exists(paths.ApiUserConfigPath)) { File.Copy(paths.ApiUserConfigPath, paths.BundleApiUserConfigPath); } /**** ** Always uninstall old files ****/ // restore game launcher if (platform.IsMono() && File.Exists(paths.UnixBackupLauncherPath)) { this.PrintDebug("Removing SMAPI launcher..."); this.InteractivelyDelete(paths.UnixLauncherPath); File.Move(paths.UnixBackupLauncherPath, paths.UnixLauncherPath); } // remove old files string[] removePaths = this.GetUninstallPaths(paths.GameDir, paths.ModsDir) .Where(path => Directory.Exists(path) || File.Exists(path)) .ToArray(); if (removePaths.Any()) { this.PrintDebug(action == ScriptAction.Install ? "Removing previous SMAPI files..." : "Removing SMAPI files..."); foreach (string path in removePaths) { this.InteractivelyDelete(path); } } // move global save data folder (changed in 3.2) { string dataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StardewValley"); DirectoryInfo oldDir = new DirectoryInfo(Path.Combine(dataPath, "Saves", ".smapi")); DirectoryInfo newDir = new DirectoryInfo(Path.Combine(dataPath, ".smapi")); if (oldDir.Exists) { if (newDir.Exists) { this.InteractivelyDelete(oldDir.FullName); } else { oldDir.MoveTo(newDir.FullName); } } } /**** ** Install new files ****/ if (action == ScriptAction.Install) { // copy SMAPI files to game dir this.PrintDebug("Adding SMAPI files..."); foreach (FileSystemInfo sourceEntry in paths.BundleDir.EnumerateFileSystemInfos().Where(this.ShouldCopy)) { this.InteractivelyDelete(Path.Combine(paths.GameDir.FullName, sourceEntry.Name)); this.RecursiveCopy(sourceEntry, paths.GameDir); } // replace mod launcher (if possible) if (platform.IsMono()) { this.PrintDebug("Safely replacing game launcher..."); // back up & remove current launcher if (File.Exists(paths.UnixLauncherPath)) { if (!File.Exists(paths.UnixBackupLauncherPath)) { File.Move(paths.UnixLauncherPath, paths.UnixBackupLauncherPath); } else { this.InteractivelyDelete(paths.UnixLauncherPath); } } // add new launcher File.Move(paths.UnixSmapiLauncherPath, paths.UnixLauncherPath); // mark file executable // (MSBuild doesn't keep permission flags for files zipped in a build task.) // (Note: exclude from Windows build because antivirus apps can flag the process start code as suspicious.) #if !SMAPI_FOR_WINDOWS new Process { StartInfo = new ProcessStartInfo { FileName = "chmod", Arguments = $"755 \"{paths.UnixLauncherPath}\"", CreateNoWindow = true } }.Start(); #endif } // create mods directory (if needed) if (!paths.ModsDir.Exists) { this.PrintDebug("Creating mods directory..."); paths.ModsDir.Create(); } // add or replace bundled mods DirectoryInfo bundledModsDir = new DirectoryInfo(Path.Combine(paths.BundlePath, "Mods")); if (bundledModsDir.Exists && bundledModsDir.EnumerateDirectories().Any()) { this.PrintDebug("Adding bundled mods..."); ModFolder[] targetMods = toolkit.GetModFolders(paths.ModsPath).ToArray(); foreach (ModFolder sourceMod in toolkit.GetModFolders(bundledModsDir.FullName)) { // validate source mod if (sourceMod.Manifest == null) { this.PrintWarning($" ignored invalid bundled mod {sourceMod.DisplayName}: {sourceMod.ManifestParseError}"); continue; } if (!this.BundledModIDs.Contains(sourceMod.Manifest.UniqueID)) { this.PrintWarning($" ignored unknown '{sourceMod.DisplayName}' mod in the installer folder. To add mods, put them here instead: {paths.ModsPath}"); continue; } // find target folder ModFolder targetMod = targetMods.FirstOrDefault(p => p.Manifest?.UniqueID?.Equals(sourceMod.Manifest.UniqueID, StringComparison.OrdinalIgnoreCase) == true); DirectoryInfo defaultTargetFolder = new DirectoryInfo(Path.Combine(paths.ModsPath, sourceMod.Directory.Name)); DirectoryInfo targetFolder = targetMod?.Directory ?? defaultTargetFolder; this.PrintDebug(targetFolder.FullName == defaultTargetFolder.FullName ? $" adding {sourceMod.Manifest.Name}..." : $" adding {sourceMod.Manifest.Name} to {Path.Combine(paths.ModsDir.Name, PathUtilities.GetRelativePath(paths.ModsPath, targetFolder.FullName))}..." ); // remove existing folder if (targetFolder.Exists) { this.InteractivelyDelete(targetFolder.FullName); } // copy files this.RecursiveCopy(sourceMod.Directory, paths.ModsDir, filter: this.ShouldCopy); } } // set SMAPI's color scheme if defined if (scheme != MonitorColorScheme.AutoDetect) { string text = File .ReadAllText(paths.ApiConfigPath) .Replace(@"""UseScheme"": ""AutoDetect""", $@"""UseScheme"": ""{scheme}"""); File.WriteAllText(paths.ApiConfigPath, text); } // remove obsolete appdata mods this.InteractivelyRemoveAppDataMods(paths.ModsDir, bundledModsDir); } } Console.WriteLine(); Console.WriteLine(); /********* ** Step 7: final instructions *********/ if (platform == Platform.Windows) { if (action == ScriptAction.Install) { this.PrintSuccess("SMAPI is installed! If you use Steam, set your launch options to enable achievements (see smapi.io/install):"); this.PrintSuccess($" \"{Path.Combine(paths.GamePath, "StardewModdingAPI.exe")}\" %command%"); Console.WriteLine(); this.PrintSuccess("If you don't use Steam, launch StardewModdingAPI.exe in your game folder to play with mods."); } else { this.PrintSuccess("SMAPI is removed! If you configured Steam to launch SMAPI, don't forget to clear your launch options."); } } else { this.PrintSuccess(action == ScriptAction.Install ? "SMAPI is installed! Launch the game the same way as before to play with mods." : "SMAPI is removed! Launch the game the same way as before to play without mods." ); } Console.ReadKey(); }
protected async Task <TResult> RunIsolatedAsync(string configurationFile) { var assemblyDirectory = AssemblyPaths.Any() ? Path.GetDirectoryName(Path.GetFullPath(PathUtilities.ExpandFileWildcards(AssemblyPaths).First())) : configurationFile; var bindingRedirects = GetBindingRedirects(); var assemblies = GetAssemblies(assemblyDirectory); if (UseNuGetCache) { var defaultNugetPackages = LoadDefaultNugetCache(); ReferencePaths = ReferencePaths.Concat(defaultNugetPackages).ToArray(); } using (var isolated = new AppDomainIsolation <IsolatedCommandAssemblyLoader <TResult> >(assemblyDirectory, AssemblyConfig, bindingRedirects, assemblies)) { return(await Task.Run(() => isolated.Object.Run(GetType().FullName, JsonConvert.SerializeObject(this), AssemblyPaths, ReferencePaths)).ConfigureAwait(false)); } }
public override PortableExecutableReference GetReference(string fullPath, MetadataReferenceProperties properties = default(MetadataReferenceProperties)) { Debug.Assert(PathUtilities.IsAbsolute(fullPath)); return(new CachingMetadataReference(fullPath, properties)); }
protected override bool CanImportCore(Stream stream, string filename = null) { return(PathUtilities.MatchesAnyExtension(filename, Extensions)); }
// virtual for testing protected virtual bool IsVisibleFileSystemEntry(string fullPath) { Debug.Assert(PathUtilities.IsAbsolute(fullPath)); return(IOUtilities.PerformIO(() => (File.GetAttributes(fullPath) & (FileAttributes.Hidden | FileAttributes.System)) == 0, false)); }
private CompletionItem CreateFileSystemEntryItem(string fullPath, bool isDirectory) => CommonCompletionItem.Create( PathUtilities.GetFileName(fullPath), glyph: isDirectory ? _folderGlyph : _fileGlyph, description: fullPath.ToSymbolDisplayParts(), rules: _itemRules);
// virtual for testing protected virtual bool DirectoryExists(string fullPath) { Debug.Assert(PathUtilities.IsAbsolute(fullPath)); return(Directory.Exists(fullPath)); }
// virtual for testing protected virtual IEnumerable <string> EnumerateFiles(string fullDirectoryPath) { Debug.Assert(PathUtilities.IsAbsolute(fullDirectoryPath)); return(IOUtilities.PerformIO(() => Directory.EnumerateFiles(fullDirectoryPath), Array.Empty <string>())); }
// internal for testing internal ImmutableArray <CompletionItem> GetItems(string directoryPath, CancellationToken cancellationToken) { if (!PathUtilities.IsUnixLikePlatform && directoryPath.Length == 1 && directoryPath[0] == '\\') { // The user has typed only "\". In this case, we want to add "\\" to the list. return(ImmutableArray.Create(CreateNetworkRoot())); } var result = ArrayBuilder <CompletionItem> .GetInstance(); var pathKind = PathUtilities.GetPathKind(directoryPath); switch (pathKind) { case PathKind.Empty: // base directory if (_baseDirectoryOpt != null) { result.AddRange(GetItemsInDirectory(_baseDirectoryOpt, cancellationToken)); } // roots if (PathUtilities.IsUnixLikePlatform) { result.AddRange(CreateUnixRoot()); } else { foreach (var drive in GetLogicalDrives()) { result.Add(CreateLogicalDriveItem(drive.TrimEnd(s_windowsDirectorySeparator))); } result.Add(CreateNetworkRoot()); } // entries on search paths foreach (var searchPath in _searchPaths) { result.AddRange(GetItemsInDirectory(searchPath, cancellationToken)); } break; case PathKind.Absolute: case PathKind.RelativeToCurrentDirectory: case PathKind.RelativeToCurrentParent: case PathKind.RelativeToCurrentRoot: var fullDirectoryPath = FileUtilities.ResolveRelativePath(directoryPath, basePath: null, baseDirectory: _baseDirectoryOpt); if (fullDirectoryPath != null) { result.AddRange(GetItemsInDirectory(fullDirectoryPath, cancellationToken)); } else { // invalid path result.Clear(); } break; case PathKind.Relative: // base directory: if (_baseDirectoryOpt != null) { result.AddRange(GetItemsInDirectory(PathUtilities.CombineAbsoluteAndRelativePaths(_baseDirectoryOpt, directoryPath), cancellationToken)); } // search paths: foreach (var searchPath in _searchPaths) { result.AddRange(GetItemsInDirectory(PathUtilities.CombineAbsoluteAndRelativePaths(searchPath, directoryPath), cancellationToken)); } break; case PathKind.RelativeToDriveDirectory: // Paths "C:dir" are not supported, but when the path doesn't include any directory, i.e. "C:", // we return the drive itself. if (directoryPath.Length == 2) { result.Add(CreateLogicalDriveItem(directoryPath)); } break; default: throw ExceptionUtilities.UnexpectedValue(pathKind); } return(result.ToImmutableAndFree()); }
private void TestChangeExtension(string path, string extension, string expected) { Assert.Equal(expected, PathUtilities.ChangeExtension(path, extension)); Assert.Equal(expected, Path.ChangeExtension(path, extension)); }
private void TestRemoveExtension(string path, string expected) { Assert.Equal(expected, PathUtilities.RemoveExtension(path)); Assert.Equal(expected, Path.GetFileNameWithoutExtension(path)); }
protected override async Task <CommandResult> ExecuteAsync( string path, MSBuildWorkspace workspace, IProgress <ProjectLoadProgress> progress = null, CancellationToken cancellationToken = default(CancellationToken)) { if (!string.Equals(Path.GetExtension(path), ".sln", StringComparison.OrdinalIgnoreCase)) { WriteLine($"File is not a solution file: '{path}'.", ConsoleColor.Red, Verbosity.Minimal); return(CommandResult.Fail); } workspace.LoadMetadataForReferencedProjects = true; var consoleProgress = new ConsoleProgressReporter(shouldSaveProgress: true); var loader = new MSBuildProjectLoader(workspace); WriteLine($"Load solution '{path}'", Verbosity.Minimal); SolutionInfo solutionInfo = await loader.LoadSolutionInfoAsync(path, consoleProgress, cancellationToken); string solutionDirectory = Path.GetDirectoryName(solutionInfo.FilePath); Dictionary <string, ImmutableArray <ProjectInfo> > projectInfos = solutionInfo.Projects .GroupBy(f => f.FilePath) .ToDictionary(f => f.Key, f => f.ToImmutableArray()); Dictionary <string, List <string> > projects = consoleProgress.Projects; int nameMaxLength = projects.Max(f => Path.GetFileNameWithoutExtension(f.Key).Length); int targetFrameworksMaxLength = projects.Max(f => { List <string> frameworks = f.Value; return((frameworks != null) ? $"({string.Join(", ", frameworks)})".Length : 0); }); bool anyHasTargetFrameworks = projects.Any(f => f.Value != null); WriteLine(); WriteLine($"{projects.Count} {((projects.Count == 1) ? "project" : "projects")} found in solution '{Path.GetFileNameWithoutExtension(solutionInfo.FilePath)}' [{solutionInfo.FilePath}]", ConsoleColor.Green, Verbosity.Minimal); foreach (KeyValuePair <string, List <string> > kvp in projects .OrderBy(f => Path.GetFileName(f.Key))) { string projectPath = kvp.Key; List <string> targetFrameworks = kvp.Value; ProjectInfo projectInfo = projectInfos[projectPath][0]; string projectName = Path.GetFileNameWithoutExtension(projectPath); Write($" {projectName.PadRight(nameMaxLength)} {projectInfo.Language}", Verbosity.Normal); if (anyHasTargetFrameworks) { Write(" ", Verbosity.Normal); } if (targetFrameworks != null) { string targetFrameworksText = $"({string.Join(", ", targetFrameworks.OrderBy(f => f))})"; Write(targetFrameworksText.PadRight(targetFrameworksMaxLength), Verbosity.Normal); } else { Write(new string(' ', targetFrameworksMaxLength), Verbosity.Normal); } WriteLine($" [{PathUtilities.TrimStart(projectPath, solutionDirectory)}]", Verbosity.Normal); } WriteLine(); return(CommandResult.Success); }
public static bool IsSamePath(string p1, string p2) => PathUtilities.PathsEqual(Environment.ExpandEnvironmentVariables(p1), Environment.ExpandEnvironmentVariables(p2));
protected virtual bool FileExists(string fullPath) { Debug.Assert(fullPath == null || PathUtilities.IsAbsolute(fullPath)); return(File.Exists(fullPath)); }
public override Compilation CreateCompilation(TextWriter consoleOutput, TouchedFileLogger touchedFilesLogger, ErrorLogger errorLogger) { var parseOptions = Arguments.ParseOptions; // We compute script parse options once so we don't have to do it repeatedly in // case there are many script files. var scriptParseOptions = parseOptions.WithKind(SourceCodeKind.Script); bool hadErrors = false; var sourceFiles = Arguments.SourceFiles; var trees = new SyntaxTree[sourceFiles.Length]; var normalizedFilePaths = new string[sourceFiles.Length]; var diagnosticBag = DiagnosticBag.GetInstance(); if (Arguments.CompilationOptions.ConcurrentBuild) { Parallel.For(0, sourceFiles.Length, UICultureUtilities.WithCurrentUICulture <int>(i => { //NOTE: order of trees is important!! trees[i] = ParseFile(parseOptions, scriptParseOptions, ref hadErrors, sourceFiles[i], diagnosticBag, out normalizedFilePaths[i]); })); } else { for (int i = 0; i < sourceFiles.Length; i++) { //NOTE: order of trees is important!! trees[i] = ParseFile(parseOptions, scriptParseOptions, ref hadErrors, sourceFiles[i], diagnosticBag, out normalizedFilePaths[i]); } } // If errors had been reported in ParseFile, while trying to read files, then we should simply exit. if (hadErrors) { Debug.Assert(diagnosticBag.HasAnyErrors()); ReportErrors(diagnosticBag.ToReadOnlyAndFree(), consoleOutput, errorLogger); return(null); } else { Debug.Assert(diagnosticBag.IsEmptyWithoutResolution); diagnosticBag.Free(); } var diagnostics = new List <DiagnosticInfo>(); var uniqueFilePaths = new HashSet <string>(StringComparer.OrdinalIgnoreCase); for (int i = 0; i < sourceFiles.Length; i++) { var normalizedFilePath = normalizedFilePaths[i]; Debug.Assert(normalizedFilePath != null); Debug.Assert(PathUtilities.IsAbsolute(normalizedFilePath)); if (!uniqueFilePaths.Add(normalizedFilePath)) { // warning CS2002: Source file '{0}' specified multiple times diagnostics.Add(new DiagnosticInfo(MessageProvider, (int)ErrorCode.WRN_FileAlreadyIncluded, Arguments.PrintFullPaths ? normalizedFilePath : _diagnosticFormatter.RelativizeNormalizedPath(normalizedFilePath))); trees[i] = null; } } if (Arguments.TouchedFilesPath != null) { foreach (var path in uniqueFilePaths) { touchedFilesLogger.AddRead(path); } } var assemblyIdentityComparer = DesktopAssemblyIdentityComparer.Default; var appConfigPath = this.Arguments.AppConfigPath; if (appConfigPath != null) { try { using (var appConfigStream = new FileStream(appConfigPath, FileMode.Open, FileAccess.Read)) { assemblyIdentityComparer = DesktopAssemblyIdentityComparer.LoadFromXml(appConfigStream); } if (touchedFilesLogger != null) { touchedFilesLogger.AddRead(appConfigPath); } } catch (Exception ex) { diagnostics.Add(new DiagnosticInfo(MessageProvider, (int)ErrorCode.ERR_CantReadConfigFile, appConfigPath, ex.Message)); } } var xmlFileResolver = new LoggingXmlFileResolver(Arguments.BaseDirectory, touchedFilesLogger); var sourceFileResolver = new LoggingSourceFileResolver(ImmutableArray <string> .Empty, Arguments.BaseDirectory, Arguments.PathMap, touchedFilesLogger); MetadataReferenceResolver referenceDirectiveResolver; var resolvedReferences = ResolveMetadataReferences(diagnostics, touchedFilesLogger, out referenceDirectiveResolver); if (ReportErrors(diagnostics, consoleOutput, errorLogger)) { return(null); } var strongNameProvider = new LoggingStrongNameProvider(Arguments.KeyFileSearchPaths, touchedFilesLogger, _tempDirectory); var compilation = CSharpCompilation.Create( Arguments.CompilationName, trees.WhereNotNull(), resolvedReferences, Arguments.CompilationOptions. WithMetadataReferenceResolver(referenceDirectiveResolver). WithAssemblyIdentityComparer(assemblyIdentityComparer). WithStrongNameProvider(strongNameProvider). WithXmlReferenceResolver(xmlFileResolver). WithSourceReferenceResolver(sourceFileResolver)); return(compilation); }
public void Write(ProxyFile file, CancellationToken token) { //Cancel if requested; token.ThrowIfCancellationRequested(); var header = file.Header; var proxyContentFiles = file.ContentFiles.OfType <ProxyContentFile>(); //For now replacement write is not supported... bool allContentFilesLoaded = proxyContentFiles.All(x => x.IsContentLoaded); if (allContentFilesLoaded) { using (var target = new FileStream(file.Path, FileMode.OpenOrCreate)) { uint fileTableOffset = (uint)Marshal.SizeOf(typeof(ProxyHeader)); //Póki co może być obliczona z ilości proxyContentFiles, bo to z nich zostanę utworzone wpisy fileTableEntries //Sytuacja by się zmieniła jeśli te wpisy byłby by przechowywane od momentu odczytu, anie odrzuacane i odtwarzane jak obecnie. uint fileTableLength = (uint)proxyContentFiles.Count() * ProxyFileTableEntry.EntryLength; uint contentOffset = fileTableOffset + fileTableLength; var contentWriteInfo = WriteLoadedContentFiles(target, contentOffset, proxyContentFiles, token); //We are writing fileTable entries after writing the content, because we need to write actual offsets and lengths of content files. var fileTableEntries = CreateFileTableEntries(proxyContentFiles); WriteFileTableEntries(target, (uint)fileTableOffset, fileTableEntries); uint pathTableOffset = contentOffset + contentWriteInfo.Length; uint pathTableLength = (uint)proxyContentFiles.Count() * ProxyPathTableEntry.EntryLength; var pathTableEntries = CreatePathTableEntries(proxyContentFiles); WritePathTableEntries(target, pathTableOffset, pathTableEntries); header.FileTableOffset = fileTableOffset; header.FileTableLength = fileTableLength; header.FileTableEntriesCount = (uint)fileTableEntries.Count(); header.ContentOffset = contentOffset; header.ContentLength = contentWriteInfo.Length; header.PathTableOffset = pathTableOffset; header.PathTableLength = pathTableLength; header.PathTableEntriesCount = (uint)pathTableEntries.Count(); WriteHeader(target, header); } } else { //We are checking it here, since when the content is not loaded, the file have to exist //so it could be read for content. if (!File.Exists(file.Path)) { throw new ArgumentException( String.Format("A following ProxyPCPC file: \"{0}\" doesn't exist", file.Path), "edataFile"); } String temporaryProxyPath = PathUtilities.GetTemporaryPath(file.Path); //To avoid too many nested try catches. FileStream source = null; FileStream target = null; try { source = new FileStream(file.Path, FileMode.Open); target = new FileStream(temporaryProxyPath, FileMode.Create); uint fileTableOffset = (uint)Marshal.SizeOf(typeof(ProxyHeader)); //Póki co może być obliczona z ilości proxyContentFiles, bo to z nich zostanę utworzone wpisy fileTableEntries //Sytuacja by się zmieniła jeśli te wpisy byłby by przechowywane od momentu odczytu, anie odrzuacane i odtwarzane jak obecnie. uint fileTableLength = (uint)proxyContentFiles.Count() * ProxyFileTableEntry.EntryLength; uint contentOffset = fileTableOffset + fileTableLength; var contentWriteInfo = WriteNotLoadedContentFiles(source, target, contentOffset, proxyContentFiles, token); //We are writing fileTable entries after writing the content, because we need to write actual offsets and lengths of content files. var fileTableEntries = CreateFileTableEntries(proxyContentFiles); WriteFileTableEntries(target, (uint)fileTableOffset, fileTableEntries); uint pathTableOffset = contentOffset + contentWriteInfo.Length; uint pathTableLength = (uint)proxyContentFiles.Count() * ProxyPathTableEntry.EntryLength; var pathTableEntries = CreatePathTableEntries(proxyContentFiles); WritePathTableEntries(target, pathTableOffset, pathTableEntries); header.FileTableOffset = fileTableOffset; header.FileTableLength = fileTableLength; header.FileTableEntriesCount = (uint)fileTableEntries.Count(); header.ContentOffset = contentOffset; header.ContentLength = contentWriteInfo.Length; header.PathTableOffset = pathTableOffset; header.PathTableLength = pathTableLength; header.PathTableEntriesCount = (uint)pathTableEntries.Count(); WriteHeader(target, header); //Free file handles before the file move and delete CloseStreams(source, target); //Replace temporary file File.Delete(file.Path); File.Move(temporaryProxyPath, file.Path); } finally { //Spr czy zostały już zwolnione...? CloseStreams(source, target); if (File.Exists(temporaryProxyPath)) { File.Delete(temporaryProxyPath); } } } }
public static List <string> GetAdditionalLibraryDirectories(this VCLinkerTool tool) => PathUtilities.SplitPaths(tool.AdditionalLibraryDirectories, ';', ',');
private void _openPDF_Click(object sender, EventArgs e) { PathUtilities.OpenFileInApplication(_model.PdfFilePath); }
public static List <string> GetAdditionalDependencies(this VCLinkerTool tool) => PathUtilities.SplitPathsByWhitespace(tool.AdditionalDependencies);
/// <summary> /// Generates the LSIF content for a single document. /// </summary> /// <returns>The ID of the outputted Document vertex.</returns> /// <remarks> /// The high level algorithm here is we are going to walk across each token, produce a <see cref="Graph.Range"/> for that token's span, /// bind that token, and then link up the various features. So we'll link that range to the symbols it defines or references, /// will link it to results like Quick Info, and more. This method has a <paramref name="topLevelSymbolsResultSetTracker"/> that /// lets us link symbols across files, and will only talk about "top level" symbols that aren't things like locals that can't /// leak outside a file. /// </remarks> private static Id <Graph.LsifDocument> GenerateForDocument( SemanticModel semanticModel, HostLanguageServices languageServices, OptionSet options, IResultSetTracker topLevelSymbolsResultSetTracker, ILsifJsonWriter lsifJsonWriter, IdFactory idFactory) { var syntaxTree = semanticModel.SyntaxTree; var sourceText = semanticModel.SyntaxTree.GetText(); var syntaxFactsService = languageServices.GetRequiredService <ISyntaxFactsService>(); var semanticFactsService = languageServices.GetRequiredService <ISemanticFactsService>(); string?contentBase64Encoded = null; // TODO: move to checking the enum member mentioned in https://github.com/dotnet/roslyn/issues/49326 when that // is implemented. In the mean time, we'll use a heuristic of the path being a relative path as a way to indicate // this is a source generated file. if (!PathUtilities.IsAbsolute(syntaxTree.FilePath)) { var text = semanticModel.SyntaxTree.GetText(); // We always use UTF-8 encoding when writing out file contents, as that's expected by LSIF implementations. // TODO: when we move to .NET Core, is there a way to reduce allocatios here? contentBase64Encoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(text.ToString())); } var documentVertex = new Graph.LsifDocument(new Uri(syntaxTree.FilePath, UriKind.RelativeOrAbsolute), GetLanguageKind(semanticModel.Language), contentBase64Encoded, idFactory); lsifJsonWriter.Write(documentVertex); lsifJsonWriter.Write(new Event(Event.EventKind.Begin, documentVertex.GetId(), idFactory)); // As we are processing this file, we are going to encounter symbols that have a shared resultSet with other documents like types // or methods. We're also going to encounter locals that never leave this document. We don't want those locals being held by // the topLevelSymbolsResultSetTracker, so we'll make another tracker for document local symbols, and then have a delegating // one that picks the correct one of the two. var documentLocalSymbolsResultSetTracker = new SymbolHoldingResultSetTracker(lsifJsonWriter, semanticModel.Compilation, idFactory); var symbolResultsTracker = new DelegatingResultSetTracker(symbol => { if (symbol.Kind == SymbolKind.Local || symbol.Kind == SymbolKind.RangeVariable || symbol.Kind == SymbolKind.Label) { // These symbols can go in the document local one because they can't escape methods return(documentLocalSymbolsResultSetTracker); } else if (symbol.ContainingType != null && symbol.DeclaredAccessibility == Accessibility.Private && symbol.ContainingType.Locations.Length == 1) { // This is a private member in a class that isn't partial, so it can't escape the file return(documentLocalSymbolsResultSetTracker); } else { return(topLevelSymbolsResultSetTracker); } }); // We will walk the file token-by-token, making a range for each one and then attaching information for it var rangeVertices = new List <Id <Graph.Range> >(); foreach (var syntaxToken in syntaxTree.GetRoot().DescendantTokens(descendIntoTrivia: true)) { // We'll only create the Range vertex once it's needed, but any number of bits of code might create it first, // so we'll just make it Lazy. var lazyRangeVertex = new Lazy <Graph.Range>(() => { var rangeVertex = Graph.Range.FromTextSpan(syntaxToken.Span, sourceText, idFactory); lsifJsonWriter.Write(rangeVertex); rangeVertices.Add(rangeVertex.GetId()); return(rangeVertex); }, LazyThreadSafetyMode.None); var declaredSymbol = semanticFactsService.GetDeclaredSymbol(semanticModel, syntaxToken, CancellationToken.None); ISymbol?referencedSymbol = null; if (syntaxFactsService.IsBindableToken(syntaxToken)) { var bindableParent = syntaxFactsService.TryGetBindableParent(syntaxToken); if (bindableParent != null) { var symbolInfo = semanticModel.GetSymbolInfo(bindableParent); if (symbolInfo.Symbol != null && IncludeSymbolInReferences(symbolInfo.Symbol)) { referencedSymbol = symbolInfo.Symbol; } } } if (declaredSymbol != null || referencedSymbol != null) { // For now, we will link the range to the original definition, preferring the definition, as this is the symbol // that would be used if we invoke a feature on this range. This is analogous to the logic in // SymbolFinder.FindSymbolAtPositionAsync where if a token is both a reference and definition we'll prefer the // definition. Once we start supporting hover we'll have to remove the "original definition" part of this, since // since we show different contents for different constructed types there. var symbolForLinkedResultSet = (declaredSymbol ?? referencedSymbol) !.OriginalDefinition; var symbolForLinkedResultSetId = symbolResultsTracker.GetResultSetIdForSymbol(symbolForLinkedResultSet); lsifJsonWriter.Write(Edge.Create("next", lazyRangeVertex.Value.GetId(), symbolForLinkedResultSetId, idFactory)); if (declaredSymbol != null) { var definitionResultsId = symbolResultsTracker.GetResultIdForSymbol(declaredSymbol, Methods.TextDocumentDefinitionName, () => new DefinitionResult(idFactory)); lsifJsonWriter.Write(new Item(definitionResultsId.As <DefinitionResult, Vertex>(), lazyRangeVertex.Value.GetId(), documentVertex.GetId(), idFactory)); } if (referencedSymbol != null) { // Create the link from the references back to this range. Note: this range can be reference to a // symbol but the range can point a different symbol's resultSet. This can happen if the token is // both a definition of a symbol (where we will point to the definition) but also a reference to some // other symbol. var referenceResultsId = symbolResultsTracker.GetResultIdForSymbol(referencedSymbol.OriginalDefinition, Methods.TextDocumentReferencesName, () => new ReferenceResult(idFactory)); lsifJsonWriter.Write(new Item(referenceResultsId.As <ReferenceResult, Vertex>(), lazyRangeVertex.Value.GetId(), documentVertex.GetId(), idFactory, property: "references")); } // Write hover information for the symbol, if edge has not already been added. // 'textDocument/hover' edge goes from the symbol ResultSet vertex to the hover result // See https://github.com/Microsoft/language-server-protocol/blob/main/indexFormat/specification.md#resultset for an example. if (symbolResultsTracker.ResultSetNeedsInformationalEdgeAdded(symbolForLinkedResultSet, Methods.TextDocumentHoverName)) { // TODO: Can we avoid the WaitAndGetResult_CanCallOnBackground call by adding a sync method to compute hover? var hover = HoverHandler.GetHoverAsync(semanticModel, syntaxToken.SpanStart, languageServices, CancellationToken.None).WaitAndGetResult_CanCallOnBackground(CancellationToken.None); if (hover != null) { var hoverResult = new HoverResult(hover, idFactory); lsifJsonWriter.Write(hoverResult); lsifJsonWriter.Write(Edge.Create(Methods.TextDocumentHoverName, symbolForLinkedResultSetId, hoverResult.GetId(), idFactory)); } } } } lsifJsonWriter.Write(Edge.Create("contains", documentVertex.GetId(), rangeVertices, idFactory)); // Write the folding ranges for the document. var foldingRanges = FoldingRangesHandler.GetFoldingRanges(syntaxTree, languageServices, options, isMetadataAsSource: false, CancellationToken.None); var foldingRangeResult = new FoldingRangeResult(foldingRanges, idFactory); lsifJsonWriter.Write(foldingRangeResult); lsifJsonWriter.Write(Edge.Create(Methods.TextDocumentFoldingRangeName, documentVertex.GetId(), foldingRangeResult.GetId(), idFactory)); lsifJsonWriter.Write(new Event(Event.EventKind.End, documentVertex.GetId(), idFactory)); return(documentVertex.GetId()); }
public static void AddFile(this IArchive archive, string filePath) { archive.AddFile(filePath, PathUtilities.GetFilename(filePath)); }
/// <summary> /// Loads references, set options and execute files specified in the initialization file. /// Also prints logo unless <paramref name="isRestarting"/> is true. /// </summary> private async Task <EvaluationState> InitializeContextAsync( Task <EvaluationState> lastTask, RemoteAsyncOperation <RemoteExecutionResult> operation, string initializationFileOpt, bool isRestarting) { Debug.Assert(initializationFileOpt == null || PathUtilities.IsAbsolute(initializationFileOpt)); var state = await ReportUnhandledExceptionIfAny(lastTask).ConfigureAwait(false); try { // TODO (tomat): this is also done in CommonInteractiveEngine, perhaps we can pass the parsed command lines to here? if (!isRestarting) { Console.Out.WriteLine(_replServiceProvider.Logo); } if (File.Exists(initializationFileOpt)) { Console.Out.WriteLine(string.Format(FeaturesResources.LoadingContextFrom, Path.GetFileName(initializationFileOpt))); var parser = _replServiceProvider.CommandLineParser; // The base directory for relative paths is the directory that contains the .rsp file. // Note that .rsp files included by this .rsp file will share the base directory (Dev10 behavior of csc/vbc). var rspDirectory = Path.GetDirectoryName(initializationFileOpt); var args = parser.Parse(new[] { "@" + initializationFileOpt }, rspDirectory, RuntimeEnvironment.GetRuntimeDirectory(), null /* TODO: pass a valid value*/); foreach (var error in args.Errors) { var writer = (error.Severity == DiagnosticSeverity.Error) ? Console.Error : Console.Out; writer.WriteLine(error.GetMessage(CultureInfo.CurrentCulture)); } if (args.Errors.Length == 0) { // TODO (tomat): other arguments // TODO (tomat): parse options var metadataResolver = CreateMetadataReferenceResolver(args.ReferencePaths, rspDirectory); _hostObject.ReferencePaths.Clear(); _hostObject.ReferencePaths.AddRange(args.ReferencePaths); _hostObject.SourcePaths.Clear(); var metadataReferences = new List <PortableExecutableReference>(); foreach (CommandLineReference cmdLineReference in args.MetadataReferences) { // interactive command line parser doesn't accept modules or linked assemblies Debug.Assert(cmdLineReference.Properties.Kind == MetadataImageKind.Assembly && !cmdLineReference.Properties.EmbedInteropTypes); var resolvedReferences = metadataResolver.ResolveReference(cmdLineReference.Reference, baseFilePath: null, properties: MetadataReferenceProperties.Assembly); if (!resolvedReferences.IsDefaultOrEmpty) { metadataReferences.AddRange(resolvedReferences); } } // only search for scripts next to the .rsp file: var sourceSearchPaths = ImmutableArray <string> .Empty; var rspState = new EvaluationState( state.ScriptStateOpt, state.ScriptOptions.AddReferences(metadataReferences), sourceSearchPaths, args.ReferencePaths, rspDirectory); foreach (CommandLineSourceFile file in args.SourceFiles) { // execute all files as scripts (matches csi/vbi semantics) string fullPath = ResolveRelativePath(file.Path, rspDirectory, sourceSearchPaths, displayPath: true); if (fullPath != null) { var newScriptState = await ExecuteFileAsync(rspState, fullPath).ConfigureAwait(false); if (newScriptState != null) { rspState = rspState.WithScriptState(newScriptState); } } } state = new EvaluationState( rspState.ScriptStateOpt, rspState.ScriptOptions, ImmutableArray <string> .Empty, args.ReferencePaths, state.WorkingDirectory); } } if (!isRestarting) { Console.Out.WriteLine(FeaturesResources.TypeHelpForMoreInformation); } } catch (Exception e) { ReportUnhandledException(e); } finally { state = CompleteExecution(state, operation, success: true); } return(state); }
/// <summary> /// We ignore references that are in a directory that contains the names "Packages". /// These directories are most likely the ones produced by NuGet, and we don't want /// to offer to add .dll reference manually for dlls that are part of NuGet packages. /// /// Note that this is only a heuristic (though a good one), and we should remove this /// when we can get an API from NuGet that tells us if a reference is actually provided /// by a nuget packages. /// /// This heuristic will do the right thing in practically all cases for all. It /// prevents the very unpleasant experience of us offering to add a direct metadata /// reference to something that should only be referenced as a nuget package. /// /// It does mean that if the following is true: /// You have a project that has a non-nuget metadata reference to something in a "packages" /// directory, and you are in another project that uses a type name that would have matched /// an accessible type from that dll. then we will not offer to add that .dll reference to /// that other project. /// /// However, that would be an exceedingly uncommon case that is degraded. Whereas we're /// vastly improved in the common case. This is a totally acceptable and desirable outcome /// for such a heuristic. /// </summary> private bool IsInPackagesDirectory(PortableExecutableReference reference) { return(PathUtilities.ContainsPathComponent(reference.FilePath, "packages", ignoreCase: true)); }
private string Normalize(string original) { return(PathUtilities.NormalizePath(original).ToLower()); }
public string GetPatchPoint() { string newWeatherPath = null; string dest = PathUtilities.GetAbsolutePath(entryFilePath.Text, this.explorerPresenter.ApsimXFile.FileName); DateTime startDate = calendarStart.Date; if (startDate.Year < 1889) { ShowMessage(MessageType.Warning, "SILO data is not available before 1889", "Invalid start date"); return(null); } DateTime endDate = calendarEnd.Date; if (endDate.CompareTo(DateTime.Today) >= 0) { ShowMessage(MessageType.Warning, "SILO data end date can be no later than yesterday", "Invalid end date"); return(null); } if (endDate.CompareTo(startDate) < 0) { ShowMessage(MessageType.Warning, "The end date must be after the start date!", "Invalid dates"); return(null); } if (String.IsNullOrWhiteSpace(entryEmail.Text)) { ShowMessage(MessageType.Warning, "The SILO data API requires you to provide your e-mail address", "E-mail address required"); return(null); } // Patch point get a bit complicated. We need a BOM station number, but can't really expect the user // to know that in advance. So what we can attempt to do is use the provided lat and long in the geocoding service // to get us a placename, then use the SILO name search API to find a list of stations for us. // If we get multiple stations, we let the user choose the one they wish to use. string url = googleGeocodingApi + "latlng=" + entryLatitude.Text + ',' + entryLongitude.Text; try { MemoryStream stream = WebUtilities.ExtractDataFromURL(url); stream.Position = 0; JsonTextReader reader = new JsonTextReader(new StreamReader(stream)); // Parsing the JSON gets a little tricky with a forward-reading parser. We're trying to track // down a "short_name" address component of "locality" type (I guess). string locName = ""; while (reader.Read()) { if (reader.TokenType == JsonToken.PropertyName && reader.Value.Equals("address_components")) { reader.Read(); if (reader.TokenType == JsonToken.StartArray) { JArray arr = JArray.Load(reader); foreach (JToken token in arr) { JToken typesToken = token.Last; JArray typesArray = typesToken.First as JArray; for (int i = 0; i < typesArray.Count; i++) { if (typesArray[i].ToString() == "locality") { locName = token["short_name"].ToString(); break; } } if (!string.IsNullOrEmpty(locName)) { break; } } } } if (!string.IsNullOrEmpty(locName)) { break; } } if (string.IsNullOrEmpty(locName)) { ShowMessage(MessageType.Error, "Unable to find a name key for the specified location", "Error determining location"); return(null); } int stationNumber = -1; if (locName.Contains(" ")) // the SILO API doesn't handle spaces well { Regex regex = new Regex(" ."); locName = regex.Replace(locName, "_"); } string stationUrl = String.Format("https://www.longpaddock.qld.gov.au/cgi-bin/silo/PatchedPointDataset.php?format=name&nameFrag={0}", locName); MemoryStream stationStream = WebUtilities.ExtractDataFromURL(stationUrl); stationStream.Position = 0; StreamReader streamReader = new StreamReader(stationStream); string stationInfo = streamReader.ReadToEnd(); string[] stationLines = stationInfo.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); if (stationLines.Length == 0) { ShowMessage(MessageType.Error, "Unable to find a BOM station for this location", "Cannot find station"); return(null); } if (stationLines.Length == 1) { string[] lineInfo = stationLines[0].Split('|'); stationNumber = Int32.Parse(lineInfo[0]); } else { MessageDialog md = new MessageDialog(owningView.MainWidget.Toplevel as Window, DialogFlags.Modal, MessageType.Question, ButtonsType.OkCancel, "Which station do you wish to use?"); md.Title = "Select BOM Station"; Gtk.TreeView tree = new Gtk.TreeView(); ListStore list = new ListStore(typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string)); tree.AppendColumn("Number", new CellRendererText(), "text", 0); tree.AppendColumn("Name", new CellRendererText(), "text", 1); tree.AppendColumn("Latitude", new CellRendererText(), "text", 2); tree.AppendColumn("Longitude", new CellRendererText(), "text", 3); tree.AppendColumn("State", new CellRendererText(), "text", 4); tree.AppendColumn("Elevation", new CellRendererText(), "text", 5); tree.AppendColumn("Notes", new CellRendererText(), "text", 6); foreach (string stationLine in stationLines) { string[] lineInfo = stationLine.Split('|'); list.AppendValues(lineInfo); } tree.Model = list; md.VBox.PackStart(tree, true, true, 5); md.VBox.ShowAll(); ResponseType result = (ResponseType)md.Run(); if (result == ResponseType.Ok) { TreeIter iter; tree.Selection.GetSelected(out iter); string stationString = (string)list.GetValue(iter, 0); stationNumber = Int32.Parse(stationString); } md.Destroy(); } if (stationNumber >= 0) // Phew! We finally have a station number. Now fetch the data. { string pointUrl = String.Format("https://www.longpaddock.qld.gov.au/cgi-bin/silo/PatchedPointDataset.php?start={0:yyyyMMdd}&finish={1:yyyyMMdd}&station={2}&format=apsim&username={3}", startDate, endDate, stationNumber, System.Net.WebUtility.UrlEncode(entryEmail.Text)); MemoryStream pointStream = WebUtilities.ExtractDataFromURL(pointUrl); pointStream.Seek(0, SeekOrigin.Begin); string headerLine = new StreamReader(pointStream).ReadLine(); pointStream.Seek(0, SeekOrigin.Begin); if (headerLine.StartsWith("[weather.met.weather]")) { using (FileStream fs = new FileStream(dest, FileMode.Create)) { pointStream.CopyTo(fs); fs.Flush(); } if (File.Exists(dest)) { newWeatherPath = dest; } } else { ShowMessage(MessageType.Error, new StreamReader(pointStream).ReadToEnd(), "Not valid APSIM weather data"); } } } catch (Exception err) { ShowMessage(MessageType.Error, err.Message, "Error"); } return(newWeatherPath); }
internal static void ParseResourceDescription( string resourceDescriptor, string baseDirectory, bool skipLeadingSeparators, //VB does this out string filePath, out string fullPath, out string fileName, out string resourceName, out string accessibility) { filePath = null; fullPath = null; fileName = null; resourceName = null; accessibility = null; // resource descriptor is: "<filePath>[,<string name>[,public|private]]" string[] parts = ParseSeparatedStrings(resourceDescriptor, resourceSeparators).ToArray(); int offset = 0; int length = parts.Length; if (skipLeadingSeparators) { for (; offset < length && string.IsNullOrEmpty(parts[offset]); offset++) { } length -= offset; } if (length >= 1) { filePath = RemoveAllQuotes(parts[offset + 0]); } if (length >= 2) { resourceName = RemoveAllQuotes(parts[offset + 1]); } if (length >= 3) { accessibility = RemoveAllQuotes(parts[offset + 2]); } if (String.IsNullOrWhiteSpace(filePath)) { return; } fileName = PathUtilities.GetFileName(filePath); fullPath = FileUtilities.ResolveRelativePath(filePath, baseDirectory); // The default resource name is the file name. // Also use the file name for the name when user specifies string like "filePath,,private" if (string.IsNullOrWhiteSpace(resourceName)) { resourceName = fileName; } }
public void ResolveRelativePath() { string baseDir = @"X:\rootdir\dir"; string[] noSearchPaths = new string[0]; // absolute path: TestPath(@"C:\abc\def.dll", @"Q:\baz\x.csx", baseDir, noSearchPaths, @"C:\abc\def.dll"); TestPath(@"C:\abc\\\\\def.dll", @"Q:\baz\x.csx", baseDir, noSearchPaths, @"C:\abc\\\\\def.dll"); // root-relative path: TestPath(@"\abc\def.dll", @"Q:\baz\x.csx", baseDir, noSearchPaths, @"Q:\abc\def.dll"); TestPath(@"\abc\def.dll", null, baseDir, noSearchPaths, @"X:\abc\def.dll"); TestPath(@"\abc\def.dll", "goo.csx", null, noSearchPaths, null); // TestPath(@"\abc\def.dll", @"C:goo.csx", null, noSearchPaths, null); // TestPath(@"/abc\def.dll", @"\goo.csx", null, noSearchPaths, null); TestPath(@"/abc\def.dll", null, @"\\x\y\z", noSearchPaths, @"\\x\y\abc\def.dll"); TestPath(@"/abc\def.dll", null, null, noSearchPaths, null); TestPath(@"/**/", null, baseDir, noSearchPaths, @"X:\**/"); TestPath(@"/a/z.txt", null, @"?:\*\<>", noSearchPaths, @"?:\a/z.txt"); // UNC path: TestPath(@"\abc\def.dll", @"\\mymachine\root\x.csx", baseDir, noSearchPaths, @"\\mymachine\root\abc\def.dll"); TestPath(@"\abc\def.dll", null, @"\\mymachine\root\x.csx", noSearchPaths, @"\\mymachine\root\abc\def.dll"); TestPath(@"\\abc\def\baz.dll", null, @"\\mymachine\root\x.csx", noSearchPaths, @"\\abc\def\baz.dll"); // incomplete UNC paths (considered absolute and returned as they are): TestPath(@"\\", null, @"\\mymachine\root\x.csx", noSearchPaths, @"\\"); TestPath(@"\\goo", null, @"\\mymachine\root\x.csx", noSearchPaths, @"\\goo"); // long UNC path: // TODO (tomat): // Doesn't work since "?" in paths is not handled by BCL // TestPath(resolver, @"\abc\def.dll", @"\\?\C:\zzz\x.csx", @"\\?\C:\abc\def.dll"); TestPath(@"./def.dll", @"Q:\abc\x.csx", baseDir, noSearchPaths, @"Q:\abc\./def.dll"); TestPath(@"./def.dll", @"Q:\abc\x.csx", baseDir, noSearchPaths, @"Q:\abc\./def.dll"); TestPath(@".", @"Q:\goo\x.csx", baseDir, noSearchPaths, @"Q:\goo"); TestPath(@"..", @"Q:\goo\x.csx", baseDir, noSearchPaths, @"Q:\goo\.."); // doesn't normalize TestPath(@".\", @"Q:\goo\x.csx", baseDir, noSearchPaths, @"Q:\goo\.\"); TestPath(@"..\", @"Q:\goo\x.csx", baseDir, noSearchPaths, @"Q:\goo\..\"); // doesn't normalize // relative base paths: TestPath(@".\y.dll", @"x.csx", baseDir, noSearchPaths, @"X:\rootdir\dir\.\y.dll"); TestPath(@".\y.dll", @"goo\x.csx", baseDir, noSearchPaths, @"X:\rootdir\dir\goo\.\y.dll"); TestPath(@".\y.dll", @".\goo\x.csx", baseDir, noSearchPaths, @"X:\rootdir\dir\.\goo\.\y.dll"); TestPath(@".\y.dll", @"..\x.csx", baseDir, noSearchPaths, @"X:\rootdir\dir\..\.\y.dll"); // doesn't normalize TestPath(@".\\y.dll", @"..\x.csx", baseDir, noSearchPaths, @"X:\rootdir\dir\..\.\\y.dll"); // doesn't normalize TestPath(@".\/y.dll", @"..\x.csx", baseDir, noSearchPaths, @"X:\rootdir\dir\..\.\/y.dll"); // doesn't normalize TestPath(@"..\y.dll", @"..\x.csx", baseDir, noSearchPaths, @"X:\rootdir\dir\..\..\y.dll"); // doesn't normalize // unqualified relative path, look in base directory: TestPath(@"y.dll", @"x.csx", baseDir, noSearchPaths, @"X:\rootdir\dir\y.dll"); TestPath(@"y.dll", @"x.csx", baseDir, new[] { @"Z:\" }, @"X:\rootdir\dir\y.dll"); // drive-relative path (not supported -> null) TestPath(@"C:y.dll", @"x.csx", baseDir, noSearchPaths, null); TestPath("C:\tools\\", null, @"d:\z", noSearchPaths, null); // invalid paths Assert.Equal(PathKind.RelativeToCurrentRoot, PathUtilities.GetPathKind(@"/c:x.dll")); TestPath(@"/c:x.dll", null, @"d:\", noSearchPaths, @"d:\c:x.dll"); Assert.Equal(PathKind.RelativeToCurrentRoot, PathUtilities.GetPathKind(@"/:x.dll")); TestPath(@"/:x.dll", null, @"d:\", noSearchPaths, @"d:\:x.dll"); Assert.Equal(PathKind.Absolute, PathUtilities.GetPathKind(@"//:x.dll")); TestPath(@"//:x.dll", null, @"d:\", noSearchPaths, @"//:x.dll"); Assert.Equal(PathKind.RelativeToDriveDirectory, PathUtilities.GetPathKind(@"c::x.dll")); TestPath(@"c::x.dll", null, @"d:\", noSearchPaths, null); Assert.Equal(PathKind.RelativeToCurrentDirectory, PathUtilities.GetPathKind(@".\:x.dll")); TestPath(@".\:x.dll", null, @"d:\z", noSearchPaths, @"d:\z\.\:x.dll"); Assert.Equal(PathKind.RelativeToCurrentParent, PathUtilities.GetPathKind(@"..\:x.dll")); TestPath(@"..\:x.dll", null, @"d:\z", noSearchPaths, @"d:\z\..\:x.dll"); // empty paths Assert.Equal(PathKind.Empty, PathUtilities.GetPathKind(@"")); TestPath(@"", @"c:\temp", @"d:\z", noSearchPaths, null); Assert.Equal(PathKind.Empty, PathUtilities.GetPathKind(" \t\r\n ")); TestPath(" \t\r\n ", @"c:\temp", @"d:\z", noSearchPaths, null); }