From b40260dfcd07032a9f00980ec9451dd4bd5b8eda Mon Sep 17 00:00:00 2001 From: LaMont Jones Date: Wed, 6 Nov 2024 12:26:10 -0800 Subject: Add find_input_delta Find_input_delta takes a list of input files and determines what files have changed since the last time that it was run. Bug: b/376287012 Test: Manual, TH Change-Id: Idaa0612e8aef8980de1955cbad8a4e4b2b0953ac --- cmd/find_input_delta/find_input_delta/Android.bp | 18 ++ cmd/find_input_delta/find_input_delta/main.go | 88 +++++++ .../find_input_delta_lib/Android.bp | 34 +++ .../find_input_delta_lib/file_list.go | 78 ++++++ .../find_input_delta_lib/file_list_test.go | 131 ++++++++++ cmd/find_input_delta/find_input_delta_lib/fs.go | 46 ++++ .../find_input_delta_lib/internal_state.go | 122 ++++++++++ .../find_input_delta_lib/internal_state_test.go | 232 ++++++++++++++++++ .../find_input_delta_proto/Android.bp | 29 +++ .../find_input_delta_proto/file_list.pb.go | 198 +++++++++++++++ .../find_input_delta_proto/file_list.proto | 34 +++ .../find_input_delta_proto/regen.sh | 3 + .../find_input_delta_proto_internal/Android.bp | 29 +++ .../internal_state.pb.go | 268 +++++++++++++++++++++ .../internal_state.proto | 39 +++ .../find_input_delta_proto_internal/regen.sh | 3 + 16 files changed, 1352 insertions(+) create mode 100644 cmd/find_input_delta/find_input_delta/Android.bp create mode 100644 cmd/find_input_delta/find_input_delta/main.go create mode 100644 cmd/find_input_delta/find_input_delta_lib/Android.bp create mode 100644 cmd/find_input_delta/find_input_delta_lib/file_list.go create mode 100644 cmd/find_input_delta/find_input_delta_lib/file_list_test.go create mode 100644 cmd/find_input_delta/find_input_delta_lib/fs.go create mode 100644 cmd/find_input_delta/find_input_delta_lib/internal_state.go create mode 100644 cmd/find_input_delta/find_input_delta_lib/internal_state_test.go create mode 100644 cmd/find_input_delta/find_input_delta_proto/Android.bp create mode 100644 cmd/find_input_delta/find_input_delta_proto/file_list.pb.go create mode 100644 cmd/find_input_delta/find_input_delta_proto/file_list.proto create mode 100644 cmd/find_input_delta/find_input_delta_proto/regen.sh create mode 100644 cmd/find_input_delta/find_input_delta_proto_internal/Android.bp create mode 100644 cmd/find_input_delta/find_input_delta_proto_internal/internal_state.pb.go create mode 100644 cmd/find_input_delta/find_input_delta_proto_internal/internal_state.proto create mode 100644 cmd/find_input_delta/find_input_delta_proto_internal/regen.sh (limited to 'cmd') diff --git a/cmd/find_input_delta/find_input_delta/Android.bp b/cmd/find_input_delta/find_input_delta/Android.bp new file mode 100644 index 000000000..6b2dbc764 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta/Android.bp @@ -0,0 +1,18 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +bootstrap_go_package { + name: "soong-cmd-find_input_delta-find_input_delta", + pkgPath: "android/soong/cmd/find_input_delta/find_input_delta", + deps: [ + "golang-protobuf-encoding-prototext", + "golang-protobuf-reflect-protoreflect", + "golang-protobuf-runtime-protoimpl", + "soong-cmd-find_input_delta-proto", + "soong-cmd-find_input_delta-lib", + ], + srcs: [ + "main.go", + ], +} diff --git a/cmd/find_input_delta/find_input_delta/main.go b/cmd/find_input_delta/find_input_delta/main.go new file mode 100644 index 000000000..6b657ea57 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta/main.go @@ -0,0 +1,88 @@ +// Copyright 2024 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 main + +import ( + "flag" + "os" + "strings" + + fid_lib "android/soong/cmd/find_input_delta/find_input_delta_lib" +) + +func main() { + var top string + var prior_state_file string + var new_state_file string + var target string + var inputs_file string + var template string + var inputs []string + var inspect bool + var err error + + flag.StringVar(&top, "top", ".", "path to top of workspace") + flag.StringVar(&prior_state_file, "prior_state", "", "prior internal state file") + flag.StringVar(&new_state_file, "new_state", "", "new internal state file") + flag.StringVar(&target, "target", "", "name of ninja output file for build action") + flag.StringVar(&inputs_file, "inputs_file", "", "file containing list of input files") + flag.StringVar(&template, "template", fid_lib.DefaultTemplate, "output template for FileList") + flag.BoolVar(&inspect, "inspect", false, "whether to inspect file contents") + + flag.Parse() + + if target == "" { + panic("must specify --target") + } + if prior_state_file == "" { + prior_state_file = target + ".pc_state" + } + if new_state_file == "" { + new_state_file = prior_state_file + ".new" + } + + if err = os.Chdir(top); err != nil { + panic(err) + } + + inputs = flag.Args() + if inputs_file != "" { + data, err := os.ReadFile(inputs_file) + if err != nil { + panic(err) + } + inputs = append(inputs, strings.Split(string(data), "\n")...) + } + + // Read the prior state + prior_state, err := fid_lib.LoadState(prior_state_file, fid_lib.OsFs) + if err != nil { + panic(err) + } + // Create the new state + new_state, err := fid_lib.CreateState(inputs, inspect, fid_lib.OsFs) + if err != nil { + panic(err) + } + if err = fid_lib.WriteState(new_state, new_state_file); err != nil { + panic(err) + } + + file_list := *fid_lib.CompareInternalState(prior_state, new_state, target) + + if err = file_list.Format(os.Stdout, template); err != nil { + panic(err) + } +} diff --git a/cmd/find_input_delta/find_input_delta_lib/Android.bp b/cmd/find_input_delta/find_input_delta_lib/Android.bp new file mode 100644 index 000000000..795b14038 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_lib/Android.bp @@ -0,0 +1,34 @@ +// Copyright 2024 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 { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +bootstrap_go_package { + name: "soong-cmd-find_input_delta-lib", + pkgPath: "android/soong/cmd/find_input_delta/find_input_delta_lib", + deps: [ + "golang-protobuf-encoding-prototext", + "golang-protobuf-reflect-protoreflect", + "golang-protobuf-runtime-protoimpl", + "soong-cmd-find_input_delta-proto", + "blueprint-pathtools", + ], + srcs: [ + "fs.go", + "file_list.go", + "internal_state.go", + ], +} diff --git a/cmd/find_input_delta/find_input_delta_lib/file_list.go b/cmd/find_input_delta/find_input_delta_lib/file_list.go new file mode 100644 index 000000000..23337adc3 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_lib/file_list.go @@ -0,0 +1,78 @@ +// Copyright 2024 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 find_input_delta_lib + +import ( + "io" + "text/template" + + fid_exp "android/soong/cmd/find_input_delta/find_input_delta_proto" + "google.golang.org/protobuf/proto" +) + +var DefaultTemplate = ` + {{- define "contents"}} + {{- range .Deletions}}-{{.}} {{end}} + {{- range .Additions}}+{{.}} {{end}} + {{- range .Changes}}+{{- .Name}} {{end}} + {{- range .Changes}} + {{- if or .Additions .Deletions .Changes}}--file {{.Name}} {{template "contents" .}}--endfile {{end}} + {{- end}} + {{- end}} + {{- template "contents" .}}` + +type FileList struct { + // The name of the parent for the list of file differences. + // For the outermost FileList, this is the name of the ninja target. + // Under `Changes`, it is the name of the changed file. + Name string + + // The added files + Additions []string + + // The deleted files + Deletions []string + + // The modified files + Changes []FileList +} + +func (fl FileList) Marshal() (*fid_exp.FileList, error) { + ret := &fid_exp.FileList{ + Name: proto.String(fl.Name), + } + if len(fl.Additions) > 0 { + ret.Additions = fl.Additions + } + for _, ch := range fl.Changes { + change, err := ch.Marshal() + if err != nil { + return nil, err + } + ret.Changes = append(ret.Changes, change) + } + if len(fl.Deletions) > 0 { + ret.Deletions = fl.Deletions + } + return ret, nil +} + +func (fl FileList) Format(wr io.Writer, format string) error { + tmpl, err := template.New("filelist").Parse(format) + if err != nil { + return err + } + return tmpl.Execute(wr, fl) +} diff --git a/cmd/find_input_delta/find_input_delta_lib/file_list_test.go b/cmd/find_input_delta/find_input_delta_lib/file_list_test.go new file mode 100644 index 000000000..2459f1ead --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_lib/file_list_test.go @@ -0,0 +1,131 @@ +// Copyright 2024 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 find_input_delta_lib + +import ( + "bytes" + "slices" + "testing" + + // For Assert*. + "android/soong/android" +) + +func (fl *FileList) Equal(other *FileList) bool { + if fl.Name != other.Name { + return false + } + if !slices.Equal(fl.Additions, other.Additions) { + return false + } + if !slices.Equal(fl.Deletions, other.Deletions) { + return false + } + if len(fl.Changes) != len(other.Changes) { + return false + } + for idx, ch := range fl.Changes { + if !ch.Equal(&other.Changes[idx]) { + return false + } + } + return true +} + +func TestFormat(t *testing.T) { + testCases := []struct { + Name string + Template string + Input FileList + Expected string + Err error + }{ + { + Name: "no contents", + Template: DefaultTemplate, + Input: FileList{ + Name: "target", + Additions: []string{"add1", "add2"}, + Deletions: []string{"del1", "del2"}, + Changes: []FileList{ + FileList{Name: "mod1"}, + FileList{Name: "mod2"}, + }, + }, + Expected: "-del1 -del2 +add1 +add2 +mod1 +mod2 ", + Err: nil, + }, + { + Name: "adds", + Template: DefaultTemplate, + Input: FileList{ + Name: "target", + Additions: []string{"add1", "add2"}, + }, + Expected: "+add1 +add2 ", + Err: nil, + }, + { + Name: "deletes", + Template: DefaultTemplate, + Input: FileList{ + Name: "target", + Deletions: []string{"del1", "del2"}, + }, + Expected: "-del1 -del2 ", + Err: nil, + }, + { + Name: "changes", + Template: DefaultTemplate, + Input: FileList{ + Name: "target", + Changes: []FileList{ + FileList{Name: "mod1"}, + FileList{Name: "mod2"}, + }, + }, + Expected: "+mod1 +mod2 ", + Err: nil, + }, + { + Name: "with contents", + Template: DefaultTemplate, + Input: FileList{ + Name: "target", + Additions: []string{"add1", "add2"}, + Deletions: []string{"del1", "del2"}, + Changes: []FileList{ + FileList{ + Name: "mod1", + }, + FileList{ + Name: "mod2", + Additions: []string{"a1"}, + Deletions: []string{"d1"}, + }, + }, + }, + Expected: "-del1 -del2 +add1 +add2 +mod1 +mod2 --file mod2 -d1 +a1 --endfile ", + Err: nil, + }, + } + for _, tc := range testCases { + buf := bytes.NewBuffer([]byte{}) + err := tc.Input.Format(buf, tc.Template) + android.AssertSame(t, tc.Name, tc.Err, err) + android.AssertSame(t, tc.Name, tc.Expected, buf.String()) + } +} diff --git a/cmd/find_input_delta/find_input_delta_lib/fs.go b/cmd/find_input_delta/find_input_delta_lib/fs.go new file mode 100644 index 000000000..4a83ed7ff --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_lib/fs.go @@ -0,0 +1,46 @@ +// Copyright 2024 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 find_input_delta_lib + +import ( + "io" + "io/fs" + "os" +) + +// OsFs provides a minimal implementation so that we can use testing/fstest for +// unit tests. +var OsFs fileSystem = osFS{} + +type fileSystem interface { + Open(path string) (fs.File, error) + Stat(path string) (os.FileInfo, error) + ReadFile(path string) ([]byte, error) +} + +type file interface { + io.Closer + io.Reader + io.ReaderAt + io.Seeker + Stat() (os.FileInfo, error) +} + +// osFS implements fileSystem using the local disk. +type osFS struct{} + +func (osFS) Open(path string) (fs.File, error) { return os.Open(path) } +func (osFS) Stat(path string) (os.FileInfo, error) { return os.Stat(path) } +func (osFS) ReadFile(path string) ([]byte, error) { return os.ReadFile(path) } diff --git a/cmd/find_input_delta/find_input_delta_lib/internal_state.go b/cmd/find_input_delta/find_input_delta_lib/internal_state.go new file mode 100644 index 000000000..b2ff8c704 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_lib/internal_state.go @@ -0,0 +1,122 @@ +// Copyright 2024 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 find_input_delta_lib + +import ( + "errors" + "fmt" + "io/fs" + "slices" + + fid_proto "android/soong/cmd/find_input_delta/find_input_delta_proto_internal" + "github.com/google/blueprint/pathtools" + "google.golang.org/protobuf/proto" +) + +// Load the internal state from a file. +// If the file does not exist, an empty state is returned. +func LoadState(filename string, fsys fs.ReadFileFS) (*fid_proto.PartialCompileInputs, error) { + var message = &fid_proto.PartialCompileInputs{} + data, err := fsys.ReadFile(filename) + if err != nil && !errors.Is(err, fs.ErrNotExist) { + return message, err + } + proto.Unmarshal(data, message) + return message, nil +} + +type StatReadFileFS interface { + fs.StatFS + fs.ReadFileFS +} + +// Create the internal state by examining the inputs. +func CreateState(inputs []string, inspect_contents bool, fsys StatReadFileFS) (*fid_proto.PartialCompileInputs, error) { + ret := &fid_proto.PartialCompileInputs{} + slices.Sort(inputs) + for _, input := range inputs { + stat, err := fs.Stat(fsys, input) + if err != nil { + return ret, err + } + pci := &fid_proto.PartialCompileInput{ + Name: proto.String(input), + MtimeNsec: proto.Int64(stat.ModTime().UnixNano()), + // If we ever have an easy hash, assign it here. + } + if inspect_contents { + contents, err := InspectFileContents(input) + if err != nil { + return ret, err + } + if contents != nil { + pci.Contents = contents + } + } + ret.InputFiles = append(ret.InputFiles, pci) + } + return ret, nil +} + +// Inspect the file and extract the state of the elements in the archive. +// If this is not an archive of some sort, nil is returned. +func InspectFileContents(name string) ([]*fid_proto.PartialCompileInput, error) { + // TODO: Actually inspect the contents. + fmt.Printf("inspecting contents for %s\n", name) + return nil, nil +} + +func WriteState(s *fid_proto.PartialCompileInputs, path string) error { + data, err := proto.Marshal(s) + if err != nil { + return err + } + return pathtools.WriteFileIfChanged(path, data, 0644) +} + +func CompareInternalState(prior, other *fid_proto.PartialCompileInputs, target string) *FileList { + return CompareInputFiles(prior.GetInputFiles(), other.GetInputFiles(), target) +} + +func CompareInputFiles(prior, other []*fid_proto.PartialCompileInput, name string) *FileList { + fl := &FileList{ + Name: name, + } + PriorMap := make(map[string]*fid_proto.PartialCompileInput, len(prior)) + // We know that the lists are properly sorted, so we can simply compare them. + for _, v := range prior { + PriorMap[v.GetName()] = v + } + otherMap := make(map[string]*fid_proto.PartialCompileInput, len(other)) + for _, v := range other { + name = v.GetName() + otherMap[name] = v + if _, ok := PriorMap[name]; !ok { + // Added file + fl.Additions = append(fl.Additions, name) + } else if !proto.Equal(PriorMap[name], v) { + // Changed file + fl.Changes = append(fl.Changes, *CompareInputFiles(PriorMap[name].GetContents(), v.GetContents(), name)) + } + } + for _, v := range prior { + name := v.GetName() + if _, ok := otherMap[name]; !ok { + // Deleted file + fl.Deletions = append(fl.Deletions, name) + } + } + return fl +} diff --git a/cmd/find_input_delta/find_input_delta_lib/internal_state_test.go b/cmd/find_input_delta/find_input_delta_lib/internal_state_test.go new file mode 100644 index 000000000..20b8efaa8 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_lib/internal_state_test.go @@ -0,0 +1,232 @@ +// Copyright 2024 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 find_input_delta_lib + +import ( + "errors" + "io/fs" + "testing" + "testing/fstest" + "time" + + // For Assert*. + "android/soong/android" + + fid_proto "android/soong/cmd/find_input_delta/find_input_delta_proto_internal" + "google.golang.org/protobuf/proto" +) + +// Various state files + +func marshalProto(t *testing.T, message proto.Message) []byte { + data, err := proto.Marshal(message) + if err != nil { + t.Errorf("%v", err) + } + return data +} + +func protoFile(name string, mtime_nsec int64, hash string, contents []*fid_proto.PartialCompileInput) (pci *fid_proto.PartialCompileInput) { + pci = &fid_proto.PartialCompileInput{ + Name: proto.String(name), + } + if mtime_nsec != 0 { + pci.MtimeNsec = proto.Int64(mtime_nsec) + } + if len(hash) > 0 { + pci.Hash = proto.String(hash) + } + if contents != nil { + pci.Contents = contents + } + return +} + +func TestLoadState(t *testing.T) { + testCases := []struct { + Name string + Filename string + Mapfs fs.ReadFileFS + Expected *fid_proto.PartialCompileInputs + Err error + }{ + { + Name: "missing file", + Filename: "missing", + Mapfs: fstest.MapFS{}, + Expected: &fid_proto.PartialCompileInputs{}, + Err: nil, + }, + { + Name: "bad file", + Filename: ".", + Mapfs: OsFs, + Expected: &fid_proto.PartialCompileInputs{}, + Err: errors.New("read failed"), + }, + { + Name: "file with mtime", + Filename: "state.old", + Mapfs: fstest.MapFS{ + "state.old": &fstest.MapFile{ + Data: marshalProto(t, &fid_proto.PartialCompileInputs{ + InputFiles: []*fid_proto.PartialCompileInput{ + protoFile("input1", 100, "", nil), + }, + }), + }, + }, + Expected: &fid_proto.PartialCompileInputs{ + InputFiles: []*fid_proto.PartialCompileInput{ + protoFile("input1", 100, "", nil), + }, + }, + Err: nil, + }, + { + Name: "file with mtime and hash", + Filename: "state.old", + Mapfs: fstest.MapFS{ + "state.old": &fstest.MapFile{ + Data: marshalProto(t, &fid_proto.PartialCompileInputs{ + InputFiles: []*fid_proto.PartialCompileInput{ + protoFile("input1", 100, "crc:crc_value", nil), + }, + }), + }, + }, + Expected: &fid_proto.PartialCompileInputs{ + InputFiles: []*fid_proto.PartialCompileInput{ + protoFile("input1", 100, "crc:crc_value", nil), + }, + }, + Err: nil, + }, + } + for _, tc := range testCases { + actual, err := LoadState(tc.Filename, tc.Mapfs) + if tc.Err == nil { + android.AssertSame(t, tc.Name, tc.Err, err) + } else if err == nil { + t.Errorf("%s: expected error, did not get one", tc.Name) + } + if !proto.Equal(tc.Expected, actual) { + t.Errorf("%s: expected %v, actual %v", tc.Name, tc.Expected, actual) + } + } +} + +func TestCreateState(t *testing.T) { + testCases := []struct { + Name string + Inputs []string + Inspect bool + Mapfs StatReadFileFS + Expected *fid_proto.PartialCompileInputs + Err error + }{ + { + Name: "no inputs", + Inputs: []string{}, + Mapfs: fstest.MapFS{}, + Expected: &fid_proto.PartialCompileInputs{}, + Err: nil, + }, + { + Name: "files found", + Inputs: []string{"baz", "foo", "bar"}, + Mapfs: fstest.MapFS{ + "foo": &fstest.MapFile{ModTime: time.Unix(0, 100).UTC()}, + "baz": &fstest.MapFile{ModTime: time.Unix(0, 300).UTC()}, + "bar": &fstest.MapFile{ModTime: time.Unix(0, 200).UTC()}, + }, + Expected: &fid_proto.PartialCompileInputs{ + InputFiles: []*fid_proto.PartialCompileInput{ + // Files are always sorted. + protoFile("bar", 200, "", nil), + protoFile("baz", 300, "", nil), + protoFile("foo", 100, "", nil), + }, + }, + Err: nil, + }, + } + for _, tc := range testCases { + actual, err := CreateState(tc.Inputs, tc.Inspect, tc.Mapfs) + if tc.Err == nil { + android.AssertSame(t, tc.Name, tc.Err, err) + } else if err == nil { + t.Errorf("%s: expected error, did not get one", tc.Name) + } + if !proto.Equal(tc.Expected, actual) { + t.Errorf("%s: expected %v, actual %v", tc.Name, tc.Expected, actual) + } + } +} + +func TestCompareInternalState(t *testing.T) { + testCases := []struct { + Name string + Target string + Prior *fid_proto.PartialCompileInputs + New *fid_proto.PartialCompileInputs + Expected *FileList + }{ + { + Name: "prior is empty", + Target: "foo", + Prior: &fid_proto.PartialCompileInputs{}, + New: &fid_proto.PartialCompileInputs{ + InputFiles: []*fid_proto.PartialCompileInput{ + protoFile("file1", 100, "", nil), + }, + }, + Expected: &FileList{ + Name: "foo", + Additions: []string{"file1"}, + }, + }, + { + Name: "one of each", + Target: "foo", + Prior: &fid_proto.PartialCompileInputs{ + InputFiles: []*fid_proto.PartialCompileInput{ + protoFile("file0", 100, "", nil), + protoFile("file1", 100, "", nil), + protoFile("file2", 200, "", nil), + }, + }, + New: &fid_proto.PartialCompileInputs{ + InputFiles: []*fid_proto.PartialCompileInput{ + protoFile("file0", 100, "", nil), + protoFile("file1", 200, "", nil), + protoFile("file3", 300, "", nil), + }, + }, + Expected: &FileList{ + Name: "foo", + Additions: []string{"file3"}, + Changes: []FileList{FileList{Name: "file1"}}, + Deletions: []string{"file2"}, + }, + }, + } + for _, tc := range testCases { + actual := CompareInternalState(tc.Prior, tc.New, tc.Target) + if !tc.Expected.Equal(actual) { + t.Errorf("%s: expected %q, actual %q", tc.Name, tc.Expected, actual) + } + } +} diff --git a/cmd/find_input_delta/find_input_delta_proto/Android.bp b/cmd/find_input_delta/find_input_delta_proto/Android.bp new file mode 100644 index 000000000..18eba6bb8 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_proto/Android.bp @@ -0,0 +1,29 @@ +// Copyright 2024 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 { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +bootstrap_go_package { + name: "soong-cmd-find_input_delta-proto", + pkgPath: "android/soong/cmd/find_input_delta/find_input_delta_proto", + deps: [ + "golang-protobuf-reflect-protoreflect", + "golang-protobuf-runtime-protoimpl", + ], + srcs: [ + "target_delta_files.pb.go", + ], +} diff --git a/cmd/find_input_delta/find_input_delta_proto/file_list.pb.go b/cmd/find_input_delta/find_input_delta_proto/file_list.pb.go new file mode 100644 index 000000000..648ef224a --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_proto/file_list.pb.go @@ -0,0 +1,198 @@ +// +// Copyright (C) 2024 The Android Open-Source Project +// +// 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. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v3.21.12 +// source: file_list.proto + +package proto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type FileList struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The name of the file. + // In the outermost message, this is the name of the Ninja target. + // When used in `changes`, this is the name of the changed file. + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // The added files. + Additions []string `protobuf:"bytes,2,rep,name=additions" json:"additions,omitempty"` + // The deleted files. + Deletions []string `protobuf:"bytes,3,rep,name=deletions" json:"deletions,omitempty"` + // The changed files. + Changes []*FileList `protobuf:"bytes,4,rep,name=changes" json:"changes,omitempty"` +} + +func (x *FileList) Reset() { + *x = FileList{} + if protoimpl.UnsafeEnabled { + mi := &file_file_list_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FileList) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FileList) ProtoMessage() {} + +func (x *FileList) ProtoReflect() protoreflect.Message { + mi := &file_file_list_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FileList.ProtoReflect.Descriptor instead. +func (*FileList) Descriptor() ([]byte, []int) { + return file_file_list_proto_rawDescGZIP(), []int{0} +} + +func (x *FileList) GetName() string { + if x != nil && x.Name != nil { + return *x.Name + } + return "" +} + +func (x *FileList) GetAdditions() []string { + if x != nil { + return x.Additions + } + return nil +} + +func (x *FileList) GetDeletions() []string { + if x != nil { + return x.Deletions + } + return nil +} + +func (x *FileList) GetChanges() []*FileList { + if x != nil { + return x.Changes + } + return nil +} + +var File_file_list_proto protoreflect.FileDescriptor + +var file_file_list_proto_rawDesc = []byte{ + 0x0a, 0x0f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x12, 0x1e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x66, 0x69, 0x6e, 0x64, 0x5f, + 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x22, 0x9e, 0x01, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x42, + 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x28, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, + 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x73, 0x42, 0x26, 0x5a, 0x24, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, + 0x6f, 0x6e, 0x67, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, + 0x65, 0x6c, 0x74, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, +} + +var ( + file_file_list_proto_rawDescOnce sync.Once + file_file_list_proto_rawDescData = file_file_list_proto_rawDesc +) + +func file_file_list_proto_rawDescGZIP() []byte { + file_file_list_proto_rawDescOnce.Do(func() { + file_file_list_proto_rawDescData = protoimpl.X.CompressGZIP(file_file_list_proto_rawDescData) + }) + return file_file_list_proto_rawDescData +} + +var file_file_list_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_file_list_proto_goTypes = []interface{}{ + (*FileList)(nil), // 0: android.find_input_delta_proto.FileList +} +var file_file_list_proto_depIdxs = []int32{ + 0, // 0: android.find_input_delta_proto.FileList.changes:type_name -> android.find_input_delta_proto.FileList + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_file_list_proto_init() } +func file_file_list_proto_init() { + if File_file_list_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_file_list_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FileList); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_file_list_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_file_list_proto_goTypes, + DependencyIndexes: file_file_list_proto_depIdxs, + MessageInfos: file_file_list_proto_msgTypes, + }.Build() + File_file_list_proto = out.File + file_file_list_proto_rawDesc = nil + file_file_list_proto_goTypes = nil + file_file_list_proto_depIdxs = nil +} diff --git a/cmd/find_input_delta/find_input_delta_proto/file_list.proto b/cmd/find_input_delta/find_input_delta_proto/file_list.proto new file mode 100644 index 000000000..d7faca9c8 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_proto/file_list.proto @@ -0,0 +1,34 @@ +// +// Copyright (C) 2024 The Android Open-Source Project +// +// 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 = "proto2"; +package android.find_input_delta_proto; +option go_package = "android/soong/find_input_delta/proto"; + +message FileList { + // The name of the file. + // In the outermost message, this is the name of the Ninja target. + // When used in `changes`, this is the name of the changed file. + optional string name = 1; + + // The added files. + repeated string additions = 2; + + // The deleted files. + repeated string deletions = 3; + + // The changed files. + repeated FileList changes = 4; +} diff --git a/cmd/find_input_delta/find_input_delta_proto/regen.sh b/cmd/find_input_delta/find_input_delta_proto/regen.sh new file mode 100644 index 000000000..d77365941 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_proto/regen.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +aprotoc --go_out=paths=source_relative:. file_list.proto diff --git a/cmd/find_input_delta/find_input_delta_proto_internal/Android.bp b/cmd/find_input_delta/find_input_delta_proto_internal/Android.bp new file mode 100644 index 000000000..00ba9ff03 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_proto_internal/Android.bp @@ -0,0 +1,29 @@ +// Copyright 2024 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 { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +bootstrap_go_package { + name: "soong-cmd-find_input_delta-proto_internal", + pkgPath: "android/soong/cmd/find_input_delta/find_input_delta_proto_internal", + deps: [ + "golang-protobuf-reflect-protoreflect", + "golang-protobuf-runtime-protoimpl", + ], + srcs: [ + "internal_state.pb.go", + ], +} diff --git a/cmd/find_input_delta/find_input_delta_proto_internal/internal_state.pb.go b/cmd/find_input_delta/find_input_delta_proto_internal/internal_state.pb.go new file mode 100644 index 000000000..2229a324d --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_proto_internal/internal_state.pb.go @@ -0,0 +1,268 @@ +// +// Copyright (C) 2024 The Android Open-Source Project +// +// 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. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v3.21.12 +// source: internal_state.proto + +package proto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// The state of all inputs. +type PartialCompileInputs struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The status of each file. + InputFiles []*PartialCompileInput `protobuf:"bytes,1,rep,name=input_files,json=inputFiles" json:"input_files,omitempty"` +} + +func (x *PartialCompileInputs) Reset() { + *x = PartialCompileInputs{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_state_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PartialCompileInputs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PartialCompileInputs) ProtoMessage() {} + +func (x *PartialCompileInputs) ProtoReflect() protoreflect.Message { + mi := &file_internal_state_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PartialCompileInputs.ProtoReflect.Descriptor instead. +func (*PartialCompileInputs) Descriptor() ([]byte, []int) { + return file_internal_state_proto_rawDescGZIP(), []int{0} +} + +func (x *PartialCompileInputs) GetInputFiles() []*PartialCompileInput { + if x != nil { + return x.InputFiles + } + return nil +} + +// The state of one input. +type PartialCompileInput struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The name of the file. + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // The timestamp of the file in (Unix) nanoseconds. + MtimeNsec *int64 `protobuf:"varint,2,opt,name=mtime_nsec,json=mtimeNsec" json:"mtime_nsec,omitempty"` + // The hash of the file, in the form ‘{HASHNAME}:{VALUE}’ + Hash *string `protobuf:"bytes,3,opt,name=hash" json:"hash,omitempty"` + // Contents of the file, if the file was inspected (such as jar files, etc). + Contents []*PartialCompileInput `protobuf:"bytes,4,rep,name=contents" json:"contents,omitempty"` +} + +func (x *PartialCompileInput) Reset() { + *x = PartialCompileInput{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_state_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PartialCompileInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PartialCompileInput) ProtoMessage() {} + +func (x *PartialCompileInput) ProtoReflect() protoreflect.Message { + mi := &file_internal_state_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PartialCompileInput.ProtoReflect.Descriptor instead. +func (*PartialCompileInput) Descriptor() ([]byte, []int) { + return file_internal_state_proto_rawDescGZIP(), []int{1} +} + +func (x *PartialCompileInput) GetName() string { + if x != nil && x.Name != nil { + return *x.Name + } + return "" +} + +func (x *PartialCompileInput) GetMtimeNsec() int64 { + if x != nil && x.MtimeNsec != nil { + return *x.MtimeNsec + } + return 0 +} + +func (x *PartialCompileInput) GetHash() string { + if x != nil && x.Hash != nil { + return *x.Hash + } + return "" +} + +func (x *PartialCompileInput) GetContents() []*PartialCompileInput { + if x != nil { + return x.Contents + } + return nil +} + +var File_internal_state_proto protoreflect.FileDescriptor + +var file_internal_state_proto_rawDesc = []byte{ + 0x0a, 0x14, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, + 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, + 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6c, 0x0a, 0x14, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, + 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x54, + 0x0a, 0x0b, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x66, 0x69, + 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x43, 0x6f, 0x6d, 0x70, + 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, + 0x69, 0x6c, 0x65, 0x73, 0x22, 0xad, 0x01, 0x0a, 0x13, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, + 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6e, 0x73, 0x65, 0x63, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x6d, 0x74, 0x69, 0x6d, 0x65, 0x4e, 0x73, 0x65, 0x63, 0x12, + 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, + 0x61, 0x73, 0x68, 0x12, 0x4f, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, + 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, + 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, + 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x43, 0x6f, + 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x73, 0x42, 0x26, 0x5a, 0x24, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, + 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, + 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, +} + +var ( + file_internal_state_proto_rawDescOnce sync.Once + file_internal_state_proto_rawDescData = file_internal_state_proto_rawDesc +) + +func file_internal_state_proto_rawDescGZIP() []byte { + file_internal_state_proto_rawDescOnce.Do(func() { + file_internal_state_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_state_proto_rawDescData) + }) + return file_internal_state_proto_rawDescData +} + +var file_internal_state_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_internal_state_proto_goTypes = []interface{}{ + (*PartialCompileInputs)(nil), // 0: android.find_input_delta_proto.PartialCompileInputs + (*PartialCompileInput)(nil), // 1: android.find_input_delta_proto.PartialCompileInput +} +var file_internal_state_proto_depIdxs = []int32{ + 1, // 0: android.find_input_delta_proto.PartialCompileInputs.input_files:type_name -> android.find_input_delta_proto.PartialCompileInput + 1, // 1: android.find_input_delta_proto.PartialCompileInput.contents:type_name -> android.find_input_delta_proto.PartialCompileInput + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_internal_state_proto_init() } +func file_internal_state_proto_init() { + if File_internal_state_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_internal_state_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PartialCompileInputs); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_internal_state_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PartialCompileInput); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_internal_state_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_internal_state_proto_goTypes, + DependencyIndexes: file_internal_state_proto_depIdxs, + MessageInfos: file_internal_state_proto_msgTypes, + }.Build() + File_internal_state_proto = out.File + file_internal_state_proto_rawDesc = nil + file_internal_state_proto_goTypes = nil + file_internal_state_proto_depIdxs = nil +} diff --git a/cmd/find_input_delta/find_input_delta_proto_internal/internal_state.proto b/cmd/find_input_delta/find_input_delta_proto_internal/internal_state.proto new file mode 100644 index 000000000..113fc6434 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_proto_internal/internal_state.proto @@ -0,0 +1,39 @@ +// +// Copyright (C) 2024 The Android Open-Source Project +// +// 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 = "proto2"; +package android.find_input_delta_proto; +option go_package = "android/soong/find_input_delta/proto"; + +// The state of all inputs. +message PartialCompileInputs { + // The status of each file. + repeated PartialCompileInput input_files = 1; +} + +// The state of one input. +message PartialCompileInput { + // The name of the file. + optional string name = 1; + + // The timestamp of the file in (Unix) nanoseconds. + optional int64 mtime_nsec = 2; + + // The hash of the file, in the form ‘{HASHNAME}:{VALUE}’ + optional string hash = 3; + + // Contents of the file, if the file was inspected (such as jar files, etc). + repeated PartialCompileInput contents = 4; +} diff --git a/cmd/find_input_delta/find_input_delta_proto_internal/regen.sh b/cmd/find_input_delta/find_input_delta_proto_internal/regen.sh new file mode 100644 index 000000000..cbaf7d056 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_proto_internal/regen.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +aprotoc --go_out=paths=source_relative:. internal_state.proto -- cgit v1.2.3-59-g8ed1b