diff --git a/arduino/discovery/discovery.go b/arduino/discovery/discovery.go index b8c3537b5f4..1832f1e77d3 100644 --- a/arduino/discovery/discovery.go +++ b/arduino/discovery/discovery.go @@ -97,6 +97,12 @@ type Port struct { var tr = i18n.Tr +// Equals returns true if the given port has the same address and protocol +// of the current port. +func (p *Port) Equals(o *Port) bool { + return p.Address == o.Address && p.Protocol == o.Protocol +} + // ToRPC converts Port into rpc.Port func (p *Port) ToRPC() *rpc.Port { props := p.Properties @@ -113,6 +119,24 @@ func (p *Port) ToRPC() *rpc.Port { } } +// PortFromRPCPort converts an *rpc.Port to a *Port +func PortFromRPCPort(o *rpc.Port) (p *Port) { + if o == nil { + return nil + } + res := &Port{ + Address: o.Address, + AddressLabel: o.Label, + Protocol: o.Protocol, + ProtocolLabel: o.ProtocolLabel, + HardwareID: o.HardwareId, + } + if o.Properties != nil { + res.Properties = properties.NewFromHashmap(o.Properties) + } + return res +} + func (p *Port) String() string { if p == nil { return "none" @@ -120,6 +144,18 @@ func (p *Port) String() string { return p.Address } +// Clone creates a copy of this Port +func (p *Port) Clone() *Port { + if p == nil { + return nil + } + var res Port = *p + if p.Properties != nil { + res.Properties = p.Properties.Clone() + } + return &res +} + // Event is a pluggable discovery event type Event struct { Type string diff --git a/arduino/discovery/discovery_client/main.go b/arduino/discovery/discovery_client/main.go index dd556691fe4..b9e1cfd0988 100644 --- a/arduino/discovery/discovery_client/main.go +++ b/arduino/discovery/discovery_client/main.go @@ -51,10 +51,12 @@ func main() { fmt.Printf(" Address: %s\n", port.Address) fmt.Printf(" Protocol: %s\n", port.Protocol) if ev.Type == "add" { - keys := port.Properties.Keys() - sort.Strings(keys) - for _, k := range keys { - fmt.Printf(" %s=%s\n", k, port.Properties.Get(k)) + if port.Properties != nil { + keys := port.Properties.Keys() + sort.Strings(keys) + for _, k := range keys { + fmt.Printf(" %s=%s\n", k, port.Properties.Get(k)) + } } } fmt.Println() diff --git a/commands/board/list.go b/commands/board/list.go index 5098ced4cfd..1ac055253b9 100644 --- a/commands/board/list.go +++ b/commands/board/list.go @@ -34,6 +34,7 @@ import ( "github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/internal/inventory" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" + "github.com/arduino/go-properties-orderedmap" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -128,20 +129,22 @@ func apiByVidPid(vid, pid string) ([]*rpc.BoardListItem, error) { }, nil } -func identifyViaCloudAPI(port *discovery.Port) ([]*rpc.BoardListItem, error) { +func identifyViaCloudAPI(props *properties.Map) ([]*rpc.BoardListItem, error) { // If the port is not USB do not try identification via cloud - id := port.Properties - if !id.ContainsKey("vid") || !id.ContainsKey("pid") { + if !props.ContainsKey("vid") || !props.ContainsKey("pid") { return nil, nil } logrus.Debug("Querying builder API for board identification...") - return cachedAPIByVidPid(id.Get("vid"), id.Get("pid")) + return cachedAPIByVidPid(props.Get("vid"), props.Get("pid")) } // identify returns a list of boards checking first the installed platforms or the Cloud API func identify(pme *packagemanager.Explorer, port *discovery.Port) ([]*rpc.BoardListItem, error) { boards := []*rpc.BoardListItem{} + if port.Properties == nil { + return boards, nil + } // first query installed cores through the Package Manager logrus.Debug("Querying installed cores for board identification...") @@ -167,7 +170,7 @@ func identify(pme *packagemanager.Explorer, port *discovery.Port) ([]*rpc.BoardL // if installed cores didn't recognize the board, try querying // the builder API if the board is a USB device port if len(boards) == 0 { - items, err := identifyViaCloudAPI(port) + items, err := identifyViaCloudAPI(port.Properties) if err != nil { // this is bad, but keep going logrus.WithError(err).Debug("Error querying builder API") diff --git a/commands/board/list_test.go b/commands/board/list_test.go index cf1dca37e4c..f99d942cf29 100644 --- a/commands/board/list_test.go +++ b/commands/board/list_test.go @@ -103,10 +103,7 @@ func TestGetByVidPidMalformedResponse(t *testing.T) { } func TestBoardDetectionViaAPIWithNonUSBPort(t *testing.T) { - port := &discovery.Port{ - Properties: properties.NewMap(), - } - items, err := identifyViaCloudAPI(port) + items, err := identifyViaCloudAPI(properties.NewMap()) require.NoError(t, err) require.Empty(t, items) } diff --git a/commands/daemon/daemon.go b/commands/daemon/daemon.go index bcf173381c7..1cb5a667b60 100644 --- a/commands/daemon/daemon.go +++ b/commands/daemon/daemon.go @@ -297,15 +297,27 @@ func (s *ArduinoCoreServerImpl) PlatformList(ctx context.Context, req *rpc.Platf // Upload FIXMEDOC func (s *ArduinoCoreServerImpl) Upload(req *rpc.UploadRequest, stream rpc.ArduinoCoreService_UploadServer) error { syncSend := NewSynchronizedSend(stream.Send) - outStream := feedStreamTo(func(data []byte) { syncSend.Send(&rpc.UploadResponse{OutStream: data}) }) - errStream := feedStreamTo(func(data []byte) { syncSend.Send(&rpc.UploadResponse{ErrStream: data}) }) - err := upload.Upload(stream.Context(), req, outStream, errStream) + outStream := feedStreamTo(func(data []byte) { + syncSend.Send(&rpc.UploadResponse{ + Message: &rpc.UploadResponse_OutStream{OutStream: data}, + }) + }) + errStream := feedStreamTo(func(data []byte) { + syncSend.Send(&rpc.UploadResponse{ + Message: &rpc.UploadResponse_ErrStream{ErrStream: data}, + }) + }) + res, err := upload.Upload(stream.Context(), req, outStream, errStream) outStream.Close() errStream.Close() - if err != nil { - return convertErrorToRPCStatus(err) + if res != nil { + syncSend.Send(&rpc.UploadResponse{ + Message: &rpc.UploadResponse_Result{ + Result: res, + }, + }) } - return nil + return convertErrorToRPCStatus(err) } // UploadUsingProgrammer FIXMEDOC diff --git a/commands/upload/burnbootloader.go b/commands/upload/burnbootloader.go index f47e22fd239..99efe2be757 100644 --- a/commands/upload/burnbootloader.go +++ b/commands/upload/burnbootloader.go @@ -39,7 +39,7 @@ func BurnBootloader(ctx context.Context, req *rpc.BurnBootloaderRequest, outStre } defer release() - err := runProgramAction( + _, err := runProgramAction( pme, nil, // sketch "", // importFile diff --git a/commands/upload/upload.go b/commands/upload/upload.go index 8de4bc009f6..75f8aae9238 100644 --- a/commands/upload/upload.go +++ b/commands/upload/upload.go @@ -21,16 +21,19 @@ import ( "io" "path/filepath" "strings" + "time" "github.com/arduino/arduino-cli/arduino" "github.com/arduino/arduino-cli/arduino/cores" "github.com/arduino/arduino-cli/arduino/cores/packagemanager" + "github.com/arduino/arduino-cli/arduino/discovery" "github.com/arduino/arduino-cli/arduino/globals" "github.com/arduino/arduino-cli/arduino/serialutils" "github.com/arduino/arduino-cli/arduino/sketch" "github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/executils" "github.com/arduino/arduino-cli/i18n" + f "github.com/arduino/arduino-cli/internal/algorithms" rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" paths "github.com/arduino/go-paths-helper" properties "github.com/arduino/go-properties-orderedmap" @@ -123,7 +126,7 @@ func getUserFields(toolID string, platformRelease *cores.PlatformRelease) []*rpc } // Upload FIXMEDOC -func Upload(ctx context.Context, req *rpc.UploadRequest, outStream io.Writer, errStream io.Writer) error { +func Upload(ctx context.Context, req *rpc.UploadRequest, outStream io.Writer, errStream io.Writer) (*rpc.UploadResult, error) { logrus.Tracef("Upload %s on %s started", req.GetSketchPath(), req.GetFqbn()) // TODO: make a generic function to extract sketch from request @@ -131,16 +134,16 @@ func Upload(ctx context.Context, req *rpc.UploadRequest, outStream io.Writer, er sketchPath := paths.New(req.GetSketchPath()) sk, err := sketch.New(sketchPath) if err != nil && req.GetImportDir() == "" && req.GetImportFile() == "" { - return &arduino.CantOpenSketchError{Cause: err} + return nil, &arduino.CantOpenSketchError{Cause: err} } - pme, release := commands.GetPackageManagerExplorer(req) + pme, pmeRelease := commands.GetPackageManagerExplorer(req) if pme == nil { - return &arduino.InvalidInstanceError{} + return nil, &arduino.InvalidInstanceError{} } - defer release() + defer pmeRelease() - if err := runProgramAction( + updatedPort, err := runProgramAction( pme, sk, req.GetImportFile(), @@ -155,11 +158,14 @@ func Upload(ctx context.Context, req *rpc.UploadRequest, outStream io.Writer, er errStream, req.GetDryRun(), req.GetUserFields(), - ); err != nil { - return err + ) + if err != nil { + return nil, err } - return nil + return &rpc.UploadResult{ + UpdatedUploadPort: updatedPort, + }, nil } // UsingProgrammer FIXMEDOC @@ -169,7 +175,7 @@ func UsingProgrammer(ctx context.Context, req *rpc.UploadUsingProgrammerRequest, if req.GetProgrammer() == "" { return &arduino.MissingProgrammerError{} } - err := Upload(ctx, &rpc.UploadRequest{ + _, err := Upload(ctx, &rpc.UploadRequest{ Instance: req.GetInstance(), SketchPath: req.GetSketchPath(), ImportFile: req.GetImportFile(), @@ -186,36 +192,38 @@ func UsingProgrammer(ctx context.Context, req *rpc.UploadUsingProgrammerRequest, func runProgramAction(pme *packagemanager.Explorer, sk *sketch.Sketch, - importFile, importDir, fqbnIn string, port *rpc.Port, + importFile, importDir, fqbnIn string, userPort *rpc.Port, programmerID string, verbose, verify, burnBootloader bool, outStream, errStream io.Writer, - dryRun bool, userFields map[string]string) error { - - if burnBootloader && programmerID == "" { - return &arduino.MissingProgrammerError{} - } + dryRun bool, userFields map[string]string, +) (*rpc.Port, error) { + port := discovery.PortFromRPCPort(userPort) if port == nil || (port.Address == "" && port.Protocol == "") { // For no-port uploads use "default" protocol - port = &rpc.Port{Protocol: "default"} + port = &discovery.Port{Protocol: "default"} } logrus.WithField("port", port).Tracef("Upload port") + if burnBootloader && programmerID == "" { + return nil, &arduino.MissingProgrammerError{} + } + fqbn, err := cores.ParseFQBN(fqbnIn) if err != nil { - return &arduino.InvalidFQBNError{Cause: err} + return nil, &arduino.InvalidFQBNError{Cause: err} } logrus.WithField("fqbn", fqbn).Tracef("Detected FQBN") // Find target board and board properties _, boardPlatform, board, boardProperties, buildPlatform, err := pme.ResolveFQBN(fqbn) if boardPlatform == nil { - return &arduino.PlatformNotFoundError{ + return nil, &arduino.PlatformNotFoundError{ Platform: fmt.Sprintf("%s:%s", fqbn.Package, fqbn.PlatformArch), Cause: err, } } else if err != nil { - return &arduino.UnknownFQBNError{Cause: err} + return nil, &arduino.UnknownFQBNError{Cause: err} } logrus. WithField("boardPlatform", boardPlatform). @@ -232,7 +240,7 @@ func runProgramAction(pme *packagemanager.Explorer, programmer = buildPlatform.Programmers[programmerID] } if programmer == nil { - return &arduino.ProgrammerNotFoundError{Programmer: programmerID} + return nil, &arduino.ProgrammerNotFoundError{Programmer: programmerID} } } @@ -253,7 +261,7 @@ func runProgramAction(pme *packagemanager.Explorer, } uploadToolID, err := getToolID(props, action, port.Protocol) if err != nil { - return err + return nil, err } var uploadToolPlatform *cores.PlatformRelease @@ -268,7 +276,7 @@ func runProgramAction(pme *packagemanager.Explorer, Trace("Upload tool") if split := strings.Split(uploadToolID, ":"); len(split) > 2 { - return &arduino.InvalidPlatformPropertyError{ + return nil, &arduino.InvalidPlatformPropertyError{ Property: fmt.Sprintf("%s.tool.%s", action, port.Protocol), // TODO: Can be done better, maybe inline getToolID(...) Value: uploadToolID} } else if len(split) == 2 { @@ -277,12 +285,12 @@ func runProgramAction(pme *packagemanager.Explorer, PlatformArchitecture: boardPlatform.Platform.Architecture, }) if p == nil { - return &arduino.PlatformNotFoundError{Platform: split[0] + ":" + boardPlatform.Platform.Architecture} + return nil, &arduino.PlatformNotFoundError{Platform: split[0] + ":" + boardPlatform.Platform.Architecture} } uploadToolID = split[1] uploadToolPlatform = pme.GetInstalledPlatformRelease(p) if uploadToolPlatform == nil { - return &arduino.PlatformNotFoundError{Platform: split[0] + ":" + boardPlatform.Platform.Architecture} + return nil, &arduino.PlatformNotFoundError{Platform: split[0] + ":" + boardPlatform.Platform.Architecture} } } @@ -309,7 +317,7 @@ func runProgramAction(pme *packagemanager.Explorer, } if !uploadProperties.ContainsKey("upload.protocol") && programmer == nil { - return &arduino.ProgrammerRequiredForUploadError{} + return nil, &arduino.ProgrammerRequiredForUploadError{} } // Set properties for verbose upload @@ -357,18 +365,35 @@ func runProgramAction(pme *packagemanager.Explorer, if !burnBootloader { importPath, sketchName, err := determineBuildPathAndSketchName(importFile, importDir, sk, fqbn) if err != nil { - return &arduino.NotFoundError{Message: tr("Error finding build artifacts"), Cause: err} + return nil, &arduino.NotFoundError{Message: tr("Error finding build artifacts"), Cause: err} } if !importPath.Exist() { - return &arduino.NotFoundError{Message: tr("Compiled sketch not found in %s", importPath)} + return nil, &arduino.NotFoundError{Message: tr("Compiled sketch not found in %s", importPath)} } if !importPath.IsDir() { - return &arduino.NotFoundError{Message: tr("Expected compiled sketch in directory %s, but is a file instead", importPath)} + return nil, &arduino.NotFoundError{Message: tr("Expected compiled sketch in directory %s, but is a file instead", importPath)} } uploadProperties.SetPath("build.path", importPath) uploadProperties.Set("build.project_name", sketchName) } + // This context is kept alive for the entire duration of the upload + uploadCtx, uploadCompleted := context.WithCancel(context.Background()) + defer uploadCompleted() + + // Start the upload port change detector. + watcher, err := pme.DiscoveryManager().Watch() + if err != nil { + return nil, err + } + defer watcher.Close() + updatedUploadPort := f.NewFuture[*discovery.Port]() + go detectUploadPort( + uploadCtx, + port, watcher.Feed(), + uploadProperties.GetBoolean("upload.wait_for_upload_port"), + updatedUploadPort) + // Force port wait to make easier to unbrick boards like the Arduino Leonardo, or similar with native USB, // when a sketch causes a crash and the native USB serial port is lost. // See https://github.com/arduino/arduino-cli/issues/1943 for the details. @@ -385,7 +410,7 @@ func runProgramAction(pme *packagemanager.Explorer, // If not using programmer perform some action required // to set the board in bootloader mode - actualPort := port + actualPort := port.Clone() if programmer == nil && !burnBootloader && (port.Protocol == "serial" || forcedSerialPortWait) { // Perform reset via 1200bps touch if requested and wait for upload port also if requested. touch := uploadProperties.GetBoolean("upload.use_1200bps_touch") @@ -439,6 +464,7 @@ func runProgramAction(pme *packagemanager.Explorer, } else { if newPortAddress != "" { actualPort.Address = newPortAddress + actualPort.AddressLabel = newPortAddress } } } @@ -455,34 +481,144 @@ func runProgramAction(pme *packagemanager.Explorer, // Get Port properties gathered using pluggable discovery uploadProperties.Set("upload.port.address", port.Address) - uploadProperties.Set("upload.port.label", port.Label) + uploadProperties.Set("upload.port.label", port.AddressLabel) uploadProperties.Set("upload.port.protocol", port.Protocol) uploadProperties.Set("upload.port.protocolLabel", port.ProtocolLabel) - for prop, value := range actualPort.Properties { - uploadProperties.Set(fmt.Sprintf("upload.port.properties.%s", prop), value) + if actualPort.Properties != nil { + for prop, value := range actualPort.Properties.AsMap() { + uploadProperties.Set(fmt.Sprintf("upload.port.properties.%s", prop), value) + } } // Run recipes for upload toolEnv := pme.GetEnvVarsForSpawnedProcess() if burnBootloader { if err := runTool("erase.pattern", uploadProperties, outStream, errStream, verbose, dryRun, toolEnv); err != nil { - return &arduino.FailedUploadError{Message: tr("Failed chip erase"), Cause: err} + return nil, &arduino.FailedUploadError{Message: tr("Failed chip erase"), Cause: err} } if err := runTool("bootloader.pattern", uploadProperties, outStream, errStream, verbose, dryRun, toolEnv); err != nil { - return &arduino.FailedUploadError{Message: tr("Failed to burn bootloader"), Cause: err} + return nil, &arduino.FailedUploadError{Message: tr("Failed to burn bootloader"), Cause: err} } } else if programmer != nil { if err := runTool("program.pattern", uploadProperties, outStream, errStream, verbose, dryRun, toolEnv); err != nil { - return &arduino.FailedUploadError{Message: tr("Failed programming"), Cause: err} + return nil, &arduino.FailedUploadError{Message: tr("Failed programming"), Cause: err} } } else { if err := runTool("upload.pattern", uploadProperties, outStream, errStream, verbose, dryRun, toolEnv); err != nil { - return &arduino.FailedUploadError{Message: tr("Failed uploading"), Cause: err} + return nil, &arduino.FailedUploadError{Message: tr("Failed uploading"), Cause: err} } } + uploadCompleted() logrus.Tracef("Upload successful") - return nil + + updatedPort := updatedUploadPort.Await() + if updatedPort == nil { + return nil, nil + } + return updatedPort.ToRPC(), nil +} + +func detectUploadPort( + uploadCtx context.Context, + uploadPort *discovery.Port, watch <-chan *discovery.Event, + waitForUploadPort bool, + result f.Future[*discovery.Port], +) { + log := logrus.WithField("task", "port_detection") + log.Tracef("Detecting new board port after upload") + + candidate := uploadPort.Clone() + defer func() { + result.Send(candidate) + }() + + // Ignore all events during the upload + for { + select { + case ev, ok := <-watch: + if !ok { + log.Error("Upload port detection failed, watcher closed") + return + } + if candidate != nil && ev.Type == "remove" && ev.Port.Equals(candidate) { + log.WithField("event", ev).Trace("User-specified port has been disconnected, forcing wait for upload port") + waitForUploadPort = true + candidate = nil + } else { + log.WithField("event", ev).Trace("Ignored watcher event before upload") + } + continue + case <-uploadCtx.Done(): + // Upload completed, move to the next phase + } + break + } + + // Pick the first port that is detected after the upload + timeout := time.After(5 * time.Second) + if !waitForUploadPort { + timeout = time.After(time.Second) + } + for { + select { + case ev, ok := <-watch: + if !ok { + log.Error("Upload port detection failed, watcher closed") + return + } + if candidate != nil && ev.Type == "remove" && candidate.Equals(ev.Port) { + log.WithField("event", ev).Trace("Candidate port is no longer available") + candidate = nil + if !waitForUploadPort { + waitForUploadPort = true + timeout = time.After(5 * time.Second) + log.Trace("User-specified port has been disconnected, now waiting for upload port, timeout extended by 5 seconds") + } + continue + } + if ev.Type != "add" { + log.WithField("event", ev).Trace("Ignored non-add event") + continue + } + + portPriority := func(port *discovery.Port) int { + if port == nil { + return 0 + } + prio := 0 + if port.HardwareID == uploadPort.HardwareID { + prio += 1000 + } + if port.Protocol == uploadPort.Protocol { + prio += 100 + } + if port.Address == uploadPort.Address { + prio += 10 + } + return prio + } + evPortPriority := portPriority(ev.Port) + candidatePriority := portPriority(candidate) + if evPortPriority <= candidatePriority { + log.WithField("event", ev).Tracef("New upload port candidate is worse than the current one (prio=%d)", evPortPriority) + continue + } + log.WithField("event", ev).Tracef("Found new upload port candidate (prio=%d)", evPortPriority) + candidate = ev.Port + + // If the current candidate have the desired HW-ID return it quickly. + if candidate.HardwareID == ev.Port.HardwareID { + timeout = time.After(time.Second) + log.Trace("New candidate port match the desired HW ID, timeout reduced to 1 second.") + continue + } + + case <-timeout: + log.WithField("selected_port", candidate).Trace("Timeout waiting for candidate port") + return + } + } } func runTool(recipeID string, props *properties.Map, outStream, errStream io.Writer, verbose bool, dryRun bool, toolEnv []string) error { diff --git a/commands/upload/upload_test.go b/commands/upload/upload_test.go index d3f69fd1baf..e1f87cd9832 100644 --- a/commands/upload/upload_test.go +++ b/commands/upload/upload_test.go @@ -184,7 +184,7 @@ func TestUploadPropertiesComposition(t *testing.T) { testRunner := func(t *testing.T, test test, verboseVerify bool) { outStream := &bytes.Buffer{} errStream := &bytes.Buffer{} - err := runProgramAction( + _, err := runProgramAction( pme, nil, // sketch "", // importFile diff --git a/docs/UPGRADING.md b/docs/UPGRADING.md index 31490513af2..d1821cf87fa 100644 --- a/docs/UPGRADING.md +++ b/docs/UPGRADING.md @@ -4,6 +4,58 @@ Here you can find a list of migration guides to handle breaking changes between ## 0.34.0 +### The gRPC `cc.arduino.cli.commands.v1.UploadRepsonse` command response has been changed. + +Previously the `UploadResponse` was used only to stream the tool output: + +``` +message UploadResponse { + // The output of the upload process. + bytes out_stream = 1; + // The error output of the upload process. + bytes err_stream = 2; +} +``` + +Now the API logic has been clarified using the `oneof` clause and another field has been added providing an +`UploadResult` message that is sent when a successful upload completes. + +``` +message UploadResponse { + oneof message { + // The output of the upload process. + bytes out_stream = 1; + // The error output of the upload process. + bytes err_stream = 2; + // The upload result + UploadResult result = 3; + } +} + +message UploadResult { + // When a board requires a port disconnection to perform the upload, this + // field returns the port where the board reconnects after the upload. + Port updated_upload_port = 1; +} +``` + +### golang API: method `github.com/arduino/arduino-cli/commands/upload.Upload` changed signature + +The `Upload` method signature has been changed from: + +```go +func Upload(ctx context.Context, req *rpc.UploadRequest, outStream io.Writer, errStream io.Writer) error { ... } +``` + +to: + +```go +func Upload(ctx context.Context, req *rpc.UploadRequest, outStream io.Writer, errStream io.Writer) (*rpc.UploadResult, error) { ... } +``` + +Now an `UploadResult` structure is returned together with the error. If you are not interested in the information +contained in the structure you can safely ignore it. + ### golang package `github.com/arduino/arduino-cli/inventory` removed from public API The package `inventory` is no more a public golang API. diff --git a/internal/algorithms/channels.go b/internal/algorithms/channels.go new file mode 100644 index 00000000000..982925322cb --- /dev/null +++ b/internal/algorithms/channels.go @@ -0,0 +1,55 @@ +// This file is part of arduino-cli. +// +// Copyright 2023 ARDUINO SA (http://www.arduino.cc/) +// +// This software is released under the GNU General Public License version 3, +// which covers the main part of arduino-cli. +// The terms of this license can be found at: +// https://www.gnu.org/licenses/gpl-3.0.en.html +// +// You can be released from the requirements of the above licenses by purchasing +// a commercial license. Buying such a license is mandatory if you want to +// modify or otherwise use the software for commercial activities involving the +// Arduino software without disclosing the source code of your own applications. +// To purchase a commercial license, send an email to license@arduino.cc. + +package f + +import "sync" + +// DiscardCh consumes all incoming messages from the given channel until it's closed. +func DiscardCh[T any](ch <-chan T) { + for range ch { + } +} + +// Future is an object that holds a result value. The value may be read and +// written asynchronously. +type Future[T any] interface { + Send(T) + Await() T +} + +type future[T any] struct { + wg sync.WaitGroup + value T +} + +// NewFuture creates a new Future[T] +func NewFuture[T any]() Future[T] { + res := &future[T]{} + res.wg.Add(1) + return res +} + +// Send a result in the Future. Threads waiting for result will be unlocked. +func (f *future[T]) Send(value T) { + f.value = value + f.wg.Done() +} + +// Await for a result from the Future, blocks until a result is available. +func (f *future[T]) Await() T { + f.wg.Wait() + return f.value +} diff --git a/internal/cli/compile/compile.go b/internal/cli/compile/compile.go index b208cc79dfd..baa1dff5f89 100644 --- a/internal/cli/compile/compile.go +++ b/internal/cli/compile/compile.go @@ -236,6 +236,8 @@ func runCompileCommand(cmd *cobra.Command, args []string) { DoNotExpandBuildProperties: showProperties == arguments.ShowPropertiesUnexpanded, } compileRes, compileError := compile.Compile(context.Background(), compileRequest, stdOut, stdErr, nil) + + var uploadRes *rpc.UploadResult if compileError == nil && uploadAfterCompile { userFieldRes, err := upload.SupportedUserFields(context.Background(), &rpc.SupportedUserFieldsRequest{ Instance: inst, @@ -268,8 +270,10 @@ func runCompileCommand(cmd *cobra.Command, args []string) { UserFields: fields, } - if err := upload.Upload(context.Background(), uploadRequest, stdOut, stdErr); err != nil { + if res, err := upload.Upload(context.Background(), uploadRequest, stdOut, stdErr); err != nil { feedback.Fatal(tr("Error during Upload: %v", err), feedback.ErrGeneric) + } else { + uploadRes = res } } @@ -330,6 +334,7 @@ func runCompileCommand(cmd *cobra.Command, args []string) { CompilerOut: stdIO.Stdout, CompilerErr: stdIO.Stderr, BuilderResult: compileRes, + UploadResult: uploadRes, ProfileOut: profileOut, Success: compileError == nil, showPropertiesMode: showProperties, @@ -375,6 +380,7 @@ type compileResult struct { CompilerOut string `json:"compiler_out"` CompilerErr string `json:"compiler_err"` BuilderResult *rpc.CompileResponse `json:"builder_result"` + UploadResult *rpc.UploadResult `json:"upload_result"` Success bool `json:"success"` ProfileOut string `json:"profile_out,omitempty"` Error string `json:"error,omitempty"` diff --git a/internal/cli/upload/upload.go b/internal/cli/upload/upload.go index 739bb7d29e4..1fa91086ac0 100644 --- a/internal/cli/upload/upload.go +++ b/internal/cli/upload/upload.go @@ -168,8 +168,31 @@ func runUploadCommand(command *cobra.Command, args []string) { DryRun: dryRun, UserFields: fields, } - if err := upload.Upload(context.Background(), req, stdOut, stdErr); err != nil { + if res, err := upload.Upload(context.Background(), req, stdOut, stdErr); err != nil { feedback.FatalError(err, feedback.ErrGeneric) + } else { + io := stdIOResult() + feedback.PrintResult(&uploadResult{ + Stdout: io.Stdout, + Stderr: io.Stderr, + UpdatedUploadPort: res.UpdatedUploadPort, + }) } - feedback.PrintResult(stdIOResult()) +} + +type uploadResult struct { + Stdout string `json:"stdout"` + Stderr string `json:"stderr"` + UpdatedUploadPort *rpc.Port `json:"updated_upload_port,omitempty"` +} + +func (r *uploadResult) Data() interface{} { + return r +} + +func (r *uploadResult) String() string { + if r.UpdatedUploadPort == nil { + return "" + } + return tr("New upload port: %[1]s (%[2]s)", r.UpdatedUploadPort.Address, r.UpdatedUploadPort.Protocol) } diff --git a/rpc/cc/arduino/cli/commands/v1/upload.pb.go b/rpc/cc/arduino/cli/commands/v1/upload.pb.go index 50176927a47..0398a460ba1 100644 --- a/rpc/cc/arduino/cli/commands/v1/upload.pb.go +++ b/rpc/cc/arduino/cli/commands/v1/upload.pb.go @@ -192,10 +192,12 @@ type UploadResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // The output of the upload process. - OutStream []byte `protobuf:"bytes,1,opt,name=out_stream,json=outStream,proto3" json:"out_stream,omitempty"` - // The error output of the upload process. - ErrStream []byte `protobuf:"bytes,2,opt,name=err_stream,json=errStream,proto3" json:"err_stream,omitempty"` + // Types that are assignable to Message: + // + // *UploadResponse_OutStream + // *UploadResponse_ErrStream + // *UploadResponse_Result + Message isUploadResponse_Message `protobuf_oneof:"message"` } func (x *UploadResponse) Reset() { @@ -230,20 +232,108 @@ func (*UploadResponse) Descriptor() ([]byte, []int) { return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{1} } +func (m *UploadResponse) GetMessage() isUploadResponse_Message { + if m != nil { + return m.Message + } + return nil +} + func (x *UploadResponse) GetOutStream() []byte { - if x != nil { + if x, ok := x.GetMessage().(*UploadResponse_OutStream); ok { return x.OutStream } return nil } func (x *UploadResponse) GetErrStream() []byte { - if x != nil { + if x, ok := x.GetMessage().(*UploadResponse_ErrStream); ok { return x.ErrStream } return nil } +func (x *UploadResponse) GetResult() *UploadResult { + if x, ok := x.GetMessage().(*UploadResponse_Result); ok { + return x.Result + } + return nil +} + +type isUploadResponse_Message interface { + isUploadResponse_Message() +} + +type UploadResponse_OutStream struct { + // The output of the upload process. + OutStream []byte `protobuf:"bytes,1,opt,name=out_stream,json=outStream,proto3,oneof"` +} + +type UploadResponse_ErrStream struct { + // The error output of the upload process. + ErrStream []byte `protobuf:"bytes,2,opt,name=err_stream,json=errStream,proto3,oneof"` +} + +type UploadResponse_Result struct { + // The upload result + Result *UploadResult `protobuf:"bytes,3,opt,name=result,proto3,oneof"` +} + +func (*UploadResponse_OutStream) isUploadResponse_Message() {} + +func (*UploadResponse_ErrStream) isUploadResponse_Message() {} + +func (*UploadResponse_Result) isUploadResponse_Message() {} + +type UploadResult struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // When a board requires a port disconnection to perform the upload, this + // field returns the port where the board reconnects after the upload. + UpdatedUploadPort *Port `protobuf:"bytes,1,opt,name=updated_upload_port,json=updatedUploadPort,proto3" json:"updated_upload_port,omitempty"` +} + +func (x *UploadResult) Reset() { + *x = UploadResult{} + if protoimpl.UnsafeEnabled { + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UploadResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UploadResult) ProtoMessage() {} + +func (x *UploadResult) ProtoReflect() protoreflect.Message { + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[2] + 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 UploadResult.ProtoReflect.Descriptor instead. +func (*UploadResult) Descriptor() ([]byte, []int) { + return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{2} +} + +func (x *UploadResult) GetUpdatedUploadPort() *Port { + if x != nil { + return x.UpdatedUploadPort + } + return nil +} + type ProgrammerIsRequiredForUploadError struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -253,7 +343,7 @@ type ProgrammerIsRequiredForUploadError struct { func (x *ProgrammerIsRequiredForUploadError) Reset() { *x = ProgrammerIsRequiredForUploadError{} if protoimpl.UnsafeEnabled { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[2] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -266,7 +356,7 @@ func (x *ProgrammerIsRequiredForUploadError) String() string { func (*ProgrammerIsRequiredForUploadError) ProtoMessage() {} func (x *ProgrammerIsRequiredForUploadError) ProtoReflect() protoreflect.Message { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[2] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -279,7 +369,7 @@ func (x *ProgrammerIsRequiredForUploadError) ProtoReflect() protoreflect.Message // Deprecated: Use ProgrammerIsRequiredForUploadError.ProtoReflect.Descriptor instead. func (*ProgrammerIsRequiredForUploadError) Descriptor() ([]byte, []int) { - return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{2} + return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{3} } type UploadUsingProgrammerRequest struct { @@ -326,7 +416,7 @@ type UploadUsingProgrammerRequest struct { func (x *UploadUsingProgrammerRequest) Reset() { *x = UploadUsingProgrammerRequest{} if protoimpl.UnsafeEnabled { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[3] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -339,7 +429,7 @@ func (x *UploadUsingProgrammerRequest) String() string { func (*UploadUsingProgrammerRequest) ProtoMessage() {} func (x *UploadUsingProgrammerRequest) ProtoReflect() protoreflect.Message { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[3] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -352,7 +442,7 @@ func (x *UploadUsingProgrammerRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UploadUsingProgrammerRequest.ProtoReflect.Descriptor instead. func (*UploadUsingProgrammerRequest) Descriptor() ([]byte, []int) { - return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{3} + return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{4} } func (x *UploadUsingProgrammerRequest) GetInstance() *Instance { @@ -446,7 +536,7 @@ type UploadUsingProgrammerResponse struct { func (x *UploadUsingProgrammerResponse) Reset() { *x = UploadUsingProgrammerResponse{} if protoimpl.UnsafeEnabled { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[4] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -459,7 +549,7 @@ func (x *UploadUsingProgrammerResponse) String() string { func (*UploadUsingProgrammerResponse) ProtoMessage() {} func (x *UploadUsingProgrammerResponse) ProtoReflect() protoreflect.Message { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[4] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -472,7 +562,7 @@ func (x *UploadUsingProgrammerResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UploadUsingProgrammerResponse.ProtoReflect.Descriptor instead. func (*UploadUsingProgrammerResponse) Descriptor() ([]byte, []int) { - return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{4} + return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{5} } func (x *UploadUsingProgrammerResponse) GetOutStream() []byte { @@ -521,7 +611,7 @@ type BurnBootloaderRequest struct { func (x *BurnBootloaderRequest) Reset() { *x = BurnBootloaderRequest{} if protoimpl.UnsafeEnabled { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[5] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -534,7 +624,7 @@ func (x *BurnBootloaderRequest) String() string { func (*BurnBootloaderRequest) ProtoMessage() {} func (x *BurnBootloaderRequest) ProtoReflect() protoreflect.Message { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[5] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -547,7 +637,7 @@ func (x *BurnBootloaderRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BurnBootloaderRequest.ProtoReflect.Descriptor instead. func (*BurnBootloaderRequest) Descriptor() ([]byte, []int) { - return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{5} + return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{6} } func (x *BurnBootloaderRequest) GetInstance() *Instance { @@ -620,7 +710,7 @@ type BurnBootloaderResponse struct { func (x *BurnBootloaderResponse) Reset() { *x = BurnBootloaderResponse{} if protoimpl.UnsafeEnabled { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[6] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -633,7 +723,7 @@ func (x *BurnBootloaderResponse) String() string { func (*BurnBootloaderResponse) ProtoMessage() {} func (x *BurnBootloaderResponse) ProtoReflect() protoreflect.Message { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[6] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -646,7 +736,7 @@ func (x *BurnBootloaderResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use BurnBootloaderResponse.ProtoReflect.Descriptor instead. func (*BurnBootloaderResponse) Descriptor() ([]byte, []int) { - return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{6} + return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{7} } func (x *BurnBootloaderResponse) GetOutStream() []byte { @@ -675,7 +765,7 @@ type ListProgrammersAvailableForUploadRequest struct { func (x *ListProgrammersAvailableForUploadRequest) Reset() { *x = ListProgrammersAvailableForUploadRequest{} if protoimpl.UnsafeEnabled { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[7] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -688,7 +778,7 @@ func (x *ListProgrammersAvailableForUploadRequest) String() string { func (*ListProgrammersAvailableForUploadRequest) ProtoMessage() {} func (x *ListProgrammersAvailableForUploadRequest) ProtoReflect() protoreflect.Message { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[7] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -701,7 +791,7 @@ func (x *ListProgrammersAvailableForUploadRequest) ProtoReflect() protoreflect.M // Deprecated: Use ListProgrammersAvailableForUploadRequest.ProtoReflect.Descriptor instead. func (*ListProgrammersAvailableForUploadRequest) Descriptor() ([]byte, []int) { - return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{7} + return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{8} } func (x *ListProgrammersAvailableForUploadRequest) GetInstance() *Instance { @@ -729,7 +819,7 @@ type ListProgrammersAvailableForUploadResponse struct { func (x *ListProgrammersAvailableForUploadResponse) Reset() { *x = ListProgrammersAvailableForUploadResponse{} if protoimpl.UnsafeEnabled { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[8] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -742,7 +832,7 @@ func (x *ListProgrammersAvailableForUploadResponse) String() string { func (*ListProgrammersAvailableForUploadResponse) ProtoMessage() {} func (x *ListProgrammersAvailableForUploadResponse) ProtoReflect() protoreflect.Message { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[8] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -755,7 +845,7 @@ func (x *ListProgrammersAvailableForUploadResponse) ProtoReflect() protoreflect. // Deprecated: Use ListProgrammersAvailableForUploadResponse.ProtoReflect.Descriptor instead. func (*ListProgrammersAvailableForUploadResponse) Descriptor() ([]byte, []int) { - return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{8} + return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{9} } func (x *ListProgrammersAvailableForUploadResponse) GetProgrammers() []*Programmer { @@ -781,7 +871,7 @@ type SupportedUserFieldsRequest struct { func (x *SupportedUserFieldsRequest) Reset() { *x = SupportedUserFieldsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[9] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -794,7 +884,7 @@ func (x *SupportedUserFieldsRequest) String() string { func (*SupportedUserFieldsRequest) ProtoMessage() {} func (x *SupportedUserFieldsRequest) ProtoReflect() protoreflect.Message { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[9] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -807,7 +897,7 @@ func (x *SupportedUserFieldsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SupportedUserFieldsRequest.ProtoReflect.Descriptor instead. func (*SupportedUserFieldsRequest) Descriptor() ([]byte, []int) { - return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{9} + return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{10} } func (x *SupportedUserFieldsRequest) GetInstance() *Instance { @@ -850,7 +940,7 @@ type UserField struct { func (x *UserField) Reset() { *x = UserField{} if protoimpl.UnsafeEnabled { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[10] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -863,7 +953,7 @@ func (x *UserField) String() string { func (*UserField) ProtoMessage() {} func (x *UserField) ProtoReflect() protoreflect.Message { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[10] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -876,7 +966,7 @@ func (x *UserField) ProtoReflect() protoreflect.Message { // Deprecated: Use UserField.ProtoReflect.Descriptor instead. func (*UserField) Descriptor() ([]byte, []int) { - return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{10} + return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{11} } func (x *UserField) GetToolId() string { @@ -920,7 +1010,7 @@ type SupportedUserFieldsResponse struct { func (x *SupportedUserFieldsResponse) Reset() { *x = SupportedUserFieldsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[11] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -933,7 +1023,7 @@ func (x *SupportedUserFieldsResponse) String() string { func (*SupportedUserFieldsResponse) ProtoMessage() {} func (x *SupportedUserFieldsResponse) ProtoReflect() protoreflect.Message { - mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[11] + mi := &file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -946,7 +1036,7 @@ func (x *SupportedUserFieldsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SupportedUserFieldsResponse.ProtoReflect.Descriptor instead. func (*SupportedUserFieldsResponse) Descriptor() ([]byte, []int) { - return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{11} + return file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP(), []int{12} } func (x *SupportedUserFieldsResponse) GetUserFields() []*UserField { @@ -1000,130 +1090,141 @@ var file_cc_arduino_cli_commands_v1_upload_proto_rawDesc = []byte{ 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4e, 0x0a, 0x0e, 0x55, 0x70, - 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, - 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x09, 0x6f, 0x75, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x65, - 0x72, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x09, 0x65, 0x72, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x22, 0x24, 0x0a, 0x22, 0x50, 0x72, - 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x49, 0x73, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, - 0x65, 0x64, 0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x22, 0xa0, 0x04, 0x0a, 0x1c, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, - 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, - 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, - 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6b, 0x65, 0x74, 0x63, - 0x68, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6b, - 0x65, 0x74, 0x63, 0x68, 0x50, 0x61, 0x74, 0x68, 0x12, 0x34, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xa1, 0x01, 0x0a, 0x0e, 0x55, + 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, + 0x0a, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x48, 0x00, 0x52, 0x09, 0x6f, 0x75, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1f, + 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x48, 0x00, 0x52, 0x09, 0x65, 0x72, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, + 0x42, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x28, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, + 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, + 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x60, + 0x0a, 0x0c, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x50, + 0x0a, 0x13, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, + 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x63, + 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x11, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6f, 0x72, 0x74, + 0x22, 0x24, 0x0a, 0x22, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x49, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61, + 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa0, 0x04, 0x0a, 0x1c, 0x55, 0x70, 0x6c, 0x6f, 0x61, + 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, + 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, + 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, + 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x71, 0x62, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x12, 0x1f, 0x0a, + 0x0b, 0x73, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x50, 0x61, 0x74, 0x68, 0x12, 0x34, + 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, + 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x04, + 0x70, 0x6f, 0x72, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x12, 0x16, + 0x0a, 0x06, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, + 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, + 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6d, 0x70, + 0x6f, 0x72, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6d, 0x70, 0x6f, 0x72, + 0x74, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6d, 0x70, + 0x6f, 0x72, 0x74, 0x44, 0x69, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, + 0x6d, 0x6d, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x67, + 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, + 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x12, + 0x69, 0x0a, 0x0b, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x0b, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x48, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, + 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, + 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, + 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x55, + 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, + 0x75, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x1a, 0x3d, 0x0a, 0x0f, 0x55, 0x73, + 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x5d, 0x0a, 0x1d, 0x55, 0x70, 0x6c, + 0x6f, 0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x75, + 0x74, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, + 0x6f, 0x75, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x72, + 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x65, + 0x72, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x22, 0xb1, 0x03, 0x0a, 0x15, 0x42, 0x75, 0x72, + 0x6e, 0x42, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, + 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, + 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x12, 0x34, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x18, - 0x0a, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0a, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x65, 0x72, 0x69, - 0x66, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, - 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x46, 0x69, 0x6c, - 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x64, 0x69, 0x72, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x44, 0x69, 0x72, - 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x18, 0x09, + 0x66, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, + 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, - 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x12, 0x69, 0x0a, 0x0b, 0x75, 0x73, 0x65, - 0x72, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x48, - 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, - 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, - 0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x73, 0x1a, 0x3d, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x22, 0x5d, 0x0a, 0x1d, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x69, - 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6f, 0x75, 0x74, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x65, 0x72, 0x72, 0x53, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x22, 0xb1, 0x03, 0x0a, 0x15, 0x42, 0x75, 0x72, 0x6e, 0x42, 0x6f, 0x6f, 0x74, 0x6c, - 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, - 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, + 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x12, 0x62, 0x0a, 0x0b, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, - 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x12, - 0x0a, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x71, - 0x62, 0x6e, 0x12, 0x34, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x20, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, - 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, - 0x72, 0x74, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x62, - 0x6f, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, - 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x06, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x72, - 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, - 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, - 0x52, 0x75, 0x6e, 0x12, 0x62, 0x0a, 0x0b, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x66, 0x69, 0x65, 0x6c, - 0x64, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, - 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, - 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x42, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, - 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x55, 0x73, 0x65, 0x72, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x75, 0x73, 0x65, - 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x1a, 0x3d, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x56, 0x0a, 0x16, 0x42, 0x75, 0x72, 0x6e, 0x42, 0x6f, - 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6f, 0x75, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, - 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x09, 0x65, 0x72, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x22, 0x80, - 0x01, 0x0a, 0x28, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, - 0x72, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x70, - 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, - 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x66, 0x71, 0x62, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x71, 0x62, - 0x6e, 0x22, 0x75, 0x0a, 0x29, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, - 0x6d, 0x65, 0x72, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x6f, 0x72, - 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, - 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, + 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x72, 0x6e, + 0x42, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x1a, 0x3d, 0x0a, + 0x0f, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x56, 0x0a, 0x16, + 0x42, 0x75, 0x72, 0x6e, 0x42, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6f, 0x75, 0x74, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x5f, 0x73, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x65, 0x72, 0x72, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x22, 0x80, 0x01, 0x0a, 0x28, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, + 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, + 0x65, 0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x52, 0x0b, 0x70, 0x72, 0x6f, - 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x22, 0x8e, 0x01, 0x0a, 0x1a, 0x53, 0x75, 0x70, - 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, + 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, + 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x22, 0x75, 0x0a, 0x29, 0x4c, 0x69, 0x73, 0x74, 0x50, + 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, + 0x62, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, + 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, - 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x71, 0x62, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x12, 0x1a, 0x0a, - 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0x66, 0x0a, 0x09, 0x55, 0x73, 0x65, - 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, - 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, - 0x72, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, - 0x74, 0x22, 0x65, 0x0a, 0x1b, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x55, 0x73, - 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x46, 0x0a, 0x0b, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, - 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0a, 0x75, 0x73, - 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, - 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, - 0x63, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f, - 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, - 0x64, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, + 0x72, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x22, 0x8e, + 0x01, 0x0a, 0x1a, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, + 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, + 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, + 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, + 0x71, 0x62, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, + 0x66, 0x0a, 0x09, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x17, 0x0a, 0x07, + 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, + 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, + 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, + 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x22, 0x65, 0x0a, 0x1b, 0x53, 0x75, 0x70, 0x70, 0x6f, + 0x72, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x66, + 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, 0x63, + 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, + 0x6c, 0x64, 0x52, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x42, 0x48, + 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x64, + 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2d, 0x63, 0x6c, 0x69, + 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x63, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, + 0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2f, 0x76, 0x31, 0x3b, + 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1138,46 +1239,49 @@ func file_cc_arduino_cli_commands_v1_upload_proto_rawDescGZIP() []byte { return file_cc_arduino_cli_commands_v1_upload_proto_rawDescData } -var file_cc_arduino_cli_commands_v1_upload_proto_msgTypes = make([]protoimpl.MessageInfo, 15) +var file_cc_arduino_cli_commands_v1_upload_proto_msgTypes = make([]protoimpl.MessageInfo, 16) var file_cc_arduino_cli_commands_v1_upload_proto_goTypes = []interface{}{ (*UploadRequest)(nil), // 0: cc.arduino.cli.commands.v1.UploadRequest (*UploadResponse)(nil), // 1: cc.arduino.cli.commands.v1.UploadResponse - (*ProgrammerIsRequiredForUploadError)(nil), // 2: cc.arduino.cli.commands.v1.ProgrammerIsRequiredForUploadError - (*UploadUsingProgrammerRequest)(nil), // 3: cc.arduino.cli.commands.v1.UploadUsingProgrammerRequest - (*UploadUsingProgrammerResponse)(nil), // 4: cc.arduino.cli.commands.v1.UploadUsingProgrammerResponse - (*BurnBootloaderRequest)(nil), // 5: cc.arduino.cli.commands.v1.BurnBootloaderRequest - (*BurnBootloaderResponse)(nil), // 6: cc.arduino.cli.commands.v1.BurnBootloaderResponse - (*ListProgrammersAvailableForUploadRequest)(nil), // 7: cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadRequest - (*ListProgrammersAvailableForUploadResponse)(nil), // 8: cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadResponse - (*SupportedUserFieldsRequest)(nil), // 9: cc.arduino.cli.commands.v1.SupportedUserFieldsRequest - (*UserField)(nil), // 10: cc.arduino.cli.commands.v1.UserField - (*SupportedUserFieldsResponse)(nil), // 11: cc.arduino.cli.commands.v1.SupportedUserFieldsResponse - nil, // 12: cc.arduino.cli.commands.v1.UploadRequest.UserFieldsEntry - nil, // 13: cc.arduino.cli.commands.v1.UploadUsingProgrammerRequest.UserFieldsEntry - nil, // 14: cc.arduino.cli.commands.v1.BurnBootloaderRequest.UserFieldsEntry - (*Instance)(nil), // 15: cc.arduino.cli.commands.v1.Instance - (*Port)(nil), // 16: cc.arduino.cli.commands.v1.Port - (*Programmer)(nil), // 17: cc.arduino.cli.commands.v1.Programmer + (*UploadResult)(nil), // 2: cc.arduino.cli.commands.v1.UploadResult + (*ProgrammerIsRequiredForUploadError)(nil), // 3: cc.arduino.cli.commands.v1.ProgrammerIsRequiredForUploadError + (*UploadUsingProgrammerRequest)(nil), // 4: cc.arduino.cli.commands.v1.UploadUsingProgrammerRequest + (*UploadUsingProgrammerResponse)(nil), // 5: cc.arduino.cli.commands.v1.UploadUsingProgrammerResponse + (*BurnBootloaderRequest)(nil), // 6: cc.arduino.cli.commands.v1.BurnBootloaderRequest + (*BurnBootloaderResponse)(nil), // 7: cc.arduino.cli.commands.v1.BurnBootloaderResponse + (*ListProgrammersAvailableForUploadRequest)(nil), // 8: cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadRequest + (*ListProgrammersAvailableForUploadResponse)(nil), // 9: cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadResponse + (*SupportedUserFieldsRequest)(nil), // 10: cc.arduino.cli.commands.v1.SupportedUserFieldsRequest + (*UserField)(nil), // 11: cc.arduino.cli.commands.v1.UserField + (*SupportedUserFieldsResponse)(nil), // 12: cc.arduino.cli.commands.v1.SupportedUserFieldsResponse + nil, // 13: cc.arduino.cli.commands.v1.UploadRequest.UserFieldsEntry + nil, // 14: cc.arduino.cli.commands.v1.UploadUsingProgrammerRequest.UserFieldsEntry + nil, // 15: cc.arduino.cli.commands.v1.BurnBootloaderRequest.UserFieldsEntry + (*Instance)(nil), // 16: cc.arduino.cli.commands.v1.Instance + (*Port)(nil), // 17: cc.arduino.cli.commands.v1.Port + (*Programmer)(nil), // 18: cc.arduino.cli.commands.v1.Programmer } var file_cc_arduino_cli_commands_v1_upload_proto_depIdxs = []int32{ - 15, // 0: cc.arduino.cli.commands.v1.UploadRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance - 16, // 1: cc.arduino.cli.commands.v1.UploadRequest.port:type_name -> cc.arduino.cli.commands.v1.Port - 12, // 2: cc.arduino.cli.commands.v1.UploadRequest.user_fields:type_name -> cc.arduino.cli.commands.v1.UploadRequest.UserFieldsEntry - 15, // 3: cc.arduino.cli.commands.v1.UploadUsingProgrammerRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance - 16, // 4: cc.arduino.cli.commands.v1.UploadUsingProgrammerRequest.port:type_name -> cc.arduino.cli.commands.v1.Port - 13, // 5: cc.arduino.cli.commands.v1.UploadUsingProgrammerRequest.user_fields:type_name -> cc.arduino.cli.commands.v1.UploadUsingProgrammerRequest.UserFieldsEntry - 15, // 6: cc.arduino.cli.commands.v1.BurnBootloaderRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance - 16, // 7: cc.arduino.cli.commands.v1.BurnBootloaderRequest.port:type_name -> cc.arduino.cli.commands.v1.Port - 14, // 8: cc.arduino.cli.commands.v1.BurnBootloaderRequest.user_fields:type_name -> cc.arduino.cli.commands.v1.BurnBootloaderRequest.UserFieldsEntry - 15, // 9: cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance - 17, // 10: cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadResponse.programmers:type_name -> cc.arduino.cli.commands.v1.Programmer - 15, // 11: cc.arduino.cli.commands.v1.SupportedUserFieldsRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance - 10, // 12: cc.arduino.cli.commands.v1.SupportedUserFieldsResponse.user_fields:type_name -> cc.arduino.cli.commands.v1.UserField - 13, // [13:13] is the sub-list for method output_type - 13, // [13:13] is the sub-list for method input_type - 13, // [13:13] is the sub-list for extension type_name - 13, // [13:13] is the sub-list for extension extendee - 0, // [0:13] is the sub-list for field type_name + 16, // 0: cc.arduino.cli.commands.v1.UploadRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance + 17, // 1: cc.arduino.cli.commands.v1.UploadRequest.port:type_name -> cc.arduino.cli.commands.v1.Port + 13, // 2: cc.arduino.cli.commands.v1.UploadRequest.user_fields:type_name -> cc.arduino.cli.commands.v1.UploadRequest.UserFieldsEntry + 2, // 3: cc.arduino.cli.commands.v1.UploadResponse.result:type_name -> cc.arduino.cli.commands.v1.UploadResult + 17, // 4: cc.arduino.cli.commands.v1.UploadResult.updated_upload_port:type_name -> cc.arduino.cli.commands.v1.Port + 16, // 5: cc.arduino.cli.commands.v1.UploadUsingProgrammerRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance + 17, // 6: cc.arduino.cli.commands.v1.UploadUsingProgrammerRequest.port:type_name -> cc.arduino.cli.commands.v1.Port + 14, // 7: cc.arduino.cli.commands.v1.UploadUsingProgrammerRequest.user_fields:type_name -> cc.arduino.cli.commands.v1.UploadUsingProgrammerRequest.UserFieldsEntry + 16, // 8: cc.arduino.cli.commands.v1.BurnBootloaderRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance + 17, // 9: cc.arduino.cli.commands.v1.BurnBootloaderRequest.port:type_name -> cc.arduino.cli.commands.v1.Port + 15, // 10: cc.arduino.cli.commands.v1.BurnBootloaderRequest.user_fields:type_name -> cc.arduino.cli.commands.v1.BurnBootloaderRequest.UserFieldsEntry + 16, // 11: cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance + 18, // 12: cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadResponse.programmers:type_name -> cc.arduino.cli.commands.v1.Programmer + 16, // 13: cc.arduino.cli.commands.v1.SupportedUserFieldsRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance + 11, // 14: cc.arduino.cli.commands.v1.SupportedUserFieldsResponse.user_fields:type_name -> cc.arduino.cli.commands.v1.UserField + 15, // [15:15] is the sub-list for method output_type + 15, // [15:15] is the sub-list for method input_type + 15, // [15:15] is the sub-list for extension type_name + 15, // [15:15] is the sub-list for extension extendee + 0, // [0:15] is the sub-list for field type_name } func init() { file_cc_arduino_cli_commands_v1_upload_proto_init() } @@ -1213,7 +1317,7 @@ func file_cc_arduino_cli_commands_v1_upload_proto_init() { } } file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProgrammerIsRequiredForUploadError); i { + switch v := v.(*UploadResult); i { case 0: return &v.state case 1: @@ -1225,7 +1329,7 @@ func file_cc_arduino_cli_commands_v1_upload_proto_init() { } } file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UploadUsingProgrammerRequest); i { + switch v := v.(*ProgrammerIsRequiredForUploadError); i { case 0: return &v.state case 1: @@ -1237,7 +1341,7 @@ func file_cc_arduino_cli_commands_v1_upload_proto_init() { } } file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UploadUsingProgrammerResponse); i { + switch v := v.(*UploadUsingProgrammerRequest); i { case 0: return &v.state case 1: @@ -1249,7 +1353,7 @@ func file_cc_arduino_cli_commands_v1_upload_proto_init() { } } file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BurnBootloaderRequest); i { + switch v := v.(*UploadUsingProgrammerResponse); i { case 0: return &v.state case 1: @@ -1261,7 +1365,7 @@ func file_cc_arduino_cli_commands_v1_upload_proto_init() { } } file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BurnBootloaderResponse); i { + switch v := v.(*BurnBootloaderRequest); i { case 0: return &v.state case 1: @@ -1273,7 +1377,7 @@ func file_cc_arduino_cli_commands_v1_upload_proto_init() { } } file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListProgrammersAvailableForUploadRequest); i { + switch v := v.(*BurnBootloaderResponse); i { case 0: return &v.state case 1: @@ -1285,7 +1389,7 @@ func file_cc_arduino_cli_commands_v1_upload_proto_init() { } } file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListProgrammersAvailableForUploadResponse); i { + switch v := v.(*ListProgrammersAvailableForUploadRequest); i { case 0: return &v.state case 1: @@ -1297,7 +1401,7 @@ func file_cc_arduino_cli_commands_v1_upload_proto_init() { } } file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SupportedUserFieldsRequest); i { + switch v := v.(*ListProgrammersAvailableForUploadResponse); i { case 0: return &v.state case 1: @@ -1309,7 +1413,7 @@ func file_cc_arduino_cli_commands_v1_upload_proto_init() { } } file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UserField); i { + switch v := v.(*SupportedUserFieldsRequest); i { case 0: return &v.state case 1: @@ -1321,6 +1425,18 @@ func file_cc_arduino_cli_commands_v1_upload_proto_init() { } } file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UserField); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SupportedUserFieldsResponse); i { case 0: return &v.state @@ -1333,13 +1449,18 @@ func file_cc_arduino_cli_commands_v1_upload_proto_init() { } } } + file_cc_arduino_cli_commands_v1_upload_proto_msgTypes[1].OneofWrappers = []interface{}{ + (*UploadResponse_OutStream)(nil), + (*UploadResponse_ErrStream)(nil), + (*UploadResponse_Result)(nil), + } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_cc_arduino_cli_commands_v1_upload_proto_rawDesc, NumEnums: 0, - NumMessages: 15, + NumMessages: 16, NumExtensions: 0, NumServices: 0, }, diff --git a/rpc/cc/arduino/cli/commands/v1/upload.proto b/rpc/cc/arduino/cli/commands/v1/upload.proto index d0aa108c0ef..8a2b6b0215d 100644 --- a/rpc/cc/arduino/cli/commands/v1/upload.proto +++ b/rpc/cc/arduino/cli/commands/v1/upload.proto @@ -62,10 +62,20 @@ message UploadRequest { } message UploadResponse { - // The output of the upload process. - bytes out_stream = 1; - // The error output of the upload process. - bytes err_stream = 2; + oneof message { + // The output of the upload process. + bytes out_stream = 1; + // The error output of the upload process. + bytes err_stream = 2; + // The upload result + UploadResult result = 3; + } +} + +message UploadResult { + // When a board requires a port disconnection to perform the upload, this + // field returns the port where the board reconnects after the upload. + Port updated_upload_port = 1; } message ProgrammerIsRequiredForUploadError {}