// 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();
}
}
}
}