Merge pull request #73985 from BenTheElder/manual-vendor

mark vendor build targets manual
pull/564/head
Kubernetes Prow Robot 2019-02-13 16:12:02 -08:00 committed by GitHub
commit 03320c1436
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 6039 additions and 4 deletions

36
Godeps/Godeps.json generated
View File

@ -4,6 +4,7 @@
"GodepVersion": "v80-k8s-r1",
"Packages": [
"github.com/bazelbuild/bazel-gazelle/cmd/gazelle",
"github.com/bazelbuild/buildtools/buildozer",
"github.com/cespare/prettybench",
"github.com/client9/misspell/cmd/misspell",
"github.com/cloudflare/cfssl/cmd/cfssl",
@ -471,16 +472,51 @@
"Comment": "0.15.0",
"Rev": "c728ce9f663e2bff26361ba5978ec5c9e6816a3c"
},
{
"ImportPath": "github.com/bazelbuild/buildtools/api_proto",
"Comment": "0.6.0-60-g1a9c38e0df9397",
"Rev": "1a9c38e0df9397d033a1ca535596de5a7c1cf18f"
},
{
"ImportPath": "github.com/bazelbuild/buildtools/build",
"Comment": "0.6.0-60-g1a9c38e0df9397",
"Rev": "1a9c38e0df9397d033a1ca535596de5a7c1cf18f"
},
{
"ImportPath": "github.com/bazelbuild/buildtools/build_proto",
"Comment": "0.6.0-60-g1a9c38e0df9397",
"Rev": "1a9c38e0df9397d033a1ca535596de5a7c1cf18f"
},
{
"ImportPath": "github.com/bazelbuild/buildtools/buildozer",
"Comment": "0.6.0-60-g1a9c38e0df9397",
"Rev": "1a9c38e0df9397d033a1ca535596de5a7c1cf18f"
},
{
"ImportPath": "github.com/bazelbuild/buildtools/edit",
"Comment": "0.6.0-60-g1a9c38e0df9397",
"Rev": "1a9c38e0df9397d033a1ca535596de5a7c1cf18f"
},
{
"ImportPath": "github.com/bazelbuild/buildtools/file",
"Comment": "0.6.0-60-g1a9c38e0df9397",
"Rev": "1a9c38e0df9397d033a1ca535596de5a7c1cf18f"
},
{
"ImportPath": "github.com/bazelbuild/buildtools/lang",
"Comment": "0.6.0-60-g1a9c38e0df9397",
"Rev": "1a9c38e0df9397d033a1ca535596de5a7c1cf18f"
},
{
"ImportPath": "github.com/bazelbuild/buildtools/tables",
"Comment": "0.6.0-60-g1a9c38e0df9397",
"Rev": "1a9c38e0df9397d033a1ca535596de5a7c1cf18f"
},
{
"ImportPath": "github.com/bazelbuild/buildtools/wspace",
"Comment": "0.6.0-60-g1a9c38e0df9397",
"Rev": "1a9c38e0df9397d033a1ca535596de5a7c1cf18f"
},
{
"ImportPath": "github.com/beorn7/perks/quantile",
"Rev": "3ac7bf7a47d159a033b107610db8a1b6575507a4"

147
Godeps/LICENSES generated
View File

@ -14961,6 +14961,27 @@ THE SOFTWARE.
================================================================================
================================================================================
= vendor/github.com/bazelbuild/buildtools/api_proto licensed under: =
Copyright 2016 Google Inc. All Rights Reserved.
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.
= vendor/github.com/bazelbuild/buildtools/LICENSE adb52eb384caedba181cd51fbcdf4b99
================================================================================
================================================================================
= vendor/github.com/bazelbuild/buildtools/build licensed under: =
@ -14982,6 +15003,111 @@ limitations under the License.
================================================================================
================================================================================
= vendor/github.com/bazelbuild/buildtools/buildozer licensed under: =
Copyright 2016 Google Inc. All Rights Reserved.
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.
= vendor/github.com/bazelbuild/buildtools/LICENSE adb52eb384caedba181cd51fbcdf4b99
================================================================================
================================================================================
= vendor/github.com/bazelbuild/buildtools/build_proto licensed under: =
Copyright 2016 Google Inc. All Rights Reserved.
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.
= vendor/github.com/bazelbuild/buildtools/LICENSE adb52eb384caedba181cd51fbcdf4b99
================================================================================
================================================================================
= vendor/github.com/bazelbuild/buildtools/edit licensed under: =
Copyright 2016 Google Inc. All Rights Reserved.
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.
= vendor/github.com/bazelbuild/buildtools/LICENSE adb52eb384caedba181cd51fbcdf4b99
================================================================================
================================================================================
= vendor/github.com/bazelbuild/buildtools/file licensed under: =
Copyright 2016 Google Inc. All Rights Reserved.
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.
= vendor/github.com/bazelbuild/buildtools/LICENSE adb52eb384caedba181cd51fbcdf4b99
================================================================================
================================================================================
= vendor/github.com/bazelbuild/buildtools/lang licensed under: =
Copyright 2016 Google Inc. All Rights Reserved.
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.
= vendor/github.com/bazelbuild/buildtools/LICENSE adb52eb384caedba181cd51fbcdf4b99
================================================================================
================================================================================
= vendor/github.com/bazelbuild/buildtools/tables licensed under: =
@ -15003,6 +15129,27 @@ limitations under the License.
================================================================================
================================================================================
= vendor/github.com/bazelbuild/buildtools/wspace licensed under: =
Copyright 2016 Google Inc. All Rights Reserved.
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.
= vendor/github.com/bazelbuild/buildtools/LICENSE adb52eb384caedba181cd51fbcdf4b99
================================================================================
================================================================================
= vendor/github.com/beorn7/perks/quantile licensed under: =

View File

@ -56,6 +56,7 @@ fi
# won't pick them up.
REQUIRED_BINS=(
"github.com/bazelbuild/bazel-gazelle/cmd/gazelle"
"github.com/bazelbuild/buildtools/buildozer"
"github.com/cespare/prettybench"
"github.com/client9/misspell/cmd/misspell"
"github.com/cloudflare/cfssl/cmd/cfssl"

View File

@ -26,6 +26,7 @@ PATH="${GOBIN}:${PATH}"
# Install tools we need, but only from vendor/...
go install k8s.io/kubernetes/vendor/github.com/bazelbuild/bazel-gazelle/cmd/gazelle
go install k8s.io/kubernetes/vendor/github.com/bazelbuild/buildtools/buildozer
go install k8s.io/kubernetes/vendor/k8s.io/repo-infra/kazel
touch "${KUBE_ROOT}/vendor/BUILD"
@ -43,3 +44,11 @@ gazelle fix \
"${KUBE_ROOT}"
kazel
# make targets in vendor manual
# buildozer exits 3 when no changes are made ¯\_(ツ)_/¯
# https://github.com/bazelbuild/buildtools/tree/master/buildozer#error-code
buildozer -quiet 'add tags manual' '//vendor/...:%go_binary' '//vendor/...:%go_test' && ret=$? || ret=$?
if [[ $ret != 0 && $ret != 3 ]]; then
exit 1
fi

View File

@ -12,8 +12,8 @@ go_test(
name = "go_default_test",
srcs = ["crd_test.go"],
data = [
":csi-manifests",
"//cluster/addons:addon-srcs",
"//staging/src/k8s.io/csi-api/pkg/crd:manifests",
],
embed = [":go_default_library"],
deps = ["//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library"],
@ -28,9 +28,7 @@ filegroup(
filegroup(
name = "csi-manifests",
srcs = [
"//staging/src/k8s.io/csi-api/pkg/crd:manifests",
],
srcs = glob(["manifests/**"]),
visibility = ["//visibility:public"],
)

7
vendor/BUILD vendored
View File

@ -65,8 +65,15 @@ filegroup(
"//vendor/github.com/bazelbuild/bazel-gazelle/internal/version:all-srcs",
"//vendor/github.com/bazelbuild/bazel-gazelle/internal/walk:all-srcs",
"//vendor/github.com/bazelbuild/bazel-gazelle/internal/wspace:all-srcs",
"//vendor/github.com/bazelbuild/buildtools/api_proto:all-srcs",
"//vendor/github.com/bazelbuild/buildtools/build:all-srcs",
"//vendor/github.com/bazelbuild/buildtools/build_proto:all-srcs",
"//vendor/github.com/bazelbuild/buildtools/buildozer:all-srcs",
"//vendor/github.com/bazelbuild/buildtools/edit:all-srcs",
"//vendor/github.com/bazelbuild/buildtools/file:all-srcs",
"//vendor/github.com/bazelbuild/buildtools/lang:all-srcs",
"//vendor/github.com/bazelbuild/buildtools/tables:all-srcs",
"//vendor/github.com/bazelbuild/buildtools/wspace:all-srcs",
"//vendor/github.com/beorn7/perks/quantile:all-srcs",
"//vendor/github.com/blang/semver:all-srcs",
"//vendor/github.com/cespare/prettybench:all-srcs",

View File

@ -35,6 +35,7 @@ go_library(
go_binary(
name = "gazelle",
embed = [":go_default_library"],
tags = ["manual"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,24 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["api.gen.pb.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/bazelbuild/buildtools/api_proto",
importpath = "github.com/bazelbuild/buildtools/api_proto",
visibility = ["//visibility:public"],
deps = ["//vendor/github.com/golang/protobuf/proto:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,315 @@
// Code generated by protoc-gen-go.
// source: api_proto/api.proto
// DO NOT EDIT!
/*
Package devtools_buildozer is a generated protocol buffer package.
It is generated from these files:
api_proto/api.proto
It has these top-level messages:
Output
RepeatedString
*/
package devtools_buildozer
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type Output_Record_Field_ERROR int32
const (
Output_Record_Field_UNKNOWN Output_Record_Field_ERROR = 0
Output_Record_Field_MISSING Output_Record_Field_ERROR = 1
)
var Output_Record_Field_ERROR_name = map[int32]string{
0: "UNKNOWN",
1: "MISSING",
}
var Output_Record_Field_ERROR_value = map[string]int32{
"UNKNOWN": 0,
"MISSING": 1,
}
func (x Output_Record_Field_ERROR) String() string {
return proto.EnumName(Output_Record_Field_ERROR_name, int32(x))
}
func (Output_Record_Field_ERROR) EnumDescriptor() ([]byte, []int) {
return fileDescriptor0, []int{0, 0, 0, 0}
}
type Output struct {
Records []*Output_Record `protobuf:"bytes,1,rep,name=records" json:"records,omitempty"`
}
func (m *Output) Reset() { *m = Output{} }
func (m *Output) String() string { return proto.CompactTextString(m) }
func (*Output) ProtoMessage() {}
func (*Output) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (m *Output) GetRecords() []*Output_Record {
if m != nil {
return m.Records
}
return nil
}
type Output_Record struct {
Fields []*Output_Record_Field `protobuf:"bytes,1,rep,name=fields" json:"fields,omitempty"`
}
func (m *Output_Record) Reset() { *m = Output_Record{} }
func (m *Output_Record) String() string { return proto.CompactTextString(m) }
func (*Output_Record) ProtoMessage() {}
func (*Output_Record) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} }
func (m *Output_Record) GetFields() []*Output_Record_Field {
if m != nil {
return m.Fields
}
return nil
}
type Output_Record_Field struct {
// Types that are valid to be assigned to Value:
// *Output_Record_Field_Text
// *Output_Record_Field_Number
// *Output_Record_Field_Error
// *Output_Record_Field_List
Value isOutput_Record_Field_Value `protobuf_oneof:"value"`
// Used internally by Buildozer to decide whether a field should be quoted
// when printing. This does not affect the contents of 'value'.
QuoteWhenPrinting bool `protobuf:"varint,7,opt,name=quote_when_printing,json=quoteWhenPrinting" json:"quote_when_printing,omitempty"`
}
func (m *Output_Record_Field) Reset() { *m = Output_Record_Field{} }
func (m *Output_Record_Field) String() string { return proto.CompactTextString(m) }
func (*Output_Record_Field) ProtoMessage() {}
func (*Output_Record_Field) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0, 0} }
type isOutput_Record_Field_Value interface {
isOutput_Record_Field_Value()
}
type Output_Record_Field_Text struct {
Text string `protobuf:"bytes,1,opt,name=text,oneof"`
}
type Output_Record_Field_Number struct {
Number int32 `protobuf:"varint,2,opt,name=number,oneof"`
}
type Output_Record_Field_Error struct {
Error Output_Record_Field_ERROR `protobuf:"varint,3,opt,name=error,enum=devtools.buildozer.Output_Record_Field_ERROR,oneof"`
}
type Output_Record_Field_List struct {
List *RepeatedString `protobuf:"bytes,5,opt,name=list,oneof"`
}
func (*Output_Record_Field_Text) isOutput_Record_Field_Value() {}
func (*Output_Record_Field_Number) isOutput_Record_Field_Value() {}
func (*Output_Record_Field_Error) isOutput_Record_Field_Value() {}
func (*Output_Record_Field_List) isOutput_Record_Field_Value() {}
func (m *Output_Record_Field) GetValue() isOutput_Record_Field_Value {
if m != nil {
return m.Value
}
return nil
}
func (m *Output_Record_Field) GetText() string {
if x, ok := m.GetValue().(*Output_Record_Field_Text); ok {
return x.Text
}
return ""
}
func (m *Output_Record_Field) GetNumber() int32 {
if x, ok := m.GetValue().(*Output_Record_Field_Number); ok {
return x.Number
}
return 0
}
func (m *Output_Record_Field) GetError() Output_Record_Field_ERROR {
if x, ok := m.GetValue().(*Output_Record_Field_Error); ok {
return x.Error
}
return Output_Record_Field_UNKNOWN
}
func (m *Output_Record_Field) GetList() *RepeatedString {
if x, ok := m.GetValue().(*Output_Record_Field_List); ok {
return x.List
}
return nil
}
func (m *Output_Record_Field) GetQuoteWhenPrinting() bool {
if m != nil {
return m.QuoteWhenPrinting
}
return false
}
// XXX_OneofFuncs is for the internal use of the proto package.
func (*Output_Record_Field) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
return _Output_Record_Field_OneofMarshaler, _Output_Record_Field_OneofUnmarshaler, _Output_Record_Field_OneofSizer, []interface{}{
(*Output_Record_Field_Text)(nil),
(*Output_Record_Field_Number)(nil),
(*Output_Record_Field_Error)(nil),
(*Output_Record_Field_List)(nil),
}
}
func _Output_Record_Field_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
m := msg.(*Output_Record_Field)
// value
switch x := m.Value.(type) {
case *Output_Record_Field_Text:
b.EncodeVarint(1<<3 | proto.WireBytes)
b.EncodeStringBytes(x.Text)
case *Output_Record_Field_Number:
b.EncodeVarint(2<<3 | proto.WireVarint)
b.EncodeVarint(uint64(x.Number))
case *Output_Record_Field_Error:
b.EncodeVarint(3<<3 | proto.WireVarint)
b.EncodeVarint(uint64(x.Error))
case *Output_Record_Field_List:
b.EncodeVarint(5<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.List); err != nil {
return err
}
case nil:
default:
return fmt.Errorf("Output_Record_Field.Value has unexpected type %T", x)
}
return nil
}
func _Output_Record_Field_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
m := msg.(*Output_Record_Field)
switch tag {
case 1: // value.text
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
x, err := b.DecodeStringBytes()
m.Value = &Output_Record_Field_Text{x}
return true, err
case 2: // value.number
if wire != proto.WireVarint {
return true, proto.ErrInternalBadWireType
}
x, err := b.DecodeVarint()
m.Value = &Output_Record_Field_Number{int32(x)}
return true, err
case 3: // value.error
if wire != proto.WireVarint {
return true, proto.ErrInternalBadWireType
}
x, err := b.DecodeVarint()
m.Value = &Output_Record_Field_Error{Output_Record_Field_ERROR(x)}
return true, err
case 5: // value.list
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(RepeatedString)
err := b.DecodeMessage(msg)
m.Value = &Output_Record_Field_List{msg}
return true, err
default:
return false, nil
}
}
func _Output_Record_Field_OneofSizer(msg proto.Message) (n int) {
m := msg.(*Output_Record_Field)
// value
switch x := m.Value.(type) {
case *Output_Record_Field_Text:
n += proto.SizeVarint(1<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(len(x.Text)))
n += len(x.Text)
case *Output_Record_Field_Number:
n += proto.SizeVarint(2<<3 | proto.WireVarint)
n += proto.SizeVarint(uint64(x.Number))
case *Output_Record_Field_Error:
n += proto.SizeVarint(3<<3 | proto.WireVarint)
n += proto.SizeVarint(uint64(x.Error))
case *Output_Record_Field_List:
s := proto.Size(x.List)
n += proto.SizeVarint(5<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case nil:
default:
panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
}
return n
}
type RepeatedString struct {
Strings []string `protobuf:"bytes,1,rep,name=strings" json:"strings,omitempty"`
}
func (m *RepeatedString) Reset() { *m = RepeatedString{} }
func (m *RepeatedString) String() string { return proto.CompactTextString(m) }
func (*RepeatedString) ProtoMessage() {}
func (*RepeatedString) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *RepeatedString) GetStrings() []string {
if m != nil {
return m.Strings
}
return nil
}
func init() {
proto.RegisterType((*Output)(nil), "devtools.buildozer.Output")
proto.RegisterType((*Output_Record)(nil), "devtools.buildozer.Output.Record")
proto.RegisterType((*Output_Record_Field)(nil), "devtools.buildozer.Output.Record.Field")
proto.RegisterType((*RepeatedString)(nil), "devtools.buildozer.RepeatedString")
proto.RegisterEnum("devtools.buildozer.Output_Record_Field_ERROR", Output_Record_Field_ERROR_name, Output_Record_Field_ERROR_value)
}
func init() { proto.RegisterFile("api_proto/api.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 336 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0xc1, 0x4a, 0xf3, 0x40,
0x14, 0x85, 0x33, 0x6d, 0x93, 0xfc, 0xbd, 0x85, 0xd2, 0x7f, 0xea, 0x62, 0xe8, 0x2a, 0xcd, 0xc6,
0x20, 0x38, 0x42, 0xdd, 0x08, 0x2e, 0x04, 0xa1, 0xda, 0x22, 0xa6, 0x32, 0x45, 0xba, 0x2c, 0xa9,
0x19, 0xdb, 0x81, 0x98, 0x89, 0x93, 0x49, 0x15, 0x9f, 0xc3, 0x87, 0xf0, 0xb1, 0x7c, 0x14, 0xc9,
0x24, 0x15, 0x44, 0x41, 0x77, 0xf7, 0xdc, 0x7b, 0xbe, 0x73, 0x42, 0x06, 0xfa, 0x51, 0x26, 0x96,
0x99, 0x92, 0x5a, 0x1e, 0x45, 0x99, 0xa0, 0x66, 0xc2, 0x38, 0xe6, 0x5b, 0x2d, 0x65, 0x92, 0xd3,
0x55, 0x21, 0x92, 0x58, 0xbe, 0x70, 0xe5, 0xbf, 0x35, 0xc1, 0x99, 0x15, 0x3a, 0x2b, 0x34, 0x3e,
0x05, 0x57, 0xf1, 0x3b, 0xa9, 0xe2, 0x9c, 0x20, 0xaf, 0x19, 0x74, 0x46, 0x43, 0xfa, 0x1d, 0xa0,
0x95, 0x99, 0x32, 0xe3, 0x64, 0x3b, 0x62, 0xf0, 0xde, 0x00, 0xa7, 0xda, 0xe1, 0x33, 0x70, 0xee,
0x05, 0x4f, 0x3e, 0x63, 0xf6, 0x7f, 0x8d, 0xa1, 0x17, 0xa5, 0x9f, 0xd5, 0xd8, 0xe0, 0xb5, 0x01,
0xb6, 0xd9, 0xe0, 0x3d, 0x68, 0x69, 0xfe, 0xac, 0x09, 0xf2, 0x50, 0xd0, 0x9e, 0x58, 0xcc, 0x28,
0x4c, 0xc0, 0x49, 0x8b, 0x87, 0x15, 0x57, 0xa4, 0xe1, 0xa1, 0xc0, 0x9e, 0x58, 0xac, 0xd6, 0x78,
0x0c, 0x36, 0x57, 0x4a, 0x2a, 0xd2, 0xf4, 0x50, 0xd0, 0x1d, 0x1d, 0xfe, 0xb1, 0x99, 0x8e, 0x19,
0x9b, 0xb1, 0x89, 0xc5, 0x2a, 0x1a, 0x9f, 0x40, 0x2b, 0x11, 0xb9, 0x26, 0xb6, 0x87, 0x82, 0xce,
0xc8, 0xff, 0x29, 0x85, 0xf1, 0x8c, 0x47, 0x9a, 0xc7, 0x73, 0xad, 0x44, 0xba, 0x2e, 0x3f, 0xad,
0x24, 0x30, 0x85, 0xfe, 0x63, 0x21, 0x35, 0x5f, 0x3e, 0x6d, 0x78, 0xba, 0xcc, 0x94, 0x48, 0xb5,
0x48, 0xd7, 0xc4, 0xf5, 0x50, 0xf0, 0x8f, 0xfd, 0x37, 0xa7, 0xc5, 0x86, 0xa7, 0x37, 0xf5, 0xc1,
0x1f, 0x82, 0x6d, 0xba, 0x71, 0x07, 0xdc, 0xdb, 0xf0, 0x2a, 0x9c, 0x2d, 0xc2, 0x9e, 0x55, 0x8a,
0xeb, 0xe9, 0x7c, 0x3e, 0x0d, 0x2f, 0x7b, 0xe8, 0xdc, 0x05, 0x7b, 0x1b, 0x25, 0x05, 0xf7, 0x0f,
0xa0, 0xfb, 0xb5, 0x15, 0x13, 0x70, 0x73, 0x33, 0x55, 0xbf, 0xba, 0xcd, 0x76, 0x72, 0xe5, 0x98,
0x17, 0x3f, 0xfe, 0x08, 0x00, 0x00, 0xff, 0xff, 0x8d, 0x62, 0x58, 0xc4, 0x08, 0x02, 0x00, 0x00,
}

View File

@ -0,0 +1,42 @@
/*
Copyright 2016 Google Inc. All Rights Reserved.
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.
*/
syntax = "proto3";
package devtools.buildozer;
message Output {
repeated Record records = 1;
message Record {
repeated Field fields = 1;
message Field {
oneof value {
string text = 1;
int32 number = 2;
ERROR error = 3;
RepeatedString list = 5;
}
// Used internally by Buildozer to decide whether a field should be quoted
// when printing. This does not affect the contents of 'value'.
bool quote_when_printing = 7;
enum ERROR {
UNKNOWN = 0;
MISSING = 1;
}
}
}
}
message RepeatedString {
repeated string strings = 1;
}

View File

@ -0,0 +1,24 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["build.gen.pb.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/bazelbuild/buildtools/build_proto",
importpath = "github.com/bazelbuild/buildtools/build_proto",
visibility = ["//visibility:public"],
deps = ["//vendor/github.com/golang/protobuf/proto:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "go_default_library",
srcs = ["main.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/bazelbuild/buildtools/buildozer",
importpath = "github.com/bazelbuild/buildtools/buildozer",
visibility = ["//visibility:private"],
deps = [
"//vendor/github.com/bazelbuild/buildtools/edit:go_default_library",
"//vendor/github.com/bazelbuild/buildtools/tables:go_default_library",
],
)
go_binary(
name = "buildozer",
embed = [":go_default_library"],
tags = ["manual"],
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,266 @@
# Buildozer
Buildozer is a command line tool to rewrite multiple
[Bazel](https://github.com/bazelbuild/bazel) BUILD files using
standard commands.
## Dependencies
1. Protobuf go runtime: to download
`go get -u github.com/golang/protobuf/{proto,protoc-gen-go}`
## Installation
1. Change directory to the buildifier/buildozer
```bash
gopath=$(go env GOPATH)
cd $gopath/src/github.com/bazelbuild/buildtools/buildozer
```
2. Install
```bash
go install
```
## Usage
```shell
buildozer [OPTIONS] ['command args' | -f FILE ] label-list
```
Here, `label-list` is a comma-separated list of Bazel labels, for example
`//path/to/pkg1:rule1, //path/to/pkg2:rule2`. Buildozer reads commands from
`FILE` (`-` for stdin (format: `|`-separated command line arguments to buildozer,
excluding flags))
You should specify at least one command and one target. Buildozer will execute
all commands on all targets. Commands are executed in order, files are processed
in parallel.
### Targets
Targets look like Bazel labels, but there can be some differences in presence of
macros.
* Use the label notation to refer to a rule: `//buildtools/buildozer:edit`
* Use the `__pkg__` suffix to refer to the package declaration:
`//buildtools/buildozer:__pkg__`
* Use an asterisk to refer to all rules in a file: `//pkg:*`
* Use `...` to refer to all descendant BUILD files in a directory: `//pkg/...:*`
* Use percent to refer to all rules of a certain kind: `//pkg:%java_library`
* Use percent-and-number to refer to a rule that begins at a certain line:
`//pkg:%123`.
* Use `-` for the package name if you want to process standard input stream
instead of a file: `-:all_tests`.
### Options
OPTIONS include the following options:
* `-stdout` : write changed BUILD file to stdout
* `-buildifier` : format output using a specific buildifier binary. If empty, use built-in formatter.
* `-k` : apply all commands, even if there are failures
* `-quiet` : suppress informational messages
* `-shorten_labels` : convert added labels to short form, e.g. //foo:bar => :bar
* `-types`: Filter the targets, keeping only those of the given types, e.g.
`buildozer -types go_library,go_binary 'print rule' '//buildtools/buildozer:*'`
* `-eol-comments=false`: When adding new comments, put them on a separate line.
See `buildozer -help` for the full list.
### Edit commands
Buildozer supports the following commands(`'command args'`):
* `add <attr> <value(s)>`: Adds value(s) to a list attribute of a rule. If a
value is already present in the list, it is not added.
* `new_load <path> <symbol(s)>`: Add a load statement for the given path,
importing the symbols. Before using this, make sure to run
`buildozer 'fix movePackageToTop'`. Afterwards, consider running
`buildozer 'fix unusedLoads'`.
* `comment <attr>? <value>? <comment>`: Add a comment to a rule, an attribute,
or a specific value in a list. Spaces in the comment should be escaped with
backslashes.
* `print_comment <attr>? <value>?`
* `delete`: Delete a rule.
* `fix <fix(es)>?`: Apply a fix.
* `move <old_attr> <new_attr> <value(s)>`: Moves `value(s)` from the list `old_attr`
to the list `new_attr`. The wildcard `*` matches all values.
* `new <rule_kind> <rule_name> [(before|after) <relative_rule_name>]`: Add a
new rule at the end of the BUILD file (before/after `<relative_rule>`).
* `print <attr(s)>`
* `remove <attr> <value(s)>`: Removes `value(s)` from the list `attr`. The
wildcard `*` matches all attributes. Lists containing none of the `value(s)` are
not modified.
* `rename <old_attr> <new_attr>`: Rename the `old_attr` to `new_attr` which must
not yet exist.
* `replace <attr> <old_value> <new_value>`: Replaces `old_value` with `new_value`
in the list `attr`. Wildcard `*` matches all attributes. Lists not containing
`old_value` are not modified.
* `set <attr> <value(s)>`: Sets the value of an attribute. If the attribute
was already present, its old value is replaced.
* `set_if_absent <attr> <value(s)>`: Sets the value of an attribute. If the
attribute was already present, no action is taken.
* `set kind <value>`: Set the target type to value.
* `copy <attr> <from_rule>`: Copies the value of `attr` between rules. If it
exists in the `to_rule`, it will be overwritten.
* `copy_no_overwrite <attr> <from_rule>`: Copies the value of `attr` between
rules. If it exists in the `to_rule`, no action is taken.
Here, `<attr>` represents an attribute (being `add`ed/`rename`d/`delete`d etc.),
e.g.: `srcs`, `<value(s)>` represents values of the attribute and so on.
A '?' indicates that the preceding argument is optional.
The fix command without a fix specified applied to all eligible fixes.
Use `//path/to/pkg:__pkg__` as label for file level changes like `new_load` and
`new_rule`.
A transformation can be applied to all rules of a particular kind by using
`%rule_kind` at the end of the label(see examples below).
#### Examples
```bash
# Edit //pkg:rule and //pkg:rule2, and add a dependency on //base
buildozer 'add deps //base' //pkg:rule //pkg:rule2
# A load for a skylark file in //pkg
buildozer 'new_load /tools/build_rules/build_test build_test' //pkg:__pkg__
# Change the default_visibility to public for the package //pkg
buildozer 'set default_visibility //visibility:public' //pkg:__pkg__
# Change all gwt_module targets to java_library in the package //pkg
buildozer 'set kind java_library' //pkg:%gwt_module
# Replace the dependency on pkg_v1 with a dependency on pkg_v2
buildozer 'replace deps //pkg_v1 //pkg_v2' //pkg:rule
# Delete the dependency on foo in every cc_library in the package
buildozer 'remove deps foo' //pkg:%cc_library
# Delete the testonly attribute in every rule in the package
buildozer 'remove testonly' '//pkg:*'
# Add a comment to the timeout attribute of //pkg:rule_test
buildozer 'comment timeout Delete\ this\ after\ 2015-12-31.' //pkg:rule_test
# Add a new rule at the end of the file
buildozer 'new java_library foo' //pkg:__pkg__
# Add a cc_binary rule named new_bin before the rule named tests
buildozer 'new cc_binary new_bin before tests' //:__pkg__
# Copy an attribute from `protolib` to `py_protolib`.
buildozer 'copy testonly protolib' //pkg:py_protolib
# Set two attributes in the same rule
buildozer 'set compile 1' 'set srcmap 1' //pkg:rule
# Make a default explicit in all soy_js rules in a package
buildozer 'set_if_absent allowv1syntax 1' //pkg:%soy_js
# Add an attribute new_attr with value "def_val" to all cc_binary rules
# Note that special characters will automatically be escaped in the string
buildozer 'add new_attr def_val' //:%cc_binary
```
### Print commands
They work just like the edit commands. Expect a return code of 3 as they are not
modifying any file.
* `print <attribute(s)>`: For each target, prints the value of the attributes
(see below).
* `print_comment <attr>? <value>?`: Prints a comment associated with a rule,
an attribute or a specific value in a list.
The print command prints the value of the attributes. If a target doesn't have
the attribute, a warning is printed on stderr.
There are some special attributes in the `print` command:
* `kind`: displays the name of the function
* `label`: the fully qualified label
* `rule`: the entire rule definition
* `startline`: the line number on which the rule begins in the BUILD file
* `endline`: the line number on which the rule ends in the BUILD file
#### Examples
```shell
# Print the kind of a target
buildozer 'print kind' base # output: cc_library
# Print the name of all cc_library in //base
buildozer 'print name' base:%cc_library
# Get the default visibility of the //base package
buildozer 'print default_visibility' base:%package
# Print labels of cc_library targets in //base that have a deps attribute
buildozer 'print label deps' base:%cc_library 2>/dev/null | cut -d' ' -f1
# Print the list of labels in //base that explicitly set the testonly attribute:
buildozer 'print label testonly' 'base:*' 2>/dev/null
# Print the entire definition (including comments) of the //base:heapcheck rule:
buildozer 'print rule' //base:heapcheck
```
## Converting labels
Buildozer works at the syntax-level. It doesn't evaluate the BUILD files. If you
need to query the information Bazel has, please use `bazel query`. If you have a
list of Bazel labels, chances are that some of them are generated by BUILD
extensions. Labels in Buildozer are slightly different from labels in Bazel.
Bazel cares about the generated code, while Buildozer looks at the BUILD file
before macro expansion.
To see the expanded BUILD files, try:
```shell
bazel query --output=build //path/to/BUILD
```
## Do multiple changes at once
Use `buildozer -f <file>` to load a list of commands from a file. The usage is
just like arguments on the command-line, except that arguments are separated by
`|`.
```shell
$ cat /tmp/cmds
new cc_library foo|//buildtools/buildozer/BUILD
add deps //base //strings|add srcs foo.cc|//buildtools/buildozer:foo
add deps :foo|//buildtools/buildozer
$ buildozer -f /tmp/cmds
fixed //buildtools/buildozer/BUILD
```
The list of commands will typically be generated and can be large. This is
efficient: Commands are grouped so that each file is modified once. Files are
processed in parallel.
## Error code
The return code is:
* `0` on success, if changes were made
* `1` when there is a usage error
* `2` when at least one command has failed
* `3` on success, when no changes were made
## Source Structure
* `buildozer/main.go` : Entry point for the buildozer binary
* `edit/buildozer.go` : Implementation of functions for the buildozer commands
* `edit/edit.go`: Library functions to perform various operations on ASTs. These
* functions are called by the impl functions in buildozer.go
* `edit/fix.go`: Functions for various fixes for the `buildozer 'fix <fix(es)>'`
command, like cleaning unused loads, changing labels to canonical notation, etc.
* `edit/types.go`: Type information for attributes

View File

@ -0,0 +1,87 @@
/*
Copyright 2016 Google Inc. All Rights Reserved.
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.
*/
// Entry-point for Buildozer binary.
package main
import (
"flag"
"fmt"
"os"
"strings"
"github.com/bazelbuild/buildtools/edit"
"github.com/bazelbuild/buildtools/tables"
)
var (
stdout = flag.Bool("stdout", false, "write changed BUILD file to stdout")
buildifier = flag.String("buildifier", "", "format output using a specific buildifier binary. If empty, use built-in formatter")
parallelism = flag.Int("P", 0, "number of cores to use for concurrent actions")
numio = flag.Int("numio", 200, "number of concurrent actions")
commandsFile = flag.String("f", "", "file name to read commands from, use '-' for stdin (format:|-separated command line arguments to buildozer, excluding flags)")
keepGoing = flag.Bool("k", false, "apply all commands, even if there are failures")
filterRuleTypes = stringList("types", "comma-separated list of rule types to change, the default empty list means all rules")
preferEOLComments = flag.Bool("eol-comments", true, "when adding a new comment, put it on the same line if possible")
rootDir = flag.String("root_dir", "", "If present, use this folder rather than $PWD to find the root directory.")
quiet = flag.Bool("quiet", false, "suppress informational messages")
editVariables = flag.Bool("edit-variables", false, "For attributes that simply assign a variable (e.g. hdrs = LIB_HDRS), edit the build variable instead of appending to the attribute.")
isPrintingProto = flag.Bool("output_proto", false, "output serialized devtools.buildozer.Output protos instead of human-readable strings.")
tablesPath = flag.String("tables", "", "path to JSON file with custom table definitions which will replace the built-in tables")
shortenLabelsFlag = flag.Bool("shorten_labels", true, "convert added labels to short form, e.g. //foo:bar => :bar")
deleteWithComments = flag.Bool("delete_with_comments", true, "If a list attribute should be deleted even if there is a comment attached to it")
)
func stringList(name, help string) func() []string {
f := flag.String(name, "", help)
return func() []string {
if *f == "" {
return nil
}
res := strings.Split(*f, ",")
for i := range res {
res[i] = strings.TrimSpace(res[i])
}
return res
}
}
func main() {
flag.Parse()
if *tablesPath != "" {
if err := tables.ParseAndUpdateJSONDefinitions(*tablesPath, false); err != nil {
fmt.Fprintf(os.Stderr, "buildifier: failed to parse %s for -tables: %s\n", *tablesPath, err)
os.Exit(2)
}
}
edit.ShortenLabelsFlag = *shortenLabelsFlag
edit.DeleteWithComments = *deleteWithComments
edit.Opts = edit.Options{
Stdout: *stdout,
Buildifier: *buildifier,
Parallelism: *parallelism,
NumIO: *numio,
CommandsFile: *commandsFile,
KeepGoing: *keepGoing,
FilterRuleTypes: filterRuleTypes(),
PreferEOLComments: *preferEOLComments,
RootDir: *rootDir,
Quiet: *quiet,
EditVariables: *editVariables,
IsPrintingProto: *isPrintingProto,
}
os.Exit(edit.Buildozer(flag.Args()))
}

37
vendor/github.com/bazelbuild/buildtools/edit/BUILD generated vendored Normal file
View File

@ -0,0 +1,37 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"buildozer.go",
"edit.go",
"fix.go",
"types.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/bazelbuild/buildtools/edit",
importpath = "github.com/bazelbuild/buildtools/edit",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/bazelbuild/buildtools/api_proto:go_default_library",
"//vendor/github.com/bazelbuild/buildtools/build:go_default_library",
"//vendor/github.com/bazelbuild/buildtools/build_proto:go_default_library",
"//vendor/github.com/bazelbuild/buildtools/file:go_default_library",
"//vendor/github.com/bazelbuild/buildtools/lang:go_default_library",
"//vendor/github.com/bazelbuild/buildtools/wspace:go_default_library",
"//vendor/github.com/golang/protobuf/proto:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,976 @@
/*
Copyright 2016 Google Inc. All Rights Reserved.
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.
*/
// Buildozer is a tool for programatically editing BUILD files.
package edit
import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
apipb "github.com/bazelbuild/buildtools/api_proto"
"github.com/bazelbuild/buildtools/build"
"github.com/bazelbuild/buildtools/file"
"github.com/golang/protobuf/proto"
)
// Options represents choices about how buildozer should behave.
type Options struct {
Stdout bool // write changed BUILD file to stdout
Buildifier string // path to buildifier binary
Parallelism int // number of cores to use for concurrent actions
NumIO int // number of concurrent actions
CommandsFile string // file name to read commands from, use '-' for stdin (format:|-separated command line arguments to buildozer, excluding flags
KeepGoing bool // apply all commands, even if there are failures
FilterRuleTypes []string // list of rule types to change, empty means all
PreferEOLComments bool // when adding a new comment, put it on the same line if possible
RootDir string // If present, use this folder rather than $PWD to find the root dir
Quiet bool // suppress informational messages.
EditVariables bool // for attributes that simply assign a variable (e.g. hdrs = LIB_HDRS), edit the build variable instead of appending to the attribute.
IsPrintingProto bool // output serialized devtools.buildozer.Output protos instead of human-readable strings
}
// Opts represents the options to be used by buildozer, and can be overriden before calling Buildozer.
var Opts = Options{NumIO: 200, PreferEOLComments: true}
// Usage is a user-overriden func to print the program usage.
var Usage = func() {}
var fileModified = false // set to true when a file has been fixed
const stdinPackageName = "-" // the special package name to represent stdin
// CmdEnvironment stores the information the commands below have access to.
type CmdEnvironment struct {
File *build.File // the AST
Rule *build.Rule // the rule to modify
Vars map[string]*build.BinaryExpr // global variables set in the build file
Pkg string // the full package name
Args []string // the command-line arguments
output *apipb.Output_Record // output proto, stores whatever a command wants to print
}
// The cmdXXX functions implement the various commands.
func cmdAdd(env CmdEnvironment) (*build.File, error) {
attr := env.Args[0]
for _, val := range env.Args[1:] {
if IsIntList(attr) {
AddValueToListAttribute(env.Rule, attr, env.Pkg, &build.LiteralExpr{Token: val}, &env.Vars)
continue
}
strVal := &build.StringExpr{Value: ShortenLabel(val, env.Pkg)}
AddValueToListAttribute(env.Rule, attr, env.Pkg, strVal, &env.Vars)
}
return env.File, nil
}
func cmdComment(env CmdEnvironment) (*build.File, error) {
// The comment string is always the last argument in the list.
str := env.Args[len(env.Args)-1]
str = strings.Replace(str, "\\n", "\n", -1)
// Multiline comments should go on a separate line.
fullLine := !Opts.PreferEOLComments || strings.Contains(str, "\n")
str = strings.Replace("# "+str, "\n", "\n# ", -1)
comment := []build.Comment{build.Comment{Token: str}}
// The comment might be attached to a rule, an attribute, or a value in a list,
// depending on how many arguments are passed.
switch len(env.Args) {
case 1: // Attach to a rule
env.Rule.Call.Comments.Before = comment
case 2: // Attach to an attribute
if attr := env.Rule.AttrDefn(env.Args[0]); attr != nil {
if fullLine {
attr.X.Comment().Before = comment
} else {
attr.Y.Comment().Suffix = comment
}
}
case 3: // Attach to a specific value in a list
if attr := env.Rule.Attr(env.Args[0]); attr != nil {
if expr := ListFind(attr, env.Args[1], env.Pkg); expr != nil {
if fullLine {
expr.Comments.Before = comment
} else {
expr.Comments.Suffix = comment
}
}
}
default:
panic("cmdComment")
}
return env.File, nil
}
// commentsText concatenates comments into a single line.
func commentsText(comments []build.Comment) string {
var segments []string
for _, comment := range comments {
token := comment.Token
if strings.HasPrefix(token, "#") {
token = token[1:]
}
segments = append(segments, strings.TrimSpace(token))
}
return strings.Replace(strings.Join(segments, " "), "\n", " ", -1)
}
func cmdPrintComment(env CmdEnvironment) (*build.File, error) {
attrError := func() error {
return fmt.Errorf("rule \"//%s:%s\" has no attribute \"%s\"", env.Pkg, env.Rule.Name(), env.Args[0])
}
switch len(env.Args) {
case 0: // Print rule comment.
env.output.Fields = []*apipb.Output_Record_Field{
&apipb.Output_Record_Field{Value: &apipb.Output_Record_Field_Text{commentsText(env.Rule.Call.Comments.Before)}},
}
case 1: // Print attribute comment.
attr := env.Rule.AttrDefn(env.Args[0])
if attr == nil {
return nil, attrError()
}
comments := append(attr.Before, attr.Suffix...)
env.output.Fields = []*apipb.Output_Record_Field{
&apipb.Output_Record_Field{Value: &apipb.Output_Record_Field_Text{commentsText(comments)}},
}
case 2: // Print comment of a specific value in a list.
attr := env.Rule.Attr(env.Args[0])
if attr == nil {
return nil, attrError()
}
value := env.Args[1]
expr := ListFind(attr, value, env.Pkg)
if expr == nil {
return nil, fmt.Errorf("attribute \"%s\" has no value \"%s\"", env.Args[0], value)
}
comments := append(expr.Comments.Before, expr.Comments.Suffix...)
env.output.Fields = []*apipb.Output_Record_Field{
&apipb.Output_Record_Field{Value: &apipb.Output_Record_Field_Text{commentsText(comments)}},
}
default:
panic("cmdPrintComment")
}
return nil, nil
}
func cmdDelete(env CmdEnvironment) (*build.File, error) {
return DeleteRule(env.File, env.Rule), nil
}
func cmdMove(env CmdEnvironment) (*build.File, error) {
oldAttr := env.Args[0]
newAttr := env.Args[1]
if len(env.Args) == 3 && env.Args[2] == "*" {
if err := MoveAllListAttributeValues(env.Rule, oldAttr, newAttr, env.Pkg, &env.Vars); err != nil {
return nil, err
}
return env.File, nil
}
fixed := false
for _, val := range env.Args[2:] {
if deleted := ListAttributeDelete(env.Rule, oldAttr, val, env.Pkg); deleted != nil {
AddValueToListAttribute(env.Rule, newAttr, env.Pkg, deleted, &env.Vars)
fixed = true
}
}
if fixed {
return env.File, nil
}
return nil, nil
}
func cmdNew(env CmdEnvironment) (*build.File, error) {
kind := env.Args[0]
name := env.Args[1]
addAtEOF, insertionIndex, err := findInsertionIndex(env)
if err != nil {
return nil, err
}
if FindRuleByName(env.File, name) != nil {
return nil, fmt.Errorf("rule '%s' already exists", name)
}
call := &build.CallExpr{X: &build.LiteralExpr{Token: kind}}
rule := &build.Rule{Call: call}
rule.SetAttr("name", &build.StringExpr{Value: name})
if addAtEOF {
env.File.Stmt = InsertAfterLastOfSameKind(env.File.Stmt, rule.Call)
} else {
env.File.Stmt = InsertAfter(insertionIndex, env.File.Stmt, call)
}
return env.File, nil
}
// findInsertionIndex is used by cmdNew to find the place at which to insert the new rule.
func findInsertionIndex(env CmdEnvironment) (bool, int, error) {
if len(env.Args) < 4 {
return true, 0, nil
}
relativeToRuleName := env.Args[3]
ruleIdx := IndexOfRuleByName(env.File, relativeToRuleName)
if ruleIdx == -1 {
return true, 0, nil
}
switch env.Args[2] {
case "before":
return false, ruleIdx - 1, nil
case "after":
return false, ruleIdx, nil
default:
return true, 0, fmt.Errorf("Unknown relative operator '%s'; allowed: 'before', 'after'", env.Args[1])
}
}
func cmdNewLoad(env CmdEnvironment) (*build.File, error) {
env.File.Stmt = InsertLoad(env.File.Stmt, env.Args)
return env.File, nil
}
func cmdPrint(env CmdEnvironment) (*build.File, error) {
format := env.Args
if len(format) == 0 {
format = []string{"name", "kind"}
}
fields := make([]*apipb.Output_Record_Field, len(format))
for i, str := range format {
value := env.Rule.Attr(str)
if str == "kind" {
fields[i] = &apipb.Output_Record_Field{Value: &apipb.Output_Record_Field_Text{env.Rule.Kind()}}
} else if str == "label" {
if env.Rule.Attr("name") != nil {
fields[i] = &apipb.Output_Record_Field{Value: &apipb.Output_Record_Field_Text{fmt.Sprintf("//%s:%s", env.Pkg, env.Rule.Name())}}
} else {
return nil, nil
}
} else if str == "rule" {
fields[i] = &apipb.Output_Record_Field{
Value: &apipb.Output_Record_Field_Text{build.FormatString(env.Rule.Call)},
}
} else if str == "startline" {
fields[i] = &apipb.Output_Record_Field{Value: &apipb.Output_Record_Field_Number{int32(env.Rule.Call.ListStart.Line)}}
} else if str == "endline" {
fields[i] = &apipb.Output_Record_Field{Value: &apipb.Output_Record_Field_Number{int32(env.Rule.Call.End.Pos.Line)}}
} else if value == nil {
fmt.Fprintf(os.Stderr, "rule \"//%s:%s\" has no attribute \"%s\"\n",
env.Pkg, env.Rule.Name(), str)
fields[i] = &apipb.Output_Record_Field{Value: &apipb.Output_Record_Field_Error{Error: apipb.Output_Record_Field_MISSING}}
} else if lit, ok := value.(*build.LiteralExpr); ok {
fields[i] = &apipb.Output_Record_Field{Value: &apipb.Output_Record_Field_Text{lit.Token}}
} else if string, ok := value.(*build.StringExpr); ok {
fields[i] = &apipb.Output_Record_Field{
Value: &apipb.Output_Record_Field_Text{string.Value},
QuoteWhenPrinting: true,
}
} else if strList := env.Rule.AttrStrings(str); strList != nil {
fields[i] = &apipb.Output_Record_Field{Value: &apipb.Output_Record_Field_List{List: &apipb.RepeatedString{Strings: strList}}}
} else {
// Some other Expr we haven't listed above. Just print it.
fields[i] = &apipb.Output_Record_Field{Value: &apipb.Output_Record_Field_Text{build.FormatString(value)}}
}
}
env.output.Fields = fields
return nil, nil
}
func attrKeysForPattern(rule *build.Rule, pattern string) []string {
if pattern == "*" {
return rule.AttrKeys()
}
return []string{pattern}
}
func cmdRemove(env CmdEnvironment) (*build.File, error) {
if len(env.Args) == 1 { // Remove the attribute
if env.Rule.DelAttr(env.Args[0]) != nil {
return env.File, nil
}
} else { // Remove values in the attribute.
fixed := false
for _, key := range attrKeysForPattern(env.Rule, env.Args[0]) {
for _, val := range env.Args[1:] {
ListAttributeDelete(env.Rule, key, val, env.Pkg)
fixed = true
}
}
if fixed {
return env.File, nil
}
}
return nil, nil
}
func cmdRename(env CmdEnvironment) (*build.File, error) {
oldAttr := env.Args[0]
newAttr := env.Args[1]
if err := RenameAttribute(env.Rule, oldAttr, newAttr); err != nil {
return nil, err
}
return env.File, nil
}
func cmdReplace(env CmdEnvironment) (*build.File, error) {
oldV := env.Args[1]
newV := env.Args[2]
for _, key := range attrKeysForPattern(env.Rule, env.Args[0]) {
attr := env.Rule.Attr(key)
if e, ok := attr.(*build.StringExpr); ok {
if LabelsEqual(e.Value, oldV, env.Pkg) {
env.Rule.SetAttr(key, getAttrValueExpr(key, []string{newV}))
}
} else {
ListReplace(attr, oldV, newV, env.Pkg)
}
}
return env.File, nil
}
func cmdSet(env CmdEnvironment) (*build.File, error) {
attr := env.Args[0]
args := env.Args[1:]
if attr == "kind" {
env.Rule.SetKind(args[0])
} else {
env.Rule.SetAttr(attr, getAttrValueExpr(attr, args))
}
return env.File, nil
}
func cmdSetIfAbsent(env CmdEnvironment) (*build.File, error) {
attr := env.Args[0]
args := env.Args[1:]
if attr == "kind" {
return nil, fmt.Errorf("setting 'kind' is not allowed for set_if_absent. Got %s", env.Args)
}
if env.Rule.Attr(attr) == nil {
env.Rule.SetAttr(attr, getAttrValueExpr(attr, args))
}
return env.File, nil
}
func getAttrValueExpr(attr string, args []string) build.Expr {
switch {
case attr == "kind":
return nil
case IsIntList(attr):
var list []build.Expr
for _, i := range args {
list = append(list, &build.LiteralExpr{Token: i})
}
return &build.ListExpr{List: list}
case IsList(attr) && !(len(args) == 1 && strings.HasPrefix(args[0], "glob(")):
var list []build.Expr
for _, i := range args {
list = append(list, &build.StringExpr{Value: i})
}
return &build.ListExpr{List: list}
case IsString(attr):
return &build.StringExpr{Value: args[0]}
default:
return &build.LiteralExpr{Token: args[0]}
}
}
func cmdCopy(env CmdEnvironment) (*build.File, error) {
attrName := env.Args[0]
from := env.Args[1]
return copyAttributeBetweenRules(env, attrName, from)
}
func cmdCopyNoOverwrite(env CmdEnvironment) (*build.File, error) {
attrName := env.Args[0]
from := env.Args[1]
if env.Rule.Attr(attrName) != nil {
return env.File, nil
}
return copyAttributeBetweenRules(env, attrName, from)
}
func copyAttributeBetweenRules(env CmdEnvironment, attrName string, from string) (*build.File, error) {
fromRule := FindRuleByName(env.File, from)
if fromRule == nil {
return nil, fmt.Errorf("could not find rule '%s'", from)
}
attr := fromRule.Attr(attrName)
if attr == nil {
return nil, fmt.Errorf("rule '%s' does not have attribute '%s'", from, attrName)
}
ast, err := build.Parse("" /* filename */, []byte(build.FormatString(attr)))
if err != nil {
return nil, fmt.Errorf("could not parse attribute value %v", build.FormatString(attr))
}
env.Rule.SetAttr(attrName, ast.Stmt[0])
return env.File, nil
}
func cmdFix(env CmdEnvironment) (*build.File, error) {
// Fix the whole file
if env.Rule.Kind() == "package" {
return FixFile(env.File, env.Pkg, env.Args), nil
}
// Fix a specific rule
return FixRule(env.File, env.Pkg, env.Rule, env.Args), nil
}
// CommandInfo provides a command function and info on incoming arguments.
type CommandInfo struct {
Fn func(CmdEnvironment) (*build.File, error)
MinArg int
MaxArg int
Template string
}
// AllCommands associates the command names with their function and number
// of arguments.
var AllCommands = map[string]CommandInfo{
"add": {cmdAdd, 2, -1, "<attr> <value(s)>"},
"new_load": {cmdNewLoad, 1, -1, "<path> <symbol(s)>"},
"comment": {cmdComment, 1, 3, "<attr>? <value>? <comment>"},
"print_comment": {cmdPrintComment, 0, 2, "<attr>? <value>?"},
"delete": {cmdDelete, 0, 0, ""},
"fix": {cmdFix, 0, -1, "<fix(es)>?"},
"move": {cmdMove, 3, -1, "<old_attr> <new_attr> <value(s)>"},
"new": {cmdNew, 2, 4, "<rule_kind> <rule_name> [(before|after) <relative_rule_name>]"},
"print": {cmdPrint, 0, -1, "<attribute(s)>"},
"remove": {cmdRemove, 1, -1, "<attr> <value(s)>"},
"rename": {cmdRename, 2, 2, "<old_attr> <new_attr>"},
"replace": {cmdReplace, 3, 3, "<attr> <old_value> <new_value>"},
"set": {cmdSet, 2, -1, "<attr> <value(s)>"},
"set_if_absent": {cmdSetIfAbsent, 2, -1, "<attr> <value(s)>"},
"copy": {cmdCopy, 2, 2, "<attr> <from_rule>"},
"copy_no_overwrite": {cmdCopyNoOverwrite, 2, 2, "<attr> <from_rule>"},
}
func expandTargets(f *build.File, rule string) ([]*build.Rule, error) {
if r := FindRuleByName(f, rule); r != nil {
return []*build.Rule{r}, nil
} else if r := FindExportedFile(f, rule); r != nil {
return []*build.Rule{r}, nil
} else if rule == "all" || rule == "*" {
// "all" is a valid name, it is a wildcard only if no such rule is found.
return f.Rules(""), nil
} else if strings.HasPrefix(rule, "%") {
// "%java_library" will match all java_library functions in the package
// "%<LINENUM>" will match the rule which begins at LINENUM.
// This is for convenience, "%" is not a valid character in bazel targets.
kind := rule[1:]
if linenum, err := strconv.Atoi(kind); err == nil {
if r := f.RuleAt(linenum); r != nil {
return []*build.Rule{r}, nil
}
} else {
return f.Rules(kind), nil
}
}
return nil, fmt.Errorf("rule '%s' not found", rule)
}
func filterRules(rules []*build.Rule) (result []*build.Rule) {
if len(Opts.FilterRuleTypes) == 0 {
return rules
}
for _, rule := range rules {
acceptableType := false
for _, filterType := range Opts.FilterRuleTypes {
if rule.Kind() == filterType {
acceptableType = true
break
}
}
if acceptableType || rule.Kind() == "package" {
result = append(result, rule)
}
}
return
}
// command contains a list of tokens that describe a buildozer command.
type command struct {
tokens []string
}
// checkCommandUsage checks the number of argument of a command.
// It prints an error and usage when it is not valid.
func checkCommandUsage(name string, cmd CommandInfo, count int) {
if count >= cmd.MinArg && (cmd.MaxArg == -1 || count <= cmd.MaxArg) {
return
}
if count < cmd.MinArg {
fmt.Fprintf(os.Stderr, "Too few arguments for command '%s', expected at least %d.\n",
name, cmd.MinArg)
} else {
fmt.Fprintf(os.Stderr, "Too many arguments for command '%s', expected at most %d.\n",
name, cmd.MaxArg)
}
Usage()
}
// Match text that only contains spaces if they're escaped with '\'.
var spaceRegex = regexp.MustCompile(`(\\ |[^ ])+`)
// SplitOnSpaces behaves like strings.Fields, except that spaces can be escaped.
// " some dummy\\ string" -> ["some", "dummy string"]
func SplitOnSpaces(input string) []string {
result := spaceRegex.FindAllString(input, -1)
for i, s := range result {
result[i] = strings.Replace(s, `\ `, " ", -1)
}
return result
}
// parseCommands parses commands and targets they should be applied on from
// a list of arguments.
// Each argument can be either:
// - a command (as defined by AllCommands) and its parameters, separated by
// whitespace
// - a target all commands that are parsed during one call to parseCommands
// should be applied on
func parseCommands(args []string) (commands []command, targets []string) {
for _, arg := range args {
commandTokens := SplitOnSpaces(arg)
cmd, found := AllCommands[commandTokens[0]]
if found {
checkCommandUsage(commandTokens[0], cmd, len(commandTokens)-1)
commands = append(commands, command{commandTokens})
} else {
targets = append(targets, arg)
}
}
return
}
// commandsForTarget contains commands to be executed on the given target.
type commandsForTarget struct {
target string
commands []command
}
// commandsForFile contains the file name and all commands that should be
// applied on that file, indexed by their target.
type commandsForFile struct {
file string
commands []commandsForTarget
}
// commandError returns an error that formats 'err' in the context of the
// commands to be executed on the given target.
func commandError(commands []command, target string, err error) error {
return fmt.Errorf("error while executing commands %s on target %s: %s", commands, target, err)
}
// rewriteResult contains the outcome of applying fixes to a single file.
type rewriteResult struct {
file string
errs []error
modified bool
records []*apipb.Output_Record
}
// getGlobalVariables returns the global variable assignments in the provided list of expressions.
// That is, for each variable assignment of the form
// a = v
// vars["a"] will contain the BinaryExpr whose Y value is the assignment "a = v".
func getGlobalVariables(exprs []build.Expr) (vars map[string]*build.BinaryExpr) {
vars = make(map[string]*build.BinaryExpr)
for _, expr := range exprs {
if binExpr, ok := expr.(*build.BinaryExpr); ok {
if binExpr.Op != "=" {
continue
}
if lhs, ok := binExpr.X.(*build.LiteralExpr); ok {
vars[lhs.Token] = binExpr
}
}
}
return vars
}
// When checking the filesystem, we need to look for any of the
// possible buildFileNames. For historical reasons, the
// parts of the tool that generate paths that we may want to examine
// continue to assume that build files are all named "BUILD".
var buildFileNames = [...]string{"BUILD.bazel", "BUILD", "BUCK"}
var buildFileNamesSet = map[string]bool{
"BUILD.bazel": true,
"BUILD": true,
"BUCK": true,
}
// rewrite parses the BUILD file for the given file, transforms the AST,
// and write the changes back in the file (or on stdout).
func rewrite(commandsForFile commandsForFile) *rewriteResult {
name := commandsForFile.file
var data []byte
var err error
var fi os.FileInfo
records := []*apipb.Output_Record{}
if name == stdinPackageName { // read on stdin
data, err = ioutil.ReadAll(os.Stdin)
if err != nil {
return &rewriteResult{file: name, errs: []error{err}}
}
} else {
origName := name
for _, suffix := range buildFileNames {
if strings.HasSuffix(name, "/"+suffix) {
name = strings.TrimSuffix(name, suffix)
break
}
}
for _, suffix := range buildFileNames {
name = name + suffix
data, fi, err = file.ReadFile(name)
if err == nil {
break
}
name = strings.TrimSuffix(name, suffix)
}
if err != nil {
data, fi, err = file.ReadFile(name)
}
if err != nil {
err = errors.New("file not found or not readable")
return &rewriteResult{file: origName, errs: []error{err}}
}
}
f, err := build.Parse(name, data)
if err != nil {
return &rewriteResult{file: name, errs: []error{err}}
}
vars := map[string]*build.BinaryExpr{}
if Opts.EditVariables {
vars = getGlobalVariables(f.Stmt)
}
var errs []error
changed := false
for _, commands := range commandsForFile.commands {
target := commands.target
commands := commands.commands
_, absPkg, rule := InterpretLabelForWorkspaceLocation(Opts.RootDir, target)
_, pkg, _ := ParseLabel(target)
if pkg == stdinPackageName { // Special-case: This is already absolute
absPkg = stdinPackageName
}
targets, err := expandTargets(f, rule)
if err != nil {
cerr := commandError(commands, target, err)
errs = append(errs, cerr)
if !Opts.KeepGoing {
return &rewriteResult{file: name, errs: errs, records: records}
}
}
targets = filterRules(targets)
for _, cmd := range commands {
for _, r := range targets {
cmdInfo := AllCommands[cmd.tokens[0]]
record := &apipb.Output_Record{}
newf, err := cmdInfo.Fn(CmdEnvironment{f, r, vars, absPkg, cmd.tokens[1:], record})
if len(record.Fields) != 0 {
records = append(records, record)
}
if err != nil {
cerr := commandError([]command{cmd}, target, err)
if Opts.KeepGoing {
errs = append(errs, cerr)
} else {
return &rewriteResult{file: name, errs: []error{cerr}, records: records}
}
}
if newf != nil {
changed = true
f = newf
}
}
}
}
if !changed {
return &rewriteResult{file: name, errs: errs, records: records}
}
f = RemoveEmptyPackage(f)
ndata, err := runBuildifier(f)
if err != nil {
return &rewriteResult{file: name, errs: []error{fmt.Errorf("running buildifier: %v", err)}, records: records}
}
if Opts.Stdout || name == stdinPackageName {
os.Stdout.Write(ndata)
return &rewriteResult{file: name, errs: errs, records: records}
}
if bytes.Equal(data, ndata) {
return &rewriteResult{file: name, errs: errs, records: records}
}
if err := EditFile(fi, name); err != nil {
return &rewriteResult{file: name, errs: []error{err}, records: records}
}
if err := file.WriteFile(name, ndata); err != nil {
return &rewriteResult{file: name, errs: []error{err}, records: records}
}
fileModified = true
return &rewriteResult{file: name, errs: errs, modified: true, records: records}
}
// EditFile is a function that does any prework needed before editing a file.
// e.g. "checking out for write" from a locking source control repo.
var EditFile = func(fi os.FileInfo, name string) error {
return nil
}
// runBuildifier formats the build file f.
// Runs Opts.Buildifier if it's non-empty, otherwise uses built-in formatter.
// Opts.Buildifier is useful to force consistency with other tools that call Buildifier.
func runBuildifier(f *build.File) ([]byte, error) {
if Opts.Buildifier == "" {
build.Rewrite(f, nil)
return build.Format(f), nil
}
cmd := exec.Command(Opts.Buildifier)
data := build.Format(f)
cmd.Stdin = bytes.NewBuffer(data)
stdout := bytes.NewBuffer(nil)
stderr := bytes.NewBuffer(nil)
cmd.Stdout = stdout
cmd.Stderr = stderr
err := cmd.Run()
if stderr.Len() > 0 {
return nil, fmt.Errorf("%s", stderr.Bytes())
}
if err != nil {
return nil, err
}
return stdout.Bytes(), nil
}
// Given a target, whose package may contain a trailing "/...", returns all
// extisting BUILD file paths which match the package.
func targetExpressionToBuildFiles(target string) []string {
file, _, _ := InterpretLabelForWorkspaceLocation(Opts.RootDir, target)
if Opts.RootDir == "" {
var err error
if file, err = filepath.Abs(file); err != nil {
fmt.Printf("Cannot make path absolute: %s\n", err.Error())
os.Exit(1)
}
}
if !strings.HasSuffix(file, "/.../BUILD") {
return []string{file}
}
var buildFiles []string
searchDirs := []string{strings.TrimSuffix(file, "/.../BUILD")}
for len(searchDirs) != 0 {
lastIndex := len(searchDirs) - 1
dir := searchDirs[lastIndex]
searchDirs = searchDirs[:lastIndex]
dirFiles, err := ioutil.ReadDir(dir)
if err != nil {
continue
}
for _, dirFile := range dirFiles {
if dirFile.IsDir() {
searchDirs = append(searchDirs, path.Join(dir, dirFile.Name()))
} else if _, ok := buildFileNamesSet[dirFile.Name()]; ok {
buildFiles = append(buildFiles, path.Join(dir, dirFile.Name()))
}
}
}
return buildFiles
}
// appendCommands adds the given commands to be applied to each of the given targets
// via the commandMap.
func appendCommands(commandMap map[string][]commandsForTarget, args []string) {
commands, targets := parseCommands(args)
for _, target := range targets {
if strings.HasSuffix(target, "/BUILD") {
target = strings.TrimSuffix(target, "/BUILD") + ":__pkg__"
}
var buildFiles []string
_, pkg, _ := ParseLabel(target)
if pkg == stdinPackageName {
buildFiles = []string{stdinPackageName}
} else {
buildFiles = targetExpressionToBuildFiles(target)
}
for _, file := range buildFiles {
commandMap[file] = append(commandMap[file], commandsForTarget{target, commands})
}
}
}
func appendCommandsFromFile(commandsByFile map[string][]commandsForTarget, fileName string) {
var reader io.Reader
if Opts.CommandsFile == stdinPackageName {
reader = os.Stdin
} else {
rc := file.OpenReadFile(Opts.CommandsFile)
reader = rc
defer rc.Close()
}
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
line := scanner.Text()
if line == "" {
continue
}
args := strings.Split(line, "|")
appendCommands(commandsByFile, args)
}
if err := scanner.Err(); err != nil {
fmt.Fprintf(os.Stderr, "Error while reading commands file: %v", scanner.Err())
}
}
func printRecord(writer io.Writer, record *apipb.Output_Record) {
fields := record.Fields
line := make([]string, len(fields))
for i, field := range fields {
switch value := field.Value.(type) {
case *apipb.Output_Record_Field_Text:
if field.QuoteWhenPrinting && strings.ContainsRune(value.Text, ' ') {
line[i] = fmt.Sprintf("%q", value.Text)
} else {
line[i] = value.Text
}
break
case *apipb.Output_Record_Field_Number:
line[i] = strconv.Itoa(int(value.Number))
break
case *apipb.Output_Record_Field_Error:
switch value.Error {
case apipb.Output_Record_Field_UNKNOWN:
line[i] = "(unknown)"
break
case apipb.Output_Record_Field_MISSING:
line[i] = "(missing)"
break
}
break
case *apipb.Output_Record_Field_List:
line[i] = fmt.Sprintf("[%s]", strings.Join(value.List.Strings, " "))
break
}
}
fmt.Fprint(writer, strings.Join(line, " ")+"\n")
}
// Buildozer loops over all arguments on the command line fixing BUILD files.
func Buildozer(args []string) int {
commandsByFile := make(map[string][]commandsForTarget)
if Opts.CommandsFile != "" {
appendCommandsFromFile(commandsByFile, Opts.CommandsFile)
} else {
if len(args) == 0 {
Usage()
}
appendCommands(commandsByFile, args)
}
numFiles := len(commandsByFile)
if Opts.Parallelism > 0 {
runtime.GOMAXPROCS(Opts.Parallelism)
}
results := make(chan *rewriteResult, numFiles)
data := make(chan commandsForFile)
for i := 0; i < Opts.NumIO; i++ {
go func(results chan *rewriteResult, data chan commandsForFile) {
for commandsForFile := range data {
results <- rewrite(commandsForFile)
}
}(results, data)
}
for file, commands := range commandsByFile {
data <- commandsForFile{file, commands}
}
close(data)
records := []*apipb.Output_Record{}
hasErrors := false
for i := 0; i < numFiles; i++ {
fileResults := <-results
if fileResults == nil {
continue
}
hasErrors = hasErrors || len(fileResults.errs) > 0
for _, err := range fileResults.errs {
fmt.Fprintf(os.Stderr, "%s: %s\n", fileResults.file, err)
}
if fileResults.modified && !Opts.Quiet {
fmt.Fprintf(os.Stderr, "fixed %s\n", fileResults.file)
}
if fileResults.records != nil {
records = append(records, fileResults.records...)
}
}
if Opts.IsPrintingProto {
data, err := proto.Marshal(&apipb.Output{Records: records})
if err != nil {
log.Fatal("marshaling error: ", err)
}
fmt.Fprintf(os.Stdout, "%s", data)
} else {
for _, record := range records {
printRecord(os.Stdout, record)
}
}
if hasErrors {
return 2
}
if !fileModified && !Opts.Stdout {
return 3
}
return 0
}

823
vendor/github.com/bazelbuild/buildtools/edit/edit.go generated vendored Normal file
View File

@ -0,0 +1,823 @@
/*
Copyright 2016 Google Inc. All Rights Reserved.
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 edit provides high-level auxiliary functions for AST manipulation
// on BUILD files.
package edit
import (
"fmt"
"os"
"path"
"path/filepath"
"sort"
"strconv"
"strings"
"github.com/bazelbuild/buildtools/build"
"github.com/bazelbuild/buildtools/wspace"
)
var (
// ShortenLabelsFlag if true converts added labels to short form , e.g. //foo:bar => :bar
ShortenLabelsFlag = true
// DeleteWithComments if true a list attribute will be be deleted in ListDelete, even if there is a comment attached to it
DeleteWithComments = true
)
// ParseLabel parses a Blaze label (eg. //devtools/buildozer:rule), and returns
// the repo name ("" for the main repo), package (with leading slashes trimmed)
// and rule name (e.g. ["", "devtools/buildozer", "rule"]).
func ParseLabel(target string) (string, string, string) {
repo := ""
if strings.HasPrefix(target, "@") {
target = strings.TrimLeft(target, "@")
parts := strings.SplitN(target, "/", 2)
if len(parts) == 1 {
// "@foo" -> "foo", "", "foo" (ie @foo//:foo)
return target, "", target
}
repo = parts[0]
target = "/" + parts[1]
}
// TODO(bazel-team): check if the next line can now be deleted
target = strings.TrimRight(target, ":") // labels can end with ':'
parts := strings.SplitN(target, ":", 2)
parts[0] = strings.TrimPrefix(parts[0], "//")
if len(parts) == 1 {
if strings.HasPrefix(target, "//") {
// "//absolute/pkg" -> "absolute/pkg", "pkg"
return repo, parts[0], path.Base(parts[0])
}
// "relative/label" -> "", "relative/label"
return repo, "", parts[0]
}
return repo, parts[0], parts[1]
}
// ShortenLabel rewrites labels to use the canonical form (the form
// recommended by build-style). This behavior can be disabled using the
// --noshorten_labels flag for projects that consistently use long-form labels.
// "//foo/bar:bar" => "//foo/bar", or ":bar" when possible.
func ShortenLabel(label string, pkg string) string {
if !ShortenLabelsFlag {
return label
}
if !strings.HasPrefix(label, "//") {
// It doesn't look like a long label, so we preserve it.
return label
}
repo, labelPkg, rule := ParseLabel(label)
if repo == "" && labelPkg == pkg { // local label
return ":" + rule
}
slash := strings.LastIndex(labelPkg, "/")
if (slash >= 0 && labelPkg[slash+1:] == rule) || labelPkg == rule {
return "//" + labelPkg
}
return label
}
// LabelsEqual returns true if label1 and label2 are equal. The function
// takes care of the optional ":" prefix and differences between long-form
// labels and local labels.
func LabelsEqual(label1, label2, pkg string) bool {
str1 := strings.TrimPrefix(ShortenLabel(label1, pkg), ":")
str2 := strings.TrimPrefix(ShortenLabel(label2, pkg), ":")
return str1 == str2
}
// isFile returns true if the path refers to a regular file after following
// symlinks.
func isFile(path string) bool {
path, err := filepath.EvalSymlinks(path)
if err != nil {
return false
}
info, err := os.Stat(path)
if err != nil {
return false
}
return info.Mode().IsRegular()
}
// InterpretLabelForWorkspaceLocation returns the name of the BUILD file to
// edit, the full package name, and the rule. It takes a workspace-rooted
// directory to use.
func InterpretLabelForWorkspaceLocation(root string, target string) (buildFile string, pkg string, rule string) {
repo, pkg, rule := ParseLabel(target)
rootDir, relativePath := wspace.FindWorkspaceRoot(root)
if repo != "" {
files, err := wspace.FindRepoBuildFiles(rootDir)
if err == nil {
if buildFile, ok := files[repo]; ok {
return buildFile, pkg, rule
}
}
// TODO(rodrigoq): report error for other repos
}
if strings.HasPrefix(target, "//") {
buildFile = path.Join(rootDir, pkg, "BUILD")
return
}
if isFile(pkg) {
// allow operation on other files like WORKSPACE
buildFile = pkg
pkg = path.Join(relativePath, filepath.Dir(pkg))
return
}
if pkg != "" {
buildFile = pkg + "/BUILD"
} else {
buildFile = "BUILD"
}
pkg = path.Join(relativePath, pkg)
return
}
// InterpretLabel returns the name of the BUILD file to edit, the full
// package name, and the rule. It uses the pwd for resolving workspace file paths.
func InterpretLabel(target string) (buildFile string, pkg string, rule string) {
return InterpretLabelForWorkspaceLocation("", target)
}
// ExprToRule returns a Rule from an Expr.
// The boolean is false iff the Expr is not a function call, or does not have
// the expected kind.
func ExprToRule(expr build.Expr, kind string) (*build.Rule, bool) {
call, ok := expr.(*build.CallExpr)
if !ok {
return nil, false
}
k, ok := call.X.(*build.LiteralExpr)
if !ok || k.Token != kind {
return nil, false
}
return &build.Rule{Call: call}, true
}
// ExistingPackageDeclaration returns the package declaration, or nil if there is none.
func ExistingPackageDeclaration(f *build.File) *build.Rule {
for _, stmt := range f.Stmt {
if rule, ok := ExprToRule(stmt, "package"); ok {
return rule
}
}
return nil
}
// PackageDeclaration returns the package declaration. If it doesn't
// exist, it is created at the top of the BUILD file, after leading
// comments.
func PackageDeclaration(f *build.File) *build.Rule {
if pkg := ExistingPackageDeclaration(f); pkg != nil {
return pkg
}
all := []build.Expr{}
added := false
call := &build.CallExpr{X: &build.LiteralExpr{Token: "package"}}
// Skip CommentBlocks and find a place to insert the package declaration.
for _, stmt := range f.Stmt {
_, ok := stmt.(*build.CommentBlock)
if !ok && !added {
all = append(all, call)
added = true
}
all = append(all, stmt)
}
if !added { // In case the file is empty.
all = append(all, call)
}
f.Stmt = all
return &build.Rule{Call: call}
}
// RemoveEmptyPackage removes empty package declarations from the file, i.e.:
// package()
// This might appear because of a buildozer transformation (e.g. when removing a package
// attribute). Removing it is required for the file to be valid.
func RemoveEmptyPackage(f *build.File) *build.File {
var all []build.Expr
for _, stmt := range f.Stmt {
if call, ok := stmt.(*build.CallExpr); ok {
functionName, ok := call.X.(*build.LiteralExpr)
if ok && functionName.Token == "package" && len(call.List) == 0 {
continue
}
}
all = append(all, stmt)
}
return &build.File{Path: f.Path, Comments: f.Comments, Stmt: all}
}
// InsertAfter inserts an expression after index i.
func InsertAfter(i int, stmt []build.Expr, expr build.Expr) []build.Expr {
i = i + 1 // index after the element at i
result := make([]build.Expr, len(stmt)+1)
copy(result[0:i], stmt[0:i])
result[i] = expr
copy(result[i+1:], stmt[i:])
return result
}
// IndexOfLast finds the index of the last expression of a specific kind.
func IndexOfLast(stmt []build.Expr, Kind string) int {
lastIndex := -1
for i, s := range stmt {
sAsCallExpr, ok := s.(*build.CallExpr)
if !ok {
continue
}
literal, ok := sAsCallExpr.X.(*build.LiteralExpr)
if ok && literal.Token == Kind {
lastIndex = i
}
}
return lastIndex
}
// InsertAfterLastOfSameKind inserts an expression after the last expression of the same kind.
func InsertAfterLastOfSameKind(stmt []build.Expr, expr *build.CallExpr) []build.Expr {
index := IndexOfLast(stmt, expr.X.(*build.LiteralExpr).Token)
if index == -1 {
return InsertAtEnd(stmt, expr)
}
return InsertAfter(index, stmt, expr)
}
// InsertAtEnd inserts an expression at the end of a list, before trailing comments.
func InsertAtEnd(stmt []build.Expr, expr build.Expr) []build.Expr {
var i int
for i = len(stmt) - 1; i >= 0; i-- {
_, ok := stmt[i].(*build.CommentBlock)
if !ok {
break
}
}
return InsertAfter(i, stmt, expr)
}
// FindRuleByName returns the rule in the file that has the given name.
// If the name is "__pkg__", it returns the global package declaration.
func FindRuleByName(f *build.File, name string) *build.Rule {
if name == "__pkg__" {
return PackageDeclaration(f)
}
i := IndexOfRuleByName(f, name)
if i != -1 {
return &build.Rule{Call: f.Stmt[i].(*build.CallExpr)}
}
return nil
}
// UseImplicitName returns the rule in the file if it meets these conditions:
// - It is the only unnamed rule in the file.
// - The file path's ending directory name and the passed rule name match.
// In the Pants Build System, by pantsbuild, the use of an implicit name makes
// creating targets easier. This function implements such names.
func UseImplicitName(f *build.File, rule string) *build.Rule {
// We disallow empty names
if f.Path == "BUILD" {
return nil
}
ruleCount := 0
var temp, found *build.Rule
pkg := filepath.Base(filepath.Dir(f.Path))
for _, stmt := range f.Stmt {
call, ok := stmt.(*build.CallExpr)
if !ok {
continue
}
temp = &build.Rule{Call: call}
if temp.Kind() != "" && temp.Name() == "" {
ruleCount++
found = temp
}
}
if ruleCount == 1 {
if rule == pkg {
return found
}
}
return nil
}
// IndexOfRuleByName returns the index (in f.Stmt) of the CallExpr which defines a rule named `name`, or -1 if it doesn't exist.
func IndexOfRuleByName(f *build.File, name string) int {
linenum := -1
if strings.HasPrefix(name, "%") {
// "%<LINENUM>" will match the rule which begins at LINENUM.
// This is for convenience, "%" is not a valid character in bazel targets.
if result, err := strconv.Atoi(name[1:]); err == nil {
linenum = result
}
}
for i, stmt := range f.Stmt {
call, ok := stmt.(*build.CallExpr)
if !ok {
continue
}
r := &build.Rule{Call: call}
start, _ := call.X.Span()
if r.Name() == name || start.Line == linenum {
return i
}
}
return -1
}
// FindExportedFile returns the first exports_files call which contains the
// file 'name', or nil if not found
func FindExportedFile(f *build.File, name string) *build.Rule {
for _, r := range f.Rules("exports_files") {
if len(r.Call.List) == 0 {
continue
}
pkg := "" // Files are not affected by the package name
if ListFind(r.Call.List[0], name, pkg) != nil {
return r
}
}
return nil
}
// DeleteRule returns the AST without the specified rule
func DeleteRule(f *build.File, rule *build.Rule) *build.File {
var all []build.Expr
for _, stmt := range f.Stmt {
if stmt == rule.Call {
continue
}
all = append(all, stmt)
}
return &build.File{Path: f.Path, Comments: f.Comments, Stmt: all}
}
// DeleteRuleByName returns the AST without the rules that have the
// given name.
func DeleteRuleByName(f *build.File, name string) *build.File {
var all []build.Expr
for _, stmt := range f.Stmt {
call, ok := stmt.(*build.CallExpr)
if !ok {
all = append(all, stmt)
continue
}
r := &build.Rule{Call: call}
if r.Name() != name {
all = append(all, stmt)
}
}
return &build.File{Path: f.Path, Comments: f.Comments, Stmt: all}
}
// DeleteRuleByKind removes the rules of the specified kind from the AST.
// Returns an updated copy of f.
func DeleteRuleByKind(f *build.File, kind string) *build.File {
var all []build.Expr
for _, stmt := range f.Stmt {
call, ok := stmt.(*build.CallExpr)
if !ok {
all = append(all, stmt)
continue
}
k, ok := call.X.(*build.LiteralExpr)
if !ok || k.Token != kind {
all = append(all, stmt)
}
}
return &build.File{Path: f.Path, Comments: f.Comments, Stmt: all}
}
// AllLists returns all the lists concatenated in an expression.
// For example, in: glob(["*.go"]) + [":rule"]
// the function will return [[":rule"]].
func AllLists(e build.Expr) []*build.ListExpr {
switch e := e.(type) {
case *build.ListExpr:
return []*build.ListExpr{e}
case *build.BinaryExpr:
if e.Op == "+" {
return append(AllLists(e.X), AllLists(e.Y)...)
}
}
return nil
}
// FirstList works in the same way as AllLists, except that it
// returns only one list, or nil.
func FirstList(e build.Expr) *build.ListExpr {
switch e := e.(type) {
case *build.ListExpr:
return e
case *build.BinaryExpr:
if e.Op == "+" {
li := FirstList(e.X)
if li == nil {
return FirstList(e.Y)
}
return li
}
}
return nil
}
// AllStrings returns all the string literals concatenated in an expression.
// For example, in: "foo" + x + "bar"
// the function will return ["foo", "bar"].
func AllStrings(e build.Expr) []*build.StringExpr {
switch e := e.(type) {
case *build.StringExpr:
return []*build.StringExpr{e}
case *build.BinaryExpr:
if e.Op == "+" {
return append(AllStrings(e.X), AllStrings(e.Y)...)
}
}
return nil
}
// ListFind looks for a string in the list expression (which may be a
// concatenation of lists). It returns the element if it is found. nil
// otherwise.
func ListFind(e build.Expr, item string, pkg string) *build.StringExpr {
item = ShortenLabel(item, pkg)
for _, li := range AllLists(e) {
for _, elem := range li.List {
str, ok := elem.(*build.StringExpr)
if ok && LabelsEqual(str.Value, item, pkg) {
return str
}
}
}
return nil
}
// hasComments returns whether the StringExpr literal has a comment attached to it.
func hasComments(literal *build.StringExpr) bool {
return len(literal.Before) > 0 || len(literal.Suffix) > 0
}
// ContainsComments returns whether the expr has a comment that includes str.
func ContainsComments(expr build.Expr, str string) bool {
str = strings.ToLower(str)
com := expr.Comment()
comments := append(com.Before, com.Suffix...)
comments = append(comments, com.After...)
for _, c := range comments {
if strings.Contains(strings.ToLower(c.Token), str) {
return true
}
}
return false
}
// ListDelete deletes the item from a list expression in e and returns
// the StringExpr deleted, or nil otherwise.
func ListDelete(e build.Expr, item, pkg string) (deleted *build.StringExpr) {
deleted = nil
item = ShortenLabel(item, pkg)
for _, li := range AllLists(e) {
var all []build.Expr
for _, elem := range li.List {
if str, ok := elem.(*build.StringExpr); ok {
if LabelsEqual(str.Value, item, pkg) && (DeleteWithComments || !hasComments(str)) {
deleted = str
continue
}
}
all = append(all, elem)
}
li.List = all
}
return deleted
}
// ListAttributeDelete deletes string item from list attribute attr, deletes attr if empty,
// and returns the StringExpr deleted, or nil otherwise.
func ListAttributeDelete(rule *build.Rule, attr, item, pkg string) *build.StringExpr {
deleted := ListDelete(rule.Attr(attr), item, pkg)
if deleted != nil {
if listExpr, ok := rule.Attr(attr).(*build.ListExpr); ok && len(listExpr.List) == 0 {
rule.DelAttr(attr)
}
}
return deleted
}
// ListReplace replaces old with value in all lists in e and returns a Boolean
// to indicate whether the replacement was successful.
func ListReplace(e build.Expr, old, value, pkg string) bool {
replaced := false
old = ShortenLabel(old, pkg)
for _, li := range AllLists(e) {
for k, elem := range li.List {
str, ok := elem.(*build.StringExpr)
if !ok || !LabelsEqual(str.Value, old, pkg) {
continue
}
li.List[k] = &build.StringExpr{Value: ShortenLabel(value, pkg), Comments: *elem.Comment()}
replaced = true
}
}
return replaced
}
// isExprLessThan compares two Expr statements. Currently, only labels are supported.
func isExprLessThan(x1, x2 build.Expr) bool {
str1, ok1 := x1.(*build.StringExpr)
str2, ok2 := x2.(*build.StringExpr)
if ok1 != ok2 {
return ok2
}
if ok1 && ok2 {
// Labels starting with // are put at the end.
pre1 := strings.HasPrefix(str1.Value, "//")
pre2 := strings.HasPrefix(str2.Value, "//")
if pre1 != pre2 {
return pre2
}
return str1.Value < str2.Value
}
return false
}
func sortedInsert(list []build.Expr, item build.Expr) []build.Expr {
i := 0
for ; i < len(list); i++ {
if isExprLessThan(item, list[i]) {
break
}
}
res := make([]build.Expr, 0, len(list)+1)
res = append(res, list[:i]...)
res = append(res, item)
res = append(res, list[i:]...)
return res
}
// attributeMustNotBeSorted returns true if the list in the attribute cannot be
// sorted. For some attributes, it makes sense to try to do a sorted insert
// (e.g. deps), even when buildifier will not sort it for conservative reasons.
// For a few attributes, sorting will never make sense.
func attributeMustNotBeSorted(rule, attr string) bool {
// TODO(bazel-team): Come up with a more complete list.
return attr == "args"
}
// getVariable returns the binary expression that assignes a variable to expr, if expr is
// an identifier of a variable that vars contains a mapping for.
func getVariable(expr build.Expr, vars *map[string]*build.BinaryExpr) (varAssignment *build.BinaryExpr) {
if vars == nil {
return nil
}
if literal, ok := expr.(*build.LiteralExpr); ok {
if varAssignment = (*vars)[literal.Token]; varAssignment != nil {
return varAssignment
}
}
return nil
}
// AddValueToList adds a value to a list. If the expression is
// not a list, a list with a single element is appended to the original
// expression.
func AddValueToList(oldList build.Expr, pkg string, item build.Expr, sorted bool) build.Expr {
if oldList == nil {
return &build.ListExpr{List: []build.Expr{item}}
}
str, ok := item.(*build.StringExpr)
if ok && ListFind(oldList, str.Value, pkg) != nil {
// The value is already in the list.
return oldList
}
li := FirstList(oldList)
if li != nil {
if sorted {
li.List = sortedInsert(li.List, item)
} else {
li.List = append(li.List, item)
}
return oldList
}
list := &build.ListExpr{List: []build.Expr{item}}
concat := &build.BinaryExpr{Op: "+", X: oldList, Y: list}
return concat
}
// AddValueToListAttribute adds the given item to the list attribute identified by name and pkg.
func AddValueToListAttribute(r *build.Rule, name string, pkg string, item build.Expr, vars *map[string]*build.BinaryExpr) {
old := r.Attr(name)
sorted := !attributeMustNotBeSorted(r.Kind(), name)
if varAssignment := getVariable(old, vars); varAssignment != nil {
varAssignment.Y = AddValueToList(varAssignment.Y, pkg, item, sorted)
} else {
r.SetAttr(name, AddValueToList(old, pkg, item, sorted))
}
}
// MoveAllListAttributeValues moves all values from list attribute oldAttr to newAttr,
// and deletes oldAttr.
func MoveAllListAttributeValues(rule *build.Rule, oldAttr, newAttr, pkg string, vars *map[string]*build.BinaryExpr) error {
if rule.Attr(oldAttr) == nil {
return fmt.Errorf("no attribute %s found in %s", oldAttr, rule.Name())
}
if rule.Attr(newAttr) == nil {
RenameAttribute(rule, oldAttr, newAttr)
return nil
}
if listExpr, ok := rule.Attr(oldAttr).(*build.ListExpr); ok {
for _, val := range listExpr.List {
AddValueToListAttribute(rule, newAttr, pkg, val, vars)
}
rule.DelAttr(oldAttr)
return nil
}
return fmt.Errorf("%s already exists and %s is not a simple list", newAttr, oldAttr)
}
// DictionarySet looks for the key in the dictionary expression. If value is not nil,
// it replaces the current value with it. In all cases, it returns the current value.
func DictionarySet(dict *build.DictExpr, key string, value build.Expr) build.Expr {
for _, e := range dict.List {
kv, _ := e.(*build.KeyValueExpr)
if k, ok := kv.Key.(*build.StringExpr); ok && k.Value == key {
if value != nil {
kv.Value = value
}
return kv.Value
}
}
if value != nil {
kv := &build.KeyValueExpr{Key: &build.StringExpr{Value: key}, Value: value}
dict.List = append(dict.List, kv)
}
return nil
}
// RenameAttribute renames an attribute in a rule.
func RenameAttribute(r *build.Rule, oldName, newName string) error {
if r.Attr(newName) != nil {
return fmt.Errorf("attribute %s already exists in rule %s", newName, r.Name())
}
for _, kv := range r.Call.List {
as, ok := kv.(*build.BinaryExpr)
if !ok || as.Op != "=" {
continue
}
k, ok := as.X.(*build.LiteralExpr)
if !ok || k.Token != oldName {
continue
}
k.Token = newName
return nil
}
return fmt.Errorf("no attribute %s found in rule %s", oldName, r.Name())
}
// EditFunction is a wrapper around build.Edit. The callback is called only on
// functions 'name'.
func EditFunction(v build.Expr, name string, f func(x *build.CallExpr, stk []build.Expr) build.Expr) build.Expr {
return build.Edit(v, func(expr build.Expr, stk []build.Expr) build.Expr {
call, ok := expr.(*build.CallExpr)
if !ok {
return nil
}
fct, ok := call.X.(*build.LiteralExpr)
if !ok || fct.Token != name {
return nil
}
return f(call, stk)
})
}
// UsedSymbols returns the set of symbols used in the BUILD file (variables, function names).
func UsedSymbols(f *build.File) map[string]bool {
symbols := make(map[string]bool)
build.Walk(f, func(expr build.Expr, stack []build.Expr) {
literal, ok := expr.(*build.LiteralExpr)
if !ok {
return
}
// Check if we are on the left-side of an assignment
for _, e := range stack {
if as, ok := e.(*build.BinaryExpr); ok {
if as.Op == "=" && as.X == expr {
return
}
}
}
symbols[literal.Token] = true
})
return symbols
}
func newLoad(args []string) *build.CallExpr {
load := &build.CallExpr{
X: &build.LiteralExpr{
Token: "load",
},
List: []build.Expr{},
ForceCompact: true,
}
for _, a := range args {
load.List = append(load.List, &build.StringExpr{Value: a})
}
return load
}
// appendLoad tries to find an existing load location and append symbols to it.
func appendLoad(stmts []build.Expr, args []string) bool {
if len(args) == 0 {
return false
}
location := args[0]
symbolsToLoad := make(map[string]bool)
for _, s := range args[1:] {
symbolsToLoad[s] = true
}
var lastLoad *build.CallExpr
for _, s := range stmts {
call, ok := s.(*build.CallExpr)
if !ok {
continue
}
if l, ok := call.X.(*build.LiteralExpr); !ok || l.Token != "load" {
continue
}
if len(call.List) < 2 {
continue
}
if s, ok := call.List[0].(*build.StringExpr); !ok || s.Value != location {
continue // Loads a different file.
}
for _, arg := range call.List[1:] {
if s, ok := arg.(*build.StringExpr); ok {
delete(symbolsToLoad, s.Value) // Already loaded.
}
}
// Remember the last insert location, but potentially remove more symbols
// that are already loaded in other subsequent calls.
lastLoad = call
}
if lastLoad == nil {
return false
}
// Append the remaining loads to the last load location.
sortedSymbols := []string{}
for s := range symbolsToLoad {
sortedSymbols = append(sortedSymbols, s)
}
sort.Strings(sortedSymbols)
for _, s := range sortedSymbols {
lastLoad.List = append(lastLoad.List, &build.StringExpr{Value: s})
}
return true
}
// InsertLoad inserts a load statement at the top of the list of statements.
// The load statement is constructed using args. Symbols that are already loaded
// from the given filepath are ignored. If stmts already contains a load for the
// location in arguments, appends the symbols to load to it.
func InsertLoad(stmts []build.Expr, args []string) []build.Expr {
if appendLoad(stmts, args) {
return stmts
}
load := newLoad(args)
var all []build.Expr
added := false
for _, stmt := range stmts {
_, isComment := stmt.(*build.CommentBlock)
if isComment || added {
all = append(all, stmt)
continue
}
all = append(all, load)
all = append(all, stmt)
added = true
}
if !added { // Empty file or just comments.
all = append(all, load)
}
return all
}

569
vendor/github.com/bazelbuild/buildtools/edit/fix.go generated vendored Normal file
View File

@ -0,0 +1,569 @@
/*
Copyright 2016 Google Inc. All Rights Reserved.
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.
*/
// Functions to clean and fix BUILD files
package edit
import (
"regexp"
"sort"
"strings"
"github.com/bazelbuild/buildtools/build"
)
// splitOptionsWithSpaces is a cleanup function.
// It splits options strings that contain a space. This change
// should be safe as Blaze is splitting those strings, but we will
// eventually get rid of this misfeature.
// eg. it converts from:
// copts = ["-Dfoo -Dbar"]
// to:
// copts = ["-Dfoo", "-Dbar"]
func splitOptionsWithSpaces(_ *build.File, r *build.Rule, _ string) bool {
var attrToRewrite = []string{
"copts",
"linkopts",
}
fixed := false
for _, attrName := range attrToRewrite {
attr := r.Attr(attrName)
if attr != nil {
for _, li := range AllLists(attr) {
fixed = splitStrings(li) || fixed
}
}
}
return fixed
}
func splitStrings(list *build.ListExpr) bool {
var all []build.Expr
fixed := false
for _, e := range list.List {
str, ok := e.(*build.StringExpr)
if !ok {
all = append(all, e)
continue
}
if strings.Contains(str.Value, " ") && !strings.Contains(str.Value, "'\"") {
fixed = true
for i, substr := range strings.Fields(str.Value) {
item := &build.StringExpr{Value: substr}
if i == 0 {
item.Comments = str.Comments
}
all = append(all, item)
}
} else {
all = append(all, str)
}
}
list.List = all
return fixed
}
// shortenLabels rewrites the labels in the rule using the short notation.
func shortenLabels(_ *build.File, r *build.Rule, pkg string) bool {
fixed := false
for _, attr := range r.AttrKeys() {
e := r.Attr(attr)
if !ContainsLabels(attr) {
continue
}
for _, li := range AllLists(e) {
for _, elem := range li.List {
str, ok := elem.(*build.StringExpr)
if ok && str.Value != ShortenLabel(str.Value, pkg) {
str.Value = ShortenLabel(str.Value, pkg)
fixed = true
}
}
}
}
return fixed
}
// removeVisibility removes useless visibility attributes.
func removeVisibility(f *build.File, r *build.Rule, pkg string) bool {
pkgDecl := PackageDeclaration(f)
defaultVisibility := pkgDecl.AttrStrings("default_visibility")
// If no default_visibility is given, it is implicitly private.
if len(defaultVisibility) == 0 {
defaultVisibility = []string{"//visibility:private"}
}
visibility := r.AttrStrings("visibility")
if len(visibility) == 0 || len(visibility) != len(defaultVisibility) {
return false
}
sort.Strings(defaultVisibility)
sort.Strings(visibility)
for i, vis := range visibility {
if vis != defaultVisibility[i] {
return false
}
}
r.DelAttr("visibility")
return true
}
// removeTestOnly removes the useless testonly attributes.
func removeTestOnly(f *build.File, r *build.Rule, pkg string) bool {
pkgDecl := PackageDeclaration(f)
def := strings.HasSuffix(r.Kind(), "_test") || r.Kind() == "test_suite"
if !def {
if pkgDecl.Attr("default_testonly") == nil {
def = strings.HasPrefix(pkg, "javatests/")
} else if pkgDecl.AttrLiteral("default_testonly") == "1" {
def = true
} else if pkgDecl.AttrLiteral("default_testonly") != "0" {
// Non-literal value: it's not safe to do a change.
return false
}
}
testonly := r.AttrLiteral("testonly")
if def && testonly == "1" {
r.DelAttr("testonly")
return true
}
if !def && testonly == "0" {
r.DelAttr("testonly")
return true
}
return false
}
func genruleRenameDepsTools(_ *build.File, r *build.Rule, _ string) bool {
return r.Kind() == "genrule" && RenameAttribute(r, "deps", "tools") == nil
}
// explicitHeuristicLabels adds $(location ...) for each label in the string s.
func explicitHeuristicLabels(s string, labels map[string]bool) string {
// Regexp comes from LABEL_CHAR_MATCHER in
// java/com/google/devtools/build/lib/analysis/LabelExpander.java
re := regexp.MustCompile("[a-zA-Z0-9:/_.+-]+|[^a-zA-Z0-9:/_.+-]+")
parts := re.FindAllString(s, -1)
changed := false
canChange := true
for i, part := range parts {
// We don't want to add $(location when it's already present.
// So we skip the next label when we see location(s).
if part == "location" || part == "locations" {
canChange = false
}
if !labels[part] {
if labels[":"+part] { // leading colon is often missing
part = ":" + part
} else {
continue
}
}
if !canChange {
canChange = true
continue
}
parts[i] = "$(location " + part + ")"
changed = true
}
if changed {
return strings.Join(parts, "")
}
return s
}
func addLabels(r *build.Rule, attr string, labels map[string]bool) {
a := r.Attr(attr)
if a == nil {
return
}
for _, li := range AllLists(a) {
for _, item := range li.List {
if str, ok := item.(*build.StringExpr); ok {
labels[str.Value] = true
}
}
}
}
// genruleFixHeuristicLabels modifies the cmd attribute of genrules, so
// that they don't rely on heuristic label expansion anymore.
// Label expansion is made explicit with the $(location ...) command.
func genruleFixHeuristicLabels(_ *build.File, r *build.Rule, _ string) bool {
if r.Kind() != "genrule" {
return false
}
cmd := r.Attr("cmd")
if cmd == nil {
return false
}
labels := make(map[string]bool)
addLabels(r, "tools", labels)
addLabels(r, "srcs", labels)
fixed := false
for _, str := range AllStrings(cmd) {
newVal := explicitHeuristicLabels(str.Value, labels)
if newVal != str.Value {
fixed = true
str.Value = newVal
}
}
return fixed
}
// sortExportsFiles sorts the first argument of exports_files if it is a list.
func sortExportsFiles(_ *build.File, r *build.Rule, _ string) bool {
if r.Kind() != "exports_files" || len(r.Call.List) == 0 {
return false
}
build.SortStringList(r.Call.List[0])
return true
}
// removeVarref replaces all varref('x') with '$(x)'.
// The goal is to eventually remove varref from the build language.
func removeVarref(_ *build.File, r *build.Rule, _ string) bool {
fixed := false
EditFunction(r.Call, "varref", func(call *build.CallExpr, stk []build.Expr) build.Expr {
if len(call.List) != 1 {
return nil
}
str, ok := (call.List[0]).(*build.StringExpr)
if !ok {
return nil
}
fixed = true
str.Value = "$(" + str.Value + ")"
// Preserve suffix comments from the function call
str.Comment().Suffix = append(str.Comment().Suffix, call.Comment().Suffix...)
return str
})
return fixed
}
// sortGlob sorts the list argument to glob.
func sortGlob(_ *build.File, r *build.Rule, _ string) bool {
fixed := false
EditFunction(r.Call, "glob", func(call *build.CallExpr, stk []build.Expr) build.Expr {
if len(call.List) == 0 {
return nil
}
build.SortStringList(call.List[0])
fixed = true
return call
})
return fixed
}
func evaluateListConcatenation(expr build.Expr) build.Expr {
if _, ok := expr.(*build.ListExpr); ok {
return expr
}
bin, ok := expr.(*build.BinaryExpr)
if !ok || bin.Op != "+" {
return expr
}
li1, ok1 := evaluateListConcatenation(bin.X).(*build.ListExpr)
li2, ok2 := evaluateListConcatenation(bin.Y).(*build.ListExpr)
if !ok1 || !ok2 {
return expr
}
res := *li1
res.List = append(li1.List, li2.List...)
return &res
}
// mergeLiteralLists evaluates the concatenation of two literal lists.
// e.g. [1, 2] + [3, 4] -> [1, 2, 3, 4]
func mergeLiteralLists(_ *build.File, r *build.Rule, _ string) bool {
fixed := false
build.Edit(r.Call, func(expr build.Expr, stk []build.Expr) build.Expr {
newexpr := evaluateListConcatenation(expr)
fixed = fixed || (newexpr != expr)
return newexpr
})
return fixed
}
// usePlusEqual replaces uses of extend and append with the += operator.
// e.g. foo.extend(bar) => foo += bar
// foo.append(bar) => foo += [bar]
func usePlusEqual(f *build.File) bool {
fixed := false
for i, stmt := range f.Stmt {
call, ok := stmt.(*build.CallExpr)
if !ok {
continue
}
dot, ok := call.X.(*build.DotExpr)
if !ok || len(call.List) != 1 {
continue
}
obj, ok := dot.X.(*build.LiteralExpr)
if !ok {
continue
}
var fix *build.BinaryExpr
if dot.Name == "extend" {
fix = &build.BinaryExpr{X: obj, Op: "+=", Y: call.List[0]}
} else if dot.Name == "append" {
list := &build.ListExpr{List: []build.Expr{call.List[0]}}
fix = &build.BinaryExpr{X: obj, Op: "+=", Y: list}
} else {
continue
}
fix.Comments = call.Comments // Keep original comments
f.Stmt[i] = fix
fixed = true
}
return fixed
}
func isNonemptyComment(comment *build.Comments) bool {
return len(comment.Before)+len(comment.Suffix)+len(comment.After) > 0
}
// Checks whether a call or any of its arguments have a comment
func hasComment(call *build.CallExpr) bool {
if isNonemptyComment(call.Comment()) {
return true
}
for _, arg := range call.List {
if isNonemptyComment(arg.Comment()) {
return true
}
}
return false
}
// cleanUnusedLoads removes symbols from load statements that are not used in the file.
// It also cleans symbols loaded multiple times, sorts symbol list, and removes load
// statements when the list is empty.
func cleanUnusedLoads(f *build.File) bool {
// If the file needs preprocessing, leave it alone.
for _, stmt := range f.Stmt {
if _, ok := stmt.(*build.PythonBlock); ok {
return false
}
}
symbols := UsedSymbols(f)
fixed := false
var all []build.Expr
for _, stmt := range f.Stmt {
rule, ok := ExprToRule(stmt, "load")
if !ok || len(rule.Call.List) == 0 || hasComment(rule.Call) {
all = append(all, stmt)
continue
}
var args []build.Expr
for _, arg := range rule.Call.List[1:] { // first argument is the path, we keep it
symbol, ok := loadedSymbol(arg)
if !ok || symbols[symbol] {
args = append(args, arg)
if ok {
// If the same symbol is loaded twice, we'll remove it.
delete(symbols, symbol)
}
} else {
fixed = true
}
}
if len(args) > 0 { // Keep the load statement if it loads at least one symbol.
li := &build.ListExpr{List: args}
build.SortStringList(li)
rule.Call.List = append(rule.Call.List[:1], li.List...)
all = append(all, rule.Call)
} else {
fixed = true
}
}
f.Stmt = all
return fixed
}
// loadedSymbol parses the symbol token from a load statement argument,
// supporting aliases.
func loadedSymbol(arg build.Expr) (string, bool) {
symbol, ok := arg.(*build.StringExpr)
if ok {
return symbol.Value, ok
}
// try an aliased symbol
if binExpr, ok := arg.(*build.BinaryExpr); ok && binExpr.Op == "=" {
if keyExpr, ok := binExpr.X.(*build.LiteralExpr); ok {
return keyExpr.Token, ok
}
}
return "", false
}
// movePackageDeclarationToTheTop ensures that the call to package() is done
// before everything else (except comments).
func movePackageDeclarationToTheTop(f *build.File) bool {
pkg := ExistingPackageDeclaration(f)
if pkg == nil {
return false
}
all := []build.Expr{}
inserted := false // true when the package declaration has been inserted
for _, stmt := range f.Stmt {
_, isComment := stmt.(*build.CommentBlock)
_, isBinaryExpr := stmt.(*build.BinaryExpr) // e.g. variable declaration
_, isLoad := ExprToRule(stmt, "load")
if isComment || isBinaryExpr || isLoad {
all = append(all, stmt)
continue
}
if stmt == pkg.Call {
if inserted {
// remove the old package
continue
}
return false // the file was ok
}
if !inserted {
all = append(all, pkg.Call)
inserted = true
}
all = append(all, stmt)
}
f.Stmt = all
return true
}
// moveToPackage is an auxilliary function used by moveLicensesAndDistribs.
// The function shouldn't appear more than once in the file (depot cleanup has
// been done).
func moveToPackage(f *build.File, attrname string) bool {
var all []build.Expr
fixed := false
for _, stmt := range f.Stmt {
rule, ok := ExprToRule(stmt, attrname)
if !ok || len(rule.Call.List) != 1 {
all = append(all, stmt)
continue
}
pkgDecl := PackageDeclaration(f)
pkgDecl.SetAttr(attrname, rule.Call.List[0])
pkgDecl.AttrDefn(attrname).Comments = *stmt.Comment()
fixed = true
}
f.Stmt = all
return fixed
}
// moveLicensesAndDistribs replaces the 'licenses' and 'distribs' functions
// with an attribute in package.
// Before: licenses(["notice"])
// After: package(licenses = ["notice"])
func moveLicensesAndDistribs(f *build.File) bool {
fixed1 := moveToPackage(f, "licenses")
fixed2 := moveToPackage(f, "distribs")
return fixed1 || fixed2
}
// AllRuleFixes is a list of all Buildozer fixes that can be applied on a rule.
var AllRuleFixes = []struct {
Name string
Fn func(file *build.File, rule *build.Rule, pkg string) bool
Message string
}{
{"sortGlob", sortGlob,
"Sort the list in a call to glob"},
{"splitOptions", splitOptionsWithSpaces,
"Each option should be given separately in the list"},
{"shortenLabels", shortenLabels,
"Style: Use the canonical label notation"},
{"removeVisibility", removeVisibility,
"This visibility attribute is useless (it corresponds to the default value)"},
{"removeTestOnly", removeTestOnly,
"This testonly attribute is useless (it corresponds to the default value)"},
{"genruleRenameDepsTools", genruleRenameDepsTools,
"'deps' attribute in genrule has been renamed 'tools'"},
{"genruleFixHeuristicLabels", genruleFixHeuristicLabels,
"$(location) should be called explicitely"},
{"sortExportsFiles", sortExportsFiles,
"Files in exports_files should be sorted"},
{"varref", removeVarref,
"All varref('foo') should be replaced with '$foo'"},
{"mergeLiteralLists", mergeLiteralLists,
"Remove useless list concatenation"},
}
// FileLevelFixes is a list of all Buildozer fixes that apply on the whole file.
var FileLevelFixes = []struct {
Name string
Fn func(file *build.File) bool
Message string
}{
{"movePackageToTop", movePackageDeclarationToTheTop,
"The package declaration should be the first rule in a file"},
{"usePlusEqual", usePlusEqual,
"Prefer '+=' over 'extend' or 'append'"},
{"unusedLoads", cleanUnusedLoads,
"Remove unused symbols from load statements"},
{"moveLicensesAndDistribs", moveLicensesAndDistribs,
"Move licenses and distribs to the package function"},
}
// FixRule aims to fix errors in BUILD files, remove deprecated features, and
// simplify the code.
func FixRule(f *build.File, pkg string, rule *build.Rule, fixes []string) *build.File {
fixesAsMap := make(map[string]bool)
for _, fix := range fixes {
fixesAsMap[fix] = true
}
fixed := false
for _, fix := range AllRuleFixes {
if len(fixes) == 0 || fixesAsMap[fix.Name] {
fixed = fix.Fn(f, rule, pkg) || fixed
}
}
if !fixed {
return nil
}
return f
}
// FixFile fixes everything it can in the BUILD file.
func FixFile(f *build.File, pkg string, fixes []string) *build.File {
fixesAsMap := make(map[string]bool)
for _, fix := range fixes {
fixesAsMap[fix] = true
}
fixed := false
for _, rule := range f.Rules("") {
res := FixRule(f, pkg, rule, fixes)
if res != nil {
fixed = true
f = res
}
}
for _, fix := range FileLevelFixes {
if len(fixes) == 0 || fixesAsMap[fix.Name] {
fixed = fix.Fn(f) || fixed
}
}
if !fixed {
return nil
}
return f
}

59
vendor/github.com/bazelbuild/buildtools/edit/types.go generated vendored Normal file
View File

@ -0,0 +1,59 @@
/*
Copyright 2016 Google Inc. All Rights Reserved.
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.
*/
// Type information for attributes.
package edit
import (
buildpb "github.com/bazelbuild/buildtools/build_proto"
"github.com/bazelbuild/buildtools/lang"
)
var typeOf = lang.TypeOf
// IsList returns true for all attributes whose type is a list.
func IsList(attr string) bool {
ty := typeOf[attr]
return ty == buildpb.Attribute_STRING_LIST ||
ty == buildpb.Attribute_LABEL_LIST ||
ty == buildpb.Attribute_OUTPUT_LIST ||
ty == buildpb.Attribute_FILESET_ENTRY_LIST ||
ty == buildpb.Attribute_INTEGER_LIST ||
ty == buildpb.Attribute_LICENSE ||
ty == buildpb.Attribute_DISTRIBUTION_SET
}
// IsIntList returns true for all attributes whose type is an int list.
func IsIntList(attr string) bool {
return typeOf[attr] == buildpb.Attribute_INTEGER_LIST
}
// IsString returns true for all attributes whose type is a string or a label.
func IsString(attr string) bool {
ty := typeOf[attr]
return ty == buildpb.Attribute_LABEL ||
ty == buildpb.Attribute_STRING ||
ty == buildpb.Attribute_OUTPUT
}
// IsStringDict returns true for all attributes whose type is a string dictionary.
func IsStringDict(attr string) bool {
return typeOf[attr] == buildpb.Attribute_STRING_DICT
}
// ContainsLabels returns true for all attributes whose type is a label or a label list.
func ContainsLabels(attr string) bool {
ty := typeOf[attr]
return ty == buildpb.Attribute_LABEL_LIST ||
ty == buildpb.Attribute_LABEL
}

23
vendor/github.com/bazelbuild/buildtools/file/BUILD generated vendored Normal file
View File

@ -0,0 +1,23 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["file.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/bazelbuild/buildtools/file",
importpath = "github.com/bazelbuild/buildtools/file",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

48
vendor/github.com/bazelbuild/buildtools/file/file.go generated vendored Normal file
View File

@ -0,0 +1,48 @@
/*
Copyright 2016 Google Inc. All Rights Reserved.
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 file provides utility file operations.
package file
import (
"fmt"
"io"
"io/ioutil"
"os"
)
// ReadFile is like ioutil.ReadFile.
func ReadFile(name string) ([]byte, os.FileInfo, error) {
fi, err := os.Stat(name)
if err != nil {
return nil, nil, err
}
data, err := ioutil.ReadFile(name)
return data, fi, err
}
// WriteFile is like ioutil.WriteFile
func WriteFile(name string, data []byte) error {
return ioutil.WriteFile(name, data, 0644)
}
// OpenReadFile is like os.Open.
func OpenReadFile(name string) io.ReadCloser {
f, err := os.Open(name)
if err != nil {
fmt.Fprintf(os.Stderr, "Could not open %s\n", name)
os.Exit(1)
}
return f
}

24
vendor/github.com/bazelbuild/buildtools/lang/BUILD generated vendored Normal file
View File

@ -0,0 +1,24 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["tables.gen.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/bazelbuild/buildtools/lang",
importpath = "github.com/bazelbuild/buildtools/lang",
visibility = ["//visibility:public"],
deps = ["//vendor/github.com/bazelbuild/buildtools/build_proto:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

Binary file not shown.

245
vendor/github.com/bazelbuild/buildtools/lang/tables.gen.go generated vendored Executable file
View File

@ -0,0 +1,245 @@
// Generated file, do not edit.
package lang
import buildpb "github.com/bazelbuild/buildtools/build_proto"
var TypeOf = map[string]buildpb.Attribute_Discriminator{
"aar": buildpb.Attribute_LABEL,
"actual": buildpb.Attribute_LABEL,
"aliases": buildpb.Attribute_STRING_LIST,
"all_files": buildpb.Attribute_LABEL,
"alwayslink": buildpb.Attribute_BOOLEAN,
"app_asset_catalogs": buildpb.Attribute_LABEL_LIST,
"app_bundle_id": buildpb.Attribute_STRING,
"app_deps": buildpb.Attribute_LABEL_LIST,
"app_entitlements": buildpb.Attribute_LABEL,
"app_icon": buildpb.Attribute_STRING,
"app_infoplists": buildpb.Attribute_LABEL_LIST,
"app_name": buildpb.Attribute_STRING,
"app_provisioning_profile": buildpb.Attribute_LABEL,
"app_resources": buildpb.Attribute_LABEL_LIST,
"app_storyboards": buildpb.Attribute_LABEL_LIST,
"app_strings": buildpb.Attribute_LABEL_LIST,
"app_structured_resources": buildpb.Attribute_LABEL_LIST,
"archives": buildpb.Attribute_LABEL_LIST,
"args": buildpb.Attribute_STRING_LIST,
"artifact": buildpb.Attribute_STRING,
"asset_catalogs": buildpb.Attribute_LABEL_LIST,
"assets": buildpb.Attribute_LABEL_LIST,
"assets_dir": buildpb.Attribute_STRING,
"avoid_deps": buildpb.Attribute_LABEL_LIST,
"binary": buildpb.Attribute_LABEL,
"binary_type": buildpb.Attribute_STRING,
"blacklisted_protos": buildpb.Attribute_LABEL_LIST,
"bootclasspath": buildpb.Attribute_LABEL_LIST,
"build_file": buildpb.Attribute_STRING,
"build_file_content": buildpb.Attribute_STRING,
"bundle_id": buildpb.Attribute_STRING,
"bundle_imports": buildpb.Attribute_LABEL_LIST,
"bundle_loader": buildpb.Attribute_LABEL,
"bundles": buildpb.Attribute_LABEL_LIST,
"classpath_resources": buildpb.Attribute_LABEL_LIST,
"cmd": buildpb.Attribute_STRING,
"command_line": buildpb.Attribute_STRING,
"commit": buildpb.Attribute_STRING,
"compatible_with": buildpb.Attribute_LABEL_LIST,
"compiler_files": buildpb.Attribute_LABEL,
"constraints": buildpb.Attribute_STRING_LIST,
"copts": buildpb.Attribute_STRING_LIST,
"cpu": buildpb.Attribute_STRING,
"create_executable": buildpb.Attribute_BOOLEAN,
"crunch_png": buildpb.Attribute_BOOLEAN,
"custom_package": buildpb.Attribute_STRING,
"data": buildpb.Attribute_LABEL_LIST,
"datamodels": buildpb.Attribute_LABEL_LIST,
"default": buildpb.Attribute_LABEL,
"default_copts": buildpb.Attribute_STRING_LIST,
"default_deprecation": buildpb.Attribute_STRING,
"default_hdrs_check": buildpb.Attribute_STRING,
"default_ios_sdk_version": buildpb.Attribute_STRING,
"default_macosx_sdk_version": buildpb.Attribute_STRING,
"default_python_version": buildpb.Attribute_STRING,
"default_testonly": buildpb.Attribute_BOOLEAN,
"default_tvos_sdk_version": buildpb.Attribute_STRING,
"default_visibility": buildpb.Attribute_STRING_LIST,
"default_watchos_sdk_version": buildpb.Attribute_STRING,
"defines": buildpb.Attribute_STRING_LIST,
"densities": buildpb.Attribute_STRING_LIST,
"deploy_manifest_lines": buildpb.Attribute_STRING_LIST,
"deprecation": buildpb.Attribute_STRING,
"deps": buildpb.Attribute_LABEL_LIST,
"dex_shards": buildpb.Attribute_INTEGER,
"dexopts": buildpb.Attribute_STRING_LIST,
"distribs": buildpb.Attribute_DISTRIBUTION_SET,
"dwp_files": buildpb.Attribute_LABEL,
"dylibs": buildpb.Attribute_LABEL_LIST,
"dynamic_runtime_libs": buildpb.Attribute_LABEL_LIST,
"enable_modules": buildpb.Attribute_BOOLEAN,
"encoding": buildpb.Attribute_STRING,
"entitlements": buildpb.Attribute_LABEL,
"entry_classes": buildpb.Attribute_STRING_LIST,
"executable": buildpb.Attribute_BOOLEAN,
"exported_plugins": buildpb.Attribute_LABEL_LIST,
"exports": buildpb.Attribute_LABEL_LIST,
"exports_manifest": buildpb.Attribute_BOOLEAN,
"expression": buildpb.Attribute_STRING,
"ext_bundle_id": buildpb.Attribute_STRING,
"ext_entitlements": buildpb.Attribute_LABEL,
"ext_families": buildpb.Attribute_STRING_LIST,
"ext_infoplists": buildpb.Attribute_LABEL_LIST,
"ext_provisioning_profile": buildpb.Attribute_LABEL,
"ext_resources": buildpb.Attribute_LABEL_LIST,
"ext_strings": buildpb.Attribute_LABEL_LIST,
"ext_structured_resources": buildpb.Attribute_LABEL_LIST,
"extclasspath": buildpb.Attribute_LABEL_LIST,
"extensions": buildpb.Attribute_LABEL_LIST,
"extra_actions": buildpb.Attribute_LABEL_LIST,
"extra_srcs": buildpb.Attribute_LABEL_LIST,
"families": buildpb.Attribute_STRING_LIST,
"features": buildpb.Attribute_STRING_LIST,
"flaky": buildpb.Attribute_BOOLEAN,
"framework_imports": buildpb.Attribute_LABEL_LIST,
"genclass": buildpb.Attribute_LABEL_LIST,
"generates_api": buildpb.Attribute_BOOLEAN,
"hdrs": buildpb.Attribute_LABEL_LIST,
"header_compiler": buildpb.Attribute_LABEL_LIST,
"heuristic_label_expansion": buildpb.Attribute_BOOLEAN,
"idl_import_root": buildpb.Attribute_STRING,
"idl_parcelables": buildpb.Attribute_LABEL_LIST,
"idl_srcs": buildpb.Attribute_LABEL_LIST,
"ijar": buildpb.Attribute_LABEL_LIST,
"imports": buildpb.Attribute_STRING_LIST,
"includes": buildpb.Attribute_STRING_LIST,
"incremental_dexing": buildpb.Attribute_TRISTATE,
"infoplist": buildpb.Attribute_LABEL,
"infoplists": buildpb.Attribute_LABEL_LIST,
"init_submodules": buildpb.Attribute_BOOLEAN,
"ios_device_arg": buildpb.Attribute_STRING_LIST,
"ios_test_target_device": buildpb.Attribute_LABEL,
"ios_version": buildpb.Attribute_STRING,
"ipa_post_processor": buildpb.Attribute_LABEL,
"is_dynamic": buildpb.Attribute_BOOLEAN,
"jars": buildpb.Attribute_LABEL_LIST,
"javabuilder": buildpb.Attribute_LABEL_LIST,
"javac": buildpb.Attribute_LABEL_LIST,
"javac_supports_workers": buildpb.Attribute_BOOLEAN,
"javacopts": buildpb.Attribute_STRING_LIST,
"jre_deps": buildpb.Attribute_LABEL_LIST,
"jvm_flags": buildpb.Attribute_STRING_LIST,
"jvm_opts": buildpb.Attribute_STRING_LIST,
"launch_image": buildpb.Attribute_STRING,
"launch_storyboard": buildpb.Attribute_LABEL,
"launcher": buildpb.Attribute_LABEL,
"licenses": buildpb.Attribute_LICENSE,
"linker_files": buildpb.Attribute_LABEL,
"linkopts": buildpb.Attribute_STRING_LIST,
"linkshared": buildpb.Attribute_BOOLEAN,
"linkstamp": buildpb.Attribute_LABEL,
"linkstatic": buildpb.Attribute_BOOLEAN,
"local": buildpb.Attribute_BOOLEAN,
"main": buildpb.Attribute_LABEL,
"main_class": buildpb.Attribute_STRING,
"main_dex_list": buildpb.Attribute_LABEL,
"main_dex_list_opts": buildpb.Attribute_STRING_LIST,
"main_dex_proguard_specs": buildpb.Attribute_LABEL_LIST,
"malloc": buildpb.Attribute_LABEL,
"manifest": buildpb.Attribute_LABEL,
"manifest_merger": buildpb.Attribute_STRING,
"manifest_values": buildpb.Attribute_STRING_DICT,
"message": buildpb.Attribute_STRING,
"misc": buildpb.Attribute_STRING_LIST,
"mnemonics": buildpb.Attribute_STRING_LIST,
"module_map": buildpb.Attribute_LABEL,
"multidex": buildpb.Attribute_STRING,
"name": buildpb.Attribute_STRING,
"neverlink": buildpb.Attribute_BOOLEAN,
"nocompress_extensions": buildpb.Attribute_STRING_LIST,
"nocopts": buildpb.Attribute_STRING,
"non_arc_srcs": buildpb.Attribute_LABEL_LIST,
"non_propagated_deps": buildpb.Attribute_LABEL_LIST,
"objcopy_files": buildpb.Attribute_LABEL,
"options_file": buildpb.Attribute_LABEL,
"opts": buildpb.Attribute_STRING_LIST,
"out": buildpb.Attribute_STRING,
"out_templates": buildpb.Attribute_STRING_LIST,
"output_group": buildpb.Attribute_STRING,
"output_licenses": buildpb.Attribute_LICENSE,
"output_to_bindir": buildpb.Attribute_BOOLEAN,
"outs": buildpb.Attribute_STRING_LIST,
"path": buildpb.Attribute_STRING,
"pch": buildpb.Attribute_LABEL,
"per_proto_includes": buildpb.Attribute_BOOLEAN,
"platform_type": buildpb.Attribute_STRING,
"plugin": buildpb.Attribute_LABEL,
"plugins": buildpb.Attribute_LABEL_LIST,
"portable_proto_filters": buildpb.Attribute_LABEL_LIST,
"prefix": buildpb.Attribute_STRING,
"processor_class": buildpb.Attribute_STRING,
"proguard_apply_mapping": buildpb.Attribute_LABEL,
"proguard_generate_mapping": buildpb.Attribute_BOOLEAN,
"proguard_specs": buildpb.Attribute_LABEL_LIST,
"provisioning_profile": buildpb.Attribute_LABEL,
"pytype_deps": buildpb.Attribute_LABEL_LIST,
"remote": buildpb.Attribute_STRING,
"repository": buildpb.Attribute_STRING,
"require_defined_version": buildpb.Attribute_BOOLEAN,
"requires_action_output": buildpb.Attribute_BOOLEAN,
"resource_configuration_filters": buildpb.Attribute_STRING_LIST,
"resource_files": buildpb.Attribute_LABEL_LIST,
"resource_strip_prefix": buildpb.Attribute_STRING,
"resources": buildpb.Attribute_LABEL_LIST,
"restricted_to": buildpb.Attribute_LABEL_LIST,
"runtime": buildpb.Attribute_LABEL,
"runtime_deps": buildpb.Attribute_LABEL_LIST,
"scope": buildpb.Attribute_LABEL_LIST,
"sdk_dylibs": buildpb.Attribute_STRING_LIST,
"sdk_frameworks": buildpb.Attribute_STRING_LIST,
"sdk_includes": buildpb.Attribute_STRING_LIST,
"server": buildpb.Attribute_STRING,
"settings_file": buildpb.Attribute_STRING,
"sha1": buildpb.Attribute_STRING,
"sha256": buildpb.Attribute_STRING,
"shard_count": buildpb.Attribute_INTEGER,
"singlejar": buildpb.Attribute_LABEL_LIST,
"size": buildpb.Attribute_STRING,
"source_version": buildpb.Attribute_STRING,
"srcjar": buildpb.Attribute_LABEL,
"srcs": buildpb.Attribute_LABEL_LIST,
"srcs_version": buildpb.Attribute_STRING,
"stamp": buildpb.Attribute_TRISTATE,
"static_runtime_libs": buildpb.Attribute_LABEL_LIST,
"storyboards": buildpb.Attribute_LABEL_LIST,
"strict": buildpb.Attribute_BOOLEAN,
"strings": buildpb.Attribute_LABEL_LIST,
"strip": buildpb.Attribute_BOOLEAN,
"strip_files": buildpb.Attribute_LABEL,
"strip_prefix": buildpb.Attribute_STRING,
"structured_resources": buildpb.Attribute_LABEL_LIST,
"supports_header_parsing": buildpb.Attribute_BOOLEAN,
"supports_param_files": buildpb.Attribute_BOOLEAN,
"tag": buildpb.Attribute_STRING,
"tags": buildpb.Attribute_STRING_LIST,
"target_device": buildpb.Attribute_LABEL,
"target_version": buildpb.Attribute_STRING,
"test_class": buildpb.Attribute_STRING,
"testonly": buildpb.Attribute_BOOLEAN,
"tests": buildpb.Attribute_LABEL_LIST,
"textual_hdrs": buildpb.Attribute_LABEL_LIST,
"timeout": buildpb.Attribute_STRING,
"toolchains": buildpb.Attribute_LABEL_LIST,
"tools": buildpb.Attribute_LABEL_LIST,
"type": buildpb.Attribute_STRING,
"url": buildpb.Attribute_STRING,
"use_objc_header_names": buildpb.Attribute_BOOLEAN,
"use_testrunner": buildpb.Attribute_BOOLEAN,
"values": buildpb.Attribute_STRING_DICT,
"version": buildpb.Attribute_STRING,
"versions": buildpb.Attribute_LABEL_LIST,
"visibility": buildpb.Attribute_STRING_LIST,
"weak_sdk_frameworks": buildpb.Attribute_STRING_LIST,
"xcode": buildpb.Attribute_LABEL,
"xctest": buildpb.Attribute_BOOLEAN,
"xctest_app": buildpb.Attribute_LABEL,
"xibs": buildpb.Attribute_LABEL_LIST,
"xlint": buildpb.Attribute_STRING_LIST,
}

24
vendor/github.com/bazelbuild/buildtools/wspace/BUILD generated vendored Normal file
View File

@ -0,0 +1,24 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["workspace.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/bazelbuild/buildtools/wspace",
importpath = "github.com/bazelbuild/buildtools/wspace",
visibility = ["//visibility:public"],
deps = ["//vendor/github.com/bazelbuild/buildtools/build:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,114 @@
/*
Copyright 2016 Google Inc. All Rights Reserved.
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 wspace provides a method to find the root of the bazel tree.
package wspace
import (
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/bazelbuild/buildtools/build"
)
const workspaceFile = "WORKSPACE"
func alwaysTrue(fi os.FileInfo) bool {
return true
}
var repoRootFiles = map[string]func(os.FileInfo) bool{
workspaceFile: alwaysTrue,
".buckconfig": alwaysTrue,
"pants": func(fi os.FileInfo) bool {
return fi.Mode()&os.ModeType == 0 && fi.Mode()&0100 == 0100
},
}
// findContextPath finds the context path inside of a WORKSPACE-rooted source tree.
func findContextPath(rootDir string) (string, error) {
if rootDir == "" {
return os.Getwd()
}
return rootDir, nil
}
// FindWorkspaceRoot splits the current code context (the rootDir if present,
// the working directory if not.) It returns the path of the directory
// containing the WORKSPACE file, and the rest.
func FindWorkspaceRoot(rootDir string) (root string, rest string) {
wd, err := findContextPath(rootDir)
if err != nil {
return "", ""
}
if root, err = Find(wd); err != nil {
return "", ""
}
if len(wd) == len(root) {
return root, ""
}
return root, wd[len(root)+1:]
}
// Find searches from the given dir and up for the WORKSPACE file
// returning the directory containing it, or an error if none found in the tree.
func Find(dir string) (string, error) {
if dir == "" || dir == "/" || dir == "." {
return "", os.ErrNotExist
}
for repoRootFile, fiFunc := range repoRootFiles {
if fi, err := os.Stat(filepath.Join(dir, repoRootFile)); err == nil && fiFunc(fi) {
return dir, nil
} else if !os.IsNotExist(err) {
return "", err
}
}
return Find(filepath.Dir(dir))
}
// FindRepoBuildFiles parses the WORKSPACE to find BUILD files for non-Bazel
// external repositories, specifically those defined by one of these rules:
// new_local_repository(), new_git_repository(), new_http_archive()
func FindRepoBuildFiles(root string) (map[string]string, error) {
ws := filepath.Join(root, workspaceFile)
kinds := []string{
"new_local_repository",
"new_git_repository",
"new_http_archive",
}
data, err := ioutil.ReadFile(ws)
if err != nil {
return nil, err
}
ast, err := build.Parse(ws, data)
if err != nil {
return nil, err
}
files := make(map[string]string)
for _, kind := range kinds {
for _, r := range ast.Rules(kind) {
buildFile := r.AttrString("build_file")
if buildFile == "" {
continue
}
buildFile = strings.Replace(buildFile, ":", "/", -1)
files[r.Name()] = filepath.Join(root, buildFile)
}
}
return files, nil
}

View File

@ -12,6 +12,7 @@ go_library(
go_binary(
name = "prettybench",
embed = [":go_default_library"],
tags = ["manual"],
visibility = ["//visibility:public"],
)

View File

@ -12,6 +12,7 @@ go_library(
go_binary(
name = "misspell",
embed = [":go_default_library"],
tags = ["manual"],
visibility = ["//visibility:public"],
)

View File

@ -36,6 +36,7 @@ go_library(
go_binary(
name = "cfssl",
embed = [":go_default_library"],
tags = ["manual"],
visibility = ["//visibility:public"],
)

View File

@ -12,6 +12,7 @@ go_library(
go_binary(
name = "cfssljson",
embed = [":go_default_library"],
tags = ["manual"],
visibility = ["//visibility:public"],
)

View File

@ -15,6 +15,7 @@ go_library(
go_binary(
name = "go-junit-report",
embed = [":go_default_library"],
tags = ["manual"],
visibility = ["//visibility:public"],
)

View File

@ -16,6 +16,7 @@ go_library(
go_binary(
name = "go-bindata",
embed = [":go_default_library"],
tags = ["manual"],
visibility = ["//visibility:public"],
)

View File

@ -37,6 +37,7 @@ go_library(
go_binary(
name = "ginkgo",
embed = [":go_default_library"],
tags = ["manual"],
visibility = ["//visibility:public"],
)

View File

@ -16,6 +16,7 @@ go_library(
go_binary(
name = "golint",
embed = [":go_default_library"],
tags = ["manual"],
visibility = ["//visibility:public"],
)

View File

@ -17,6 +17,7 @@ go_library(
go_binary(
name = "openapi-gen",
embed = [":go_default_library"],
tags = ["manual"],
visibility = ["//visibility:public"],
)

View File

@ -21,6 +21,7 @@ go_library(
go_binary(
name = "kazel",
embed = [":go_default_library"],
tags = ["manual"],
visibility = ["//visibility:public"],
)