Repository: docker/compose
File: pkg/compose/attach.go (Go)

Code before:
	containerType "github.com/docker/docker/api/types/container"
	"github.com/docker/docker/pkg/stdcopy"
	"github.com/moby/term"

	"github.com/docker/compose/v5/pkg/api"
	"github.com/docker/compose/v5/pkg/utils"
)

func (s *composeService) attach(ctx context.Context, project *types.Project, listener api.ContainerEventListener, selectedServices []string) (Containers, error) {
	containers, err := s.getContainers(ctx, project.Name, oneOffExclude, true, selectedServices...)
	if err != nil {
		return nil, err
	}
	if len(containers) == 0 {
		return containers, nil
	}

	containers.sorted() // This enforces predictable colors assignment

	var names []string
	for _, c := range containers {
		names = append(names, getContainerNameWithoutProject(c))
	}

	_, _ = fmt.Fprintf(s.stdout(), "Attaching to %s\n", strings.Join(names, ", "))

	for _, ctr := range containers {
		err := s.attachContainer(ctx, ctr, listener)
		if err != nil {
			return nil, err
		}
	}
	return containers, err
}

func (s *composeService) attachContainer(ctx context.Context, container containerType.Summary, listener api.ContainerEventListener) error {
	service := container.Labels[api.ServiceLabel]
	name := getContainerNameWithoutProject(container)
	return s.doAttachContainer(ctx, service, container.ID, name, listener)
}

func (s *composeService) doAttachContainer(ctx context.Context, service, id, name string, listener api.ContainerEventListener) error {
	inspect, err := s.apiClient().ContainerInspect(ctx, id)
	if err != nil {
		return err
	}

	wOut := utils.GetWriter(func(line string) {
		listener(api.ContainerEvent{
			Type:    api.ContainerEventLog,
			Source:  name,

Review comment (bug):
Slightly wondering how useful these are, other than "please the linter"; logging here would try to write to `stderr`, which may also fail

Code after:
	"github.com/docker/docker/pkg/stdcopy"
	"github.com/sirupsen/logrus"

	"github.com/docker/compose/v5/pkg/api"
	"github.com/docker/compose/v5/pkg/utils"
)

func (s *composeService) attach(ctx context.Context, project *types.Project, listener api.ContainerEventListener, selectedServices []string) (Containers, error) {
	containers, err := s.getContainers(ctx, project.Name, oneOffExclude, true, selectedServices...)
	if err != nil {
		return nil, err
	}
	if len(containers) == 0 {
		return containers, nil
	}

	containers.sorted() // This enforces predictable colors assignment

	var names []string
	for _, c := range containers {
		names = append(names, getContainerNameWithoutProject(c))
	}

	_, err = fmt.Fprintf(s.stdout(), "Attaching to %s\n", strings.Join(names, ", "))
	if err != nil {
		logrus.Debugf("failed to write attach message: %v", err)
	}

	for _, ctr := range containers {
		err := s.attachContainer(ctx, ctr, listener)
		if err != nil {
			return nil, err
		}
	}
	return containers, nil
}

func (s *composeService) attachContainer(ctx context.Context, container containerType.Summary, listener api.ContainerEventListener) error {
	service := container.Labels[api.ServiceLabel]
	name := getContainerNameWithoutProject(container)
	return s.doAttachContainer(ctx, service, container.ID, name, listener)
}

func (s *composeService) doAttachContainer(ctx context.Context, service, id, name string, listener api.ContainerEventListener) error {
	inspect, err := s.apiClient().ContainerInspect(ctx, id)
	if err != nil {
		return err
	}

	wOut := utils.GetWriter(func(line string) {
		listener(api.ContainerEvent{