syntax = "proto3";

package gitaly;

option go_package = "gitlab.com/gitlab-org/gitaly-proto/go/gitalypb";

import "shared.proto";

service OperationService {
  rpc UserCreateBranch(UserCreateBranchRequest) returns (UserCreateBranchResponse) {
    option (op_type) = {
      op: MUTATOR
      target_repository_field: "1"
    };
  }
  rpc UserUpdateBranch(UserUpdateBranchRequest) returns (UserUpdateBranchResponse) {
    option (op_type) = {
      op: MUTATOR
      target_repository_field: "1"
    };
  }
  rpc UserDeleteBranch(UserDeleteBranchRequest) returns (UserDeleteBranchResponse) {
    option (op_type) = {
      op: MUTATOR
      target_repository_field: "1"
    };
  }
  rpc UserCreateTag(UserCreateTagRequest) returns (UserCreateTagResponse) {
    option (op_type) = {
      op: MUTATOR
      target_repository_field: "1"
    };
  }
  rpc UserDeleteTag(UserDeleteTagRequest) returns (UserDeleteTagResponse) {
    option (op_type) = {
      op: MUTATOR
      target_repository_field: "1"
    };
  }
  rpc UserMergeToRef(UserMergeToRefRequest) returns (UserMergeToRefResponse) {
    option (op_type) = {
      op: MUTATOR
      target_repository_field: "1"
    };
  }
  rpc UserMergeBranch(stream UserMergeBranchRequest) returns (stream UserMergeBranchResponse) {
    option (op_type) = {
      op: MUTATOR
      target_repository_field: "1"
    };
  }
  rpc UserFFBranch(UserFFBranchRequest) returns (UserFFBranchResponse) {
    option (op_type) = {
      op: MUTATOR
      target_repository_field: "1"
    };
  }
  rpc UserCherryPick(UserCherryPickRequest) returns (UserCherryPickResponse) {
    option (op_type) = {
      op: MUTATOR
      target_repository_field: "1"
    };
  }
  rpc UserCommitFiles(stream UserCommitFilesRequest) returns (UserCommitFilesResponse) {
    option (op_type) = {
      op: MUTATOR
      target_repository_field: "1.1"
    };
  }
  rpc UserRebase(UserRebaseRequest) returns (UserRebaseResponse) {
    option deprecated = true;
    option (op_type) = {
      op: MUTATOR
      target_repository_field: "1"
    };
  }
  rpc UserRebaseConfirmable(stream UserRebaseConfirmableRequest) returns (stream UserRebaseConfirmableResponse) {
    option (op_type) = {
      op: MUTATOR
      target_repository_field: "1.1"
    };
  }
  rpc UserRevert(UserRevertRequest) returns (UserRevertResponse) {
    option (op_type) = {
      op: MUTATOR
      target_repository_field: "1"
    };
  }
  rpc UserSquash(UserSquashRequest) returns (UserSquashResponse) {
    option (op_type) = {
      op: MUTATOR
      target_repository_field: "1"
    };
  }
  rpc UserApplyPatch(stream UserApplyPatchRequest) returns (UserApplyPatchResponse) {
    option (op_type) = {
      op: MUTATOR
      target_repository_field: "1.1"
    };
  }
  rpc UserUpdateSubmodule(UserUpdateSubmoduleRequest) returns (UserUpdateSubmoduleResponse) {
    option (op_type) = {
      op: MUTATOR
      target_repository_field: "1"
    };
  }
}

message UserCreateBranchRequest {
  Repository repository = 1;
  bytes branch_name = 2;
  User user = 3;
  bytes start_point = 4;
}

message UserCreateBranchResponse {
  Branch branch = 1;
  // Error returned by the pre-receive hook. If no error was thrown,
  // it's the empty string ("")
  string pre_receive_error = 2;
}

message UserUpdateBranchRequest {
  Repository repository = 1;
  bytes branch_name = 2;
  User user = 3;
  bytes newrev = 4;
  bytes oldrev = 5;
}

message UserUpdateBranchResponse {
  string pre_receive_error = 1;
}

message UserDeleteBranchRequest {
  Repository repository = 1;
  bytes branch_name = 2;
  User user = 3;
}

message UserDeleteBranchResponse {
  string pre_receive_error = 1;
}

message UserDeleteTagRequest {
  Repository repository = 1;
  bytes tag_name = 2;
  User user = 3;
}

message UserDeleteTagResponse {
  string pre_receive_error = 1;
}

message UserCreateTagRequest {
  Repository repository = 1;
  bytes tag_name = 2;
  User user = 3;
  bytes target_revision = 4;
  bytes message = 5;
}

message UserCreateTagResponse {
  Tag tag = 1;
  bool exists = 2;
  string pre_receive_error = 3;
}

message UserMergeBranchRequest {
  // First message
  Repository repository = 1;
  User user = 2;
  string commit_id = 3;
  bytes branch = 4;
  bytes message = 5;

  // Second message
  // Tell the server to apply the merge to the branch
  bool apply = 6;
}

message UserMergeBranchResponse {
  // First message
  // The merge commit the branch will be updated to. The caller can still abort the merge.
  string commit_id = 1;

  reserved 2;
  // Second message
  // If set, the merge has been applied to the branch.
  OperationBranchUpdate branch_update = 3;
  string pre_receive_error = 4;
}

message UserMergeToRefRequest {
  // UserMergeRef creates a merge commit and updates target_ref to point to that
  // new commit. The first parent of the merge commit (the main line) is taken
  // from first_parent_ref. The second parent is specified by its commit ID in source_sha.
  // If target_ref already exists it will be overwritten.
  Repository repository = 1;
  User user = 2;
  string source_sha = 3;
  // branch is deprecated in favor of `first_parent_ref`.
  bytes branch = 4;
  bytes target_ref = 5;
  bytes message = 6;
  bytes first_parent_ref = 7;
}

message UserMergeToRefResponse {
  string commit_id = 1;
  string pre_receive_error = 2;
}

message OperationBranchUpdate {
  // If this string is non-empty the branch has been updated.
  string commit_id = 1;
  // Used for cache invalidation in GitLab
  bool repo_created = 2;
  // Used for cache invalidation in GitLab
  bool branch_created = 3;
}

message UserFFBranchRequest {
  Repository repository = 1;
  User user = 2;
  string commit_id = 3;
  bytes branch = 4;
}

message UserFFBranchResponse {
  OperationBranchUpdate branch_update = 1;
  string pre_receive_error = 2;
}

message UserCherryPickRequest {
  Repository repository = 1;
  User user = 2;
  GitCommit commit = 3;
  bytes branch_name = 4;
  bytes message = 5;
  bytes start_branch_name = 6;
  Repository start_repository = 7;
}

message UserCherryPickResponse {
  OperationBranchUpdate branch_update = 1;
  string create_tree_error = 2;
  string commit_error = 3;
  string pre_receive_error = 4;
}

message UserRevertRequest {
  Repository repository = 1;
  User user = 2;
  GitCommit commit = 3;
  bytes branch_name = 4;
  bytes message = 5;
  bytes start_branch_name = 6;
  Repository start_repository = 7;
}

message UserRevertResponse {
  OperationBranchUpdate branch_update = 1;
  string create_tree_error = 2;
  string commit_error = 3;
  string pre_receive_error = 4;
}

message UserCommitFilesActionHeader {
  enum ActionType {
    CREATE = 0;
    CREATE_DIR = 1;
    UPDATE = 2;
    MOVE = 3;
    DELETE = 4;
    CHMOD = 5;
  }
  ActionType action = 1;
  bytes file_path = 2;
  bytes previous_path = 3;
  bool base64_content = 4;
  bool execute_filemode = 5;
  // Move actions that change the file path, but not its content, should set
  // infer_content to true instead of populating the content field. Ignored for
  // other action types.
  bool infer_content = 6;
}

message UserCommitFilesAction {
  oneof user_commit_files_action_payload {
    UserCommitFilesActionHeader header = 1;
    bytes content = 2;
  }
}

message UserCommitFilesRequestHeader {
  Repository repository = 1;
  User user = 2;
  bytes branch_name = 3;
  bytes commit_message = 4;
  bytes commit_author_name = 5;
  bytes commit_author_email = 6;
  bytes start_branch_name = 7;
  Repository start_repository = 8;
  bool force = 9;
  string start_sha = 10;
}

message UserCommitFilesRequest {
  oneof user_commit_files_request_payload {
    // For each request stream there should be first a request with a header and
    // then n requests with actions
    UserCommitFilesRequestHeader header = 1;
    UserCommitFilesAction action = 2;
  }
}

message UserCommitFilesResponse {
  OperationBranchUpdate branch_update = 1;
  string index_error = 2;
  string pre_receive_error = 3;
}

// DEPRECATED: https://gitlab.com/gitlab-org/gitaly/issues/1628
message UserRebaseRequest {
  option deprecated = true;

  Repository repository = 1;
  User user = 2;
  string rebase_id = 3;
  bytes branch = 4;
  string branch_sha = 5;
  Repository remote_repository = 6;
  bytes remote_branch = 7;
}

// DEPRECATED: https://gitlab.com/gitlab-org/gitaly/issues/1628
message UserRebaseResponse {
  option deprecated = true;

  string rebase_sha = 1;
  string pre_receive_error = 2;
  string git_error = 3;
}

message UserRebaseConfirmableRequest {
  message Header {
    Repository repository = 1;
    User user = 2;
    string rebase_id = 3;
    bytes branch = 4;
    string branch_sha = 5;
    Repository remote_repository = 6;
    bytes remote_branch = 7;
  }

  oneof user_rebase_confirmable_request_payload {
    // For each request stream there must be first a request with a header
    // containing details about the rebase to perform.
    Header header = 1;
    // A second request must be made to confirm that the rebase should
    // be applied to the branch.
    bool apply = 2;
  }
}

message UserRebaseConfirmableResponse {
  oneof user_rebase_confirmable_response_payload {
    // The first response will contain the rebase commit the branch will
    // be updated to. The caller can still abort the rebase.
    string rebase_sha = 1;
    // The second response confirms that the rebase has been applied to
    // the branch.
    bool rebase_applied = 2;
  }
  string pre_receive_error = 3;
  string git_error = 4;
}

message UserSquashRequest {
  Repository repository = 1;
  User user = 2;
  string squash_id = 3;
  bytes branch = 4;
  string start_sha = 5;
  string end_sha = 6;
  User author = 7;
  bytes commit_message = 8;
}

message UserSquashResponse {
  string squash_sha = 1;
  // DEPRECATED: https://gitlab.com/gitlab-org/gitaly-proto/merge_requests/161
  reserved 2;
  reserved "pre_receive_error";
  string git_error = 3;
}

message UserApplyPatchRequest {
  message Header {
    Repository repository = 1;
    User user = 2;
    bytes target_branch = 3;
  }

  oneof user_apply_patch_request_payload {
    Header header = 1;
    bytes patches = 2;
  }
}

message UserApplyPatchResponse {
  OperationBranchUpdate branch_update = 1;
}

message UserUpdateSubmoduleRequest {
  Repository repository = 1;
  User user = 2;
  string commit_sha = 3;
  bytes branch = 4;
  bytes submodule = 5;
  bytes commit_message = 6;
}

message UserUpdateSubmoduleResponse {
  OperationBranchUpdate branch_update = 1;
  string pre_receive_error = 2;
  // DEPRECATED: https://gitlab.com/gitlab-org/gitaly-proto/merge_requests/237
  reserved 3;
  reserved "create_tree_error";
  string commit_error = 4;
}
