Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cmd/buf/internal/command/dep/depgraph/depgraph.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,9 +253,9 @@ func (e *externalModule) addDeps(
depExternalModule, ok := moduleFullNameOrOpaqueIDToExternalModule[depFullNameOrOpaqueID]
if ok {
// If this dependency has already been seen, we can simply update our current module
// and return early.
// and continue to the next dependency.
e.Deps = append(e.Deps, depExternalModule)
return nil
continue
}
// Otherwise, we create a new external module for our direct dependency. However, we do
// not add it to our map yet, we only add it once all transitive dependencies have been
Expand Down
89 changes: 89 additions & 0 deletions cmd/buf/internal/command/dep/depgraph/depgraph_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2020-2026 Buf Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package depgraph

import (
"bytes"
"encoding/json"
"path/filepath"
"testing"

"buf.build/go/app/appcmd"
"buf.build/go/app/appcmd/appcmdtesting"
"buf.build/go/app/appext"
"github.com/bufbuild/buf/cmd/buf/internal/internaltesting"
"github.com/stretchr/testify/require"
)

// TestJSONFormatSharedDep is a regression test for a bug where addDeps had
// a "return nil" instead of "continue" when a dependency was already in the
// seen map, causing all subsequent dependencies to be silently dropped.
//
// The workspace has three local modules: alpha -> common, zeta -> {alpha, common}.
// Because modules are walked alphabetically, both of zeta's deps are already
// in the seen map when zeta is processed, which triggered the early return.
func TestJSONFormatSharedDep(t *testing.T) {
t.Parallel()
var stdout bytes.Buffer
appcmdtesting.Run(
t,
func(name string) *appcmd.Command {
return NewCommand(name, appext.NewBuilder(name))
},
appcmdtesting.WithExpectedExitCode(0),
appcmdtesting.WithEnv(internaltesting.NewEnvFunc(t)),
appcmdtesting.WithStdout(&stdout),
appcmdtesting.WithArgs(
"--format", "json",
filepath.Join("testdata", "shared_dep_workspace"),
),
)
var got []externalModule
require.NoError(t, json.Unmarshal(stdout.Bytes(), &got))
clearDigests(got)
expected := []externalModule{
{
Name: "alpha",
Local: true,
Deps: []externalModule{
{Name: "common", Local: true},
},
},
{
Name: "common",
Local: true,
},
{
Name: "zeta",
Local: true,
Deps: []externalModule{
{Name: "alpha", Local: true, Deps: []externalModule{
{Name: "common", Local: true},
}},
{Name: "common", Local: true},
},
},
}
require.Equal(t, expected, got)
}

// clearDigests zeros out Digest fields so we can compare structures without
// depending on content hashes.
func clearDigests(modules []externalModule) {
for i := range modules {
modules[i].Digest = ""
clearDigests(modules[i].Deps)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
syntax = "proto3";

package alpha.v1;

import "common.proto";

message Foo {
common.v1.Shared shared = 1;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
version: v2
modules:
- path: alpha
- path: common
- path: zeta
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
syntax = "proto3";

package common.v1;

message Shared {
string value = 1;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
syntax = "proto3";

package zeta.v1;

import "common.proto";
import "alpha.proto";

message Bar {
common.v1.Shared shared = 1;
alpha.v1.Foo foo = 2;
}
Loading