Select every repository under the source directory, or a --repos subset, and run fixtures in name order.
- commit
- 8a2a593b1192858eaebf68333fbbe9f7b40ba53a
- parent
- 974ca1d9aef3def7b6a0e2a82d9c05a2d486a105
- author
- Dami <dami.etoile@gmail.com>
| M | scripts/ | 3 | +-- |
| M | scripts/ | 36 | +++++++++++++++++++----------- |
@@ -248,8 +248,7 @@ async function benchmarkFixture(fixture, index) {
248248 try {249249 const fixtures = (await readdir(reposDir,{withFileTypes:true})).filter(entry=>entry.isDirectory() && (!only.length || only.includes(entry.name.replace(/\.git$/,""))))250250 .map(entry=>join(resolve(reposDir),entry.name));251- const order=["nzip","bindws","diagramzip","strudel","doorbearer","atlas"];252- fixtures.sort((a,b)=>order.indexOf(basename(a).replace(/\.git$/,""))-order.indexOf(basename(b).replace(/\.git$/,"")));251+ fixtures.sort((a,b)=>basename(a).localeCompare(basename(b)));253252 for (let i=0;i<fixtures.length;i++) await benchmarkFixture(fixtures[i],i);254253 } finally {255254 control.close(); probes.close();@@ -1,15 +1,21 @@
11 #!/usr/bin/env python322 """Prepare immutable bare Git benchmark fixtures and inventory corpus metadata.33 4-Usage: prepare-git-performance.py --source-directory ~/Developer --out /tmp/tinyrelay-corpus5-The output directory must not already exist. Each selected repository is cloned4+Usage: prepare-git-performance.py --source-directory ~/Developer --out /tmp/tinyrelay-corpus [--repos a,b]5+Every Git repository directly under the source directory is selected unless6+--repos names a subset. The output directory must not already exist. Each selected repository is cloned67 with --bare --no-local; the source working trees are never modified.78 """89 from __future__ import annotations910 import argparse, json, os, shutil, subprocess, tempfile1011 from pathlib import Path1112 12-NAMES = ("nzip", "bindws", "diagramzip", "strudel", "doorbearer", "atlas")13+def is_repository(path: Path) -> bool:14+ return (path / ".git").exists() or (path / "HEAD").exists()15+16+def select(source: Path, names: list[str] | None) -> list[str]:17+ if names: return names18+ return sorted(p.name for p in source.iterdir() if p.is_dir() and is_repository(p))1319 1420 def run(*args: str, cwd: Path | None = None, input: str | None = None) -> str:1521 p = subprocess.run(args, cwd=cwd, input=input, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)@@ -59,14 +65,16 @@ def inventory(repo: Path, name: str) -> dict:
5965 "blobs_over_10MiB": sum(size > 10 * 1024 * 1024 for size, _ in blob_sizes),6066 }6167 62-def prepare(source: Path, out: Path) -> list[dict]:68+def prepare(source: Path, out: Path, names: list[str] | None = None) -> list[dict]:6369 if out.exists(): raise FileExistsError(f"refusing existing destination: {out}")70+ selected = select(source, names)71+ if not selected: raise FileNotFoundError(f"no repositories under {source}")6472 out.mkdir(parents=True)6573 rows = []6674 try:67- for name in NAMES:75+ for name in selected:6876 src = source / name69- if not (src / ".git").exists() and not (src / "HEAD").exists(): raise FileNotFoundError(f"missing source repository: {src}")77+ if not is_repository(src): raise FileNotFoundError(f"missing source repository: {src}")7078 dest = out / (name + ".git")7179 run("git", "clone", "--bare", "--no-local", str(src), str(dest))7280 rows.append(inventory(dest, name))@@ -82,24 +90,26 @@ def self_test() -> None:
8290 src.mkdir(); run("git", "init", "-b", "trunk", str(src)); run("git", "-C", str(src), "config", "user.email", "test@example.invalid"); run("git", "-C", str(src), "config", "user.name", "test")8391 (src / "tracked").write_text("tracked\n"); run("git", "-C", str(src), "add", "tracked"); run("git", "-C", str(src), "commit", "-m", "one"); run("git", "-C", str(src), "branch", "feature"); run("git", "-C", str(src), "tag", "v1")8492 (src / "uncommitted").write_text("must not be copied\n")85- # Exercise prepare() itself without copying the real corpus: six source86- # names all point at the same tiny synthetic repository.87- for name in NAMES: os.symlink(src, root / name, target_is_directory=True)88- rows = prepare(root, out)89- assert len(rows) == len(NAMES)93+ # Exercise prepare() itself without copying a real corpus: three94+ # fixture names all point at the same tiny synthetic repository.95+ names = ("alpha", "beta", "gamma")96+ for name in names: os.symlink(src, root / name, target_is_directory=True)97+ rows = prepare(root, out, list(names))98+ assert len(rows) == len(names)9099 row = rows[0]91100 assert row["head_branch"] == "refs/heads/trunk" and row["head"] == run("git", "-C", str(src), "rev-parse", "HEAD")92101 assert row["tags"] == 1 and row["all_commits"] == 193- assert "uncommitted" not in run("git", "--git-dir", str(out / "nzip.git"), "ls-tree", "-r", "--name-only", "HEAD")102+ assert "uncommitted" not in run("git", "--git-dir", str(out / "alpha.git"), "ls-tree", "-r", "--name-only", "HEAD")94103 95104 if __name__ == "__main__":96105 parser = argparse.ArgumentParser(description=__doc__)97106 parser.add_argument("--source-directory", type=Path, default=Path.home() / "Developer")98107 parser.add_argument("--out", type=Path)108+ parser.add_argument("--repos", help="comma-separated repository directory names to select")99109 parser.add_argument("--self-test", action="store_true")100110 args = parser.parse_args()101111 if args.self_test: self_test()102112 else:103113 if args.out is None: parser.error("--out is required unless --self-test is used")104- rows = prepare(args.source_directory.expanduser(), args.out.expanduser())114+ rows = prepare(args.source_directory.expanduser(), args.out.expanduser(), args.repos.split(",") if args.repos else None)105115 print(json.dumps(rows, indent=2))