diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..5272401
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+MutagenSdk/Proto/**/*.proto linguist-generated=true
diff --git a/Coder.Desktop.sln b/Coder.Desktop.sln
index 2f78a8a..7d85caa 100644
--- a/Coder.Desktop.sln
+++ b/Coder.Desktop.sln
@@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vpn.DebugClient", "Vpn.Debu
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Installer", "Installer\Installer.csproj", "{39F5B55A-09D8-477D-A3FA-ADAC29C52605}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MutagenSdk", "MutagenSdk\MutagenSdk.csproj", "{E2477ADC-03DA-490D-9369-79A4CC4A58D2}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -203,6 +205,22 @@ Global
{39F5B55A-09D8-477D-A3FA-ADAC29C52605}.Release|x64.Build.0 = Release|Any CPU
{39F5B55A-09D8-477D-A3FA-ADAC29C52605}.Release|x86.ActiveCfg = Release|Any CPU
{39F5B55A-09D8-477D-A3FA-ADAC29C52605}.Release|x86.Build.0 = Release|Any CPU
+ {E2477ADC-03DA-490D-9369-79A4CC4A58D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E2477ADC-03DA-490D-9369-79A4CC4A58D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E2477ADC-03DA-490D-9369-79A4CC4A58D2}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+ {E2477ADC-03DA-490D-9369-79A4CC4A58D2}.Debug|ARM64.Build.0 = Debug|Any CPU
+ {E2477ADC-03DA-490D-9369-79A4CC4A58D2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {E2477ADC-03DA-490D-9369-79A4CC4A58D2}.Debug|x64.Build.0 = Debug|Any CPU
+ {E2477ADC-03DA-490D-9369-79A4CC4A58D2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {E2477ADC-03DA-490D-9369-79A4CC4A58D2}.Debug|x86.Build.0 = Debug|Any CPU
+ {E2477ADC-03DA-490D-9369-79A4CC4A58D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E2477ADC-03DA-490D-9369-79A4CC4A58D2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E2477ADC-03DA-490D-9369-79A4CC4A58D2}.Release|ARM64.ActiveCfg = Release|Any CPU
+ {E2477ADC-03DA-490D-9369-79A4CC4A58D2}.Release|ARM64.Build.0 = Release|Any CPU
+ {E2477ADC-03DA-490D-9369-79A4CC4A58D2}.Release|x64.ActiveCfg = Release|Any CPU
+ {E2477ADC-03DA-490D-9369-79A4CC4A58D2}.Release|x64.Build.0 = Release|Any CPU
+ {E2477ADC-03DA-490D-9369-79A4CC4A58D2}.Release|x86.ActiveCfg = Release|Any CPU
+ {E2477ADC-03DA-490D-9369-79A4CC4A58D2}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/MutagenSdk/MutagenClient.cs b/MutagenSdk/MutagenClient.cs
new file mode 100644
index 0000000..1b3e375
--- /dev/null
+++ b/MutagenSdk/MutagenClient.cs
@@ -0,0 +1,55 @@
+using Coder.Desktop.MutagenSdk.Proto.Service.Synchronization;
+using Grpc.Core;
+using Grpc.Net.Client;
+
+namespace Coder.Desktop.MutagenSdk;
+
+public class MutagenClient : IDisposable
+{
+ private readonly GrpcChannel _channel;
+
+ public readonly Synchronization.SynchronizationClient Synchronization;
+
+ public MutagenClient(string dataDir)
+ {
+ // Check for the lock file first, since it should exist if it's running.
+ var daemonLockFile = Path.Combine(dataDir, "daemon", "daemon.lock");
+ if (!File.Exists(daemonLockFile))
+ throw new FileNotFoundException(
+ "Mutagen daemon lock file not found, did the mutagen daemon start successfully?", daemonLockFile);
+
+ // Read the IPC named pipe address from the sock file.
+ var daemonSockFile = Path.Combine(dataDir, "daemon", "daemon.sock");
+ if (!File.Exists(daemonSockFile))
+ throw new FileNotFoundException(
+ "Mutagen daemon socket file not found, did the mutagen daemon start successfully?", daemonSockFile);
+ var daemonSockAddress = File.ReadAllText(daemonSockFile).Trim();
+ if (string.IsNullOrWhiteSpace(daemonSockAddress))
+ throw new InvalidOperationException(
+ "Mutagen daemon socket address is empty, did the mutagen daemon start successfully?");
+
+ const string namedPipePrefix = @"\\.\pipe\";
+ if (!daemonSockAddress.StartsWith(namedPipePrefix))
+ throw new InvalidOperationException("Mutagen daemon socket address is not a named pipe address");
+ var pipeName = daemonSockAddress[namedPipePrefix.Length..];
+
+ var connectionFactory = new NamedPipesConnectionFactory(pipeName);
+ var socketsHttpHandler = new SocketsHttpHandler
+ {
+ ConnectCallback = connectionFactory.ConnectAsync,
+ };
+
+ _channel = GrpcChannel.ForAddress("http://localhost", new GrpcChannelOptions
+ {
+ Credentials = ChannelCredentials.Insecure,
+ HttpHandler = socketsHttpHandler,
+ });
+ Synchronization = new Synchronization.SynchronizationClient(_channel);
+ }
+
+ public void Dispose()
+ {
+ _channel.Dispose();
+ GC.SuppressFinalize(this);
+ }
+}
diff --git a/MutagenSdk/MutagenSdk.csproj b/MutagenSdk/MutagenSdk.csproj
new file mode 100644
index 0000000..d2b8f90
--- /dev/null
+++ b/MutagenSdk/MutagenSdk.csproj
@@ -0,0 +1,25 @@
+
+
+
+ Coder.Desktop.MutagenSdk
+ Coder.Desktop.MutagenSdk
+ net8.0
+ enable
+ enable
+ true
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
diff --git a/MutagenSdk/NamedPipesConnectionFactory.cs b/MutagenSdk/NamedPipesConnectionFactory.cs
new file mode 100644
index 0000000..5768137
--- /dev/null
+++ b/MutagenSdk/NamedPipesConnectionFactory.cs
@@ -0,0 +1,36 @@
+using System.IO.Pipes;
+using System.Security.Principal;
+
+namespace Coder.Desktop.MutagenSdk;
+
+public class NamedPipesConnectionFactory
+{
+ private readonly string _pipeName;
+
+ public NamedPipesConnectionFactory(string pipeName)
+ {
+ _pipeName = pipeName;
+ }
+
+ public async ValueTask ConnectAsync(SocketsHttpConnectionContext _,
+ CancellationToken cancellationToken = default)
+ {
+ var client = new NamedPipeClientStream(
+ ".",
+ _pipeName,
+ PipeDirection.InOut,
+ PipeOptions.WriteThrough | PipeOptions.Asynchronous,
+ TokenImpersonationLevel.Anonymous);
+
+ try
+ {
+ await client.ConnectAsync(cancellationToken);
+ return client;
+ }
+ catch
+ {
+ await client.DisposeAsync();
+ throw;
+ }
+ }
+}
diff --git a/MutagenSdk/Proto/filesystem/behavior/probe_mode.proto b/MutagenSdk/Proto/filesystem/behavior/probe_mode.proto
new file mode 100644
index 0000000..c804d84
--- /dev/null
+++ b/MutagenSdk/Proto/filesystem/behavior/probe_mode.proto
@@ -0,0 +1,51 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/filesystem/behavior/probe_mode.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package behavior;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Filesystem.Behavior";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/filesystem/behavior";
+
+// ProbeMode specifies the mode for filesystem probing.
+enum ProbeMode {
+ // ProbeMode_ProbeModeDefault represents an unspecified probe mode. It
+ // should be converted to one of the following values based on the desired
+ // default behavior.
+ ProbeModeDefault = 0;
+ // ProbeMode_ProbeModeProbe specifies that filesystem behavior should be
+ // determined using temporary files or, if possible, a "fast-path" mechanism
+ // (such as filesystem format detection) that provides quick but certain
+ // determination of filesystem behavior.
+ ProbeModeProbe = 1;
+ // ProbeMode_ProbeModeAssume specifies that filesystem behavior should be
+ // assumed based on the underlying platform. This is not as accurate as
+ // ProbeMode_ProbeModeProbe.
+ ProbeModeAssume = 2;
+}
+
diff --git a/MutagenSdk/Proto/selection/selection.proto b/MutagenSdk/Proto/selection/selection.proto
new file mode 100644
index 0000000..c4a0c20
--- /dev/null
+++ b/MutagenSdk/Proto/selection/selection.proto
@@ -0,0 +1,48 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/selection/selection.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package selection;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Selection";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/selection";
+
+// Selection encodes a selection mechanism that can be used to select a
+// collection of sessions. It should have exactly one member set.
+message Selection {
+ // All, if true, indicates that all sessions should be selected.
+ bool all = 1;
+ // Specifications is a list of session specifications. Each element may be
+ // either a session identifier or name (or a prefix thereof). If non-empty,
+ // it indicates that these specifications should be used to select sessions.
+ repeated string specifications = 2;
+ // LabelSelector is a label selector specification. If present (non-empty),
+ // it indicates that this selector should be used to select sessions.
+ string labelSelector = 3;
+}
+
diff --git a/MutagenSdk/Proto/service/synchronization/synchronization.proto b/MutagenSdk/Proto/service/synchronization/synchronization.proto
new file mode 100644
index 0000000..0f978e2
--- /dev/null
+++ b/MutagenSdk/Proto/service/synchronization/synchronization.proto
@@ -0,0 +1,170 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/service\synchronization\synchronization.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package synchronization;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Service.Synchronization";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/service/synchronization";
+
+import "selection/selection.proto";
+import "synchronization/configuration.proto";
+import "synchronization/state.proto";
+import "url/url.proto";
+
+// CreationSpecification contains the metadata required for a new session.
+message CreationSpecification {
+ // Alpha is the alpha endpoint URL for the session.
+ url.URL alpha = 1;
+ // Beta is the beta endpoint URL for the session.
+ url.URL beta = 2;
+ // Configuration is the base session configuration. It is the result of
+ // merging the global configuration (unless disabled), any manually
+ // specified configuration file, and any command line configuration
+ // parameters.
+ synchronization.Configuration configuration = 3;
+ // ConfigurationAlpha is the alpha-specific session configuration. It is
+ // determined based on command line configuration parameters.
+ synchronization.Configuration configurationAlpha = 4;
+ // ConfigurationBeta is the beta-specific session configuration. It is
+ // determined based on command line configuration parameters.
+ synchronization.Configuration configurationBeta = 5;
+ // Name is the name for the session object.
+ string name = 6;
+ // Labels are the labels for the session object.
+ map labels = 7;
+ // Paused indicates whether or not to create the session pre-paused.
+ bool paused = 8;
+}
+
+// CreateRequest encodes a request for session creation.
+message CreateRequest {
+ // Prompter is the prompter identifier to use for creating sessions.
+ string prompter = 1;
+ // Specification is the creation specification.
+ CreationSpecification specification = 2;
+}
+
+// CreateResponse encodes a session creation response.
+message CreateResponse {
+ // Session is the resulting session identifier.
+ string session = 1;
+}
+
+// ListRequest encodes a request for session metadata.
+message ListRequest {
+ // Selection is the session selection criteria.
+ selection.Selection selection = 1;
+ // PreviousStateIndex is the previously seen state index. 0 may be provided
+ // to force an immediate state listing.
+ uint64 previousStateIndex = 2;
+}
+
+// ListResponse encodes session metadata.
+message ListResponse {
+ // StateIndex is the state index associated with the session metadata.
+ uint64 stateIndex = 1;
+ // SessionStates are the session metadata states.
+ repeated synchronization.State sessionStates = 2;
+}
+
+// FlushRequest encodes a request to flush sessions.
+message FlushRequest {
+ // Prompter is the prompter to use for status message updates.
+ string prompter = 1;
+ // Selection is the session selection criteria.
+ selection.Selection selection = 2;
+ // SkipWait indicates whether or not the operation should avoid blocking.
+ bool skipWait = 3;
+}
+
+// FlushResponse indicates completion of flush operation(s).
+message FlushResponse{}
+
+// PauseRequest encodes a request to pause sessions.
+message PauseRequest {
+ // Prompter is the prompter to use for status message updates.
+ string prompter = 1;
+ // Selection is the session selection criteria.
+ selection.Selection selection = 2;
+}
+
+// PauseResponse indicates completion of pause operation(s).
+message PauseResponse{}
+
+// ResumeRequest encodes a request to resume sessions.
+message ResumeRequest {
+ // Prompter is the prompter identifier to use for resuming sessions.
+ string prompter = 1;
+ // Selection is the session selection criteria.
+ selection.Selection selection = 2;
+}
+
+// ResumeResponse indicates completion of resume operation(s).
+message ResumeResponse{}
+
+// ResetRequest encodes a request to reset sessions.
+message ResetRequest {
+ // Prompter is the prompter identifier to use for resetting sessions.
+ string prompter = 1;
+ // Selection is the session selection criteria.
+ selection.Selection selection = 2;
+}
+
+// ResetResponse indicates completion of reset operation(s).
+message ResetResponse{}
+
+// TerminateRequest encodes a request to terminate sessions.
+message TerminateRequest {
+ // Prompter is the prompter to use for status message updates.
+ string prompter = 1;
+ // Selection is the session selection criteria.
+ selection.Selection selection = 2;
+}
+
+// TerminateResponse indicates completion of termination operation(s).
+message TerminateResponse{}
+
+// Synchronization manages the lifecycle of synchronization sessions.
+service Synchronization {
+ // Create creates a new session.
+ rpc Create(CreateRequest) returns (CreateResponse) {}
+ // List returns metadata for existing sessions.
+ rpc List(ListRequest) returns (ListResponse) {}
+ // Flush flushes sessions.
+ rpc Flush(FlushRequest) returns (FlushResponse) {}
+ // Pause pauses sessions.
+ rpc Pause(PauseRequest) returns (PauseResponse) {}
+ // Resume resumes paused or disconnected sessions.
+ rpc Resume(ResumeRequest) returns (ResumeResponse) {}
+ // Reset resets sessions' histories.
+ rpc Reset(ResetRequest) returns (ResetResponse) {}
+ // Terminate terminates sessions.
+ rpc Terminate(TerminateRequest) returns (TerminateResponse) {}
+}
+
diff --git a/MutagenSdk/Proto/synchronization/compression/algorithm.proto b/MutagenSdk/Proto/synchronization/compression/algorithm.proto
new file mode 100644
index 0000000..857c1bc
--- /dev/null
+++ b/MutagenSdk/Proto/synchronization/compression/algorithm.proto
@@ -0,0 +1,50 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/synchronization/compression/algorithm.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package compression;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Synchronization.Compression";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/synchronization/compression";
+
+// Algorithm specifies a compression algorithm.
+enum Algorithm {
+ // Algorithm_AlgorithmDefault represents an unspecified compression
+ // algorithm. It should be converted to one of the following values based on
+ // the desired default behavior.
+ AlgorithmDefault = 0;
+ // Algorithm_AlgorithmNone specifies that no compression should be used.
+ AlgorithmNone = 1;
+ // Algorithm_AlgorithmDeflate specifies that DEFLATE compression should be
+ // used.
+ AlgorithmDeflate = 2;
+ // Algorithm_AlgorithmZstandard specifies that Zstandard compression should
+ // be used.
+ AlgorithmZstandard = 3;
+}
+
diff --git a/MutagenSdk/Proto/synchronization/configuration.proto b/MutagenSdk/Proto/synchronization/configuration.proto
new file mode 100644
index 0000000..a115a49
--- /dev/null
+++ b/MutagenSdk/Proto/synchronization/configuration.proto
@@ -0,0 +1,176 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/synchronization/configuration.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package synchronization;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Synchronization";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/synchronization";
+
+import "filesystem/behavior/probe_mode.proto";
+import "synchronization/scan_mode.proto";
+import "synchronization/stage_mode.proto";
+import "synchronization/watch_mode.proto";
+import "synchronization/compression/algorithm.proto";
+import "synchronization/core/mode.proto";
+import "synchronization/core/permissions_mode.proto";
+import "synchronization/core/symbolic_link_mode.proto";
+import "synchronization/core/ignore/syntax.proto";
+import "synchronization/core/ignore/ignore_vcs_mode.proto";
+import "synchronization/hashing/algorithm.proto";
+
+// Configuration encodes session configuration parameters. It is used for create
+// commands to specify configuration options, for loading global configuration
+// options, and for storing a merged configuration inside sessions. It should be
+// considered immutable.
+message Configuration {
+ // Synchronization parameters (fields 11-20).
+ // NOTE: These run from field indices 11-20 (rather than 1-10, which are
+ // reserved for symbolic link configuration parameters) due to the
+ // historical order in which these fields were added. Field 17 (the digest
+ // algorithm) is also listed out of its chronological order of addition due
+ // to its relative importance in the configuration.
+
+ // SynchronizationMode specifies the synchronization mode that should be
+ // used in synchronization.
+ core.SynchronizationMode synchronizationMode = 11;
+
+ // HashingAlgorithm specifies the content hashing algorithm used to track
+ // content and perform differential transfers.
+ hashing.Algorithm hashingAlgorithm = 17;
+
+ // MaximumEntryCount specifies the maximum number of filesystem entries that
+ // endpoints will tolerate managing. A zero value indicates no limit.
+ uint64 maximumEntryCount = 12;
+
+ // MaximumStagingFileSize is the maximum (individual) file size that
+ // endpoints will stage. A zero value indicates no limit.
+ uint64 maximumStagingFileSize = 13;
+
+ // ProbeMode specifies the filesystem probing mode.
+ behavior.ProbeMode probeMode = 14;
+
+ // ScanMode specifies the synchronization root scanning mode.
+ ScanMode scanMode = 15;
+
+ // StageMode specifies the file staging mode.
+ StageMode stageMode = 16;
+
+ // Fields 18-20 are reserved for future synchronization configuration
+ // parameters.
+
+
+ // Symbolic link configuration parameters (fields 1-10).
+ // NOTE: These run from field indices 1-10. The reason for this is that
+ // symbolic link configuration parameters is due to the historical order in
+ // which configuration fields were added.
+
+ // SymbolicLinkMode specifies the symbolic link mode.
+ core.SymbolicLinkMode symbolicLinkMode = 1;
+
+ // Fields 2-10 are reserved for future symbolic link configuration
+ // parameters.
+
+
+ // Watch configuration parameters (fields 21-30).
+
+ // WatchMode specifies the filesystem watching mode.
+ WatchMode watchMode = 21;
+
+ // WatchPollingInterval specifies the interval (in seconds) for poll-based
+ // file monitoring. A value of 0 specifies that the default interval should
+ // be used.
+ uint32 watchPollingInterval = 22;
+
+ // Fields 23-30 are reserved for future watch configuration parameters.
+
+
+ // Ignore configuration parameters (fields 31-60).
+
+ // IgnoreSyntax specifies the syntax and semantics to use for ignores.
+ // NOTE: This field is out of order due to the historical order in which it
+ // was added.
+ ignore.Syntax ignoreSyntax = 34;
+
+ // DefaultIgnores specifies the ignore patterns brought in from the global
+ // configuration.
+ // DEPRECATED: This field is no longer used when loading from global
+ // configuration. Instead, ignores provided by global configuration are
+ // simply merged into the ignore list of the main configuration. However,
+ // older sessions still use this field.
+ repeated string defaultIgnores = 31;
+
+ // Ignores specifies the ignore patterns brought in from the create request.
+ repeated string ignores = 32;
+
+ // IgnoreVCSMode specifies the VCS ignore mode that should be used in
+ // synchronization.
+ ignore.IgnoreVCSMode ignoreVCSMode = 33;
+
+ // Fields 35-60 are reserved for future ignore configuration parameters.
+
+
+ // Permissions configuration parameters (fields 61-80).
+
+ // PermissionsMode species the manner in which permissions should be
+ // propagated between endpoints.
+ core.PermissionsMode permissionsMode = 61;
+
+ // Field 62 is reserved for PermissionsPreservationMode.
+
+ // DefaultFileMode specifies the default permission mode to use for new
+ // files in "portable" permission propagation mode.
+ uint32 defaultFileMode = 63;
+
+ // DefaultDirectoryMode specifies the default permission mode to use for new
+ // files in "portable" permission propagation mode.
+ uint32 defaultDirectoryMode = 64;
+
+ // DefaultOwner specifies the default owner identifier to use when setting
+ // ownership of new files and directories in "portable" permission
+ // propagation mode.
+ string defaultOwner = 65;
+
+ // DefaultGroup specifies the default group identifier to use when setting
+ // ownership of new files and directories in "portable" permission
+ // propagation mode.
+ string defaultGroup = 66;
+
+ // Fields 67-80 are reserved for future permission configuration parameters.
+
+
+ // Compression configuration parameters (fields 81-90).
+
+ // CompressionAlgorithm specifies the compression algorithm to use when
+ // communicating with the endpoint. This only applies to remote endpoints.
+ compression.Algorithm compressionAlgorithm = 81;
+
+ // Fields 82-90 are reserved for future compression configuration
+ // parameters.
+}
+
diff --git a/MutagenSdk/Proto/synchronization/core/change.proto b/MutagenSdk/Proto/synchronization/core/change.proto
new file mode 100644
index 0000000..0ea5b98
--- /dev/null
+++ b/MutagenSdk/Proto/synchronization/core/change.proto
@@ -0,0 +1,50 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/synchronization/core/change.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package core;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Synchronization.Core";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/synchronization/core";
+
+import "synchronization/core/entry.proto";
+
+// Change encodes a change to an entry hierarchy. Change objects should be
+// considered immutable and must not be modified.
+message Change {
+ // Path is the path of the root of the change (relative to the
+ // synchronization root).
+ string path = 1;
+ // Old represents the old filesystem hierarchy at the change path. It may be
+ // nil if no content previously existed.
+ Entry old = 2;
+ // New represents the new filesystem hierarchy at the change path. It may be
+ // nil if content has been deleted.
+ Entry new = 3;
+}
+
diff --git a/MutagenSdk/Proto/synchronization/core/conflict.proto b/MutagenSdk/Proto/synchronization/core/conflict.proto
new file mode 100644
index 0000000..717c164
--- /dev/null
+++ b/MutagenSdk/Proto/synchronization/core/conflict.proto
@@ -0,0 +1,54 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/synchronization/core/conflict.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package core;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Synchronization.Core";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/synchronization/core";
+
+import "synchronization/core/change.proto";
+
+// Conflict encodes conflicting changes on alpha and beta that prevent
+// synchronization of a particular path. Conflict objects should be considered
+// immutable and must not be modified.
+message Conflict {
+ // Root is the root path for the conflict (relative to the synchronization
+ // root). While this can (in theory) be computed based on the change lists
+ // contained within the conflict, doing so relies on those change lists
+ // being constructed and ordered in a particular manner that's not possible
+ // to enforce. Additionally, conflicts are often sorted by their root path,
+ // and dynamically computing it on every sort comparison operation would be
+ // prohibitively expensive.
+ string root = 1;
+ // AlphaChanges are the relevant changes on alpha.
+ repeated Change alphaChanges = 2;
+ // BetaChanges are the relevant changes on beta.
+ repeated Change betaChanges = 3;
+}
+
diff --git a/MutagenSdk/Proto/synchronization/core/entry.proto b/MutagenSdk/Proto/synchronization/core/entry.proto
new file mode 100644
index 0000000..be2d1fa
--- /dev/null
+++ b/MutagenSdk/Proto/synchronization/core/entry.proto
@@ -0,0 +1,111 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/synchronization/core/entry.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package core;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Synchronization.Core";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/synchronization/core";
+
+// EntryKind encodes the type of entry represented by an Entry object.
+enum EntryKind {
+ // EntryKind_Directory indicates a directory.
+ Directory = 0;
+ // EntryKind_File indicates a regular file.
+ File = 1;
+ // EntryKind_SymbolicLink indicates a symbolic link.
+ SymbolicLink = 2;
+
+ // Values 3-99 are reserved for future synchronizable entry types.
+
+ // EntryKind_Untracked indicates content (or the root of content) that is
+ // intentionally excluded from synchronization by Mutagen. This includes
+ // explicitly ignored content, content that is ignored due to settings (such
+ // as symbolic links in the "ignore" symbolic link mode), as well as content
+ // types that Mutagen doesn't understand and/or have a way to propagate
+ // (such as FIFOs and Unix domain sockets). This type of entry is not
+ // synchronizable.
+ Untracked = 100;
+ // EntryKind_Problematic indicates content (or the root of content) that
+ // would normally be synchronized, but which is currently inaccessible to
+ // scanning. This includes (but is not limited to) content that is modified
+ // concurrently with scanning, content that is inaccessible due to
+ // permissions, content that can't be read due to filesystem errors, content
+ // that cannot be properly encoded given the current settings (such as
+ // absolute symbolic links found when using the "portable" symbolic link
+ // mode), and content that Mutagen cannot scan or watch reliably (such as
+ // directories that are also mount points). This type of entry is not
+ // synchronizable.
+ Problematic = 101;
+ // EntryKind_PhantomDirectory indicates a directory that was recorded with
+ // an ignore mask. This type is used to support Docker-style ignore syntax
+ // and semantics, which allow directories to be unignored by child content
+ // that is explicitly unignored. This type is pseudo-synchronizable; entries
+ // containing phantom contents must have those contents reified (to tracked
+ // or ignored directories) using ReifyPhantomDirectories before Reconcile.
+ PhantomDirectory = 102;
+
+ // Values 102 - 199 are reserved for future unsynchronizable entry types.
+}
+
+// Entry encodes a filesystem entry (e.g. a directory, a file, or a symbolic
+// link). A nil Entry represents an absence of content. An zero-value Entry
+// represents an empty Directory. Entry objects should be considered immutable
+// and must not be modified.
+message Entry {
+ // Kind encodes the type of filesystem entry being represented.
+ EntryKind kind = 1;
+
+ // Fields 2-4 are reserved for future common entry data.
+
+ // Contents represents a directory entry's contents. It must only be non-nil
+ // for directory entries.
+ map contents = 5;
+
+ // Fields 6-7 are reserved for future directory entry data.
+
+ // Digest represents the hash of a file entry's contents. It must only be
+ // non-nil for file entries.
+ bytes digest = 8;
+ // Executable indicates whether or not a file entry is marked as executable.
+ // It must only be set (if appropriate) for file entries.
+ bool executable = 9;
+
+ // Fields 10-11 are reserved for future file entry data.
+
+ // Target is the symbolic link target for symbolic link entries. It must be
+ // non-empty if and only if the entry is a symbolic link.
+ string target = 12;
+
+ // Fields 13-14 are reserved for future symbolic link entry data.
+
+ // Problem indicates the relevant error for problematic content. It must be
+ // non-empty if and only if the entry represents problematic content.
+ string problem = 15;
+}
+
diff --git a/MutagenSdk/Proto/synchronization/core/ignore/ignore_vcs_mode.proto b/MutagenSdk/Proto/synchronization/core/ignore/ignore_vcs_mode.proto
new file mode 100644
index 0000000..5ad0da1
--- /dev/null
+++ b/MutagenSdk/Proto/synchronization/core/ignore/ignore_vcs_mode.proto
@@ -0,0 +1,48 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/synchronization/core/ignore/ignore_vcs_mode.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package ignore;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Synchronization.Core.Ignore";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/synchronization/core/ignore";
+
+// IgnoreVCSMode specifies the mode for ignoring VCS directories.
+enum IgnoreVCSMode {
+ // IgnoreVCSMode_IgnoreVCSModeDefault represents an unspecified VCS ignore
+ // mode. It is not valid for use with Scan. It should be converted to one of
+ // the following values based on the desired default behavior.
+ IgnoreVCSModeDefault = 0;
+ // IgnoreVCSMode_IgnoreVCSModeIgnore indicates that VCS directories should
+ // be ignored.
+ IgnoreVCSModeIgnore = 1;
+ // IgnoreVCSMode_IgnoreVCSModePropagate indicates that VCS directories
+ // should be propagated.
+ IgnoreVCSModePropagate = 2;
+}
+
diff --git a/MutagenSdk/Proto/synchronization/core/ignore/syntax.proto b/MutagenSdk/Proto/synchronization/core/ignore/syntax.proto
new file mode 100644
index 0000000..430f9cb
--- /dev/null
+++ b/MutagenSdk/Proto/synchronization/core/ignore/syntax.proto
@@ -0,0 +1,48 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/synchronization/core/ignore/syntax.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package ignore;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Synchronization.Core.Ignore";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/synchronization/core/ignore";
+
+// Syntax specifies the syntax and semantics for ignore specifications.
+enum Syntax {
+ // Syntax_SyntaxDefault represents an unspecified ignore syntax. It is not
+ // valid for use with core synchronization functions. It should be converted
+ // to one of the following values based on the desired default behavior.
+ SyntaxDefault = 0;
+ // Syntax_SyntaxMutagen specifies that Mutagen-style ignore syntax and
+ // semantics should be used.
+ SyntaxMutagen = 1;
+ // Syntax_SyntaxDocker specifies that Docker-style ignore syntax and
+ // semantics should be used.
+ SyntaxDocker = 2;
+}
+
diff --git a/MutagenSdk/Proto/synchronization/core/mode.proto b/MutagenSdk/Proto/synchronization/core/mode.proto
new file mode 100644
index 0000000..79678a2
--- /dev/null
+++ b/MutagenSdk/Proto/synchronization/core/mode.proto
@@ -0,0 +1,71 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/synchronization/core/mode.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package core;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Synchronization.Core";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/synchronization/core";
+
+// SynchronizationMode specifies the mode for synchronization, encoding both
+// directionality and conflict resolution behavior.
+enum SynchronizationMode {
+ // SynchronizationMode_SynchronizationModeDefault represents an unspecified
+ // synchronization mode. It is not valid for use with Reconcile. It should
+ // be converted to one of the following values based on the desired default
+ // behavior.
+ SynchronizationModeDefault = 0;
+
+ // SynchronizationMode_SynchronizationModeTwoWaySafe represents a
+ // bidirectional synchronization mode where automatic conflict resolution is
+ // performed only in cases where no data would be lost. Specifically, this
+ // means that modified contents are allowed to propagate to the opposite
+ // endpoint if the corresponding contents on the opposite endpoint are
+ // unmodified or deleted. All other conflicts are left unresolved.
+ SynchronizationModeTwoWaySafe = 1;
+
+ // SynchronizationMode_SynchronizationModeTwoWayResolved is the same as
+ // SynchronizationMode_SynchronizationModeTwoWaySafe, but specifies that the
+ // alpha endpoint should win automatically in any conflict between alpha and
+ // beta, including cases where alpha has deleted contents that beta has
+ // modified.
+ SynchronizationModeTwoWayResolved = 2;
+
+ // SynchronizationMode_SynchronizationModeOneWaySafe represents a
+ // unidirectional synchronization mode where contents and changes propagate
+ // from alpha to beta, but won't overwrite any creations or modifications on
+ // beta.
+ SynchronizationModeOneWaySafe = 3;
+
+ // SynchronizationMode_SynchronizationModeOneWayReplica represents a
+ // unidirectional synchronization mode where contents on alpha are mirrored
+ // (verbatim) to beta, overwriting any conflicting contents on beta and
+ // deleting any extraneous contents on beta.
+ SynchronizationModeOneWayReplica = 4;
+}
+
diff --git a/MutagenSdk/Proto/synchronization/core/permissions_mode.proto b/MutagenSdk/Proto/synchronization/core/permissions_mode.proto
new file mode 100644
index 0000000..d011f89
--- /dev/null
+++ b/MutagenSdk/Proto/synchronization/core/permissions_mode.proto
@@ -0,0 +1,52 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/synchronization/core/permissions_mode.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package core;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Synchronization.Core";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/synchronization/core";
+
+// PermissionsMode specifies the mode for handling permission propagation.
+enum PermissionsMode {
+ // PermissionsMode_PermissionsModeDefault represents an unspecified
+ // permissions mode. It is not valid for use with Scan. It should be
+ // converted to one of the following values based on the desired default
+ // behavior.
+ PermissionsModeDefault = 0;
+ // PermissionsMode_PermissionsModePortable specifies that permissions should
+ // be propagated in a portable fashion. This means that only executability
+ // bits are managed by Mutagen and that manual specifications for ownership
+ // and base file permissions are used.
+ PermissionsModePortable = 1;
+ // PermissionsMode_PermissionsModeManual specifies that only manual
+ // permission specifications should be used. In this case, Mutagen does not
+ // perform any propagation of permissions.
+ PermissionsModeManual = 2;
+}
+
diff --git a/MutagenSdk/Proto/synchronization/core/problem.proto b/MutagenSdk/Proto/synchronization/core/problem.proto
new file mode 100644
index 0000000..de4aad3
--- /dev/null
+++ b/MutagenSdk/Proto/synchronization/core/problem.proto
@@ -0,0 +1,45 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/synchronization/core/problem.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package core;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Synchronization.Core";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/synchronization/core";
+
+// Problem indicates an issue or error encountered at some stage of a
+// synchronization cycle. Problem objects should be considered immutable and
+// must not be modified.
+message Problem {
+ // Path is the path at which the problem occurred (relative to the
+ // synchronization root).
+ string path = 1;
+ // Error is a human-readable summary of the problem.
+ string error = 2;
+}
+
diff --git a/MutagenSdk/Proto/synchronization/core/symbolic_link_mode.proto b/MutagenSdk/Proto/synchronization/core/symbolic_link_mode.proto
new file mode 100644
index 0000000..e9f0663
--- /dev/null
+++ b/MutagenSdk/Proto/synchronization/core/symbolic_link_mode.proto
@@ -0,0 +1,55 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/synchronization/core/symbolic_link_mode.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package core;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Synchronization.Core";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/synchronization/core";
+
+// SymbolicLinkMode specifies the mode for handling symbolic links.
+enum SymbolicLinkMode {
+ // SymbolicLinkMode_SymbolicLinkModeDefault represents an unspecified
+ // symbolic link mode. It is not valid for use with Scan or Transition. It
+ // should be converted to one of the following values based on the desired
+ // default behavior.
+ SymbolicLinkModeDefault = 0;
+ // SymbolicLinkMode_SymbolicLinkModeIgnore specifies that all symbolic links
+ // should be ignored.
+ SymbolicLinkModeIgnore = 1;
+ // SymbolicLinkMode_SymbolicLinkModePortable specifies that only portable
+ // symbolic links should be synchronized. Any absolute symbolic links or
+ // symbolic links which are otherwise non-portable will be treate as
+ // problematic content.
+ SymbolicLinkModePortable = 2;
+ // SymbolicLinkMode_SymbolicLinkModePOSIXRaw specifies that symbolic links
+ // should be propagated in their raw form. It is only valid on POSIX systems
+ // and only makes sense in the context of POSIX-to-POSIX synchronization.
+ SymbolicLinkModePOSIXRaw = 3;
+}
+
diff --git a/MutagenSdk/Proto/synchronization/hashing/algorithm.proto b/MutagenSdk/Proto/synchronization/hashing/algorithm.proto
new file mode 100644
index 0000000..1e155c7
--- /dev/null
+++ b/MutagenSdk/Proto/synchronization/hashing/algorithm.proto
@@ -0,0 +1,48 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/synchronization/hashing/algorithm.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package hashing;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Synchronization.Hashing";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/synchronization/hashing";
+
+// Algorithm specifies a hashing algorithm.
+enum Algorithm {
+ // Algorithm_AlgorithmDefault represents an unspecified hashing algorithm.
+ // It should be converted to one of the following values based on the
+ // desired default behavior.
+ AlgorithmDefault = 0;
+ // Algorithm_AlgorithmSHA1 specifies that SHA-1 hashing should be used.
+ AlgorithmSHA1 = 1;
+ // Algorithm_AlgorithmSHA256 specifies that SHA-256 hashing should be used.
+ AlgorithmSHA256 = 2;
+ // Algorithm_AlgorithmXXH128 specifies that XXH128 hashing should be used.
+ AlgorithmXXH128 = 3;
+}
+
diff --git a/MutagenSdk/Proto/synchronization/rsync/receive.proto b/MutagenSdk/Proto/synchronization/rsync/receive.proto
new file mode 100644
index 0000000..bb71149
--- /dev/null
+++ b/MutagenSdk/Proto/synchronization/rsync/receive.proto
@@ -0,0 +1,58 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/synchronization/rsync/receive.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package rsync;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Synchronization.Rsync";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/synchronization/rsync";
+
+// ReceiverState encodes that status of an rsync receiver. It should be
+// considered immutable.
+message ReceiverState {
+ // Path is the path currently being received.
+ string path = 1;
+ // ReceivedSize is the number of bytes that have been received for the
+ // current path from both block and data operations.
+ uint64 receivedSize = 2;
+ // ExpectedSize is the number of bytes expected for the current path.
+ uint64 expectedSize = 3;
+ // ReceivedFiles is the number of files that have already been received.
+ uint64 receivedFiles = 4;
+ // ExpectedFiles is the total number of files expected.
+ uint64 expectedFiles = 5;
+ // TotalReceivedSize is the total number of bytes that have been received
+ // for all files from both block and data operations.
+ uint64 totalReceivedSize = 6;
+ // TODO: We may want to add statistics on the speedup offered by the rsync
+ // algorithm in terms of data volume, though obviously this can't account
+ // for any savings that might come from compression at the transport layer.
+ // It would also be really nice to have TotalExpectedSize, but this is
+ // prohibitively difficult and expensive to compute.
+}
+
diff --git a/MutagenSdk/Proto/synchronization/scan_mode.proto b/MutagenSdk/Proto/synchronization/scan_mode.proto
new file mode 100644
index 0000000..ea8c264
--- /dev/null
+++ b/MutagenSdk/Proto/synchronization/scan_mode.proto
@@ -0,0 +1,48 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/synchronization/scan_mode.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package synchronization;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Synchronization";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/synchronization";
+
+// ScanMode specifies the mode for synchronization root scanning.
+enum ScanMode {
+ // ScanMode_ScanModeDefault represents an unspecified scan mode. It should
+ // be converted to one of the following values based on the desired default
+ // behavior.
+ ScanModeDefault = 0;
+ // ScanMode_ScanModeFull specifies that full scans should be performed on
+ // each synchronization cycle.
+ ScanModeFull = 1;
+ // ScanMode_ScanModeAccelerated specifies that scans should attempt to use
+ // watch-based acceleration.
+ ScanModeAccelerated = 2;
+}
+
diff --git a/MutagenSdk/Proto/synchronization/session.proto b/MutagenSdk/Proto/synchronization/session.proto
new file mode 100644
index 0000000..49329ba
--- /dev/null
+++ b/MutagenSdk/Proto/synchronization/session.proto
@@ -0,0 +1,102 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/synchronization/session.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package synchronization;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Synchronization";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/synchronization";
+
+import "google/protobuf/timestamp.proto";
+
+import "synchronization/configuration.proto";
+import "synchronization/version.proto";
+import "url/url.proto";
+
+// Session represents a synchronization session configuration and persistent
+// state. It is mutable within the context of the daemon, so it should be
+// accessed and modified in a synchronized fashion. Outside of the daemon (e.g.
+// when returned via the API), it should be considered immutable.
+message Session {
+ // The identifier, version, creationTime, and creatingVersion* fields are
+ // considered the "header" fields for all session versions. A message
+ // composed purely of these fields is guaranteed to be compatible with all
+ // future session versions. This can be used to dispatch session decoding to
+ // more specific message structures once multiple session version formats
+ // are implemented.
+
+ // Identifier is the (unique) session identifier. It is static. It cannot be
+ // empty.
+ string identifier = 1;
+ // Version is the session version. It is static.
+ Version version = 2;
+ // CreationTime is the creation time of the session. It is static. It cannot
+ // be nil.
+ google.protobuf.Timestamp creationTime = 3;
+ // CreatingVersionMajor is the major version component of the version of
+ // Mutagen which created the session. It is static.
+ uint32 creatingVersionMajor = 4;
+ // CreatingVersionMinor is the minor version component of the version of
+ // Mutagen which created the session. It is static.
+ uint32 creatingVersionMinor = 5;
+ // CreatingVersionPatch is the patch version component of the version of
+ // Mutagen which created the session. It is static.
+ uint32 creatingVersionPatch = 6;
+
+ // The remaining fields are those currently used by session version 1.
+
+ // Alpha is the alpha endpoint URL. It is static. It cannot be nil.
+ url.URL alpha = 7;
+ // Beta is the beta endpoint URL. It is static. It cannot be nil.
+ url.URL beta = 8;
+ // Configuration is the flattened session configuration. It is static. It
+ // cannot be nil.
+ Configuration configuration = 9;
+ // ConfigurationAlpha are the alpha-specific session configuration
+ // overrides. It is static. It may be nil for existing sessions loaded from
+ // disk, but it is not considered valid unless non-nil, so it should be
+ // replaced with an empty default value in-memory if a nil on-disk value is
+ // detected.
+ Configuration configurationAlpha = 11;
+ // ConfigurationBeta are the beta-specific session configuration overrides.
+ // It is static. It may be nil for existing sessions loaded from disk, but
+ // it is not considered valid unless non-nil, so it should be replaced with
+ // an empty default value in-memory if a nil on-disk value is detected.
+ Configuration configurationBeta = 12;
+ // Name is a user-friendly name for the session. It may be empty and is not
+ // guaranteed to be unique across all sessions. It is only used as a simpler
+ // handle for specifying sessions. It is static.
+ string name = 14;
+ // Labels are the session labels. They are static.
+ map labels = 13;
+ // Paused indicates whether or not the session is marked as paused.
+ bool paused = 10;
+ // NOTE: Fields 11, 12, 13, and 14 are used above. They are out of order for
+ // historical reasons.
+}
+
diff --git a/MutagenSdk/Proto/synchronization/stage_mode.proto b/MutagenSdk/Proto/synchronization/stage_mode.proto
new file mode 100644
index 0000000..ffea648
--- /dev/null
+++ b/MutagenSdk/Proto/synchronization/stage_mode.proto
@@ -0,0 +1,52 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/synchronization/stage_mode.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package synchronization;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Synchronization";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/synchronization";
+
+// StageMode specifies the mode for file staging.
+enum StageMode {
+ // StageMode_StageModeDefault represents an unspecified staging mode. It
+ // should be converted to one of the following values based on the desired
+ // default behavior.
+ StageModeDefault = 0;
+ // StageMode_StageModeMutagen specifies that files should be staged in the
+ // Mutagen data directory.
+ StageModeMutagen = 1;
+ // StageMode_StageModeNeighboring specifies that files should be staged in a
+ // directory which neighbors the synchronization root.
+ StageModeNeighboring = 2;
+ // StageMode_StageModeInternal specified that files should be staged in a
+ // directory contained within a synchronization root. This mode will only
+ // function if the synchronization root already exists.
+ StageModeInternal = 3;
+}
+
diff --git a/MutagenSdk/Proto/synchronization/state.proto b/MutagenSdk/Proto/synchronization/state.proto
new file mode 100644
index 0000000..ec816fe
--- /dev/null
+++ b/MutagenSdk/Proto/synchronization/state.proto
@@ -0,0 +1,161 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/synchronization/state.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package synchronization;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Synchronization";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/synchronization";
+
+import "synchronization/rsync/receive.proto";
+import "synchronization/session.proto";
+import "synchronization/core/conflict.proto";
+import "synchronization/core/problem.proto";
+
+// Status encodes the status of a synchronization session.
+enum Status {
+ // Status_Disconnected indicates that the session is unpaused but not
+ // currently connected or connecting to either endpoint.
+ Disconnected = 0;
+ // Status_HaltedOnRootEmptied indicates that the session is halted due to
+ // the root emptying safety check.
+ HaltedOnRootEmptied = 1;
+ // Status_HaltedOnRootDeletion indicates that the session is halted due to
+ // the root deletion safety check.
+ HaltedOnRootDeletion = 2;
+ // Status_HaltedOnRootTypeChange indicates that the session is halted due to
+ // the root type change safety check.
+ HaltedOnRootTypeChange = 3;
+ // Status_ConnectingAlpha indicates that the session is attempting to
+ // connect to the alpha endpoint.
+ ConnectingAlpha = 4;
+ // Status_ConnectingBeta indicates that the session is attempting to connect
+ // to the beta endpoint.
+ ConnectingBeta = 5;
+ // Status_Watching indicates that the session is watching for filesystem
+ // changes.
+ Watching = 6;
+ // Status_Scanning indicates that the session is scanning the filesystem on
+ // each endpoint.
+ Scanning = 7;
+ // Status_WaitingForRescan indicates that the session is waiting to retry
+ // scanning after an error during the previous scanning operation.
+ WaitingForRescan = 8;
+ // Status_Reconciling indicates that the session is performing
+ // reconciliation.
+ Reconciling = 9;
+ // Status_StagingAlpha indicates that the session is staging files on alpha.
+ StagingAlpha = 10;
+ // Status_StagingBeta indicates that the session is staging files on beta.
+ StagingBeta = 11;
+ // Status_Transitioning indicates that the session is performing transition
+ // operations on each endpoint.
+ Transitioning = 12;
+ // Status_Saving indicates that the session is recording synchronization
+ // history to disk.
+ Saving = 13;
+}
+
+// EndpointState encodes the current state of a synchronization endpoint. It is
+// mutable within the context of the daemon, so it should be accessed and
+// modified in a synchronized fashion. Outside of the daemon (e.g. when returned
+// via the API), it should be considered immutable.
+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;
+ // Directories is the number of synchronizable directory entries contained
+ // in the last snapshot from the endpoint.
+ uint64 directories = 3;
+ // Files is the number of synchronizable file entries contained in the last
+ // snapshot from the endpoint.
+ uint64 files = 4;
+ // SymbolicLinks is the number of synchronizable symbolic link entries
+ // contained in the last snapshot from the endpoint.
+ uint64 symbolicLinks = 5;
+ // TotalFileSize is the total size of all synchronizable files referenced by
+ // the last snapshot from the endpoint.
+ 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 = 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 = 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 = 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 = 10;
+ // StagingProgress is the rsync staging progress. It is non-nil if and only
+ // if the endpoint is currently staging files.
+ rsync.ReceiverState stagingProgress = 11;
+}
+
+// State encodes the current state of a synchronization session. It is mutable
+// within the context of the daemon, so it should be accessed and modified in a
+// synchronized fashion. Outside of the daemon (e.g. when returned via the API),
+// it should be considered immutable.
+message State {
+ // Session is the session metadata. If the session is paused, then the
+ // remainder of the fields in this structure should be ignored.
+ Session session = 1;
+ // Status is the session status.
+ Status status = 2;
+ // LastError is the last error to occur during synchronization. It is
+ // cleared after a successful synchronization cycle.
+ string lastError = 3;
+ // SuccessfulCycles is the number of successful synchronization cycles to
+ // occur since successfully connecting to the endpoints.
+ uint64 successfulCycles = 4;
+ // Conflicts are the content conflicts identified during reconciliation.
+ // This list may be a truncated version of the full list if too many
+ // conflicts are encountered to report via the API, in which case
+ // ExcludedConflicts will be non-zero.
+ repeated core.Conflict conflicts = 5;
+ // ExcludedConflicts is the number of conflicts that have been excluded from
+ // Conflicts due to truncation. This value can be non-zero only if conflicts
+ // is non-empty.
+ uint64 excludedConflicts = 6;
+ // AlphaState encodes the state of the alpha endpoint. It is always non-nil.
+ EndpointState alphaState = 7;
+ // BetaState encodes the state of the beta endpoint. It is always non-nil.
+ EndpointState betaState = 8;
+}
+
diff --git a/MutagenSdk/Proto/synchronization/version.proto b/MutagenSdk/Proto/synchronization/version.proto
new file mode 100644
index 0000000..a9034a4
--- /dev/null
+++ b/MutagenSdk/Proto/synchronization/version.proto
@@ -0,0 +1,45 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/synchronization/version.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package synchronization;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Synchronization";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/synchronization";
+
+// Version specifies a session version, providing default behavior that can vary
+// without affecting existing sessions.
+enum Version {
+ // Invalid is the default session version and represents an unspecfied and
+ // invalid version. It is used as a sanity check to ensure that version is
+ // set for a session.
+ Invalid = 0;
+ // Version1 represents session version 1.
+ Version1 = 1;
+}
+
diff --git a/MutagenSdk/Proto/synchronization/watch_mode.proto b/MutagenSdk/Proto/synchronization/watch_mode.proto
new file mode 100644
index 0000000..0f8515d
--- /dev/null
+++ b/MutagenSdk/Proto/synchronization/watch_mode.proto
@@ -0,0 +1,55 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/synchronization/watch_mode.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package synchronization;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Synchronization";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/synchronization";
+
+// WatchMode specifies the mode for filesystem watching.
+enum WatchMode {
+ // WatchMode_WatchModeDefault represents an unspecified watch mode. It
+ // should be converted to one of the following values based on the desired
+ // default behavior.
+ WatchModeDefault = 0;
+ // WatchMode_WatchModePortable specifies that native recursive watching
+ // should be used to monitor paths on systems that support it if those paths
+ // fall under the home directory. In these cases, a watch on the entire home
+ // directory is established and filtered for events pertaining to the
+ // specified path. On all other systems and for all other paths, poll-based
+ // watching is used.
+ WatchModePortable = 1;
+ // WatchMode_WatchModeForcePoll specifies that only poll-based watching
+ // should be used.
+ WatchModeForcePoll = 2;
+ // WatchMode_WatchModeNoWatch specifies that no watching should be used
+ // (i.e. no events should be generated).
+ WatchModeNoWatch = 3;
+}
+
diff --git a/MutagenSdk/Proto/url/url.proto b/MutagenSdk/Proto/url/url.proto
new file mode 100644
index 0000000..cfa337f
--- /dev/null
+++ b/MutagenSdk/Proto/url/url.proto
@@ -0,0 +1,92 @@
+/*
+ * This file was taken from
+ * https://github.com/mutagen-io/mutagen/tree/v0.18.1/pkg/url/url.proto
+ *
+ * MIT License
+ *
+ * Copyright (c) 2016-present Docker, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+syntax = "proto3";
+
+package url;
+option csharp_namespace = "Coder.Desktop.MutagenSdk.Proto.Url";
+
+option go_package = "github.com/mutagen-io/mutagen/pkg/url";
+
+// Kind indicates the kind of a URL.
+enum Kind {
+ // Synchronization indicates a synchronization URL.
+ Synchronization = 0;
+ // Forwarding indicates a forwarding URL.
+ Forwarding = 1;
+}
+
+// Protocol indicates a location type.
+enum Protocol {
+ // Local indicates that the resource is on the local system.
+ Local = 0;
+ // SSH indicates that the resource is accessible via SSH.
+ SSH = 1;
+
+ // Enumeration value 2 is reserved for custom protocols.
+
+ // Enumeration value 3 was previously used for the mutagen.io-based tunnel
+ // protocol. This protocol was experimental and only available as part of
+ // the v0.11.x release series. It should not be re-used.
+
+ // Enumeration values 4-10 are reserved for core protocols.
+
+ // Docker indicates that the resource is inside a Docker container.
+ Docker = 11;
+}
+
+// URL represents a pointer to a resource. It should be considered immutable.
+message URL {
+ // Kind indicates the URL kind.
+ // NOTE: This field number is out of order for historical reasons.
+ Kind kind = 7;
+ // Protocol indicates a location type.
+ Protocol protocol = 1;
+ // User is the user under which a resource should be accessed.
+ string user = 2;
+ // Host is protocol-specific, but generally indicates the location of the
+ // remote.
+ string host = 3;
+ // Port indicates a TCP port via which to access the remote location, if
+ // applicable.
+ uint32 port = 4;
+ // Path indicates the path of a resource.
+ string path = 5;
+ // Environment contains captured environment variable information. It is not
+ // a required component and its contents and their behavior depend on the
+ // transport implementation.
+ map environment = 6;
+
+ // Field 7 is already used above for the kind field. It is out of order for
+ // historical reasons.
+
+ // Parameters are internal transport parameters. These are set for URLs
+ // generated internally that require additional metadata. Parameters are not
+ // required and their behavior is dependent on the transport implementation.
+ map parameters = 8;
+}
+
diff --git a/MutagenSdk/Update-Proto.ps1 b/MutagenSdk/Update-Proto.ps1
new file mode 100644
index 0000000..09f00fd
--- /dev/null
+++ b/MutagenSdk/Update-Proto.ps1
@@ -0,0 +1,140 @@
+# Usage: Update-Proto.ps1 -mutagenTag
+param (
+ [Parameter(Mandatory = $true)]
+ [string] $mutagenTag
+)
+
+$ErrorActionPreference = "Stop"
+
+$repo = "mutagen-io/mutagen"
+$protoPrefix = "pkg"
+$entryFile = "service\synchronization\synchronization.proto"
+
+$outputNamespace = "Coder.Desktop.MutagenSdk.Proto"
+$outputDir = "MutagenSdk\Proto"
+
+$cloneDir = Join-Path $env:TEMP "coder-desktop-mutagen-proto"
+if (Test-Path $cloneDir) {
+ Write-Host "Found existing mutagen repo at $cloneDir, checking out $mutagenTag..."
+ # Checkout tag and clean
+ Push-Location $cloneDir
+ try {
+ & git.exe clean -fdx
+ if ($LASTEXITCODE -ne 0) { throw "Failed to clean $mutagenTag" }
+ # If we're already on the tag, we don't need to fetch or checkout.
+ if ((& git.exe name-rev --name-only HEAD) -eq "tags/$mutagenTag") {
+ Write-Host "Already on $mutagenTag"
+ }
+ else {
+ & git.exe fetch --all
+ if ($LASTEXITCODE -ne 0) { throw "Failed to fetch all tags" }
+ & git.exe checkout $mutagenTag
+ if ($LASTEXITCODE -ne 0) { throw "Failed to checkout $mutagenTag" }
+ }
+ }
+ finally {
+ Pop-Location
+ }
+}
+else {
+ New-Item -ItemType Directory -Path $cloneDir -Force
+
+ Write-Host "Cloning mutagen repo to $cloneDir..."
+ & git.exe clone `
+ --depth 1 `
+ --branch $mutagenTag `
+ "https://github.com/$repo.git" `
+ $cloneDir
+}
+
+# Read and format the license header for the copied files.
+$licenseContent = Get-Content (Join-Path $cloneDir "LICENSE")
+# Find the index where MIT License starts so we don't include the preamble.
+$mitStartIndex = $licenseContent.IndexOf("MIT License")
+$licenseHeader = ($licenseContent[$mitStartIndex..($licenseContent.Length - 1)] | ForEach-Object { (" * " + $_).TrimEnd() }) -join "`n"
+
+$entryFilePath = Join-Path $cloneDir (Join-Path $protoPrefix $entryFile)
+if (-not (Test-Path $entryFilePath)) {
+ throw "Failed to find $entryFilePath in mutagen repo"
+}
+
+# Map of src (in the mutagen repo) to dst (within the $outputDir).
+$filesToCopy = @{
+ $entryFilePath = $entryFile
+}
+
+function Add-ImportedFiles([string] $path) {
+ $content = Get-Content $path
+ foreach ($line in $content) {
+ if ($line -match '^import "(.+)"') {
+ $importPath = $matches[1]
+
+ # If the import path starts with google, it doesn't exist in the
+ # mutagen repo, so we need to skip it.
+ if ($importPath -match '^google/') {
+ Write-Host "Skipping $importPath"
+ continue
+ }
+
+ # Mutagen generates from within the pkg directory, so we need to add
+ # the prefix.
+ $filePath = Join-Path $cloneDir (Join-Path $protoPrefix $importPath)
+ if (-not $filesToCopy.ContainsKey($filePath)) {
+ Write-Host "Adding $filePath $importPath"
+ $filesToCopy[$filePath] = $importPath
+ Add-ImportedFiles $filePath
+ }
+ }
+ }
+}
+
+Add-ImportedFiles $entryFilePath
+
+$repoRoot = Resolve-Path (Join-Path $PSScriptRoot "..")
+Push-Location $repoRoot
+if (Test-Path $outputDir) {
+ Remove-Item -Recurse -Force $outputDir
+}
+New-Item -ItemType Directory -Path $outputDir -Force
+
+try {
+ foreach ($filePath in $filesToCopy.Keys) {
+ $protoPath = $filesToCopy[$filePath]
+ $dstPath = Join-Path $outputDir $protoPath
+ $destDir = Split-Path -Path $dstPath -Parent
+ if (-not (Test-Path $destDir)) {
+ New-Item -ItemType Directory -Path $destDir -Force
+ }
+ Copy-Item -Force $filePath $dstPath
+
+ # Determine the license header.
+ $fileHeader = "/*`n" +
+ " * This file was taken from`n" +
+ " * https://github.com/$repo/tree/$mutagenTag/$protoPrefix/$protoPath`n" +
+ " *`n" +
+ $licenseHeader +
+ "`n */`n`n"
+
+ # Determine the csharp_namespace for the file.
+ # Remove the filename and capitalize the first letter of each component
+ # of the path, then join with dots.
+ $protoDir = Split-Path -Path $protoPath -Parent
+ $csharpNamespaceSuffix = ($protoDir -split '[/\\]' | ForEach-Object { $_.Substring(0, 1).ToUpper() + $_.Substring(1) }) -join '.'
+ $csharpNamespace = "$outputNamespace"
+ if ($csharpNamespaceSuffix) {
+ $csharpNamespace += ".$csharpNamespaceSuffix"
+ }
+
+ # Add the csharp_namespace declaration.
+ $content = Get-Content $dstPath -Raw
+ $content = $fileHeader + $content
+ $content = $content -replace '(?m)^(package .*?;)', "`$1`noption csharp_namespace = `"$csharpNamespace`";"
+
+ # Replace all LF with CRLF to avoid spurious diffs in git.
+ $content = $content -replace "(?