-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRunKey.cs
More file actions
37 lines (33 loc) · 1.57 KB
/
Copy pathRunKey.cs
File metadata and controls
37 lines (33 loc) · 1.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using System.Security.Cryptography;
using System.Text;
namespace Tman;
/// <summary>
/// Identity of a run for the purposes of dedup locking and parallel-slot admission.
/// A run belongs to the bucket "<name-or-command>@<scope dir>", so a `test` run in
/// one project neither blocks nor consumes a slot from a `test` run in another.
/// </summary>
public static class RunKey
{
/// <summary>Scope directory for a run: the .tman.kdl dir when one governs it, else the cwd.</summary>
public static string ScopeDir(TmanConfig? config, string? cwd = null) =>
config?.Dir ?? cwd ?? Directory.GetCurrentDirectory();
/// <summary>
/// Bucket key. Named runs bucket by name; unnamed runs bucket by command basename, so
/// `npm` and `/usr/bin/npm` in the same directory share a bucket.
/// </summary>
public static string For(string? name, string command, string scopeDir) =>
$"{name ?? Canon.CommandLabel(command)}@{Canon.Dir(scopeDir)}";
/// <summary>
/// Filesystem-safe lock file stem. The readable prefix keeps `ls ~/.tman/runs` diagnosable;
/// the hash suffix keeps two keys that sanitize alike from sharing a lock.
/// </summary>
public static string LockStem(string key)
{
var prefix = new string(key.TakeWhile(c => c != '@')
.Select(c => char.IsLetterOrDigit(c) || c is '-' or '_' or '.' ? c : '_')
.Take(32)
.ToArray());
var hash = Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(key))).ToLowerInvariant()[..8];
return $"{prefix}-{hash}";
}
}