Skip to content
zit Artifact [6ee3665ab2]
Login

Artifact [6ee3665ab2]

Artifact 6ee3665ab26e204a9aeae5d8fa85a12784e47e41f6bffc03826e92cd65732b45:


//! A scratch directory owned by one harness run (dst, smoke). A fixed name
//! let two concurrent runs from one checkout delete or collide with each
//! other's workspace; a name carrying the pid and a random suffix, created
//! exclusively, cannot. A directory that held the old fixed name is left
//! alone: it may belong to an older run still in flight.

const std = @import("std");
const builtin = @import("builtin");

/// Room for a parent path plus `-<pid>-<16 hex>`.
pub const max_path = 4096;

/// Create `<prefix>-<pid>-<16 hex>` under `dir` and return its path in
/// `buf`. `prefix` may carry parent components; the parent must exist.
pub fn create(io: std.Io, dir: std.Io.Dir, buf: *[max_path]u8, prefix: []const u8) ![]const u8 {
    const pid = getpid();
    var attempt: u32 = 0;
    while (true) : (attempt += 1) {
        var suffix: [8]u8 = undefined;
        io.random(&suffix);
        const path = try std.fmt.bufPrint(buf, "{s}-{d}-{x}", .{ prefix, pid, suffix });
        dir.createDir(io, path, .default_dir) catch |e| switch (e) {
            // Another run won this name; draw again. Bounded so a broken
            // random source fails loudly instead of spinning.
            error.PathAlreadyExists => if (attempt < 16) continue else return e,
            else => return e,
        };
        return path;
    }
}

fn getpid() i64 {
    return if (builtin.os.tag == .linux) std.os.linux.getpid() else std.c.getpid();
}

test "create makes distinct directories under one prefix" {
    const io = std.testing.io;
    var tmp = std.testing.tmpDir(.{});
    defer tmp.cleanup();
    var buf_a: [max_path]u8 = undefined;
    var buf_b: [max_path]u8 = undefined;
    const a = try create(io, tmp.dir, &buf_a, "ws");
    const b = try create(io, tmp.dir, &buf_b, "ws");
    try std.testing.expect(!std.mem.eql(u8, a, b));
    try std.testing.expect(std.mem.startsWith(u8, a, "ws-"));
    var da = try tmp.dir.openDir(io, a, .{});
    da.close(io);
    var db = try tmp.dir.openDir(io, b, .{});
    db.close(io);
}