diff --git a/README.md b/README.md
index b9b9954..f03a170 100644
--- a/README.md
+++ b/README.md
@@ -2,3 +2,81 @@ MfGames.IO CIL
==============
This a small collection of classes and extensions to make working with System.IO a little bit easier.
+
+## Installation
+
+At the moment, this library is not on [NuGet.org](https://nuget.org/). Instead,
+it is hosted at [MyGet](https://www.myget.org/feed/Packages/mfgames).
+
+```
+dotnet add package MfGames.IO --source https://www.myget.org/F/mfgames/api/v3/index.json
+```
+
+The repository can also be added to a project by setting the `NuGet.Config` file.
+
+```
+
+
+
+
+
+
+
+```
+
+## Extensions
+
+### DirectoryInfo Extensions
+
+#### `DirectoryInfo? CreateIfMissing(this DirectoryInfo? directory)`
+
+Creates `directory` if it doesn't exist and `directory` is not null. This will
+also create any parent directories to duplicate the `mkdir -p directory`
+functionality that inspired it.
+
+#### `DirectoryInfo? FindGitRoot(this DirectoryInfo?)`
+
+Finds the Git root from the given directory, using `FindSelfOrParent`.
+
+#### `DirectoryInfo? FindParent(this DirectoryInfo?, Func match)`
+
+Finds a parent directory that returns true from the given `match`. This does not
+check the given `directory`, but only parents. If none are found, this returns
+null.
+
+#### `DirectoryInfo? FindSelfOrParent(this DirectoryInfo?, Func match)`
+
+Finds a parent directory that returns true from the given `match`. This checks
+the given `directory` before going to parents. If none are found, this returns
+null.
+
+#### `DirectoryInfo GetDirectory(this DirectoryInfo directory, string[] paths)`
+
+The equivalent of `new DirectoryInfo(Path.Combine(directory.FullName, ...paths))`.
+
+#### `FileInfo GetFile(this DirectoryInfo directory, string[] paths)`
+
+The equivalent of `new FileInfo(Path.Combine(directory.FullName, ...paths))`.
+
+#### `bool IsGitRoot(this DirectoryInfo? directory)`
+
+Returns `true` if the given directory is non-null and contains the `.git` folder.
+Otherwise, returns false.
+
+### FileInfo Extensions
+
+#### `string ReadAllText(this FileInfo file)`
+
+The same as `File.ReadAllText(file.GetFullPath)`.
+
+#### `string ReadAllText(this FileInfo file, Encoding encoding)`
+
+The same as `File.ReadAllText(file.GetFullPath, encoding)`.
+
+#### `void WriteAllText(this FileInfo file, string text)`
+
+The same as `File.WriteAllText(file.GetFullPath, text)`.
+
+#### `void WriteAllText(this FileInfo file, string text, Encoding encoding)`
+
+The same as `File.WriteAllText(file.GetFullPath, text, encoding)`.
diff --git a/src/MfGames.IO/Extensions/DirectoryInfoExtensions.cs b/src/MfGames.IO/Extensions/DirectoryInfoExtensions.cs
index 40e0460..67e9fbb 100644
--- a/src/MfGames.IO/Extensions/DirectoryInfoExtensions.cs
+++ b/src/MfGames.IO/Extensions/DirectoryInfoExtensions.cs
@@ -1,4 +1,6 @@
+using System;
using System.IO;
+using System.Linq;
namespace MfGames.IO.Extensions
{
@@ -12,12 +14,14 @@ namespace MfGames.IO.Extensions
/// as needed.
///
///
- public static void CreateIfMissing(this DirectoryInfo? directory)
+ /// The directory passed in.
+ public static DirectoryInfo? CreateIfMissing(
+ this DirectoryInfo? directory)
{
// Ignore blanks.
if (directory == null)
{
- return;
+ return directory;
}
// Check the parent first. We don't have to worry about null because
@@ -29,6 +33,139 @@ namespace MfGames.IO.Extensions
{
directory.Create();
}
+
+ return directory;
+ }
+
+ ///
+ /// Searches for the Git root starting at the given directory.
+ ///
+ /// The directory to start searching.
+ /// The directory containing `.git`, otherwise null.
+ public static DirectoryInfo? FindGitRoot(this DirectoryInfo? directory)
+ {
+ return directory.FindSelfOrParent(IsGitRoot);
+ }
+
+ ///
+ /// Searches for a parent that matches the given `match` method. This
+ /// will not compare the given directory to see if it matches.
+ ///
+ /// The directory to start searching.
+ /// The function that takes a directory to determine a match.
+ /// A parent directory that matches, otherwise null.
+ public static DirectoryInfo? FindParent(
+ this DirectoryInfo? directory,
+ Func match)
+ {
+ return directory == null
+ ? null
+ : FindSelfOrParent(directory.Parent, match);
+ }
+
+ ///
+ /// 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.
+ ///
+ /// The directory to start searching.
+ /// The function that takes a directory to determine a match.
+ /// A parent directory that matches, otherwise null.
+ public static DirectoryInfo? FindSelfOrParent(
+ this DirectoryInfo? directory,
+ Func match)
+ {
+ while (true)
+ {
+ // Validate our inputs.
+ if (match == null)
+ {
+ throw new ArgumentNullException(nameof(match));
+ }
+
+ // If the directory is null, just return null.
+ if (directory == null)
+ {
+ return null;
+ }
+
+ // Check this directory for a match, otherwise move up.
+ if (match(directory)) return directory;
+
+ directory = directory.Parent;
+ }
+ }
+
+ ///
+ /// Gets a DirectoryInfo by combining the path components with the
+ /// directory full path.
+ ///
+ /// The directory to get the root path.
+ /// Additional child paths.
+ /// A DirectoryInfo of the given path.
+ 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;
+ }
+
+ ///
+ /// Gets a FileInfo by combining the path components with the directory
+ /// full path.
+ ///
+ /// The directory to get the root path.
+ /// Additional child paths.
+ /// A FileInfo of the given path.
+ 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;
+ }
+
+ ///
+ /// Determines if the given directory contains a ".git" folder. If given
+ /// a null, this will always return false.
+ ///
+ /// The directory to inspect.
+ /// True if the directory contains ".git", otherwise false.
+ public static bool IsGitRoot(this DirectoryInfo? directory)
+ {
+ return directory != null
+ && directory.GetDirectories(".git").Length > 0;
}
}
}