syntax = "proto3";

package mesh.v1;

import "mesh/v1/git_model.proto";
import "mesh/v1/stream.proto";
import "mesh/v1/throttle.proto";

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

message RpcCgiEnvironment {
  string content_type = 1;
  optional int64 content_length = 2;
  string path_info = 3;
  string query_string = 4;
  string remote_addr = 5;
  string remote_user = 6;
  string request_method = 7;
  string server_protocol = 8;
  string server_software = 9;

  repeated string http_accept = 10;
  repeated string http_accept_encoding = 11;
  string http_content_encoding = 12;
  repeated string expect = 13;
}

enum RpcHostingOperationType {
  HOSTING_OP_UNSPECIFIED = 0;
  HOSTING_OP_ARCHIVE = 1;
  HOSTING_OP_CAPABILITIES = 2;
  HOSTING_OP_CLONE = 3;
  HOSTING_OP_FETCH = 4;
  HOSTING_OP_NEGOTIATION = 5;
  HOSTING_OP_REF_ADVERTISEMENT = 6;
  HOSTING_OP_SHALLOW_CLONE = 7;
  HOSTING_OP_SHALLOW_FETCH = 8;
  HOSTING_OP_PUSH = 9;
}

message RpcHostingPostReceiveRequest {
  repeated RpcRefUpdate ref_updates = 1;
  //For very large pushes, the request may be split into multiple fragments to not exceed the maximum message size.
  //Only the last fragment should have more_ref_updates set to false.
  bool more_ref_updates = 2;
}

message RpcHostingPostReceiveResponse {
  repeated RpcHookChunk output = 1;
}

message RpcHostingPreReceiveRequest {
  repeated RpcRefUpdate ref_updates = 1;
  //ID of the repository that contains the pending changes. This can be a different ID from the repository
  //that this hosting RPC is addressed to if a quarantine environment has been set up to stage the changes.
  string repository = 2;
  //For very large pushes, the request may be split into multiple fragments to not exceed the maximum message size.
  //Only the last fragment should have more_ref_updates set to false.
  bool more_ref_updates = 3;
}

message RpcHostingPreReceiveResponse {
  repeated RpcHookChunk output = 1;
  bool rejected = 2;
}

/* Similar to RpcStreamFragment but used for responses to read-only hosting requests
 * (has a RpcHostingStreamResult as the type of the result). */
message RpcHostingReadStreamFragment {
  oneof fragment_oneof {
    RpcStreamStart start = 1;
    RpcStreamChunk stdout = 2;
    RpcStreamChunk stderr = 3;
    RpcHostingStreamResult result = 4;
  }
}

message RpcHostingStreamResult {
  int32 exit_code = 1;

  RpcHostingOperationType operation_type = 2;
  RpcPackCacheResult cache_result = 3;
  optional string filter = 6;
  RpcHookResult hook_result = 4;
  optional uint32 protocol_version = 5;
}

/* Similar to RpcStreamFragment but used for responses to writing hosting requests
 * (has a RpcHostingStreamResult as the type of the result). */
message RpcHostingWriteStreamFragment {
  oneof fragment_oneof {
    RpcStreamStart start = 1;
    RpcStreamChunk stdout = 2;
    RpcStreamChunk stderr = 3;
    RpcHostingStreamResult result = 4;
    //Sent when the post-receive hook is triggered on the server
    RpcHostingPostReceiveRequest post_receive = 5;
    //Sent when the pre-receive hook is triggered on the server
    RpcHostingPreReceiveRequest pre_receive = 6;
  }
}

/* A fragment of a git http-backend request. The request is started when the
   HttpBackendRequest is received, which _must_ be the first fragment. After
   that, stdin is provided in chunks, with closed=true on the final one. */
message RpcHttpBackendFragment {
  oneof request_oneof {
    RpcHttpBackendRequest request = 1;
    RpcStreamChunk stdin = 2;
    RpcHostingPostReceiveResponse post_receive = 3;
    RpcHostingPreReceiveResponse pre_receive = 4;
  }
}

/* Request for git http-backend. */
message RpcHttpBackendRequest {
  string repository = 1;
  RpcGitOptions options = 2;
  RpcGitTimeouts timeouts = 3;

  RpcCgiEnvironment cgi_environment = 10;
  optional string protocol_header = 11;
}

enum RpcPackCacheResult {
  PACK_CACHE_NONE = 0;
  PACK_CACHE_HIT = 1;
  PACK_CACHE_MISS = 2;
  PACK_CACHE_BYPASS = 3;
}

/* Request for git receive-pack. receive-pack doesn't accept any command
   line parameters, so this only needs a repository, options and timeouts. */
message RpcReceivePackRequest {
  string repository = 1;
  RpcGitOptions options = 2;
  RpcGitTimeouts timeouts = 3;

  optional bool advertise_refs = 4;
  optional bool stateless_rpc = 5;
}

/* A fragment of a git receive-pack request. The request is started when the
   ReceivePackRequest is received, which _must_ be the first fragment. After
   that, stdin is provided in chunks, with closed=true on the final one. */
message RpcReceivePackFragment {
  oneof request_oneof {
    RpcReceivePackRequest request = 1;
    RpcHostingPostReceiveResponse post_receive = 3;
    RpcHostingPreReceiveResponse pre_receive = 4;
    RpcStreamChunk stdin = 2;
  }
}

/* A fragment of a git upload-archive request. The request is started when the
   UploadArchiveRequest is received, which _must_ be the first fragment. After
   that, stdin is provided in chunks, with closed=true on the final one. */
message RpcUploadArchiveFragment {
  oneof request_oneof {
    RpcUploadArchiveRequest request = 1;
    RpcStreamChunk stdin = 2;
  }
}

/* Request for git upload-archive. upload-archive doesn't accept any command
   line parameters, so this only needs a repository, options and timeouts. */
message RpcUploadArchiveRequest {
  string repository = 1;
  RpcGitOptions options = 2;
  RpcGitTimeouts timeouts = 3;
}

/* A fragment of a git upload-pack request. The request is started when the
   UploadPackRequest is received, which _must_ be the first fragment. After
   that, stdin is provided in chunks, with closed=true on the final one. */
message RpcUploadPackFragment {
  oneof request_oneof {
    RpcUploadPackRequest request = 1;
    RpcStreamChunk stdin = 2;
  }
}

/* Request for git upload-pack. */
message RpcUploadPackRequest {
  string repository = 1;
  RpcGitOptions options = 2;
  RpcGitTimeouts timeouts = 3;

  optional bool advertise_refs = 4;
  optional string protocol_env = 12;
  optional bool stateless_rpc = 5;
  optional bool strict = 6;
  //Hints which resource the operation should throttle against. Supported values are
  //PACK for normal clone and fetch operations and MIRROR_PACK when the upload-pack
  //operation is initiated by a mirror node. Any other value is ignored and results
  //in PACK throttling being applied.
  RpcThrottledResource throttled_resource = 11;
}
