Skip to content

[API Proposal]: CreateTempDirectory and a self-cleaning temporary directory scope #140

Description

@dennisdoomen

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions