From 656a0d6634d67a5779322039e6af4f2ee5546e40 Mon Sep 17 00:00:00 2001 From: Ola Rozenfeld Date: Thu, 19 Mar 2020 15:52:39 -0400 Subject: [PATCH] Adding Command proto serialization. (#129) As usual, Go proto files need to be checked in to work with go build. Modeling our pre-commit hooks after the remote-apis repo. --- .githooks/pre-commit | 13 +- check-gofmt.sh | 6 +- go/api/command/BUILD.bazel | 24 ++ go/api/command/command.pb.go | 648 +++++++++++++++++++++++++++++++++ go/api/command/command.proto | 136 +++++++ go/pkg/command/BUILD.bazel | 4 + go/pkg/command/command.go | 223 ++++++++++++ go/pkg/command/command_test.go | 81 +++++ 8 files changed, 1131 insertions(+), 4 deletions(-) create mode 100644 go/api/command/BUILD.bazel create mode 100755 go/api/command/command.pb.go create mode 100644 go/api/command/command.proto diff --git a/.githooks/pre-commit b/.githooks/pre-commit index 47ee025c..26c82696 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -1,11 +1,18 @@ #!/bin/sh - ######################################################################## # Check that all Go files have been gofmt'd. ######################################################################## # Find all change go files. gofiles=$(git diff --cached --name-only --diff-filter=ACM | grep '\.go$') -[ -z "$gofiles" ] && exit 0 -source ./check-gofmt.sh "$gofiles" +./check-gofmt.sh $gofiles + +######################################################################## +# Precommit hook to rebuild generated go code. Fails if building or +# copying the files fails. +######################################################################## +bazel build go/api/command:command_go_proto +GEN_CMD_PATH="go/api/command/command.pb.go" +cp -f "$(find $(bazel info bazel-bin) -path "*/$GEN_CMD_PATH")" "$GEN_CMD_PATH" +git add "$GEN_CMD_PATH" diff --git a/check-gofmt.sh b/check-gofmt.sh index 201bcf1e..99ea4b93 100755 --- a/check-gofmt.sh +++ b/check-gofmt.sh @@ -2,7 +2,11 @@ # Source: https://github.com/golang/go/blob/88da9ccb98ffaf84bb06b98c9a24af5d0a7025d2/misc/git/pre-commit -unformatted=$(gofmt -l "$@") +if [ "$#" -lt 1 ]; then + exit 0 +fi + +unformatted=$(gofmt -l $@) [ -z "$unformatted" ] && exit 0 # Some files are not gofmt'd. Print message and fail. diff --git a/go/api/command/BUILD.bazel b/go/api/command/BUILD.bazel new file mode 100644 index 00000000..141a1ee6 --- /dev/null +++ b/go/api/command/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_proto//proto:defs.bzl", "proto_library") +load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") + +proto_library( + name = "command_proto", + srcs = ["command.proto"], + visibility = ["//visibility:public"], + deps = ["@com_google_protobuf//:timestamp_proto"], +) + +go_proto_library( + name = "command_go_proto", + importpath = "github.com/bazelbuild/remote-apis-sdks/go/api/command", + proto = ":command_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "go_default_library", + embed = [":command_go_proto"], + importpath = "github.com/bazelbuild/remote-apis-sdks/go/api/command", + visibility = ["//visibility:public"], +) diff --git a/go/api/command/command.pb.go b/go/api/command/command.pb.go new file mode 100755 index 00000000..9eae0efe --- /dev/null +++ b/go/api/command/command.pb.go @@ -0,0 +1,648 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: go/api/command/command.proto + +package cmd + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + timestamp "github.com/golang/protobuf/ptypes/timestamp" + 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.ProtoPackageIsVersion3 // please upgrade the proto package + +type InputType_Value int32 + +const ( + InputType_UNSPECIFIED InputType_Value = 0 + InputType_DIRECTORY InputType_Value = 1 + InputType_FILE InputType_Value = 2 +) + +var InputType_Value_name = map[int32]string{ + 0: "UNSPECIFIED", + 1: "DIRECTORY", + 2: "FILE", +} + +var InputType_Value_value = map[string]int32{ + "UNSPECIFIED": 0, + "DIRECTORY": 1, + "FILE": 2, +} + +func (x InputType_Value) String() string { + return proto.EnumName(InputType_Value_name, int32(x)) +} + +func (InputType_Value) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_c902c8825c04350d, []int{2, 0} +} + +type CommandResultStatus_Value int32 + +const ( + CommandResultStatus_UNKNOWN CommandResultStatus_Value = 0 + CommandResultStatus_SUCCESS CommandResultStatus_Value = 1 + CommandResultStatus_CACHE_HIT CommandResultStatus_Value = 2 + CommandResultStatus_NON_ZERO_EXIT CommandResultStatus_Value = 3 + CommandResultStatus_TIMEOUT CommandResultStatus_Value = 4 + CommandResultStatus_INTERRUPTED CommandResultStatus_Value = 5 + CommandResultStatus_REMOTE_ERROR CommandResultStatus_Value = 6 + CommandResultStatus_LOCAL_ERROR CommandResultStatus_Value = 7 +) + +var CommandResultStatus_Value_name = map[int32]string{ + 0: "UNKNOWN", + 1: "SUCCESS", + 2: "CACHE_HIT", + 3: "NON_ZERO_EXIT", + 4: "TIMEOUT", + 5: "INTERRUPTED", + 6: "REMOTE_ERROR", + 7: "LOCAL_ERROR", +} + +var CommandResultStatus_Value_value = map[string]int32{ + "UNKNOWN": 0, + "SUCCESS": 1, + "CACHE_HIT": 2, + "NON_ZERO_EXIT": 3, + "TIMEOUT": 4, + "INTERRUPTED": 5, + "REMOTE_ERROR": 6, + "LOCAL_ERROR": 7, +} + +func (x CommandResultStatus_Value) String() string { + return proto.EnumName(CommandResultStatus_Value_name, int32(x)) +} + +func (CommandResultStatus_Value) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_c902c8825c04350d, []int{6, 0} +} + +type Command struct { + Identifiers *Identifiers `protobuf:"bytes,1,opt,name=identifiers,proto3" json:"identifiers,omitempty"` + ExecRoot string `protobuf:"bytes,2,opt,name=exec_root,json=execRoot,proto3" json:"exec_root,omitempty"` + Input *InputSpec `protobuf:"bytes,3,opt,name=input,proto3" json:"input,omitempty"` + Output *OutputSpec `protobuf:"bytes,4,opt,name=output,proto3" json:"output,omitempty"` + Args []string `protobuf:"bytes,5,rep,name=args,proto3" json:"args,omitempty"` + ExecutionTimeout int32 `protobuf:"varint,6,opt,name=execution_timeout,json=executionTimeout,proto3" json:"execution_timeout,omitempty"` + WorkingDirectory string `protobuf:"bytes,7,opt,name=working_directory,json=workingDirectory,proto3" json:"working_directory,omitempty"` + Platform map[string]string `protobuf:"bytes,8,rep,name=platform,proto3" json:"platform,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Command) Reset() { *m = Command{} } +func (m *Command) String() string { return proto.CompactTextString(m) } +func (*Command) ProtoMessage() {} +func (*Command) Descriptor() ([]byte, []int) { + return fileDescriptor_c902c8825c04350d, []int{0} +} + +func (m *Command) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Command.Unmarshal(m, b) +} +func (m *Command) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Command.Marshal(b, m, deterministic) +} +func (m *Command) XXX_Merge(src proto.Message) { + xxx_messageInfo_Command.Merge(m, src) +} +func (m *Command) XXX_Size() int { + return xxx_messageInfo_Command.Size(m) +} +func (m *Command) XXX_DiscardUnknown() { + xxx_messageInfo_Command.DiscardUnknown(m) +} + +var xxx_messageInfo_Command proto.InternalMessageInfo + +func (m *Command) GetIdentifiers() *Identifiers { + if m != nil { + return m.Identifiers + } + return nil +} + +func (m *Command) GetExecRoot() string { + if m != nil { + return m.ExecRoot + } + return "" +} + +func (m *Command) GetInput() *InputSpec { + if m != nil { + return m.Input + } + return nil +} + +func (m *Command) GetOutput() *OutputSpec { + if m != nil { + return m.Output + } + return nil +} + +func (m *Command) GetArgs() []string { + if m != nil { + return m.Args + } + return nil +} + +func (m *Command) GetExecutionTimeout() int32 { + if m != nil { + return m.ExecutionTimeout + } + return 0 +} + +func (m *Command) GetWorkingDirectory() string { + if m != nil { + return m.WorkingDirectory + } + return "" +} + +func (m *Command) GetPlatform() map[string]string { + if m != nil { + return m.Platform + } + return nil +} + +type Identifiers struct { + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + InvocationId string `protobuf:"bytes,2,opt,name=invocation_id,json=invocationId,proto3" json:"invocation_id,omitempty"` + CorrelatedInvocationsId string `protobuf:"bytes,3,opt,name=correlated_invocations_id,json=correlatedInvocationsId,proto3" json:"correlated_invocations_id,omitempty"` + ToolName string `protobuf:"bytes,4,opt,name=tool_name,json=toolName,proto3" json:"tool_name,omitempty"` + ToolVersion string `protobuf:"bytes,5,opt,name=tool_version,json=toolVersion,proto3" json:"tool_version,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Identifiers) Reset() { *m = Identifiers{} } +func (m *Identifiers) String() string { return proto.CompactTextString(m) } +func (*Identifiers) ProtoMessage() {} +func (*Identifiers) Descriptor() ([]byte, []int) { + return fileDescriptor_c902c8825c04350d, []int{1} +} + +func (m *Identifiers) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Identifiers.Unmarshal(m, b) +} +func (m *Identifiers) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Identifiers.Marshal(b, m, deterministic) +} +func (m *Identifiers) XXX_Merge(src proto.Message) { + xxx_messageInfo_Identifiers.Merge(m, src) +} +func (m *Identifiers) XXX_Size() int { + return xxx_messageInfo_Identifiers.Size(m) +} +func (m *Identifiers) XXX_DiscardUnknown() { + xxx_messageInfo_Identifiers.DiscardUnknown(m) +} + +var xxx_messageInfo_Identifiers proto.InternalMessageInfo + +func (m *Identifiers) GetCommandId() string { + if m != nil { + return m.CommandId + } + return "" +} + +func (m *Identifiers) GetInvocationId() string { + if m != nil { + return m.InvocationId + } + return "" +} + +func (m *Identifiers) GetCorrelatedInvocationsId() string { + if m != nil { + return m.CorrelatedInvocationsId + } + return "" +} + +func (m *Identifiers) GetToolName() string { + if m != nil { + return m.ToolName + } + return "" +} + +func (m *Identifiers) GetToolVersion() string { + if m != nil { + return m.ToolVersion + } + return "" +} + +type InputType struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *InputType) Reset() { *m = InputType{} } +func (m *InputType) String() string { return proto.CompactTextString(m) } +func (*InputType) ProtoMessage() {} +func (*InputType) Descriptor() ([]byte, []int) { + return fileDescriptor_c902c8825c04350d, []int{2} +} + +func (m *InputType) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_InputType.Unmarshal(m, b) +} +func (m *InputType) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_InputType.Marshal(b, m, deterministic) +} +func (m *InputType) XXX_Merge(src proto.Message) { + xxx_messageInfo_InputType.Merge(m, src) +} +func (m *InputType) XXX_Size() int { + return xxx_messageInfo_InputType.Size(m) +} +func (m *InputType) XXX_DiscardUnknown() { + xxx_messageInfo_InputType.DiscardUnknown(m) +} + +var xxx_messageInfo_InputType proto.InternalMessageInfo + +type ExcludeInput struct { + Regex string `protobuf:"bytes,1,opt,name=regex,proto3" json:"regex,omitempty"` + Type InputType_Value `protobuf:"varint,2,opt,name=type,proto3,enum=cmd.InputType_Value" json:"type,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ExcludeInput) Reset() { *m = ExcludeInput{} } +func (m *ExcludeInput) String() string { return proto.CompactTextString(m) } +func (*ExcludeInput) ProtoMessage() {} +func (*ExcludeInput) Descriptor() ([]byte, []int) { + return fileDescriptor_c902c8825c04350d, []int{3} +} + +func (m *ExcludeInput) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ExcludeInput.Unmarshal(m, b) +} +func (m *ExcludeInput) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ExcludeInput.Marshal(b, m, deterministic) +} +func (m *ExcludeInput) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExcludeInput.Merge(m, src) +} +func (m *ExcludeInput) XXX_Size() int { + return xxx_messageInfo_ExcludeInput.Size(m) +} +func (m *ExcludeInput) XXX_DiscardUnknown() { + xxx_messageInfo_ExcludeInput.DiscardUnknown(m) +} + +var xxx_messageInfo_ExcludeInput proto.InternalMessageInfo + +func (m *ExcludeInput) GetRegex() string { + if m != nil { + return m.Regex + } + return "" +} + +func (m *ExcludeInput) GetType() InputType_Value { + if m != nil { + return m.Type + } + return InputType_UNSPECIFIED +} + +type InputSpec struct { + Inputs []string `protobuf:"bytes,2,rep,name=inputs,proto3" json:"inputs,omitempty"` + ExcludeInputs []*ExcludeInput `protobuf:"bytes,3,rep,name=exclude_inputs,json=excludeInputs,proto3" json:"exclude_inputs,omitempty"` + EnvironmentVariables map[string]string `protobuf:"bytes,4,rep,name=environment_variables,json=environmentVariables,proto3" json:"environment_variables,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *InputSpec) Reset() { *m = InputSpec{} } +func (m *InputSpec) String() string { return proto.CompactTextString(m) } +func (*InputSpec) ProtoMessage() {} +func (*InputSpec) Descriptor() ([]byte, []int) { + return fileDescriptor_c902c8825c04350d, []int{4} +} + +func (m *InputSpec) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_InputSpec.Unmarshal(m, b) +} +func (m *InputSpec) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_InputSpec.Marshal(b, m, deterministic) +} +func (m *InputSpec) XXX_Merge(src proto.Message) { + xxx_messageInfo_InputSpec.Merge(m, src) +} +func (m *InputSpec) XXX_Size() int { + return xxx_messageInfo_InputSpec.Size(m) +} +func (m *InputSpec) XXX_DiscardUnknown() { + xxx_messageInfo_InputSpec.DiscardUnknown(m) +} + +var xxx_messageInfo_InputSpec proto.InternalMessageInfo + +func (m *InputSpec) GetInputs() []string { + if m != nil { + return m.Inputs + } + return nil +} + +func (m *InputSpec) GetExcludeInputs() []*ExcludeInput { + if m != nil { + return m.ExcludeInputs + } + return nil +} + +func (m *InputSpec) GetEnvironmentVariables() map[string]string { + if m != nil { + return m.EnvironmentVariables + } + return nil +} + +type OutputSpec struct { + OutputFiles []string `protobuf:"bytes,1,rep,name=output_files,json=outputFiles,proto3" json:"output_files,omitempty"` + OutputDirectories []string `protobuf:"bytes,2,rep,name=output_directories,json=outputDirectories,proto3" json:"output_directories,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *OutputSpec) Reset() { *m = OutputSpec{} } +func (m *OutputSpec) String() string { return proto.CompactTextString(m) } +func (*OutputSpec) ProtoMessage() {} +func (*OutputSpec) Descriptor() ([]byte, []int) { + return fileDescriptor_c902c8825c04350d, []int{5} +} + +func (m *OutputSpec) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_OutputSpec.Unmarshal(m, b) +} +func (m *OutputSpec) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_OutputSpec.Marshal(b, m, deterministic) +} +func (m *OutputSpec) XXX_Merge(src proto.Message) { + xxx_messageInfo_OutputSpec.Merge(m, src) +} +func (m *OutputSpec) XXX_Size() int { + return xxx_messageInfo_OutputSpec.Size(m) +} +func (m *OutputSpec) XXX_DiscardUnknown() { + xxx_messageInfo_OutputSpec.DiscardUnknown(m) +} + +var xxx_messageInfo_OutputSpec proto.InternalMessageInfo + +func (m *OutputSpec) GetOutputFiles() []string { + if m != nil { + return m.OutputFiles + } + return nil +} + +func (m *OutputSpec) GetOutputDirectories() []string { + if m != nil { + return m.OutputDirectories + } + return nil +} + +type CommandResultStatus struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *CommandResultStatus) Reset() { *m = CommandResultStatus{} } +func (m *CommandResultStatus) String() string { return proto.CompactTextString(m) } +func (*CommandResultStatus) ProtoMessage() {} +func (*CommandResultStatus) Descriptor() ([]byte, []int) { + return fileDescriptor_c902c8825c04350d, []int{6} +} + +func (m *CommandResultStatus) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CommandResultStatus.Unmarshal(m, b) +} +func (m *CommandResultStatus) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CommandResultStatus.Marshal(b, m, deterministic) +} +func (m *CommandResultStatus) XXX_Merge(src proto.Message) { + xxx_messageInfo_CommandResultStatus.Merge(m, src) +} +func (m *CommandResultStatus) XXX_Size() int { + return xxx_messageInfo_CommandResultStatus.Size(m) +} +func (m *CommandResultStatus) XXX_DiscardUnknown() { + xxx_messageInfo_CommandResultStatus.DiscardUnknown(m) +} + +var xxx_messageInfo_CommandResultStatus proto.InternalMessageInfo + +type CommandResult struct { + Status CommandResultStatus_Value `protobuf:"varint,1,opt,name=status,proto3,enum=cmd.CommandResultStatus_Value" json:"status,omitempty"` + ExitCode int32 `protobuf:"varint,2,opt,name=exit_code,json=exitCode,proto3" json:"exit_code,omitempty"` + Msg string `protobuf:"bytes,3,opt,name=msg,proto3" json:"msg,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *CommandResult) Reset() { *m = CommandResult{} } +func (m *CommandResult) String() string { return proto.CompactTextString(m) } +func (*CommandResult) ProtoMessage() {} +func (*CommandResult) Descriptor() ([]byte, []int) { + return fileDescriptor_c902c8825c04350d, []int{7} +} + +func (m *CommandResult) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CommandResult.Unmarshal(m, b) +} +func (m *CommandResult) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CommandResult.Marshal(b, m, deterministic) +} +func (m *CommandResult) XXX_Merge(src proto.Message) { + xxx_messageInfo_CommandResult.Merge(m, src) +} +func (m *CommandResult) XXX_Size() int { + return xxx_messageInfo_CommandResult.Size(m) +} +func (m *CommandResult) XXX_DiscardUnknown() { + xxx_messageInfo_CommandResult.DiscardUnknown(m) +} + +var xxx_messageInfo_CommandResult proto.InternalMessageInfo + +func (m *CommandResult) GetStatus() CommandResultStatus_Value { + if m != nil { + return m.Status + } + return CommandResultStatus_UNKNOWN +} + +func (m *CommandResult) GetExitCode() int32 { + if m != nil { + return m.ExitCode + } + return 0 +} + +func (m *CommandResult) GetMsg() string { + if m != nil { + return m.Msg + } + return "" +} + +type TimeInterval struct { + From *timestamp.Timestamp `protobuf:"bytes,1,opt,name=from,proto3" json:"from,omitempty"` + To *timestamp.Timestamp `protobuf:"bytes,2,opt,name=to,proto3" json:"to,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *TimeInterval) Reset() { *m = TimeInterval{} } +func (m *TimeInterval) String() string { return proto.CompactTextString(m) } +func (*TimeInterval) ProtoMessage() {} +func (*TimeInterval) Descriptor() ([]byte, []int) { + return fileDescriptor_c902c8825c04350d, []int{8} +} + +func (m *TimeInterval) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_TimeInterval.Unmarshal(m, b) +} +func (m *TimeInterval) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_TimeInterval.Marshal(b, m, deterministic) +} +func (m *TimeInterval) XXX_Merge(src proto.Message) { + xxx_messageInfo_TimeInterval.Merge(m, src) +} +func (m *TimeInterval) XXX_Size() int { + return xxx_messageInfo_TimeInterval.Size(m) +} +func (m *TimeInterval) XXX_DiscardUnknown() { + xxx_messageInfo_TimeInterval.DiscardUnknown(m) +} + +var xxx_messageInfo_TimeInterval proto.InternalMessageInfo + +func (m *TimeInterval) GetFrom() *timestamp.Timestamp { + if m != nil { + return m.From + } + return nil +} + +func (m *TimeInterval) GetTo() *timestamp.Timestamp { + if m != nil { + return m.To + } + return nil +} + +func init() { + proto.RegisterEnum("cmd.InputType_Value", InputType_Value_name, InputType_Value_value) + proto.RegisterEnum("cmd.CommandResultStatus_Value", CommandResultStatus_Value_name, CommandResultStatus_Value_value) + proto.RegisterType((*Command)(nil), "cmd.Command") + proto.RegisterMapType((map[string]string)(nil), "cmd.Command.PlatformEntry") + proto.RegisterType((*Identifiers)(nil), "cmd.Identifiers") + proto.RegisterType((*InputType)(nil), "cmd.InputType") + proto.RegisterType((*ExcludeInput)(nil), "cmd.ExcludeInput") + proto.RegisterType((*InputSpec)(nil), "cmd.InputSpec") + proto.RegisterMapType((map[string]string)(nil), "cmd.InputSpec.EnvironmentVariablesEntry") + proto.RegisterType((*OutputSpec)(nil), "cmd.OutputSpec") + proto.RegisterType((*CommandResultStatus)(nil), "cmd.CommandResultStatus") + proto.RegisterType((*CommandResult)(nil), "cmd.CommandResult") + proto.RegisterType((*TimeInterval)(nil), "cmd.TimeInterval") +} + +func init() { proto.RegisterFile("go/api/command/command.proto", fileDescriptor_c902c8825c04350d) } + +var fileDescriptor_c902c8825c04350d = []byte{ + // 860 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0xed, 0x8e, 0xe3, 0x34, + 0x14, 0xdd, 0xf4, 0x6b, 0xda, 0xdb, 0x76, 0x36, 0x63, 0x06, 0xc8, 0x96, 0xaf, 0x12, 0x90, 0xa8, + 0x40, 0x64, 0x44, 0x91, 0x56, 0xab, 0x45, 0x42, 0x5a, 0xa5, 0x19, 0x36, 0x62, 0x36, 0x19, 0xb9, + 0xe9, 0xf0, 0x21, 0x41, 0x94, 0x49, 0xdc, 0xca, 0x6c, 0x12, 0x57, 0x89, 0x53, 0xa6, 0xff, 0xe1, + 0x1f, 0x8f, 0xc0, 0x2b, 0xf1, 0x4e, 0xc8, 0x8e, 0x3b, 0xe9, 0x48, 0x80, 0xc4, 0xaf, 0xc4, 0xe7, + 0x1c, 0x5f, 0x5f, 0x5f, 0x9f, 0x7b, 0xe1, 0xdd, 0x0d, 0xbb, 0x88, 0xb6, 0xf4, 0x22, 0x66, 0x59, + 0x16, 0xe5, 0xc9, 0xe1, 0x6b, 0x6d, 0x0b, 0xc6, 0x19, 0x6a, 0xc7, 0x59, 0x32, 0xf9, 0x60, 0xc3, + 0xd8, 0x26, 0x25, 0x17, 0x12, 0xba, 0xad, 0xd6, 0x17, 0x9c, 0x66, 0xa4, 0xe4, 0x51, 0xb6, 0xad, + 0x55, 0xe6, 0x1f, 0x6d, 0x38, 0xb1, 0xeb, 0x7d, 0x68, 0x0e, 0x43, 0x9a, 0x90, 0x9c, 0xd3, 0x35, + 0x25, 0x45, 0x69, 0x68, 0x53, 0x6d, 0x36, 0x9c, 0xeb, 0x56, 0x9c, 0x25, 0x96, 0xdb, 0xe0, 0xf8, + 0x58, 0x84, 0xde, 0x81, 0x01, 0xb9, 0x23, 0x71, 0x58, 0x30, 0xc6, 0x8d, 0xd6, 0x54, 0x9b, 0x0d, + 0x70, 0x5f, 0x00, 0x98, 0x31, 0x8e, 0x3e, 0x86, 0x2e, 0xcd, 0xb7, 0x15, 0x37, 0xda, 0x32, 0xd4, + 0x69, 0x1d, 0x4a, 0x20, 0xcb, 0x2d, 0x89, 0x71, 0x4d, 0xa2, 0x4f, 0xa0, 0xc7, 0x2a, 0x2e, 0x64, + 0x1d, 0x29, 0x7b, 0x2c, 0x65, 0xbe, 0x84, 0xa4, 0x4e, 0xd1, 0x08, 0x41, 0x27, 0x2a, 0x36, 0xa5, + 0xd1, 0x9d, 0xb6, 0x67, 0x03, 0x2c, 0xff, 0xd1, 0x67, 0x70, 0x26, 0x8e, 0xab, 0x38, 0x65, 0x79, + 0x28, 0x2e, 0xc7, 0x2a, 0x6e, 0xf4, 0xa6, 0xda, 0xac, 0x8b, 0xf5, 0x7b, 0x22, 0xa8, 0x71, 0x21, + 0xfe, 0x95, 0x15, 0xaf, 0x69, 0xbe, 0x09, 0x13, 0x5a, 0x90, 0x98, 0xb3, 0x62, 0x6f, 0x9c, 0xc8, + 0xa4, 0x75, 0x45, 0x2c, 0x0e, 0x38, 0x7a, 0x0a, 0xfd, 0x6d, 0x1a, 0xf1, 0x35, 0x2b, 0x32, 0xa3, + 0x3f, 0x6d, 0xcf, 0x86, 0xf3, 0x89, 0x4c, 0x4c, 0x55, 0xcb, 0xba, 0x56, 0xa4, 0x93, 0xf3, 0x62, + 0x8f, 0xef, 0xb5, 0x93, 0xaf, 0x60, 0xfc, 0x80, 0x42, 0x3a, 0xb4, 0x5f, 0x93, 0xbd, 0x2c, 0xe7, + 0x00, 0x8b, 0x5f, 0x74, 0x0e, 0xdd, 0x5d, 0x94, 0x56, 0x44, 0x15, 0xac, 0x5e, 0x3c, 0x6f, 0x3d, + 0xd3, 0xcc, 0xbf, 0x34, 0x18, 0x1e, 0xd5, 0x1a, 0xbd, 0x07, 0xa0, 0x5e, 0x35, 0xa4, 0x89, 0x0a, + 0x31, 0x50, 0x88, 0x9b, 0xa0, 0x8f, 0x60, 0x4c, 0xf3, 0x1d, 0x8b, 0x23, 0x79, 0x7d, 0x9a, 0xa8, + 0x80, 0xa3, 0x06, 0x74, 0x13, 0xf4, 0x1c, 0x9e, 0xc4, 0xac, 0x28, 0x48, 0x1a, 0x71, 0x92, 0x84, + 0x0d, 0x55, 0x8a, 0x0d, 0x6d, 0xb9, 0xe1, 0xed, 0x46, 0xe0, 0x36, 0xbc, 0x9b, 0x88, 0xe7, 0xe5, + 0x8c, 0xa5, 0x61, 0x1e, 0x65, 0x44, 0x3e, 0xcf, 0x00, 0xf7, 0x05, 0xe0, 0x45, 0x19, 0x41, 0x1f, + 0xc2, 0x48, 0x92, 0x3b, 0x52, 0x94, 0x94, 0xe5, 0x46, 0x57, 0xf2, 0x43, 0x81, 0xdd, 0xd4, 0x90, + 0xf9, 0x35, 0x0c, 0xe4, 0x7b, 0x07, 0xfb, 0x2d, 0x31, 0xbf, 0x80, 0xee, 0x8d, 0xb8, 0x29, 0x7a, + 0x0c, 0xc3, 0x95, 0xb7, 0xbc, 0x76, 0x6c, 0xf7, 0xd2, 0x75, 0x16, 0xfa, 0x23, 0x34, 0x86, 0xc1, + 0xc2, 0xc5, 0x8e, 0x1d, 0xf8, 0xf8, 0x07, 0x5d, 0x43, 0x7d, 0xe8, 0x5c, 0xba, 0x57, 0x8e, 0xde, + 0x32, 0x3d, 0x18, 0x39, 0x77, 0x71, 0x5a, 0x25, 0x44, 0x86, 0x11, 0x95, 0x2b, 0xc8, 0x86, 0xdc, + 0xa9, 0x52, 0xd4, 0x0b, 0x34, 0x83, 0x0e, 0xdf, 0x6f, 0xeb, 0x72, 0x9e, 0xce, 0xcf, 0x1b, 0x9b, + 0x89, 0x63, 0x2d, 0x79, 0x26, 0x96, 0x0a, 0xf3, 0xf7, 0x96, 0x4a, 0x48, 0x18, 0x0b, 0xbd, 0x05, + 0x3d, 0x69, 0xc1, 0xd2, 0x68, 0x49, 0x4b, 0xa9, 0x15, 0x7a, 0x06, 0xa7, 0xa4, 0x3e, 0x35, 0x54, + 0x7c, 0x5b, 0x1a, 0xe0, 0x4c, 0x46, 0x3e, 0x4e, 0x08, 0x8f, 0xc9, 0xd1, 0xaa, 0x44, 0x3f, 0xc1, + 0x9b, 0x24, 0xdf, 0xd1, 0x82, 0xe5, 0x19, 0xc9, 0x79, 0xb8, 0x8b, 0x0a, 0x1a, 0xdd, 0xa6, 0xa4, + 0x34, 0x3a, 0x32, 0xc0, 0xec, 0x61, 0x07, 0x58, 0x4e, 0xa3, 0xbd, 0x39, 0x48, 0x6b, 0x3f, 0x9d, + 0x93, 0x7f, 0xa0, 0x26, 0xdf, 0xc0, 0x93, 0x7f, 0xdd, 0xf2, 0xbf, 0x7c, 0xf6, 0x33, 0x40, 0xd3, + 0x60, 0xe2, 0x21, 0xeb, 0x16, 0x0b, 0xd7, 0x54, 0x24, 0xab, 0xc9, 0x6a, 0x0c, 0x6b, 0xec, 0x52, + 0x40, 0xe8, 0x73, 0x40, 0x4a, 0x72, 0xe8, 0x1c, 0x4a, 0x0e, 0x65, 0x3b, 0xab, 0x99, 0x45, 0x43, + 0x98, 0x7f, 0x6a, 0xf0, 0x86, 0x6a, 0x14, 0x4c, 0xca, 0x2a, 0xe5, 0x4b, 0x1e, 0xf1, 0xaa, 0x34, + 0x7f, 0xd3, 0x0e, 0x1e, 0x18, 0xc2, 0xc9, 0xca, 0xfb, 0xd6, 0xf3, 0xbf, 0xf3, 0xf4, 0x47, 0x62, + 0xb1, 0x5c, 0xd9, 0xb6, 0xb3, 0x5c, 0xea, 0x9a, 0x30, 0x83, 0xfd, 0xc2, 0x7e, 0xe9, 0x84, 0x2f, + 0xdd, 0x40, 0x6f, 0xa1, 0x33, 0x18, 0x7b, 0xbe, 0x17, 0xfe, 0xe8, 0x60, 0x3f, 0x74, 0xbe, 0x77, + 0x03, 0xbd, 0x2d, 0xe4, 0x81, 0xfb, 0xca, 0xf1, 0x57, 0x81, 0xde, 0x11, 0x66, 0x72, 0xbd, 0xc0, + 0xc1, 0x78, 0x75, 0x1d, 0x38, 0x0b, 0xbd, 0x8b, 0x74, 0x18, 0x61, 0xe7, 0x95, 0x1f, 0x38, 0xa1, + 0x83, 0xb1, 0x8f, 0xf5, 0x9e, 0x90, 0x5c, 0xf9, 0xf6, 0x8b, 0x2b, 0x05, 0x9c, 0x98, 0x3b, 0x18, + 0x3f, 0xc8, 0x0e, 0x3d, 0x85, 0x5e, 0x29, 0x33, 0x94, 0xe5, 0x3b, 0x9d, 0xbf, 0x7f, 0xdc, 0xea, + 0xc7, 0x37, 0x50, 0x6e, 0x52, 0xea, 0x7a, 0xfc, 0x51, 0x1e, 0xc6, 0x2c, 0xa9, 0xab, 0xdc, 0x15, + 0xe3, 0x8f, 0x72, 0x9b, 0x25, 0x44, 0x3c, 0x48, 0x56, 0x6e, 0x54, 0x8b, 0x89, 0x5f, 0xf3, 0x17, + 0x18, 0x89, 0x59, 0xe4, 0xe6, 0x9c, 0x14, 0xbb, 0x28, 0x45, 0x16, 0x74, 0xd6, 0x05, 0xcb, 0xd4, + 0xa8, 0x9d, 0x58, 0xf5, 0xb4, 0xb6, 0x0e, 0xd3, 0xda, 0x0a, 0x0e, 0xd3, 0x1a, 0x4b, 0x1d, 0xfa, + 0x14, 0x5a, 0x9c, 0xc9, 0x73, 0xfe, 0x5b, 0xdd, 0xe2, 0xec, 0xb6, 0x27, 0xf1, 0x2f, 0xff, 0x0e, + 0x00, 0x00, 0xff, 0xff, 0x01, 0x9a, 0x8a, 0xe5, 0x26, 0x06, 0x00, 0x00, +} diff --git a/go/api/command/command.proto b/go/api/command/command.proto new file mode 100644 index 00000000..83015689 --- /dev/null +++ b/go/api/command/command.proto @@ -0,0 +1,136 @@ +syntax = "proto3"; + +package cmd; + +import "google/protobuf/timestamp.proto"; + +// A command to execute locally or remotely. +message Command { + // Identifiers used to identify this command to be passed to RE. + Identifiers identifiers = 1; + + // An absolute path to the execution root of the command. All the other paths are + // specified relatively to this path. + string exec_root = 2; + + // The command inputs. + InputSpec input = 3; + + // The command outputs. + OutputSpec output = 4; + + // Command line elements to execute. + repeated string args = 5; + + // If > 0, the maximum number of seconds to wait for command execution + // before timing out. + int32 execution_timeout = 6; + + // The working directory, relative to the exec root, for the command to run + // in. It must be a directory which exists in the input tree. If it is left + // empty, then the action is run in the exec root. + string working_directory = 7; + + // The platform to use for the remote execution. + map platform = 8; +} + +// Identifiers identifying a command that are passed to the remote server for logging. +message Identifiers { + // An optional id to use to identify a command. + string command_id = 1; + + // An optional id to use to identify an invocation. + string invocation_id = 2; + + // An optional id to use to identify a build. + string correlated_invocations_id = 3; + + // An optional tool name to pass to the remote server for logging. + string tool_name = 4; + + // An optional tool version to pass to the remote server for logging. + string tool_version = 5; +} + +message InputType { + enum Value { + // Any type will match. + UNSPECIFIED = 0; + // Only directories match. + DIRECTORY = 1; + // Only files match. + FILE = 2; + } +} + +message ExcludeInput { + // If an input matches this regular expression, ignore it. + string regex = 1; + // If an input path has this type, ignore it. + InputType.Value type = 2; +} + +message InputSpec { + // Input paths (files or directories) that need to be uploaded to the remote + // server for the command execution. + // Note: a known limitation of the first version of the proxy is that for any + // *directory* inputs, the contents of the directory will only be read once, + // and then cached throughout the proxy lifetime. Any subsequent changes to the + // directory will therefore not be captured. + repeated string inputs = 2; + + // Inputs matching these patterns will be excluded (not uploaded remotely). + repeated ExcludeInput exclude_inputs = 3; + + // Environment variables the command relies on. + map environment_variables = 4; +} + +message OutputSpec { + // Output files relative to exec root generated by the command. + repeated string output_files = 1; + + // Output directories relative to exec root generated by the command. + repeated string output_directories = 2; +} + +message CommandResultStatus { + enum Value { + // Default case. Should not be used. + UNKNOWN = 0; + // Command executed successfully. + SUCCESS = 1; + // The command did not execute and a previously cached result was + // retrieved. + CACHE_HIT = 2; + // The command executed with a non zero exit code. + NON_ZERO_EXIT = 3; + // The command timed out. + TIMEOUT = 4; + // The command was interrupted. + INTERRUPTED = 5; + // Execution of the command failed due to a remote execution error. + REMOTE_ERROR = 6; + // Execution of the command failed due to a local execution error. + LOCAL_ERROR = 7; + } +} + +// Result of a command execution returned by the proxy. +message CommandResult { + // Status of the finished run. + CommandResultStatus.Value status = 1; + + // Command exit code. + int32 exit_code = 2; + + // Optional exception trace or other message that should be displayed. + string msg = 3; +} + +// TimeInterval is used to serialize the SDK TimeInterval struct. +message TimeInterval { + google.protobuf.Timestamp from = 1; + google.protobuf.Timestamp to = 2; +} diff --git a/go/pkg/command/BUILD.bazel b/go/pkg/command/BUILD.bazel index 8dcd06e8..4c3891a6 100644 --- a/go/pkg/command/BUILD.bazel +++ b/go/pkg/command/BUILD.bazel @@ -6,9 +6,13 @@ go_library( importpath = "github.com/bazelbuild/remote-apis-sdks/go/pkg/command", visibility = ["//visibility:public"], deps = [ + "//go/api/command:go_default_library", "//go/pkg/digest:go_default_library", "@com_github_bazelbuild_remote_apis//build/bazel/remote/execution/v2:go_default_library", + "@com_github_golang_glog//:go_default_library", + "@com_github_golang_protobuf//ptypes:go_default_library_gen", "@com_github_pborman_uuid//:go_default_library", + "@io_bazel_rules_go//proto/wkt:timestamp_go_proto", ], ) diff --git a/go/pkg/command/command.go b/go/pkg/command/command.go index fa12a814..87a59223 100644 --- a/go/pkg/command/command.go +++ b/go/pkg/command/command.go @@ -10,9 +10,13 @@ import ( "time" "github.com/bazelbuild/remote-apis-sdks/go/pkg/digest" + "github.com/golang/protobuf/ptypes" "github.com/pborman/uuid" + cpb "github.com/bazelbuild/remote-apis-sdks/go/api/command" repb "github.com/bazelbuild/remote-apis/build/bazel/remote/execution/v2" + log "github.com/golang/glog" + tspb "github.com/golang/protobuf/ptypes/timestamp" ) // InputType can be specified to narrow down the matching for a given input path. @@ -467,3 +471,222 @@ func (c *Command) ToREProto() *repb.Command { } return cmdPb } + +// FromProto parses a Command struct from a proto message. +func FromProto(p *cpb.Command) *Command { + ids := &Identifiers{ + CommandID: p.GetIdentifiers().GetCommandId(), + InvocationID: p.GetIdentifiers().GetInvocationId(), + CorrelatedInvocationID: p.GetIdentifiers().GetCorrelatedInvocationsId(), + ToolName: p.GetIdentifiers().GetToolName(), + ToolVersion: p.GetIdentifiers().GetToolVersion(), + } + is := inputSpecFromProto(p.GetInput()) + return &Command{ + Identifiers: ids, + ExecRoot: p.ExecRoot, + Args: p.Args, + WorkingDir: p.WorkingDirectory, + InputSpec: is, + OutputFiles: p.GetOutput().GetOutputFiles(), + OutputDirs: p.GetOutput().GetOutputDirectories(), + Timeout: time.Duration(p.ExecutionTimeout) * time.Second, + Platform: p.Platform, + } +} + +func inputSpecFromProto(is *cpb.InputSpec) *InputSpec { + var excl []*InputExclusion + for _, ex := range is.GetExcludeInputs() { + excl = append(excl, &InputExclusion{ + Regex: ex.Regex, + Type: inputTypeFromProto(ex.Type), + }) + } + return &InputSpec{ + Inputs: is.GetInputs(), + InputExclusions: excl, + EnvironmentVariables: is.GetEnvironmentVariables(), + } +} + +func inputSpecToProto(is *InputSpec) *cpb.InputSpec { + var excl []*cpb.ExcludeInput + for _, ex := range is.InputExclusions { + excl = append(excl, &cpb.ExcludeInput{ + Regex: ex.Regex, + Type: inputTypeToProto(ex.Type), + }) + } + return &cpb.InputSpec{ + Inputs: is.Inputs, + ExcludeInputs: excl, + EnvironmentVariables: is.EnvironmentVariables, + } +} + +func inputTypeFromProto(t cpb.InputType_Value) InputType { + switch t { + case cpb.InputType_DIRECTORY: + return DirectoryInputType + case cpb.InputType_FILE: + return FileInputType + default: + return UnspecifiedInputType + } +} + +func inputTypeToProto(t InputType) cpb.InputType_Value { + switch t { + case DirectoryInputType: + return cpb.InputType_DIRECTORY + case FileInputType: + return cpb.InputType_FILE + default: + return cpb.InputType_UNSPECIFIED + } +} + +func protoStatusFromResultStatus(s ResultStatus) cpb.CommandResultStatus_Value { + switch s { + case SuccessResultStatus: + return cpb.CommandResultStatus_SUCCESS + case CacheHitResultStatus: + return cpb.CommandResultStatus_CACHE_HIT + case NonZeroExitResultStatus: + return cpb.CommandResultStatus_NON_ZERO_EXIT + case TimeoutResultStatus: + return cpb.CommandResultStatus_TIMEOUT + case InterruptedResultStatus: + return cpb.CommandResultStatus_INTERRUPTED + case RemoteErrorResultStatus: + return cpb.CommandResultStatus_REMOTE_ERROR + case LocalErrorResultStatus: + return cpb.CommandResultStatus_LOCAL_ERROR + default: + return cpb.CommandResultStatus_UNKNOWN + } +} + +func protoStatusToResultStatus(s cpb.CommandResultStatus_Value) ResultStatus { + switch s { + case cpb.CommandResultStatus_SUCCESS: + return SuccessResultStatus + case cpb.CommandResultStatus_CACHE_HIT: + return CacheHitResultStatus + case cpb.CommandResultStatus_NON_ZERO_EXIT: + return NonZeroExitResultStatus + case cpb.CommandResultStatus_TIMEOUT: + return TimeoutResultStatus + case cpb.CommandResultStatus_INTERRUPTED: + return InterruptedResultStatus + case cpb.CommandResultStatus_REMOTE_ERROR: + return RemoteErrorResultStatus + case cpb.CommandResultStatus_LOCAL_ERROR: + return LocalErrorResultStatus + default: + return UnspecifiedResultStatus + } +} + +// ToProto serializes a Command struct into a proto message. +func ToProto(cmd *Command) *cpb.Command { + if cmd == nil { + return nil + } + cPb := &cpb.Command{ + ExecRoot: cmd.ExecRoot, + Input: inputSpecToProto(cmd.InputSpec), + Output: &cpb.OutputSpec{OutputFiles: cmd.OutputFiles, OutputDirectories: cmd.OutputDirs}, + Args: cmd.Args, + ExecutionTimeout: int32(cmd.Timeout.Seconds()), + WorkingDirectory: cmd.WorkingDir, + Platform: cmd.Platform, + } + if cmd.Identifiers != nil { + cPb.Identifiers = &cpb.Identifiers{ + CommandId: cmd.Identifiers.CommandID, + InvocationId: cmd.Identifiers.InvocationID, + ToolName: cmd.Identifiers.ToolName, + } + } + return cPb +} + +// ResultToProto serializes a command.Result struct into a proto message. +func ResultToProto(res *Result) *cpb.CommandResult { + if res == nil { + return nil + } + resPb := &cpb.CommandResult{ + Status: protoStatusFromResultStatus(res.Status), + ExitCode: int32(res.ExitCode), + } + if res.Err != nil { + resPb.Msg = res.Err.Error() + } + return resPb +} + +// ResultFromProto parses a command.Result struct from a proto message. +func ResultFromProto(res *cpb.CommandResult) *Result { + if res == nil { + return nil + } + var err error + if res.Msg != "" { + err = errors.New(res.Msg) + } + return &Result{ + Status: protoStatusToResultStatus(res.Status), + ExitCode: int(res.ExitCode), + Err: err, + } +} + +// TimeToProto converts a valid time.Time into a proto Timestamp. +func TimeToProto(t time.Time) *tspb.Timestamp { + if t.IsZero() { + return nil + } + ts, err := ptypes.TimestampProto(t) + if err != nil { + log.Warningf("Unable to convert time to Timestamp: %v", err) + return nil + } + return ts +} + +// TimeFromProto converts a valid Timestamp proto into a time.Time. +func TimeFromProto(tPb *tspb.Timestamp) time.Time { + if tPb == nil { + return time.Time{} + } + t, err := ptypes.Timestamp(tPb) + if err != nil { + log.Errorf("Failed to parse RBE timestamp: %+v - > %v", tPb, err) + } + return t +} + +// TimeIntervalToProto serializes the SDK TimeInterval into a proto. +func TimeIntervalToProto(t *TimeInterval) *cpb.TimeInterval { + if t == nil { + return nil + } + return &cpb.TimeInterval{ + From: TimeToProto(t.From), + To: TimeToProto(t.To), + } +} + +// TimeIntervalFromProto parses the SDK TimeInterval from a proto. +func TimeIntervalFromProto(t *cpb.TimeInterval) *TimeInterval { + if t == nil { + return nil + } + return &TimeInterval{ + From: TimeFromProto(t.From), + To: TimeFromProto(t.To), + } +} diff --git a/go/pkg/command/command_test.go b/go/pkg/command/command_test.go index 23c12a26..1f986e2d 100644 --- a/go/pkg/command/command_test.go +++ b/go/pkg/command/command_test.go @@ -1,7 +1,9 @@ package command import ( + "errors" "testing" + "time" "github.com/golang/protobuf/proto" "github.com/google/go-cmp/cmp" @@ -375,3 +377,82 @@ func TestToREProto(t *testing.T) { }) } } + +func TestToFromProto(t *testing.T) { + cmd := &Command{ + Identifiers: &Identifiers{ + CommandID: "a", + InvocationID: "b", + ToolName: "c", + }, + Args: []string{"a", "b", "c"}, + ExecRoot: "/exec/root", + InputSpec: &InputSpec{ + Inputs: []string{"foo.h", "bar.h"}, + InputExclusions: []*InputExclusion{ + &InputExclusion{ + Regex: "*.bla", + Type: DirectoryInputType, + }, + &InputExclusion{ + Regex: "*.blo", + Type: FileInputType, + }, + }, + EnvironmentVariables: map[string]string{ + "k": "v", + "k1": "v1", + }, + }, + OutputFiles: []string{"a/b/out"}, + } + gotCmd := FromProto(ToProto(cmd)) + if diff := cmp.Diff(cmd, gotCmd); diff != "" { + t.Errorf("FromProto(ToProto()) returned diff in result: (-want +got)\n%s", diff) + } +} + +func TestResultToFromProto(t *testing.T) { + res := &Result{ + Status: CacheHitResultStatus, + ExitCode: 42, + Err: errors.New("message"), + } + gotRes := ResultFromProto(ResultToProto(res)) + if diff := cmp.Diff(res, gotRes, cmpopts.IgnoreFields(Result{}, "Err")); diff != "" { + t.Errorf("ResultFromProto(ResultToProto()) returned diff in result: (-want +got)\n%s", diff) + } + if res.Err.Error() != gotRes.Err.Error() { + t.Errorf("ResultFromProto(ResultToProto()) returned diff in error: want %v, got %v", res.Err, gotRes.Err) + } +} + +func TestTimeIntervalToFromProto(t *testing.T) { + ti := &TimeInterval{ + From: time.Now(), + To: time.Now(), + } + gotTi := TimeIntervalFromProto(TimeIntervalToProto(ti)) + if diff := cmp.Diff(ti, gotTi); diff != "" { + t.Errorf("TimeIntervalFromProto(TimeIntervalToProto()) returned diff in result: (-want +got)\n%s", diff) + } + ti = &TimeInterval{From: time.Now()} + gotTi = TimeIntervalFromProto(TimeIntervalToProto(ti)) + if diff := cmp.Diff(ti, gotTi); diff != "" { + t.Errorf("TimeIntervalFromProto(TimeIntervalToProto()) returned diff in result: (-want +got)\n%s", diff) + } + ti = &TimeInterval{To: time.Now()} + gotTi = TimeIntervalFromProto(TimeIntervalToProto(ti)) + if diff := cmp.Diff(ti, gotTi); diff != "" { + t.Errorf("TimeIntervalFromProto(TimeIntervalToProto()) returned diff in result: (-want +got)\n%s", diff) + } + ti = &TimeInterval{} + gotTi = TimeIntervalFromProto(TimeIntervalToProto(ti)) + if diff := cmp.Diff(ti, gotTi); diff != "" { + t.Errorf("TimeIntervalFromProto(TimeIntervalToProto()) returned diff in result: (-want +got)\n%s", diff) + } + gotTi = TimeIntervalFromProto(TimeIntervalToProto(nil)) + if gotTi != nil { + t.Errorf("TimeIntervalFromProto(TimeIntervalToProto()) returned %v, wanted nil", gotTi) + } +}