177 lines
6.1 KiB
C#
177 lines
6.1 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
|
|
namespace MfGames.IO.Extensions
|
|
{
|
|
/// <summary>
|
|
/// Useful extension methods for DirectoryInfo.
|
|
/// </summary>
|
|
public static class DirectoryInfoExtensions
|
|
{
|
|
/// <summary>
|
|
/// Makes sure a directory exists, creating it and any parents above it
|
|
/// as needed.
|
|
/// </summary>
|
|
/// <param name="directory"></param>
|
|
/// <returns>The directory passed in.</returns>
|
|
public static DirectoryInfo? CreateIfMissing(
|
|
this DirectoryInfo? directory)
|
|
{
|
|
// Ignore blanks.
|
|
if (directory == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// Check the parent first. We don't have to worry about null because
|
|
// we check that coming in.
|
|
directory.Parent.CreateIfMissing();
|
|
|
|
// If the directory doesn't exist, create it.
|
|
if (!Directory.Exists(directory.FullName))
|
|
{
|
|
directory.Create();
|
|
}
|
|
|
|
return directory;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Searches for the Git root starting at the given directory.
|
|
/// </summary>
|
|
/// <param name="directory">The directory to start searching.</param>
|
|
/// <returns>The directory containing `.git`, otherwise null.</returns>
|
|
public static DirectoryInfo? FindGitRoot(this DirectoryInfo? directory)
|
|
{
|
|
return directory.FindSelfOrParent(IsGitRoot);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Searches for a parent that matches the given `match` method. This
|
|
/// will not compare the given directory to see if it matches.
|
|
/// </summary>
|
|
/// <param name="directory">The directory to start searching.</param>
|
|
/// <param name="match">The function that takes a directory to determine a match.</param>
|
|
/// <returns>A parent directory that matches, otherwise null.</returns>
|
|
public static DirectoryInfo? FindParent(
|
|
this DirectoryInfo? directory,
|
|
Func<DirectoryInfo, bool> match)
|
|
{
|
|
return directory == null
|
|
? null
|
|
: FindSelfOrParent(directory.Parent, match);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Searches the given directory and parents for the first one that
|
|
/// matches (moving up the directory tree). If this does not find
|
|
/// anything, then a null will be returned.
|
|
/// </summary>
|
|
/// <param name="directory">The directory to start searching.</param>
|
|
/// <param name="match">The function that takes a directory to determine a match.</param>
|
|
/// <returns>A parent directory that matches, otherwise null.</returns>
|
|
public static DirectoryInfo? FindSelfOrParent(
|
|
this DirectoryInfo? directory,
|
|
Func<DirectoryInfo, bool> match)
|
|
{
|
|
while (true)
|
|
{
|
|
// Validate our inputs.
|
|
if (match == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(match));
|
|
}
|
|
|
|
// If the directory is null, just return null. Same with
|
|
// non-existing directories. We don't use directory.Exists here
|
|
// because it seems to be cached and we get incorrect data.
|
|
if (directory == null || !Directory.Exists(directory.FullName))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// Check this directory for a match, otherwise move up.
|
|
if (match(directory))
|
|
{
|
|
return directory;
|
|
}
|
|
|
|
directory = directory.Parent;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a DirectoryInfo by combining the path components with the
|
|
/// directory full path.
|
|
/// </summary>
|
|
/// <param name="directory">The directory to get the root path.</param>
|
|
/// <param name="paths">Additional child paths.</param>
|
|
/// <returns>A DirectoryInfo of the given path.</returns>
|
|
public static DirectoryInfo GetDirectory(
|
|
this DirectoryInfo directory,
|
|
params string[] paths)
|
|
{
|
|
if (directory == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(directory));
|
|
}
|
|
|
|
if (paths == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(paths));
|
|
}
|
|
|
|
string[] parts = new[] { directory.FullName }
|
|
.Union(paths)
|
|
.ToArray();
|
|
string path = Path.Combine(parts);
|
|
var info = new DirectoryInfo(path);
|
|
|
|
return info;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a FileInfo by combining the path components with the directory
|
|
/// full path.
|
|
/// </summary>
|
|
/// <param name="directory">The directory to get the root path.</param>
|
|
/// <param name="paths">Additional child paths.</param>
|
|
/// <returns>A FileInfo of the given path.</returns>
|
|
public static FileInfo GetFile(
|
|
this DirectoryInfo directory,
|
|
params string[] paths)
|
|
{
|
|
if (directory == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(directory));
|
|
}
|
|
|
|
if (paths == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(paths));
|
|
}
|
|
|
|
string[] parts = new[] { directory.FullName }
|
|
.Union(paths)
|
|
.ToArray();
|
|
string path = Path.Combine(parts);
|
|
var info = new FileInfo(path);
|
|
|
|
return info;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines if the given directory contains a ".git" folder. If given
|
|
/// a null, this will always return false.
|
|
/// </summary>
|
|
/// <param name="directory">The directory to inspect.</param>
|
|
/// <returns>True if the directory contains ".git", otherwise false.</returns>
|
|
public static bool IsGitRoot(this DirectoryInfo? directory)
|
|
{
|
|
return directory != null
|
|
&& directory.GetDirectories(".git").Length > 0;
|
|
}
|
|
}
|
|
}
|