on main help sign in
test(config): tests for the data directory paths
a7932c5Christian Rocha
internal/config/config.go+11−7
@@ -259,13 +259,17 @@ func (Attribution) JSONSchemaExtend(schema *jsonschema.Schema) {
259}
259}
260
260
261type Options struct {
261type Options struct {
262− ContextPaths []string `json:"context_paths,omitempty" jsonschema:"description=Paths to files containing context information for the AI,example=.cursorrules,example=CRUSH.md"`
262+ ContextPaths []string `json:"context_paths,omitempty" jsonschema:"description=Paths to files containing context information for the AI,example=.cursorrules,example=CRUSH.md"`
263− SkillsPaths []string `json:"skills_paths,omitempty" jsonschema:"description=Paths to directories containing Agent Skills (folders with SKILL.md files),example=~/.config/crush/skills,example=./skills"`
263+ SkillsPaths []string `json:"skills_paths,omitempty" jsonschema:"description=Paths to directories containing Agent Skills (folders with SKILL.md files),example=~/.config/crush/skills,example=./skills"`
264− TUI *TUIOptions `json:"tui,omitempty" jsonschema:"description=Terminal user interface options"`
264+ TUI *TUIOptions `json:"tui,omitempty" jsonschema:"description=Terminal user interface options"`
265− Debug bool `json:"debug,omitempty" jsonschema:"description=Enable debug logging,default=false"`
265+ Debug bool `json:"debug,omitempty" jsonschema:"description=Enable debug logging,default=false"`
266− DebugLSP bool `json:"debug_lsp,omitempty" jsonschema:"description=Enable debug logging for LSP servers,default=false"`
266+ DebugLSP bool `json:"debug_lsp,omitempty" jsonschema:"description=Enable debug logging for LSP servers,default=false"`
267− DisableAutoSummarize bool `json:"disable_auto_summarize,omitempty" jsonschema:"description=Disable automatic conversation summarization,default=false"`
267+ DisableAutoSummarize bool `json:"disable_auto_summarize,omitempty" jsonschema:"description=Disable automatic conversation summarization,default=false"`
268+ // DataDirectory is where Crush keeps per-project state such as
269+ // the SQLite database and workspace overrides. Relative paths are
270+ // resolved against the working directory; absolute paths are used
271+ // verbatim. After defaulting the stored value is always absolute.
268− DataDirectory string `json:"data_directory,omitempty" jsonschema:"description=Directory for storing application data (relative to working directory),default=.crush,example=.crush"` // Relative to the cwd
272+ DataDirectory string `json:"data_directory,omitempty" jsonschema:"description=Directory for storing application data. Relative paths are resolved against the working directory; absolute paths are used as-is.,default=.crush,example=.crush"`
269 DisabledTools []string `json:"disabled_tools,omitempty" jsonschema:"description=List of built-in tools to disable and hide from the agent,example=bash,example=sourcegraph"`
273 DisabledTools []string `json:"disabled_tools,omitempty" jsonschema:"description=List of built-in tools to disable and hide from the agent,example=bash,example=sourcegraph"`
270 DisableProviderAutoUpdate bool `json:"disable_provider_auto_update,omitempty" jsonschema:"description=Disable providers auto-update,default=false"`
274 DisableProviderAutoUpdate bool `json:"disable_provider_auto_update,omitempty" jsonschema:"description=Disable providers auto-update,default=false"`
271 DisableDefaultProviders bool `json:"disable_default_providers,omitempty" jsonschema:"description=Ignore all default/embedded providers. When enabled\\, providers must be fully specified in the config file with base_url\\, models\\, and api_key - no merging with defaults occurs,default=false"`
275 DisableDefaultProviders bool `json:"disable_default_providers,omitempty" jsonschema:"description=Ignore all default/embedded providers. When enabled\\, providers must be fully specified in the config file with base_url\\, models\\, and api_key - no merging with defaults occurs,default=false"`
internal/config/load_test.go+30
@@ -205,6 +205,36 @@ func TestConfig_setDefaults(t *testing.T) {
205 require.Equal(t, filepath.Join(workingDir, "state"), cfg.Options.DataDirectory)
205 require.Equal(t, filepath.Join(workingDir, "state"), cfg.Options.DataDirectory)
206 })
206 })
207
207
208+ t.Run("preserves absolute configured data directory", func(t *testing.T) {
209+ // Use a platform-appropriate absolute path so the test runs
210+ // the same way on POSIX and Windows.
211+ absDir := filepath.Join(t.TempDir(), "data")
212+ cfg := &Config{Options: &Options{DataDirectory: absDir}}
213+
214+ cfg.setDefaults(filepath.Join(t.TempDir(), "worktree"), "")
215+
216+ require.Equal(t, absDir, cfg.Options.DataDirectory)
217+ })
218+
219+ t.Run("workspace merge re-entry keeps an absolute data directory", func(t *testing.T) {
220+ // Simulate the load and reload paths: defaults are applied
221+ // twice with the data directory potentially carried through
222+ // from an earlier merge as a relative string.
223+ workingDir := filepath.Join(t.TempDir(), "worktree")
224+ cfg := &Config{}
225+ cfg.setDefaults(workingDir, "")
226+
227+ // Workspace JSON sets data_directory to a relative value; the
228+ // merge replaces the struct, then setDefaults runs again.
229+ cfg.Options.DataDirectory = "./state"
230+ cfg.setDefaults(workingDir, "")
231+
232+ require.True(t, filepath.IsAbs(cfg.Options.DataDirectory),
233+ "data directory must remain absolute after re-merge, got %q",
234+ cfg.Options.DataDirectory)
235+ require.Equal(t, filepath.Join(workingDir, "state"), cfg.Options.DataDirectory)
236+ })
237+
208 t.Run("does not adopt .crush from a parent project", func(t *testing.T) {
238 t.Run("does not adopt .crush from a parent project", func(t *testing.T) {
209 parent := t.TempDir()
239 parent := t.TempDir()
210
240
internal/swagger/docs.go+1−1
@@ -2939,7 +2939,7 @@ const docTemplate = `{
2939 }
2939 }
2940 },
2940 },
2941 "data_directory": {
2941 "data_directory": {
2942− "description": "Relative to the cwd",
2942+ "description": "DataDirectory is where Crush keeps per-project state such as the SQLite database and workspace overrides. Relative paths are resolved against the working directory; absolute paths are used verbatim. After defaulting the stored value is always absolute.",
2943 "type": "string"
2943 "type": "string"
2944 },
2944 },
2945 "debug": {
2945 "debug": {
internal/swagger/swagger.json+1−1
@@ -2932,7 +2932,7 @@
2932 }
2932 }
2933 },
2933 },
2934 "data_directory": {
2934 "data_directory": {
2935− "description": "Relative to the cwd",
2935+ "description": "DataDirectory is where Crush keeps per-project state such as the SQLite database and workspace overrides. Relative paths are resolved against the working directory; absolute paths are used verbatim. After defaulting the stored value is always absolute.",
2936 "type": "string"
2936 "type": "string"
2937 },
2937 },
2938 "debug": {
2938 "debug": {
internal/swagger/swagger.yaml+5−1
@@ -287,7 +287,11 @@ definitions:
287 type: string
287 type: string
288 type: array
288 type: array
289 data_directory:
289 data_directory:
290− description: Relative to the cwd
290+ description: |-
291+ DataDirectory is where Crush keeps per-project state such as the SQLite
292+ database and workspace overrides. Relative paths are resolved against
293+ the working directory; absolute paths are used verbatim. After
294+ defaulting the stored value is always absolute.
291 type: string
295 type: string
292 debug:
296 debug:
293 type: boolean
297 type: boolean
schema.json+1−1
@@ -423,7 +423,7 @@
423 },
423 },
424 "data_directory": {
424 "data_directory": {
425 "type": "string",
425 "type": "string",
426− "description": "Directory for storing application data (relative to working directory)",
426+ "description": "Directory for storing application data. Relative paths are resolved against the working directory; absolute paths are used as-is.",
427 "default": ".crush",
427 "default": ".crush",
428 "examples": [
428 "examples": [
429 ".crush"
429 ".crush"