Background and motivation
ChainablePath.Temp gives you the user temporary folder, but every test and script that needs its own scratch directory still has to invent a unique name, create it, and remember to delete it in a finally block. That boilerplate is repeated in nearly every test suite that touches the file system, and when the cleanup is forgotten it leaves rubbish behind on developer machines and build agents.
API Proposal
namespace Pathy
{
public readonly struct ChainablePath
{
public static ChainablePath CreateTempDirectory(string prefix = null);
}
public sealed class TemporaryDirectory : IDisposable
{
public TemporaryDirectory(string prefix = null);
public ChainablePath Path { get; }
public static implicit operator ChainablePath(TemporaryDirectory directory);
public void Dispose();
}
}
CreateTempDirectory creates and returns a uniquely named directory. TemporaryDirectory does the same but deletes the directory recursively on disposal.
API Usage
using var temp = new TemporaryDirectory("pathy-specs");
var file = temp.Path / "input.txt";
file.WriteAllText("hello");
// everything under temp.Path is removed when the scope ends
Without the scope:
var workingDirectory = ChainablePath.CreateTempDirectory();
Alternative Designs
- Only ship
CreateTempDirectory and let callers handle cleanup. Simpler, but leaves the most error-prone part unsolved.
- Ship the disposable type in a separate testing package. Reasonable, though it needs no extra dependency and is just as useful in scripts.
Risks
Dispose performs a recursive delete, which is destructive and must be extremely careful about what it is deleting; it should refuse to act on anything it did not create. Swallowing versus rethrowing cleanup failures needs a decision, since throwing from Dispose can mask the original test failure. Adding a class to a package that is currently a single struct plus extension methods is also a notable change in shape.
Background and motivation
ChainablePath.Tempgives you the user temporary folder, but every test and script that needs its own scratch directory still has to invent a unique name, create it, and remember to delete it in afinallyblock. That boilerplate is repeated in nearly every test suite that touches the file system, and when the cleanup is forgotten it leaves rubbish behind on developer machines and build agents.API Proposal
CreateTempDirectorycreates and returns a uniquely named directory.TemporaryDirectorydoes the same but deletes the directory recursively on disposal.API Usage
Without the scope:
Alternative Designs
CreateTempDirectoryand let callers handle cleanup. Simpler, but leaves the most error-prone part unsolved.Risks
Disposeperforms a recursive delete, which is destructive and must be extremely careful about what it is deleting; it should refuse to act on anything it did not create. Swallowing versus rethrowing cleanup failures needs a decision, since throwing fromDisposecan mask the original test failure. Adding a class to a package that is currently a single struct plus extension methods is also a notable change in shape.