79 lines
3.2 KiB
Go
79 lines
3.2 KiB
Go
// Package standdata resolves the paths of the measurement data the corpus-gated tests read.
|
|
//
|
|
// Two kinds of input, and the difference is the whole reason this package exists:
|
|
//
|
|
// - IN-REPO paths that git does not carry. The jieba contrast artifact sits at eval/exp16/data but
|
|
// falls under the polygon's blanket raw-data rule (eval/.gitignore), so no clone ever receives it;
|
|
// it is regenerated from jieba 0.42.1 (SHA in docs/experiments/16-bank-mining.md).
|
|
// - The STAND CORPUS — book derivatives that are versioned by their own git repository under
|
|
// <repo>/books (D39.157 п.2, moved there on 24.08; the previous address $HOME/books is dead).
|
|
//
|
|
// Both are derived from the repository root found by MARKER, never counted in ".." and never taken from
|
|
// $HOME: a default that reads a home directory is wrong for every machine but the one it was written on,
|
|
// and counting parents breaks under -trimpath. Every caller keeps its env override (TM_*), which stays
|
|
// senior to these defaults — the defaults are what a bare clone gets, not a policy.
|
|
package standdata
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
)
|
|
|
|
// standRoot is the corpus directory inside the repository. Its own git repository, its own origin, and
|
|
// the outer repo holds it in .gitignore — so a path under it is present on a stand and absent in CI.
|
|
const standRoot = "books"
|
|
|
|
// EnvOr returns the environment override for key, or def when it is unset/empty.
|
|
func EnvOr(key, def string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return def
|
|
}
|
|
|
|
// Root finds the repository root by MARKER (backend/go.mod) rather than by counting "..", so the
|
|
// derivation cannot quietly go wrong. It starts from this file's own directory, and falls back to the
|
|
// working directory when that path is not absolute — which is what -trimpath does: it rewrites
|
|
// runtime.Caller to a module-relative path, and a naive "../../.." then yields a RELATIVE root that can
|
|
// only ever miss, turning a corpus test into a permanent silent skip on every machine including the
|
|
// stand. `go test` always runs in the package directory, so the fallback is sound.
|
|
func Root() string {
|
|
start := ""
|
|
if _, self, _, ok := runtime.Caller(0); ok && filepath.IsAbs(self) {
|
|
start = filepath.Dir(self)
|
|
}
|
|
if start == "" {
|
|
wd, err := os.Getwd()
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
start = wd
|
|
}
|
|
for dir := start; ; {
|
|
if _, err := os.Stat(filepath.Join(dir, "backend", "go.mod")); err == nil {
|
|
return dir
|
|
}
|
|
parent := filepath.Dir(dir)
|
|
if parent == dir {
|
|
return ""
|
|
}
|
|
dir = parent
|
|
}
|
|
}
|
|
|
|
// RepoFile resolves parts against the repository root so an in-repo path is found wherever the clone
|
|
// lives. When the root cannot be established the returned path is deliberately un-plausible: a missing
|
|
// marker must read as "my derivation is broken", never as "the data is simply absent".
|
|
func RepoFile(parts ...string) string {
|
|
root := Root()
|
|
if root == "" {
|
|
return filepath.Join("<repo-root-not-found>", filepath.Join(parts...))
|
|
}
|
|
return filepath.Join(append([]string{root}, parts...)...)
|
|
}
|
|
|
|
// StandFile resolves parts against the stand corpus root (<repo>/books).
|
|
func StandFile(parts ...string) string {
|
|
return RepoFile(append([]string{standRoot}, parts...)...)
|
|
}
|