Skip to content

Commit 5e62578

Browse files
authored
Merge pull request #487 from eike-hass/fix/loader-filenames-mutation-on-reload
fix(loader): persist user-supplied FileNames, not the extends-mutated slice
2 parents a4038d6 + bcf2468 commit 5e62578

2 files changed

Lines changed: 40 additions & 1 deletion

File tree

src/loader/loader.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,13 @@ func Load(opts *LoaderOptions) (*types.Project, error) {
4747
if err != nil {
4848
return nil, err
4949
}
50-
mergedProject.FileNames = opts.FileNames
50+
// Record the original user-supplied file list, not opts.FileNames —
51+
// loadExtendProject mutates opts.FileNames in place when it resolves an
52+
// `extends:` directive. Persisting the mutated slice onto the long-lived
53+
// project poisons subsequent Load() calls (e.g. ReloadProject reuses
54+
// p.project.FileNames as input), causing loadExtendProject's Contains
55+
// check to fire on entries the loader itself inserted on the prior pass.
56+
mergedProject.FileNames = fileNames
5157
mergedProject.EnvFileNames = opts.EnvFileNames
5258
mergedProject.IsTuiDisabled = opts.isTuiDisabled || mergedProject.IsTuiDisabled
5359
mergedProject.IsOrderedShutdown = opts.isOrderedShutdown || mergedProject.IsOrderedShutdown

src/loader/loader_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,36 @@ func TestLoadFileWithExtendProject(t *testing.T) {
187187
}
188188
}
189189
}
190+
191+
// TestLoad_ReloadAfterExtends locks in the fix for the reload-after-extends
192+
// bug: Load() must persist the user-supplied FileNames on the returned project,
193+
// not the slice that loadExtendProject mutates while resolving `extends:`.
194+
// ProjectRunner.ReloadProject reuses project.FileNames as input to the next
195+
// Load(); if the extends target leaks into that slice, the Contains check in
196+
// loadExtendProject false-fires on the loader's own bookkeeping.
197+
func TestLoad_ReloadAfterExtends(t *testing.T) {
198+
fixture := filepath.Join("..", "..", "fixtures-code", "process-compose-with-extends.yaml")
199+
200+
opts1 := &LoaderOptions{
201+
FileNames: []string{fixture},
202+
IsInternalLoader: true,
203+
}
204+
project1, err := Load(opts1)
205+
if err != nil {
206+
t.Fatalf("initial load failed: %v", err)
207+
}
208+
if len(project1.FileNames) != 1 || project1.FileNames[0] != fixture {
209+
t.Fatalf("project.FileNames = %v, want [%s]", project1.FileNames, fixture)
210+
}
211+
212+
// Mimic ProjectRunner.ReloadProject: feed the previous project's FileNames
213+
// as the next Load's input. Before the fix this fails with
214+
// "project ... is already specified in files to load".
215+
opts2 := &LoaderOptions{
216+
FileNames: project1.FileNames,
217+
IsInternalLoader: true,
218+
}
219+
if _, err := Load(opts2); err != nil {
220+
t.Fatalf("reload after extends failed: %v", err)
221+
}
222+
}

0 commit comments

Comments
 (0)