chore: import upstream snapshot with attribution
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
// Package workspace defines the per-project index-directory marker.
|
||||
//
|
||||
// A directory that contains a `.gortex/` index directory is a Gortex
|
||||
// project root. The legacy `.gortex/workspace.toml` workspace-marker
|
||||
// handshake (Resolve / Bind / Marker) has been removed: multi-repo
|
||||
// scoping is the daemon's job, resolved per session from the client's
|
||||
// working directory (see internal/indexer.ScopeForCWD and the MCP
|
||||
// server's sessionScope), not from a marker file.
|
||||
package workspace
|
||||
|
||||
// IndexDir is the per-project index directory name: a directory that
|
||||
// contains `.gortex/` is a Gortex project root. `gortex init` creates
|
||||
// it to hold the repo's `.gortex.yaml` and related config.
|
||||
const IndexDir = ".gortex"
|
||||
@@ -0,0 +1,64 @@
|
||||
package workspace
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// DefaultIndexGitignore is written into <IndexDir>/.gitignore so a project's
|
||||
// local Gortex state (quarantine, merkle cache, sqlite sidecar, etc.) is never
|
||||
// accidentally committed. The bare `*` ignores everything under the directory.
|
||||
const DefaultIndexGitignore = "# Gortex-managed: local index state, do not commit\n*\n"
|
||||
|
||||
// knownIndexGitignoreDefaults are prior auto-written contents that
|
||||
// EnsureIndexDirGitignore is allowed to heal up to the current default. A file
|
||||
// whose normalized content matches none of these (and isn't already current) is
|
||||
// treated as user-customized and left untouched.
|
||||
var knownIndexGitignoreDefaults = []string{
|
||||
"*",
|
||||
}
|
||||
|
||||
// EnsureIndexDirGitignore writes DefaultIndexGitignore into <indexDir>/.gitignore
|
||||
// when it is absent, or heals it when it still holds a known prior default. A
|
||||
// user-customized .gitignore is left untouched. It returns whether it wrote.
|
||||
func EnsureIndexDirGitignore(indexDir string) (wrote bool, err error) {
|
||||
gi := filepath.Join(indexDir, ".gitignore")
|
||||
existing, readErr := os.ReadFile(gi)
|
||||
switch {
|
||||
case readErr == nil:
|
||||
cur := normalizeGitignore(string(existing))
|
||||
if cur == normalizeGitignore(DefaultIndexGitignore) {
|
||||
return false, nil // already current
|
||||
}
|
||||
if !isLegacyIndexGitignore(cur) {
|
||||
return false, nil // user-customized: leave it
|
||||
}
|
||||
// stale default → heal below
|
||||
case os.IsNotExist(readErr):
|
||||
// absent → write below
|
||||
default:
|
||||
return false, readErr
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(indexDir, 0o755); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := os.WriteFile(gi, []byte(DefaultIndexGitignore), 0o644); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func normalizeGitignore(s string) string {
|
||||
return strings.TrimSpace(s)
|
||||
}
|
||||
|
||||
func isLegacyIndexGitignore(normalized string) bool {
|
||||
for _, d := range knownIndexGitignoreDefaults {
|
||||
if normalizeGitignore(d) == normalized {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package workspace
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEnsureIndexDirGitignore(t *testing.T) {
|
||||
read := func(dir string) string {
|
||||
b, err := os.ReadFile(filepath.Join(dir, ".gitignore"))
|
||||
if err != nil {
|
||||
t.Fatalf("read .gitignore: %v", err)
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// created: an empty index dir gets the default written.
|
||||
t.Run("created", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
wrote, err := EnsureIndexDirGitignore(dir)
|
||||
if err != nil || !wrote {
|
||||
t.Fatalf("wrote=%v err=%v, want wrote=true", wrote, err)
|
||||
}
|
||||
if got := read(dir); got != DefaultIndexGitignore {
|
||||
t.Errorf("content = %q, want default", got)
|
||||
}
|
||||
})
|
||||
|
||||
// unchanged: a dir already holding the current default is a no-op.
|
||||
t.Run("unchanged", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
if _, err := EnsureIndexDirGitignore(dir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wrote, err := EnsureIndexDirGitignore(dir)
|
||||
if err != nil || wrote {
|
||||
t.Errorf("second call wrote=%v err=%v, want wrote=false", wrote, err)
|
||||
}
|
||||
})
|
||||
|
||||
// healed: a stale bare-`*` default is rewritten to the current default.
|
||||
t.Run("healed", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
if err := os.WriteFile(filepath.Join(dir, ".gitignore"), []byte("*\n"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wrote, err := EnsureIndexDirGitignore(dir)
|
||||
if err != nil || !wrote {
|
||||
t.Fatalf("heal wrote=%v err=%v, want wrote=true", wrote, err)
|
||||
}
|
||||
if got := read(dir); got != DefaultIndexGitignore {
|
||||
t.Errorf("healed content = %q, want default", got)
|
||||
}
|
||||
})
|
||||
|
||||
// kept: a user-customized .gitignore is left untouched.
|
||||
t.Run("kept", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
const custom = "!keepme.json\nstore.sqlite\n"
|
||||
if err := os.WriteFile(filepath.Join(dir, ".gitignore"), []byte(custom), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wrote, err := EnsureIndexDirGitignore(dir)
|
||||
if err != nil || wrote {
|
||||
t.Errorf("kept wrote=%v err=%v, want wrote=false", wrote, err)
|
||||
}
|
||||
if got := read(dir); got != custom {
|
||||
t.Errorf("customized content was altered: %q", got)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user