From d95377b7771aa585603b005280012cb35e02aed5 Mon Sep 17 00:00:00 2001 From: Jacob Howard Date: Thu, 23 Jun 2022 12:10:32 -0600 Subject: [PATCH 1/3] cli: clean up implementation of StatusLinePrinter Signed-off-by: Jacob Howard --- cmd/mutagen/daemon/connect.go | 2 +- cmd/mutagen/forward/create.go | 4 +- cmd/mutagen/forward/monitor.go | 2 +- cmd/mutagen/forward/pause.go | 4 +- cmd/mutagen/forward/resume.go | 4 +- cmd/mutagen/forward/terminate.go | 4 +- cmd/mutagen/sync/create.go | 4 +- cmd/mutagen/sync/flush.go | 4 +- cmd/mutagen/sync/monitor.go | 2 +- cmd/mutagen/sync/pause.go | 4 +- cmd/mutagen/sync/reset.go | 4 +- cmd/mutagen/sync/resume.go | 4 +- cmd/mutagen/sync/terminate.go | 4 +- cmd/output.go | 63 +++++++++++++++----------------- cmd/output_posix.go | 15 +++++++- cmd/output_windows.go | 18 ++++++++- 16 files changed, 83 insertions(+), 59 deletions(-) diff --git a/cmd/mutagen/daemon/connect.go b/cmd/mutagen/daemon/connect.go index 7ea00bf9..6f15f217 100644 --- a/cmd/mutagen/daemon/connect.go +++ b/cmd/mutagen/daemon/connect.go @@ -56,7 +56,7 @@ func Connect(autostart, enforceVersionMatch bool) (*grpc.ClientConn, error) { // Create a status line printer and defer a clear. statusLinePrinter := &cmd.StatusLinePrinter{UseStandardError: true} - defer statusLinePrinter.BreakIfNonEmpty() + defer statusLinePrinter.BreakIfPopulated() // Perform dialing in a loop until failure or success. remainingPostAutostatAttempts := autostartRetryCount diff --git a/cmd/mutagen/forward/create.go b/cmd/mutagen/forward/create.go index f24df354..73da6e52 100644 --- a/cmd/mutagen/forward/create.go +++ b/cmd/mutagen/forward/create.go @@ -74,10 +74,10 @@ func CreateWithSpecification( promptingCancel() <-promptingErrors if err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return "", grpcutil.PeelAwayRPCErrorLayer(err) } else if err = response.EnsureValid(); err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return "", fmt.Errorf("invalid create response received: %w", err) } diff --git a/cmd/mutagen/forward/monitor.go b/cmd/mutagen/forward/monitor.go index c30fa65f..04928522 100644 --- a/cmd/mutagen/forward/monitor.go +++ b/cmd/mutagen/forward/monitor.go @@ -102,7 +102,7 @@ func monitorMain(_ *cobra.Command, arguments []string) error { var statusLinePrinter *cmd.StatusLinePrinter if template == nil { statusLinePrinter = &cmd.StatusLinePrinter{} - defer statusLinePrinter.BreakIfNonEmpty() + defer statusLinePrinter.BreakIfPopulated() } // Track the last update time. diff --git a/cmd/mutagen/forward/pause.go b/cmd/mutagen/forward/pause.go index 3739a204..a8cbc78a 100644 --- a/cmd/mutagen/forward/pause.go +++ b/cmd/mutagen/forward/pause.go @@ -45,10 +45,10 @@ func PauseWithSelection( promptingCancel() <-promptingErrors if err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return grpcutil.PeelAwayRPCErrorLayer(err) } else if err = response.EnsureValid(); err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return fmt.Errorf("invalid pause response received: %w", err) } diff --git a/cmd/mutagen/forward/resume.go b/cmd/mutagen/forward/resume.go index 4e824421..3ae4c5ef 100644 --- a/cmd/mutagen/forward/resume.go +++ b/cmd/mutagen/forward/resume.go @@ -45,10 +45,10 @@ func ResumeWithSelection( promptingCancel() <-promptingErrors if err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return grpcutil.PeelAwayRPCErrorLayer(err) } else if err = response.EnsureValid(); err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return fmt.Errorf("invalid resume response received: %w", err) } diff --git a/cmd/mutagen/forward/terminate.go b/cmd/mutagen/forward/terminate.go index 7a31c76d..782bea86 100644 --- a/cmd/mutagen/forward/terminate.go +++ b/cmd/mutagen/forward/terminate.go @@ -46,10 +46,10 @@ func TerminateWithSelection( promptingCancel() <-promptingErrors if err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return grpcutil.PeelAwayRPCErrorLayer(err) } else if err = response.EnsureValid(); err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return fmt.Errorf("invalid terminate response received: %w", err) } diff --git a/cmd/mutagen/sync/create.go b/cmd/mutagen/sync/create.go index d1364533..5f7f0fa6 100644 --- a/cmd/mutagen/sync/create.go +++ b/cmd/mutagen/sync/create.go @@ -78,10 +78,10 @@ func CreateWithSpecification( promptingCancel() <-promptingErrors if err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return "", grpcutil.PeelAwayRPCErrorLayer(err) } else if err = response.EnsureValid(); err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return "", fmt.Errorf("invalid create response received: %w", err) } diff --git a/cmd/mutagen/sync/flush.go b/cmd/mutagen/sync/flush.go index ae0281da..4fd8a372 100644 --- a/cmd/mutagen/sync/flush.go +++ b/cmd/mutagen/sync/flush.go @@ -47,10 +47,10 @@ func FlushWithSelection( promptingCancel() <-promptingErrors if err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return grpcutil.PeelAwayRPCErrorLayer(err) } else if err = response.EnsureValid(); err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return fmt.Errorf("invalid flush response received: %w", err) } diff --git a/cmd/mutagen/sync/monitor.go b/cmd/mutagen/sync/monitor.go index 078ebce2..7741776d 100644 --- a/cmd/mutagen/sync/monitor.go +++ b/cmd/mutagen/sync/monitor.go @@ -152,7 +152,7 @@ func monitorMain(_ *cobra.Command, arguments []string) error { var statusLinePrinter *cmd.StatusLinePrinter if template == nil { statusLinePrinter = &cmd.StatusLinePrinter{} - defer statusLinePrinter.BreakIfNonEmpty() + defer statusLinePrinter.BreakIfPopulated() } // Track the last update time. diff --git a/cmd/mutagen/sync/pause.go b/cmd/mutagen/sync/pause.go index fe224619..84736b88 100644 --- a/cmd/mutagen/sync/pause.go +++ b/cmd/mutagen/sync/pause.go @@ -45,10 +45,10 @@ func PauseWithSelection( promptingCancel() <-promptingErrors if err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return grpcutil.PeelAwayRPCErrorLayer(err) } else if err = response.EnsureValid(); err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return fmt.Errorf("invalid pause response received: %w", err) } diff --git a/cmd/mutagen/sync/reset.go b/cmd/mutagen/sync/reset.go index 458277d4..0acc84e4 100644 --- a/cmd/mutagen/sync/reset.go +++ b/cmd/mutagen/sync/reset.go @@ -45,10 +45,10 @@ func ResetWithSelection( promptingCancel() <-promptingErrors if err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return grpcutil.PeelAwayRPCErrorLayer(err) } else if err = response.EnsureValid(); err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return fmt.Errorf("invalid reset response received: %w", err) } diff --git a/cmd/mutagen/sync/resume.go b/cmd/mutagen/sync/resume.go index 302ca6b9..fe9cada9 100644 --- a/cmd/mutagen/sync/resume.go +++ b/cmd/mutagen/sync/resume.go @@ -45,10 +45,10 @@ func ResumeWithSelection( promptingCancel() <-promptingErrors if err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return grpcutil.PeelAwayRPCErrorLayer(err) } else if err = response.EnsureValid(); err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return fmt.Errorf("invalid resume response received: %w", err) } diff --git a/cmd/mutagen/sync/terminate.go b/cmd/mutagen/sync/terminate.go index 2761179f..994ed868 100644 --- a/cmd/mutagen/sync/terminate.go +++ b/cmd/mutagen/sync/terminate.go @@ -46,10 +46,10 @@ func TerminateWithSelection( promptingCancel() <-promptingErrors if err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return grpcutil.PeelAwayRPCErrorLayer(err) } else if err = response.EnsureValid(); err != nil { - statusLinePrinter.BreakIfNonEmpty() + statusLinePrinter.BreakIfPopulated() return fmt.Errorf("invalid terminate response received: %w", err) } diff --git a/cmd/output.go b/cmd/output.go index fe331900..2df17f60 100644 --- a/cmd/output.go +++ b/cmd/output.go @@ -15,64 +15,59 @@ type StatusLinePrinter struct { // UseStandardError causes the printer to use standard error for its output // instead of standard output (the default). UseStandardError bool - // nonEmpty indicates whether or not the printer has printed any non-empty + // populated indicates whether or not the printer has printed any non-empty // content to the status line. - nonEmpty bool + populated bool } // Print prints a message to the status line, overwriting any existing content. // Color escape sequences are supported. Messages will be truncated to a // platform-dependent maximum length and padded appropriately. func (p *StatusLinePrinter) Print(message string) { - // Determine output stream. + // Determine the output stream to use. We print to color-supporting output + // streams to ensure that color escape sequences are properly handled. output := color.Output if p.UseStandardError { output = color.Error } - // Print the message, prefixed with a carriage return to wipe out the - // previous line (if any). Ensure that the status prints as a specified - // width, truncating or right-padding with space as necessary. On POSIX - // systems, this width is 80 characters and on Windows it's 79. The reason - // for 79 on Windows is that for cmd.exe consoles the line width needs to be - // narrower than the console (which is 80 columns by default) for carriage - // return wipes to work (if it's the same width, the next carriage return - // overflows to the next line, behaving exactly like a newline). We print to - // the color output so that color escape sequences are properly handled - in - // all other cases this will behave just like standard output. - // TODO: We should probably try to detect the console width. + // Print the message. fmt.Fprintf(output, statusLineFormat, message) - // Update our non-empty status. We're always non-empty after printing - // because we print padding as well. - p.nonEmpty = true + // Update our populated status. The line is always populated in this case + // because even an empty message will be padded with spaces. + // TODO: We could possibly make this more precise, e.g. tracking whether or + // not message is empty or contains only spaces. In cases like these, + // BreakIfPopulated could potentially just return the cursor to the beginning + // of the line instead of printing a newline. But it's a bit unclear what + // the semantics of this should look like, what types of whitespace should + // be classified as empty, etc. For example, an empty line might be used as + // a visual delimiter, or a message could contain tabs and/or newlines. + p.populated = true } // Clear clears any content on the status line and moves the cursor back to the // beginning of the line. func (p *StatusLinePrinter) Clear() { - // Write over any existing data. - p.Print("") - - // Determine output stream. + // Determine the output stream to use. output := os.Stdout if p.UseStandardError { output = os.Stderr } - // Wipe out any existing line. - fmt.Fprint(output, "\r") + // Wipe out any existing content and return the cursor to the beginning of + // the line. + fmt.Fprintf(output, statusLineClearFormat, "") - // Update our non-empty status. - p.nonEmpty = false + // Update our populated status. + p.populated = false } -// BreakIfNonEmpty prints a newline character if the current line is non-empty. -func (p *StatusLinePrinter) BreakIfNonEmpty() { - // If the status line contents are non-empty, then print a newline and mark - // ourselves as empty. - if p.nonEmpty { - // Determine output stream. +// BreakIfPopulated prints a newline character if the current line is non-empty. +func (p *StatusLinePrinter) BreakIfPopulated() { + // Only perform an operation if the status line is populated with content. + if p.populated { + // Determine the output stream to use. output := os.Stdout if p.UseStandardError { output = os.Stderr @@ -81,8 +76,8 @@ func (p *StatusLinePrinter) BreakIfNonEmpty() { // Print a line break. fmt.Fprintln(output) - // Update our non-empty status. - p.nonEmpty = false + // Update our populated status. + p.populated = false } } @@ -111,7 +106,7 @@ func (p *StatusLinePrompter) Prompt(message string) (string, error) { // // HACK: This is somewhat of a heuristic that relies on knowledge of how // Mutagen's internal prompting/messaging works in practice. - p.Printer.BreakIfNonEmpty() + p.Printer.BreakIfPopulated() // Perform command line prompting. // diff --git a/cmd/output_posix.go b/cmd/output_posix.go index 9a5fde35..066cfef2 100644 --- a/cmd/output_posix.go +++ b/cmd/output_posix.go @@ -3,6 +3,19 @@ package cmd const ( - // statusLineFormat is the format string to use for status line printing. + // statusLineFormat is the format string to use for status line printing. On + // POSIX systems, we truncate and pad messages (with spaces) so that the + // printed content is exactly 80 characters. This ensures that (a) all + // content from the previous line is overwritten, (b) the cursor is not + // flashing back and forth to different positions at the end of the printed + // content, and (c) that the content doesn't overflow the terminal. Of + // course, the last condition is contingent on the terminal being at least + // 80 characters wide, and newlines will occur if that's not the case, but + // 80 characters is a reasonable minimum based on the minimum width of a + // VT100 terminal. statusLineFormat = "\r%-80.80s" + // statusLineClearFormat is the format string to use for printing an empty + // string to clear the status line. It adds a carriage return to return the + // cursor to the beginning of the line. + statusLineClearFormat = statusLineFormat + "\r" ) diff --git a/cmd/output_windows.go b/cmd/output_windows.go index fe5d18e4..86e063d3 100644 --- a/cmd/output_windows.go +++ b/cmd/output_windows.go @@ -1,6 +1,22 @@ package cmd const ( - // statusLineFormat is the format string to use for status line printing. + // statusLineFormat is the format string to use for status line printing. On + // Windows systems, we truncate and pad messages (with spaces) so that the + // printed content is exactly 79 characters. This ensures that (a) all + // content from the previous line is overwritten, (b) the cursor is not + // flashing back and forth to different positions at the end of the printed + // content, and (c) that the content doesn't overflow the terminal. Of + // course, the last condition is contingent on the terminal being at least + // 80 characters wide, and newlines will occur if that's not the case, but + // 80 characters is the default width of the console on most versions of + // Windows, and modern versions are even wider. The reason we have to limit + // ourselves to 79 characters of content instead of 80 is that carriage + // return wipes don't work if the cursor has already printed a character in + // the last position of the line on Windows. statusLineFormat = "\r%-79.79s" + // statusLineClearFormat is the format string to use for printing an empty + // string to clear the status line. It adds a carriage return to return the + // cursor to the beginning of the line. + statusLineClearFormat = statusLineFormat + "\r" ) From fc49c22989551d3d4f7a2514d8ac451abed841dc Mon Sep 17 00:00:00 2001 From: Jacob Howard Date: Thu, 23 Jun 2022 12:31:34 -0600 Subject: [PATCH 2/3] cli: add color support to StatusLinePrinter and embolden monitor output Signed-off-by: Jacob Howard --- cmd/mutagen/forward/monitor.go | 8 +++++--- cmd/mutagen/sync/monitor.go | 8 +++++--- cmd/output.go | 8 +++++++- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/cmd/mutagen/forward/monitor.go b/cmd/mutagen/forward/monitor.go index 04928522..c2d82146 100644 --- a/cmd/mutagen/forward/monitor.go +++ b/cmd/mutagen/forward/monitor.go @@ -97,11 +97,13 @@ func monitorMain(_ *cobra.Command, arguments []string) error { Selection: selection, } - // If no template has been specified, then create a status line printer and - // defer a line break operation. + // If no template has been specified, then create a status line printer with + // bold text and defer a line break operation. var statusLinePrinter *cmd.StatusLinePrinter if template == nil { - statusLinePrinter = &cmd.StatusLinePrinter{} + statusLinePrinter = &cmd.StatusLinePrinter{ + Color: color.New(color.Bold), + } defer statusLinePrinter.BreakIfPopulated() } diff --git a/cmd/mutagen/sync/monitor.go b/cmd/mutagen/sync/monitor.go index 7741776d..d7678090 100644 --- a/cmd/mutagen/sync/monitor.go +++ b/cmd/mutagen/sync/monitor.go @@ -147,11 +147,13 @@ func monitorMain(_ *cobra.Command, arguments []string) error { Selection: selection, } - // If no template has been specified, then create a status line printer and - // defer a line break operation. + // If no template has been specified, then create a status line printer with + // bold text and defer a line break operation. var statusLinePrinter *cmd.StatusLinePrinter if template == nil { - statusLinePrinter = &cmd.StatusLinePrinter{} + statusLinePrinter = &cmd.StatusLinePrinter{ + Color: color.New(color.Bold), + } defer statusLinePrinter.BreakIfPopulated() } diff --git a/cmd/output.go b/cmd/output.go index 2df17f60..e822d209 100644 --- a/cmd/output.go +++ b/cmd/output.go @@ -15,6 +15,8 @@ type StatusLinePrinter struct { // UseStandardError causes the printer to use standard error for its output // instead of standard output (the default). UseStandardError bool + // Color, if non-nil, will be used for colorizing output (if possible). + Color *color.Color // populated indicates whether or not the printer has printed any non-empty // content to the status line. populated bool @@ -32,7 +34,11 @@ func (p *StatusLinePrinter) Print(message string) { } // Print the message. - fmt.Fprintf(output, statusLineFormat, message) + if p.Color != nil { + p.Color.Fprintf(output, statusLineFormat, message) + } else { + fmt.Fprintf(output, statusLineFormat, message) + } // Update our populated status. The line is always populated in this case // because even an empty message will be padded with spaces. From 496875e3f3dbd83ebcd59e9d5583262a1cc77eb7 Mon Sep 17 00:00:00 2001 From: Jacob Howard Date: Thu, 23 Jun 2022 16:05:53 -0600 Subject: [PATCH 3/3] sync: restrict synchronizable content printing to scanned endpoints Signed-off-by: Jacob Howard --- cmd/mutagen/sync/list_monitor_common.go | 14 +- pkg/api/models/synchronization/session.go | 5 + pkg/synchronization/controller.go | 2 + pkg/synchronization/state.pb.go | 183 ++++++++++++---------- pkg/synchronization/state.proto | 21 +-- 5 files changed, 124 insertions(+), 101 deletions(-) diff --git a/cmd/mutagen/sync/list_monitor_common.go b/cmd/mutagen/sync/list_monitor_common.go index 98132727..1b0e242a 100644 --- a/cmd/mutagen/sync/list_monitor_common.go +++ b/cmd/mutagen/sync/list_monitor_common.go @@ -177,12 +177,14 @@ func printEndpoint(name string, url *url.URL, configuration *synchronization.Con // Print connection status. fmt.Println("\tConnected:", common.FormatConnectionStatus(state.Connected)) - // Print content information. - fmt.Printf("\tContents: %s | %s | %s\n", - formatDirectoryCount(state.DirectoryCount), - formatFileCountAndSize(state.FileCount, state.TotalFileSize), - formatSymbolicLinkCount(state.SymbolicLinkCount), - ) + // Print content information, if available. + if state.Scanned { + fmt.Printf("\tSynchronizable contents:\n\t\t%s\n\t\t%s\n\t\t%s\n", + formatDirectoryCount(state.DirectoryCount), + formatFileCountAndSize(state.FileCount, state.TotalFileSize), + formatSymbolicLinkCount(state.SymbolicLinkCount), + ) + } // Print scan problems, if any. if len(state.ScanProblems) > 0 { diff --git a/pkg/api/models/synchronization/session.go b/pkg/api/models/synchronization/session.go index aca4bfd1..73305a9f 100644 --- a/pkg/api/models/synchronization/session.go +++ b/pkg/api/models/synchronization/session.go @@ -43,6 +43,9 @@ type EndpointState struct { // Connected indicates whether or not the controller is currently connected // to the endpoint. Connected bool `json:"connected"` + // Scanned indicates whether or not at least one scan has been performed on + // the endpoint. + Scanned bool `json:"scanned"` // DirectoryCount is the number of synchronizable directory entries // contained in the last snapshot from the endpoint. DirectoryCount uint64 `json:"directoryCount,omitempty"` @@ -139,6 +142,7 @@ func (s *Session) loadFromInternal(state *synchronization.State) { ExcludedConflicts: state.ExcludedConflicts, AlphaState: EndpointState{ Connected: state.AlphaState.Connected, + Scanned: state.AlphaState.Scanned, DirectoryCount: state.AlphaState.DirectoryCount, FileCount: state.AlphaState.FileCount, SymbolicLinkCount: state.AlphaState.SymbolicLinkCount, @@ -151,6 +155,7 @@ func (s *Session) loadFromInternal(state *synchronization.State) { }, BetaState: EndpointState{ Connected: state.BetaState.Connected, + Scanned: state.BetaState.Scanned, DirectoryCount: state.BetaState.DirectoryCount, FileCount: state.BetaState.FileCount, SymbolicLinkCount: state.BetaState.SymbolicLinkCount, diff --git a/pkg/synchronization/controller.go b/pkg/synchronization/controller.go index 9ffff8d7..9ebb99c0 100644 --- a/pkg/synchronization/controller.go +++ b/pkg/synchronization/controller.go @@ -1109,11 +1109,13 @@ func (c *controller) synchronize(ctx context.Context, alpha, beta Endpoint) erro // at the start of this function). c.stateLock.Lock() c.state.LastError = "" + c.state.AlphaState.Scanned = true c.state.AlphaState.DirectoryCount = αSnapshot.DirectoryCount c.state.AlphaState.FileCount = αSnapshot.FileCount c.state.AlphaState.SymbolicLinkCount = αSnapshot.SymbolicLinkCount c.state.AlphaState.TotalFileSize = αSnapshot.TotalFileSize c.state.AlphaState.ScanProblems = αContent.Problems() + c.state.BetaState.Scanned = true c.state.BetaState.DirectoryCount = βSnapshot.DirectoryCount c.state.BetaState.FileCount = βSnapshot.FileCount c.state.BetaState.SymbolicLinkCount = βSnapshot.SymbolicLinkCount diff --git a/pkg/synchronization/state.pb.go b/pkg/synchronization/state.pb.go index 4a8da022..5708bef1 100644 --- a/pkg/synchronization/state.pb.go +++ b/pkg/synchronization/state.pb.go @@ -143,40 +143,43 @@ type EndpointState struct { // Connected indicates whether or not the controller is currently connected // to the endpoint. Connected bool `protobuf:"varint,1,opt,name=connected,proto3" json:"connected,omitempty"` + // Scanned indicates whether or not at least one scan has been performed on + // the endpoint. + Scanned bool `protobuf:"varint,2,opt,name=scanned,proto3" json:"scanned,omitempty"` // DirectoryCount is the number of synchronizable directory entries // contained in the last snapshot from the endpoint. - DirectoryCount uint64 `protobuf:"varint,2,opt,name=directoryCount,proto3" json:"directoryCount,omitempty"` + DirectoryCount uint64 `protobuf:"varint,3,opt,name=directoryCount,proto3" json:"directoryCount,omitempty"` // FileCount is the number of synchronizable file entries contained in the // last snapshot from the endpoint. - FileCount uint64 `protobuf:"varint,3,opt,name=fileCount,proto3" json:"fileCount,omitempty"` + FileCount uint64 `protobuf:"varint,4,opt,name=fileCount,proto3" json:"fileCount,omitempty"` // SymbolicLinkCount is the number of synchronizable symbolic link entries // contained in the last snapshot from the endpoint. - SymbolicLinkCount uint64 `protobuf:"varint,4,opt,name=symbolicLinkCount,proto3" json:"symbolicLinkCount,omitempty"` + SymbolicLinkCount uint64 `protobuf:"varint,5,opt,name=symbolicLinkCount,proto3" json:"symbolicLinkCount,omitempty"` // TotalFileSize is the total size of all synchronizable files referenced by // the last snapshot from the endpoint. - TotalFileSize uint64 `protobuf:"varint,5,opt,name=totalFileSize,proto3" json:"totalFileSize,omitempty"` + TotalFileSize uint64 `protobuf:"varint,6,opt,name=totalFileSize,proto3" json:"totalFileSize,omitempty"` // ScanProblems is the list of non-terminal problems encountered during the // last scanning operation on the endpoint. This list may be a truncated // version of the full list if too many problems are encountered to report // via the API, in which case ExcludedScanProblems will be non-zero. - ScanProblems []*core.Problem `protobuf:"bytes,6,rep,name=scanProblems,proto3" json:"scanProblems,omitempty"` + ScanProblems []*core.Problem `protobuf:"bytes,7,rep,name=scanProblems,proto3" json:"scanProblems,omitempty"` // ExcludedScanProblems is the number of problems that have been excluded // from ScanProblems due to truncation. This value can be non-zero only if // ScanProblems is non-empty. - ExcludedScanProblems uint64 `protobuf:"varint,7,opt,name=excludedScanProblems,proto3" json:"excludedScanProblems,omitempty"` + ExcludedScanProblems uint64 `protobuf:"varint,8,opt,name=excludedScanProblems,proto3" json:"excludedScanProblems,omitempty"` // TransitionProblems is the list of non-terminal problems encountered // during the last transition operation on the endpoint. This list may be a // truncated version of the full list if too many problems are encountered // to report via the API, in which case ExcludedTransitionProblems will be // non-zero. - TransitionProblems []*core.Problem `protobuf:"bytes,8,rep,name=transitionProblems,proto3" json:"transitionProblems,omitempty"` + TransitionProblems []*core.Problem `protobuf:"bytes,9,rep,name=transitionProblems,proto3" json:"transitionProblems,omitempty"` // ExcludedTransitionProblems is the number of problems that have been // excluded from TransitionProblems due to truncation. This value can be // non-zero only if TransitionProblems is non-empty. - ExcludedTransitionProblems uint64 `protobuf:"varint,9,opt,name=excludedTransitionProblems,proto3" json:"excludedTransitionProblems,omitempty"` + ExcludedTransitionProblems uint64 `protobuf:"varint,10,opt,name=excludedTransitionProblems,proto3" json:"excludedTransitionProblems,omitempty"` // StagingProgress is the rsync staging progress. It is non-nil if and only // if the endpoint is currently staging files. - StagingProgress *rsync.ReceiverState `protobuf:"bytes,10,opt,name=stagingProgress,proto3" json:"stagingProgress,omitempty"` + StagingProgress *rsync.ReceiverState `protobuf:"bytes,11,opt,name=stagingProgress,proto3" json:"stagingProgress,omitempty"` } func (x *EndpointState) Reset() { @@ -218,6 +221,13 @@ func (x *EndpointState) GetConnected() bool { return false } +func (x *EndpointState) GetScanned() bool { + if x != nil { + return x.Scanned + } + return false +} + func (x *EndpointState) GetDirectoryCount() uint64 { if x != nil { return x.DirectoryCount @@ -418,85 +428,86 @@ var file_synchronization_state_proto_rawDesc = []byte{ 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x22, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, - 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xed, 0x03, 0x0a, 0x0d, + 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x87, 0x04, 0x0a, 0x0d, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x26, 0x0a, 0x0e, 0x64, - 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x0e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x2c, 0x0a, 0x11, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x63, 0x4c, 0x69, 0x6e, - 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x73, 0x79, - 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x63, 0x4c, 0x69, 0x6e, 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, - 0x24, 0x0a, 0x0d, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x46, 0x69, 0x6c, - 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x31, 0x0a, 0x0c, 0x73, 0x63, 0x61, 0x6e, 0x50, 0x72, 0x6f, - 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x52, 0x0c, 0x73, 0x63, 0x61, 0x6e, - 0x50, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x12, 0x32, 0x0a, 0x14, 0x65, 0x78, 0x63, 0x6c, - 0x75, 0x64, 0x65, 0x64, 0x53, 0x63, 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x14, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, - 0x53, 0x63, 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x12, 0x3d, 0x0a, 0x12, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x62, 0x6c, 0x65, - 0x6d, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x50, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x52, 0x12, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x12, 0x3e, 0x0a, 0x1a, 0x65, - 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x1a, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x12, 0x3e, 0x0a, 0x0f, 0x73, - 0x74, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x72, 0x73, 0x79, 0x6e, 0x63, 0x2e, 0x52, 0x65, 0x63, - 0x65, 0x69, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0f, 0x73, 0x74, 0x61, 0x67, - 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x22, 0x90, 0x03, 0x0a, 0x05, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x32, 0x0a, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, - 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x73, 0x79, 0x6e, 0x63, - 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x61, - 0x73, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, - 0x61, 0x73, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2a, 0x0a, 0x10, 0x73, 0x75, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x10, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x43, 0x79, - 0x63, 0x6c, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, - 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x43, - 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, - 0x74, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x43, 0x6f, - 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x65, - 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, - 0x12, 0x3e, 0x0a, 0x0a, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, - 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x52, 0x0a, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x12, 0x3c, 0x0a, 0x09, 0x62, 0x65, 0x74, 0x61, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x52, 0x09, 0x62, 0x65, 0x74, 0x61, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2a, 0x97, - 0x02, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x10, 0x0a, 0x0c, 0x44, 0x69, 0x73, - 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x48, - 0x61, 0x6c, 0x74, 0x65, 0x64, 0x4f, 0x6e, 0x52, 0x6f, 0x6f, 0x74, 0x45, 0x6d, 0x70, 0x74, 0x69, - 0x65, 0x64, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x48, 0x61, 0x6c, 0x74, 0x65, 0x64, 0x4f, 0x6e, - 0x52, 0x6f, 0x6f, 0x74, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0x02, 0x12, 0x1a, - 0x0a, 0x16, 0x48, 0x61, 0x6c, 0x74, 0x65, 0x64, 0x4f, 0x6e, 0x52, 0x6f, 0x6f, 0x74, 0x54, 0x79, - 0x70, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x10, 0x04, 0x12, - 0x12, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x65, 0x74, - 0x61, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x57, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x10, - 0x06, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x63, 0x61, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x10, 0x07, 0x12, - 0x14, 0x0a, 0x10, 0x57, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x46, 0x6f, 0x72, 0x52, 0x65, 0x73, - 0x63, 0x61, 0x6e, 0x10, 0x08, 0x12, 0x0f, 0x0a, 0x0b, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x63, 0x69, - 0x6c, 0x69, 0x6e, 0x67, 0x10, 0x09, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x67, 0x69, 0x6e, - 0x67, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x10, 0x0a, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x74, 0x61, 0x67, - 0x69, 0x6e, 0x67, 0x42, 0x65, 0x74, 0x61, 0x10, 0x0b, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x10, 0x0c, 0x12, 0x0a, 0x0a, 0x06, - 0x53, 0x61, 0x76, 0x69, 0x6e, 0x67, 0x10, 0x0d, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x75, 0x74, 0x61, 0x67, 0x65, 0x6e, 0x2d, 0x69, - 0x6f, 0x2f, 0x6d, 0x75, 0x74, 0x61, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x79, - 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x73, + 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x63, + 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x12, 0x26, 0x0a, 0x0e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x64, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1c, 0x0a, + 0x09, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x11, 0x73, + 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x63, 0x4c, 0x69, 0x6e, 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x63, + 0x4c, 0x69, 0x6e, 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x74, 0x6f, 0x74, + 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x0d, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, + 0x31, 0x0a, 0x0c, 0x73, 0x63, 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x18, + 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, + 0x62, 0x6c, 0x65, 0x6d, 0x52, 0x0c, 0x73, 0x63, 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x62, 0x6c, 0x65, + 0x6d, 0x73, 0x12, 0x32, 0x0a, 0x14, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x53, 0x63, + 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x14, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x53, 0x63, 0x61, 0x6e, 0x50, 0x72, + 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x12, 0x3d, 0x0a, 0x12, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x62, 0x6c, 0x65, + 0x6d, 0x52, 0x12, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, + 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x12, 0x3e, 0x0a, 0x1a, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x62, 0x6c, + 0x65, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a, 0x65, 0x78, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, + 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x12, 0x3e, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x67, 0x69, 0x6e, 0x67, + 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x72, 0x73, 0x79, 0x6e, 0x63, 0x2e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x52, 0x0f, 0x73, 0x74, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, + 0x67, 0x72, 0x65, 0x73, 0x73, 0x22, 0x90, 0x03, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, + 0x32, 0x0a, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x18, 0x2e, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x45, 0x72, 0x72, 0x6f, + 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x12, 0x2a, 0x0a, 0x10, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, + 0x43, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x73, 0x75, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x12, 0x2c, + 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, + 0x74, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x12, 0x2c, 0x0a, 0x11, + 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, + 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x12, 0x3e, 0x0a, 0x0a, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, + 0x2e, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0a, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3c, 0x0a, 0x09, 0x62, 0x65, + 0x74, 0x61, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, + 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x09, 0x62, + 0x65, 0x74, 0x61, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2a, 0x97, 0x02, 0x0a, 0x06, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x10, 0x0a, 0x0c, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x65, 0x64, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x48, 0x61, 0x6c, 0x74, 0x65, 0x64, 0x4f, + 0x6e, 0x52, 0x6f, 0x6f, 0x74, 0x45, 0x6d, 0x70, 0x74, 0x69, 0x65, 0x64, 0x10, 0x01, 0x12, 0x18, + 0x0a, 0x14, 0x48, 0x61, 0x6c, 0x74, 0x65, 0x64, 0x4f, 0x6e, 0x52, 0x6f, 0x6f, 0x74, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x48, 0x61, 0x6c, 0x74, + 0x65, 0x64, 0x4f, 0x6e, 0x52, 0x6f, 0x6f, 0x74, 0x54, 0x79, 0x70, 0x65, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, + 0x6e, 0x67, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x65, 0x74, 0x61, 0x10, 0x05, 0x12, 0x0c, 0x0a, + 0x08, 0x57, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x10, 0x06, 0x12, 0x0c, 0x0a, 0x08, 0x53, + 0x63, 0x61, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x10, 0x07, 0x12, 0x14, 0x0a, 0x10, 0x57, 0x61, 0x69, + 0x74, 0x69, 0x6e, 0x67, 0x46, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x63, 0x61, 0x6e, 0x10, 0x08, 0x12, + 0x0f, 0x0a, 0x0b, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x10, 0x09, + 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x41, 0x6c, 0x70, 0x68, 0x61, + 0x10, 0x0a, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x74, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x42, 0x65, 0x74, + 0x61, 0x10, 0x0b, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x69, 0x6e, 0x67, 0x10, 0x0c, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x61, 0x76, 0x69, 0x6e, 0x67, + 0x10, 0x0d, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x6d, 0x75, 0x74, 0x61, 0x67, 0x65, 0x6e, 0x2d, 0x69, 0x6f, 0x2f, 0x6d, 0x75, 0x74, 0x61, + 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/synchronization/state.proto b/pkg/synchronization/state.proto index f53b767b..18d560f8 100644 --- a/pkg/synchronization/state.proto +++ b/pkg/synchronization/state.proto @@ -61,40 +61,43 @@ message EndpointState { // Connected indicates whether or not the controller is currently connected // to the endpoint. bool connected = 1; + // Scanned indicates whether or not at least one scan has been performed on + // the endpoint. + bool scanned = 2; // DirectoryCount is the number of synchronizable directory entries // contained in the last snapshot from the endpoint. - uint64 directoryCount = 2; + uint64 directoryCount = 3; // FileCount is the number of synchronizable file entries contained in the // last snapshot from the endpoint. - uint64 fileCount = 3; + uint64 fileCount = 4; // SymbolicLinkCount is the number of synchronizable symbolic link entries // contained in the last snapshot from the endpoint. - uint64 symbolicLinkCount = 4; + uint64 symbolicLinkCount = 5; // TotalFileSize is the total size of all synchronizable files referenced by // the last snapshot from the endpoint. - uint64 totalFileSize = 5; + uint64 totalFileSize = 6; // ScanProblems is the list of non-terminal problems encountered during the // last scanning operation on the endpoint. This list may be a truncated // version of the full list if too many problems are encountered to report // via the API, in which case ExcludedScanProblems will be non-zero. - repeated core.Problem scanProblems = 6; + repeated core.Problem scanProblems = 7; // ExcludedScanProblems is the number of problems that have been excluded // from ScanProblems due to truncation. This value can be non-zero only if // ScanProblems is non-empty. - uint64 excludedScanProblems = 7; + uint64 excludedScanProblems = 8; // TransitionProblems is the list of non-terminal problems encountered // during the last transition operation on the endpoint. This list may be a // truncated version of the full list if too many problems are encountered // to report via the API, in which case ExcludedTransitionProblems will be // non-zero. - repeated core.Problem transitionProblems = 8; + repeated core.Problem transitionProblems = 9; // ExcludedTransitionProblems is the number of problems that have been // excluded from TransitionProblems due to truncation. This value can be // non-zero only if TransitionProblems is non-empty. - uint64 excludedTransitionProblems = 9; + uint64 excludedTransitionProblems = 10; // StagingProgress is the rsync staging progress. It is non-nil if and only // if the endpoint is currently staging files. - rsync.ReceiverState stagingProgress = 10; + rsync.ReceiverState stagingProgress = 11; } // State encodes the current state of a synchronization session. It is mutable