Skip to content

Commit f5ff116

Browse files
jesseduffieldclaude
andcommitted
Use IsProjectScoped at remaining call sites + add test
Addresses Copilot review comments on PR #797: - Containers panel title, initial focus selection, and the local-project inclusion in getDiscoveredProjects all switched from InDockerComposeProject to IsProjectScoped, so they stay consistent when -p is given outside a compose dir. - Adds TestIsProjectScoped table test covering all four combinations. InDockerComposeProject is still used at the call sites that genuinely require a compose dir (renderDockerComposeConfig, GetServices). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 3974f6f commit f5ff116

5 files changed

Lines changed: 40 additions & 11 deletions

File tree

pkg/commands/docker_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"testing"
66

77
"github.com/docker/docker/client"
8+
"github.com/jesseduffield/lazydocker/pkg/config"
89
"github.com/stretchr/testify/assert"
910
)
1011

@@ -61,3 +62,30 @@ func TestNewDockerClientVersionNegotiation(t *testing.T) {
6162
"client version should not be locked to DOCKER_API_VERSION env var")
6263
})
6364
}
65+
66+
// TestIsProjectScoped covers the predicate that drives whether the
67+
// project/services panels appear and whether the containers panel filters by
68+
// project. The "outside compose dir + -p" case is the regression we fixed
69+
// after PR #776 silently disabled it.
70+
func TestIsProjectScoped(t *testing.T) {
71+
cases := []struct {
72+
name string
73+
inDockerComposeProject bool
74+
projectName string
75+
want bool
76+
}{
77+
{"inside compose dir, no -p", true, "", true},
78+
{"inside compose dir, with -p", true, "myproject", true},
79+
{"outside compose dir, no -p", false, "", false},
80+
{"outside compose dir, with -p", false, "myproject", true},
81+
}
82+
for _, tc := range cases {
83+
t.Run(tc.name, func(t *testing.T) {
84+
c := &DockerCommand{
85+
InDockerComposeProject: tc.inDockerComposeProject,
86+
Config: &config.AppConfig{ProjectName: tc.projectName},
87+
}
88+
assert.Equal(t, tc.want, c.IsProjectScoped())
89+
})
90+
}
91+
}

pkg/gui/containers_panel.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,10 @@ func (gui *Gui) getContainersPanel() *panels.SideListPanel[*commands.Container]
9191
// Otherwise all containers are shown in a flat list regardless
9292
// of which compose project they belong to.
9393
if gui.DockerCommand.IsProjectScoped() {
94-
// This check must be inside the InDockerComposeProject guard:
95-
// outside a compose project, services are still derived from
96-
// container labels, so compose-managed containers from other
97-
// projects would be incorrectly hidden.
94+
// This check must be inside the IsProjectScoped guard: when
95+
// not project-scoped, services are still derived from container
96+
// labels, so compose-managed containers from other projects
97+
// would be incorrectly hidden.
9898
//
9999
// Note that this is O(N*M) time complexity where N is the number of services
100100
// and M is the number of containers. We expect N to be small but M may be large,

pkg/gui/gui.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ func (gui *Gui) ShouldRefresh(key string) bool {
459459
}
460460

461461
func (gui *Gui) initiallyFocusedViewName() string {
462-
if gui.DockerCommand.InDockerComposeProject {
462+
if gui.DockerCommand.IsProjectScoped() {
463463
return "services"
464464
}
465465
return "containers"

pkg/gui/project_panel.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,18 +94,19 @@ func (gui *Gui) refreshProject() error {
9494
}
9595

9696
// getDiscoveredProjects returns all docker compose projects by examining container labels.
97-
// The local project (from docker-compose.yml in the current directory) is included if
98-
// it has running containers or if InDockerComposeProject is true.
97+
// The local project (from docker-compose.yml in the current directory, or from -p) is
98+
// included even when it has no running containers, so the user always sees the project
99+
// they explicitly scoped to.
99100
func (gui *Gui) getDiscoveredProjects() []*commands.Project {
100101
containers := gui.Panels.Containers.List.GetAllItems()
101102
projectNames := gui.DockerCommand.GetProjectNames(containers)
102103

103-
// If we're in a docker compose project but it has no running containers,
104-
// still include it. We don't fall back to the directory name here to avoid
104+
// If we're scoped to a project but it has no running containers, still
105+
// include it. We don't fall back to the directory name here to avoid
105106
// briefly flashing the wrong project name on startup.
106107
localName := gui.DockerCommand.LocalProjectName
107108

108-
if gui.DockerCommand.InDockerComposeProject && localName != "" {
109+
if gui.DockerCommand.IsProjectScoped() && localName != "" {
109110
found := false
110111
for _, name := range projectNames {
111112
if name == localName {

pkg/gui/views.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ func (gui *Gui) createAllViews() error {
130130

131131
gui.Views.Containers.Highlight = true
132132
gui.Views.Containers.SelBgColor = selectedLineBgColor
133-
if gui.Config.UserConfig.Gui.ShowAllContainers || !gui.DockerCommand.InDockerComposeProject {
133+
if gui.Config.UserConfig.Gui.ShowAllContainers || !gui.DockerCommand.IsProjectScoped() {
134134
gui.Views.Containers.Title = gui.Tr.ContainersTitle
135135
} else {
136136
gui.Views.Containers.Title = gui.Tr.StandaloneContainersTitle

0 commit comments

Comments
 (0)