// Copyright (C) 2025 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 using System; using System.IO; using System.Threading.Tasks; namespace QtVsTools.Core.Common { using QtVsTools.Common; public static partial class Utils { private static LazyFactory Lazy { get; } = new(); public static string PackageInstallPath => Lazy.Get(() => PackageInstallPath, () => { var uri = new Uri(System.Reflection.Assembly.GetExecutingAssembly().EscapedCodeBase); return Path.GetDirectoryName(Uri.UnescapeDataString(uri.AbsolutePath)) + @"\"; }); public static string Unquote(string path) { path = path.Trim(); if (!string.IsNullOrEmpty(path) && path.StartsWith("\"") && path.EndsWith("\"")) return path.Substring(1, path.Length - 2); return path; } public static string SafeQuote(string path) { if (string.IsNullOrEmpty(path)) return null; path = Unquote(path); if (!path.Contains(" ")) return path; if (path.EndsWith("\\")) path += Path.DirectorySeparatorChar; return $"\"{path}\""; } /// /// Recursively copies the contents of the given directory and all its children to the /// specified target path. If the target path does not exist, it will be created. /// /// The directory to copy. /// The path where the contents will be copied to. public static void CopyDirectory(string directory, string targetPath) { var sourceDir = new DirectoryInfo(directory); if (!sourceDir.Exists) return; try { if (!Directory.Exists(targetPath)) Directory.CreateDirectory(targetPath); var files = sourceDir.GetFiles(); foreach (var file in files) { try { file.CopyTo(Path.Combine(targetPath, file.Name), true); } catch (Exception exception) { exception.Log(); } } } catch (Exception exception) { exception.Log(); } var subDirs = sourceDir.GetDirectories(); foreach (var subDir in subDirs) CopyDirectory(subDir.FullName, Path.Combine(targetPath, subDir.Name)); } /// /// Asynchronously reads the contents of a text file and returns the content as a string. /// /// The path to the file to read. /// A task representing the asynchronous operation. The task result contains the /// content of the file as a string. public static async Task ReadAllTextAsync(string filePath) { using var reader = File.OpenText(filePath); return await reader.ReadToEndAsync(); } /// /// Asynchronously writes the specified string to a file, creating the file if it does /// not exist, and overwriting the content if it does. /// /// The path to the file to write. /// The string to write to the file. /// A task representing the asynchronous operation. public static async Task WriteAllTextAsync(string filePath, string text) { using var writer = File.CreateText(filePath); await writer.WriteAsync(text); } /// /// Deletes a file specified by its path. Does not throw any exceptions. /// /// The path to the file to delete. public static void DeleteFile(string file) { try { DeleteFile(new FileInfo(file)); } catch (Exception exception) { exception.Log(); } } /// /// Deletes a file if it exists. Does not throw any exceptions. /// /// The object representing the file to delete. public static void DeleteFile(FileInfo file) { if (!file?.Exists ?? true) return; try { file.Delete(); } catch (Exception exception) { exception.Log(); } } /// /// Specifies the options for directory deletion. /// public enum Option { /// /// Only the specified directory itself is deleted, without deleting its contents. /// Shallow, /// /// The specified directory and all its contents, including subdirectories, are deleted. /// Recursive } /// /// Recursively deletes the given directory and all its contents. Does not throw any /// exceptions. /// /// The path of the directory to delete. /// Specifies the options for directory deletion. public static void DeleteDirectory(string path, Option option = Option.Shallow) { try { DeleteDirectory(new DirectoryInfo(path), option); } catch (Exception exception) { exception.Log(); } } /// /// Recursively deletes the given directory and all its contents. Does not throw any /// exceptions. /// /// The directory to delete. /// Specifies the options for directory deletion. public static void DeleteDirectory(DirectoryInfo directory, Option option = Option.Shallow) { if (!directory?.Exists ?? true) return; if (option == Option.Recursive) { foreach (var file in directory.GetFiles()) DeleteFile(file); try { foreach (var subDir in directory.GetDirectories()) DeleteDirectory(subDir, option); } catch (Exception exception) { exception.Log(); } } try { directory.Delete(); } catch (Exception exception) { exception.Log(); } } } }