syntax = "proto3";

package mesh.v1;

import "google/protobuf/descriptor.proto";
import "mesh/v1/batch.proto";
import "mesh/v1/commit.proto";
import "mesh/v1/content.proto";
import "mesh/v1/git_data.proto";
import "mesh/v1/git_plumbing.proto";
import "mesh/v1/git_porcelain.proto";
import "mesh/v1/hook_script.proto";
import "mesh/v1/hosting.proto";
import "mesh/v1/lfs.proto";
import "mesh/v1/management.proto";
import "mesh/v1/pack_cache.proto";
import "mesh/v1/pull_request.proto";
import "mesh/v1/repository.proto";
import "mesh/v1/ref.proto";
import "mesh/v1/stream.proto";
import "mesh/v1/throttle.proto";
import "mesh/v1/transaction.proto";
import "mesh/v1/work_tree.proto";

option go_package = "atlassian.com/bitbucket/mesh/rpc/v1";
option java_multiple_files = true;
option java_outer_classname = "RpcProtos";
option java_package = "com.atlassian.bitbucket.mesh.rpc.v1";

/* An RPC service for batch content. */
service BatchService {

  rpc Changes(RpcBatchChangesRequest) returns (stream RpcBatchChangesResponseFragment);

  option (service_throttle) = RESOURCE_COMMAND;
}

/* An RPC service for running git operations related to commits, including creating new commits through merging and
   rebasing */
service CommitService {

  rpc EditFile(stream RpcEditFileFragment) returns (stream RpcEditFileResponseFragment);

  rpc GetCommit(RpcGetCommitRequest) returns (RpcGetCommitResponse);

  rpc GetCommits(RpcGetCommitsRequest) returns (stream RpcGetCommitsResponseFragment);

  rpc GetCommonAncestor(RpcGetCommonAncestorRequest) returns (RpcGetCommonAncestorResponse);

  rpc LastModified(RpcLastModifiedRequest) returns (stream RpcLastModifiedResponseFragment);

  rpc Merge(stream RpcMergeFragment) returns (stream RpcMergeResponseFragment);

  rpc Rebase(stream RpcRebaseFragment) returns (stream RpcRebaseResponseFragment);

  rpc ResolveCommits(RpcResolveCommitsRequest) returns (RpcResolveCommitsResponse);

  //@since 1.5
  rpc Revert(stream RpcRevertFragment) returns (stream RpcRevertResponseFragment);

  rpc TraverseCommits(RpcTraverseCommitsRequest) returns (stream RpcTraverseCommitsResponseFragment);

  rpc TryMerge(RpcMergeRequest) returns (RpcTryMergeResponse);

  rpc TryRebase(RpcRebaseRequest) returns (RpcTryRebaseResponse);

  option (service_throttle) = RESOURCE_COMMAND;
}

/* An RPC service for everything around trees, blobs and diffs */
service ContentService {

  rpc GetNodeType(RpcGetNodeTypeRequest) returns (RpcGetNodeTypeResponse);

  rpc GetObjectInfo(RpcGetObjectInfoRequest) returns (RpcGetObjectInfoResponse);

  rpc ListDirectory(RpcListDirectoryRequest) returns (stream RpcListDirectoryResponseFragment);

  option (service_throttle) = RESOURCE_COMMAND;
}

service GitDataService {

  rpc UploadFile(stream RpcUploadFileFragment) returns (RpcUploadFileResponse);

  rpc UploadFiles(stream RpcUploadFilesFragment) returns (stream RpcUploadFilesResponse);

  rpc UploadPackFile(stream RpcUploadPackFileFragment) returns (RpcUploadPackFileResponse);

  option (service_marshaller) = MARSHALLER_ZERO_COPY;
}

/* An RPC service for invoking hook scripts */
service HookScriptService {

  rpc CallHookScripts(stream RpcCallHookScriptsFragment) returns (stream RpcCallHookScriptsResponseFragment);
}

/* An RPC service for hosting operations such as http-backend, receive-pack and upload-pack */
service HostingService {

  //HttpBackend manages throttling internally
  rpc HttpBackend(stream RpcHttpBackendFragment) returns (stream RpcHostingWriteStreamFragment);

  rpc ReceivePack(stream RpcReceivePackFragment) returns (stream RpcHostingWriteStreamFragment) {
    option (method_throttle) = RESOURCE_REFS;
  };

  rpc UploadArchive(stream RpcUploadArchiveFragment) returns (stream RpcHostingReadStreamFragment) {
    option (method_throttle) = RESOURCE_PACK;
  };

  //UploadPack manages throttling internally
  rpc UploadPack(stream RpcUploadPackFragment) returns (stream RpcHostingReadStreamFragment);

  option (service_marshaller) = MARSHALLER_ZERO_COPY;
}

/* An RPC service for performing Git LFS operations */
service LfsService {

  rpc CanStore(RpcLfsCanStoreRequest) returns (RpcLfsCanStoreResponse);

  rpc ObjectExists(RpcLfsObjectExistsRequest) returns (RpcLfsObjectExistsResponse);

  rpc ReadObject(RpcLfsReadObjectRequest) returns (stream RpcStreamChunk) {
    option (method_marshaller) = MARSHALLER_ZERO_COPY;
    option (method_throttle) = RESOURCE_LFS;
  };

  rpc WriteObject(stream RpcLfsWriteObjectFragment) returns (RpcLfsWriteObjectResponse) {
    option (method_marshaller) = MARSHALLER_ZERO_COPY;
    option (method_throttle) = RESOURCE_LFS;
  };
}

/* An RPC service to manage the Mesh node. */
service ManagementService {

  //Adds a Bitbucket Server data store. Only supported on sidecar agents
  rpc AddDataStore(RpcAddDataStoreRequest) returns (RpcAddDataStoreResponse);

  //@since 1.2
  rpc Drain(RpcDrainRequest) returns (stream RpcDrainResponseFragment);

  //@since 1.2
  rpc GetConfiguration(RpcGetConfigurationRequest) returns (RpcGetConfigurationResponse);

  rpc GetDataStores(RpcGetDataStoresRequest) returns (RpcGetDataStoresResponse);

  rpc GetNodeInfo(RpcGetNodeInfoRequest) returns (RpcGetNodeInfoResponse);

  rpc GetSupportInfo(RpcGetSupportInfoRequest) returns (RpcGetSupportInfoResponse);

  rpc GetSupportZip(RpcGetSupportZipRequest) returns (stream RpcStreamChunk) {
    option (method_marshaller) = MARSHALLER_ZERO_COPY;
  };

  //Receives a heartbeat and sends one in response. This is similar to sideband functionality, but separate to
  //allow use for uses like measuring client/server latency.
  rpc Heartbeat(RpcHeartbeat) returns (RpcHeartbeat);

  rpc MarkRepositoriesInconsistent(RpcMarkRepositoriesInconsistentRequest) returns (RpcMarkRepositoriesInconsistentResponse);

  rpc ProvisionNode(RpcProvisionNodeRequest) returns (RpcProvisionNodeResponse);

  rpc RepairRepository(RpcRepairRepositoryRequest) returns (RpcRepairRepositoryResponse);

  rpc ReplaceReadOnlyRepositories(stream RpcReplaceReadOnlyRepositoriesFragment) returns (RpcReplaceReadOnlyRepositoriesResponse);

  rpc ResetHierarchy(RpcResetHierarchyRequest) returns (RpcResetHierarchyResponse);

  rpc SetConfiguration(RpcSetConfigurationRequest) returns (RpcSetConfigurationResponse);

  rpc SetReplicaState(RpcSetReplicaStateRequest) returns (RpcSetReplicaStateResponse);

  rpc SetRepositoryReadOnly(RpcSetRepositoryReadOnlyRequest) returns (RpcSetRepositoryReadOnlyResponse);

  //Opens a sideband channel from the control plane (leader) to the node (follower) which allows bidirectional
  //messages to be exchanged between the two. Fragments are defined in terms of "leader" and "follower" rather
  //than "request" and "response" because quite often the "request" will actually originate from the _follower_
  //(which has no mechanism for initiating its own RPCs to the control plane) and the leader will be providing
  //the "response".
  rpc Sideband(stream RpcSidebandLeaderFragment) returns (stream RpcSidebandFollowerFragment);
}

/* An RPC service for managing the Pack cache */
service PackCacheService {

  rpc Clear(RpcClearPackCacheRequest) returns (RpcClearPackCacheResponse);

  rpc GetStatistics(RpcGetPackCacheStatisticsRequest) returns (RpcGetPackCacheStatisticsResponse);
}

/* An RPC service for running low-level "plumbing" Git operations. */
service PlumbingService {

  rpc Call(RpcCallRequest) returns (stream RpcStreamFragment);

  rpc CallStdin(stream RpcCallStdinFragment) returns (stream RpcStreamFragment);

  rpc CatFile(RpcCatFileRequest) returns (stream RpcStreamFragment);

  rpc CatFileBatch(stream RpcCatFileStdinFragment) returns (stream RpcStreamFragment);

  rpc CatFileBatchCheck(stream RpcCatFileStdinFragment) returns (stream RpcStreamFragment);

  rpc DiffTree(RpcDiffTreeRequest) returns (stream RpcStreamFragment);

  rpc DiffTreeStdin(stream RpcDiffTreeStdinFragment) returns (stream RpcStreamFragment);

  rpc ForEachRef(RpcForEachRefRequest) returns (stream RpcStreamFragment);

  rpc LsTree(RpcLsTreeRequest) returns (stream RpcStreamFragment);

  rpc PackObjects(RpcPackObjectsRequest) returns (stream RpcStreamFragment) {
    option (method_marshaller) = MARSHALLER_ZERO_COPY;
  };

  rpc PackObjectsStdin(stream RpcPackObjectsStdinFragment) returns (stream RpcStreamFragment) {
    option (method_marshaller) = MARSHALLER_ZERO_COPY;
  };

  rpc RevList(RpcRevListRequest) returns (stream RpcStreamFragment);

  rpc RevListStdin(stream RpcRevListStdinFragment) returns (stream RpcStreamFragment);

  option (service_throttle) = RESOURCE_COMMAND;
}

/* An RPC service for running high-level "porcelain" Git operations. */
service PorcelainService {

  rpc Archive(RpcArchiveRequest) returns (stream RpcStreamFragment);

  rpc Blame(RpcBlameRequest) returns (stream RpcStreamFragment);

  rpc Diff(RpcDiffRequest) returns (stream RpcStreamFragment);

  rpc FormatPatch(RpcFormatPatchRequest) returns (stream RpcStreamFragment);

  rpc Log(RpcLogRequest) returns (stream RpcStreamFragment);

  rpc LogStdin(stream RpcLogStdinFragment) returns (stream RpcStreamFragment);

  option (service_throttle) = RESOURCE_COMMAND;
}

/* An RPC service for performing pull request operations. */
service PullRequestService {

  //Given a collection of pull request scope changes (rescopes), calculates how each of those scope changes affect the
  //corresponding pull request. Outcomes for each rescope can either be merged, updated or declined.
  rpc BatchRescope(RpcBatchRescopePullRequestRequest) returns (stream RpcBatchRescopePullRequestResponseFragment) {
    //Rescoping is not throttled because it's an important system task that should be allowed, even when the system
    //is under load
    option (method_throttle) = RESOURCE_NONE;
  }

  //Updates the pull request refs in the repository to be in sync with the provided pull request.
  rpc BatchUpdateRefs(RpcBatchUpdatePullRequestRefsRequest) returns (RpcBatchUpdatePullRequestRefsResponse){
    //Updating PR refs is not throttled because it's an important system task that should be allowed, even when the
    //system is under load
    option (method_throttle) = RESOURCE_NONE;
  }

  rpc Delete(RpcDeletePullRequestRequest) returns (RpcDeletePullRequestResponse) {
    //Deleting pull requests is not throttled
    option (method_throttle) = RESOURCE_NONE;
  };

  //Streams the files that were changed by the pull request. If the client wishes to have access to which
  //changed files are conflicted, it needs to call TryMerge separately for conflict details.
  rpc GetChanges(RpcGetPullRequestChangesRequest) returns (stream RpcGetPullRequestChangesResponseFragment);

  //Streams commits reachable from the pull request's from_ref that are not yet reachable from its to_ref.
  //These are the commits that will be included if the pull request is merged.
  rpc GetCommits(RpcGetPullRequestCommitsRequest) returns (stream RpcGetPullRequestCommitsResponseFragment);

  //Streams the diff for the pull request. Parsing the diff output is left up to the client, which receives
  //raw stdout and stderr from "git diff".
  rpc GetDiff(RpcGetPullRequestDiffRequest) returns (stream RpcStreamFragment);

  rpc GetEffectiveDiff(RpcGetPullRequestEffectiveDiffRequest) returns (RpcGetPullRequestEffectiveDiffResponse);

  rpc Merge(stream RpcMergePullRequestFragment) returns (stream RpcMergePullRequestResponseFragment);

  rpc TryMerge(RpcMergePullRequestRequest) returns (RpcTryPullRequestMergeResponse);

  rpc UpdateRefs(RpcUpdatePullRequestRefsRequest) returns (RpcUpdatePullRequestRefsResponse) {
    //Updating PR refs is not throttled because it's an important system task that should be allowed, even when the
    //system is under load
    option (method_throttle) = RESOURCE_NONE;
  }

  option (service_throttle) = RESOURCE_COMMAND;
}

/* An RPC service for handling git refs (branches and tags). Note that most of these RPCs require bi-directional
   streaming to support pre-receive and post-receive hooks */
service RefService {

  rpc CheckFormat(RpcCheckFormatRequest) returns (RpcCheckFormatResponse);

  rpc CreateBranch(RpcCreateBranchRequest) returns (RpcCreateBranchResponse);

  rpc CreateTag(RpcCreateTagRequest) returns (RpcCreateTagResponse);

  rpc DeleteBranch(RpcDeleteBranchRequest) returns (RpcDeleteBranchResponse);

  rpc DeleteTag(RpcDeleteTagRequest) returns (RpcDeleteTagResponse);

  rpc ResolveDefaultBranch(RpcResolveDefaultBranchRequest) returns (RpcResolveDefaultBranchResponse) {
    //Resolving the default branch is cheap enough to not need throttling
    option (method_throttle) = RESOURCE_NONE;
  }

  rpc ResolveAnnotatedTags(RpcResolveAnnotatedTagRequest) returns (stream RpcResolveAnnotatedTagResponseFragment);

  rpc ResolveRefs(RpcResolveRefsRequest) returns (RpcResolveRefsResponse);

  rpc UpdateRef(RpcUpdateRefRequest) returns (RpcUpdateRefResponse);

  rpc UpdateRefs(RpcUpdateRefsRequest) returns (RpcUpdateRefsResponse);

  option (service_throttle) = RESOURCE_COMMAND;
}

/* An RPC service for managing repositories, accessing their metadata and operations on the repository as a whole. */
service RepositoryService {

  rpc BulkVerifyRepositoryIntegrity(RpcBulkVerifyRepositoryIntegrityRequest) returns (RpcBulkVerifyRepositoryIntegrityResponse);

  rpc Create(RpcCreateRepositoryRequest) returns (RpcCreateRepositoryResponse);

  rpc Delete(RpcDeleteRepositoryRequest) returns (RpcDeleteRepositoryResponse);

  rpc Fetch(RpcFetchRequest) returns (stream RpcFetchResponseFragment) {
    option (method_marshaller) = MARSHALLER_ZERO_COPY;
    option (method_throttle) = RESOURCE_COMMAND;
  };

  rpc GetDefaultBranch(RpcGetDefaultBranchRequest) returns (RpcGetDefaultBranchResponse);

  rpc GetDetails(RpcGetRepositoryDetailsRequest) returns (RpcGetRepositoryDetailsResponse);

  rpc GetReplicaDetails(RpcGetRepositoryReplicaDetailsRequest) returns (RpcGetRepositoryReplicaDetailsResponse);

  //Streams all managed repositories matching the request. This RPC will never return non-managed repositories
  //(e.g. Bitbucket Server classic repositories).
  //@since 1.3
  rpc GetRepositories(RpcGetRepositoriesRequest) returns (stream RpcGetRepositoriesResponseFragment);

  rpc GetSize(RpcGetRepositorySizeRequest) returns (RpcGetRepositorySizeResponse);

  rpc IsEmpty(RpcIsRepositoryEmptyRequest) returns (RpcIsRepositoryEmptyResponse);

  rpc IsTranscodeEnabled(RpcIsTranscodeEnabledRequest) returns (RpcIsTranscodeEnabledResponse);

  rpc Push(RpcPushRequest) returns (stream RpcPushResponseFragment) {
    option (method_marshaller) = MARSHALLER_ZERO_COPY;
    option (method_throttle) = RESOURCE_COMMAND;
  }

  rpc Repair(stream RpcRepairSourceFragment) returns (stream RpcRepairTargetFragment) {
    option (method_marshaller) = MARSHALLER_ZERO_COPY;
  };

  rpc RepairMe(stream RpcRepairTargetFragment) returns (stream RpcRepairSourceFragment) {
    option (method_marshaller) = MARSHALLER_ZERO_COPY;
  };

  rpc ScheduleGarbageCollection(RpcScheduleGarbageCollectionRequest) returns (RpcScheduleGarbageCollectionResponse);

  rpc SetDefaultBranch(RpcSetDefaultBranchRequest) returns (RpcSetDefaultBranchResponse);

  rpc SetGarbageCollectionPaused(RpcSetGarbageCollectionPausedRequest) returns (RpcSetGarbageCollectionPausedResponse);

  rpc SetMetadata(RpcSetMetadataRequest) returns (RpcSetMetadataResponse);

  rpc SetTranscodeEnabled(RpcSetTranscodeEnabledRequest) returns (RpcSetTranscodeEnabledResponse);

  //@since 1.2
  rpc VerifyConsistency(RpcVerifyRepositoryConsistencyRequest) returns (RpcVerifyRepositoryConsistencyResponse);
}

/**
 * Responsible for coordination of writes between Mesh nodes. Should not be called by Mesh clients.
 */
service TransactionService {

  rpc ApplyTransactions(RpcApplyTransactionsRequest) returns (RpcApplyTransactionsResponse);

  rpc Transact(stream RpcTransactLeaderFragment) returns (stream RpcTransactFollowerFragment);

  //For a given repository, retrieves and compares the replica details from all replicas and determines which replica(s)
  //are at the latest version, and which are inconsistent. All online replicas will update their internal consistency
  //state as needed and trigger repairs if needed.
  //
  //@since 1.2
  rpc VerifyConsistency(stream RpcVerifyConsistencyLeaderFragment) returns (stream RpcVerifyConsistencyFollowerFragment);
}

service WorkTreeService {

  rpc Close(RpcCloseWorkTreeRequest) returns (RpcCloseWorkTreeResponse);

  rpc Create(RpcCreateWorkTreeRequest) returns (RpcCreateWorkTreeResponse) {
    option (method_throttle) = RESOURCE_COMMAND;
  };

  rpc Mkdir(RpcWorkTreeMkdirRequest) returns (RpcWorkTreeMkdirResponse);

  rpc Publish(stream RpcPublishWorkTreeFragment) returns (stream RpcPublishWorkTreeResponseFragment);

  rpc WriteFile(stream RpcWriteWorkTreeFileFragment) returns (RpcWriteWorkTreeFileResponse);
}

enum RpcMarshallerType {
  MARSHALLER_UNSPECIFIED = 0;
  MARSHALLER_DEFAULT = 1;
  MARSHALLER_ZERO_COPY = 2;
}

extend google.protobuf.MethodOptions {
  RpcMarshallerType method_marshaller = 7993;
  RpcThrottledResource method_throttle = 7991;
}

extend google.protobuf.ServiceOptions {
  RpcMarshallerType service_marshaller = 7994;
  RpcThrottledResource service_throttle = 7992;
}
