syntax = "proto3";

package mesh.v1;

import "mesh/v1/git_model.proto";
import "mesh/v1/git_plumbing.proto";

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

message RpcEditFileFragment {
  oneof request_oneof {
    RpcEditFileRequest request = 1;
    RpcFileContent content = 3;
    RpcUpdateRef update_ref = 2;
  }
}

message RpcEditFileRequest {
  string repository = 1;
  RpcGitTimeouts timeouts = 3;

  RpcPerson author = 4;
  RpcBranch branch = 6;
  RpcPerson committer = 5;
  bytes message = 8;
  bytes path = 7;
  bytes source_commitish = 9;
  bytes target_branch = 10;
}

message RpcEditFileResponse {
  RpcCommit commit = 1;
}

message RpcEditFileResponseFragment {
  oneof response_oneof {
    RpcEditFileResponse response = 1;
    RpcRunEditFileHooks run_hooks = 2;
  }
}

message RpcFileContent {
  bytes data = 1;
  bool closed = 2; //True if this will be the final chunk for this stream type
}

/* Requests a commit */
message RpcGetCommitRequest {
  string repository = 1;
  RpcGitTimeouts timeouts = 3;

  //The commit to retrieve, which may be specified by ID or ref name.
  bytes commitish = 10;
  //Optional value. When set, commit messages longer than the specified length are truncated. When set to 0, the commit
  //message is not returned. If omitted or set to a negative value, the entire commit message regardless of its length
  //is returned.
  optional int32 max_message_length = 11;
  //If a path is provided, the first ancestor of the commit with commitish that affects the path is returned.
  //Note that this may be a commit with an ID different from commitish.
  bytes path = 12;
}

/* Returns the commit for an RpcGetCommitRequest */
message RpcGetCommitResponse {
  RpcCommit commit = 1;
}

/* Requests to get a series of commits */
message RpcGetCommitsRequest {
  string repository = 1;
  RpcGitTimeouts timeouts = 2;

  //Include all refs
  bool all = 3;

  //Secondary repositories whose commits should be considered
  repeated string alternates = 4;

  //Include refs/heads/*
  bool branches = 5;

  //Commits which may be identified by branch or tag name or by hash, which should be excluded from the results.
  //Note: Branch and tag names are always resolved against the primary repository.
  repeated bytes excludes = 6;

  //Whether or not the commit history will attempt to follow renames. This is only applicable for individual file paths
  bool follow_renames = 7;

  //Whether or not to ignore missing commits
  bool ignore_missing = 8;

  //Commits which may be identified by branch or tag name or by hash, which should be included in the results.
  //When a commit is both included and excluded, it is excluded.
  //Note: Branch and tag names are always resolved against the primary repository.
  repeated bytes includes = 9;

  //Optional value. When set, commit messages longer than the specified length are truncated. When set to 0, the commit
  //message is not returned. If omitted or set to a negative value, the entire commit message regardless of its length
  //is returned.
  optional int32 max_message_length = 10;

  //The strategy to use for filtering merge commits.
  RpcRevListMerges merges = 11;

  //Sort order to use for the commits
  RpcRevListOrder order = 12;

  //Paths to filter results
  repeated bytes paths = 13;

  //Optional value. When set, it will only return commits which are more recent than the epoch seconds provided.
  optional int64 since = 19;

  //Include refs/tags/*
  bool tags = 15;

  RpcRevListWalk walk = 16;

  //Range hints for pagination
  int32 limit = 17;
  int32 skip = 18;
}

message RpcGetCommitsResponseFragment {
  repeated RpcCommit commits = 1;
  //Only provided if follow_renames was set to true and a single path was provided. Maps from commit IDs (always
  //as full hashes) to the detected rename.
  map<string, RpcChange> rename_changes = 2;
}

/* Requests the common ancestor for a set of commits. */
message RpcGetCommonAncestorRequest {
  string repository = 1;
  RpcGitTimeouts timeouts = 3;

  //Alternate repositories, to allow finding the common ancestor between commits in multiple repositories.
  repeated string alternates = 11;
  //A list of 2 or more commits to find the common ancestor for. Each commit may be specified by ID or ref name.
  //If the provided list only has one commit, that commit will be returned as the common ancestor. If the list
  //is empty, no common ancestor is returned (unless required is true, which triggers a NoMergeBase error)
  repeated bytes commitishes = 10;
  //Allows the caller to indicate whether a common ancestor is required, in which case a NoMergeBase error will
  //be triggered if there's no merge base. Otherwise, if no merge base exists, the response will be empty.
  bool required = 12;
}

/* Returns the common ancestor for a CommonAncestorRequest. */
message RpcGetCommonAncestorResponse {
  string commit_id = 1;
}

/* Describes an association between a given path and the last commit to modify that path. */
message RpcLastModified {
  RpcCommit commit = 1;
  bytes path = 2;
}

/* Requests a stream containing files within the directory specified by path, with the latest commit to modify each, as
   well as the latest commit to modify the directory overall. Since the latter takes modifications to subdirectories
   into consideration, it may be newer than the latest commit for any of the directory's own files. */
message RpcLastModifiedRequest {
  string repository = 1;
  RpcGitTimeouts timeouts = 3;

  //Identifies the _starting commit_ to use when determining the latest commit, both for the request directory and
  //for the files it contains.
  bytes commitish = 10;
  //Optional value. When set, commit messages longer than the specified length are truncated. When set to 0, the
  //commit message is not returned. If omitted or set to a negative value, the entire commit message is returned
  //regardless of its length
  optional int32 max_message_length = 11;
  //The path to the _directory_ to list files for. If the provided path is for a file, the request will fail.
  bytes path = 12;
}

/* Maps a set of files to the latest commit to modify each file. Note that Protobuf's map does not offer any sort of
   iteration ordering, so the file keys in the map are not in any particular order. */
message RpcLastModifiedResponse {
  //Protobuf maps don't support bytes for keys, so this has to use a list of entries instead.
  repeated RpcLastModified modifications = 1;
}

/* A fragment of the response for a last modified request. Each fragment will either contain a map of files to their
   latest commits, or the latest commit for the specific path requested. */
message RpcLastModifiedResponseFragment {
  oneof fragment_oneof {
    RpcLastModifiedResponse response = 1;
    RpcCommit latest_commit = 2;
  }
}

/* A fragment of a request for a merge. The response type will be a MergeResponseFragment.
   The merge_request is used to start the merge, for which the response will be run_merge_hooks (to indicate that the
   client can run pre-update hooks).
   The update_ref is used to send the result from the pre-update hooks, and to start the ref update.
   The response if successful will include the updated Branch. */
message RpcMergeFragment {
  oneof request_oneof {
    RpcMergeRequest merge_request = 1;
    RpcUpdateRef update_ref = 2;
  }
}

/* Requests to try a merge or perform a merge for the given parameters. */
message RpcMergeRequest {
  string repository = 1;
  RpcGitTimeouts timeouts = 3;

  //Determines whether merges between with unrelated refs are permitted. If false, which is the default, an error will
  //be returned if the commits being merged do not share a common ancestor.
  bool allow_unrelated = 22;
  RpcPerson author = 10;
  RpcPerson committer = 11;
  bytes from_branch = 12;
  string from_commit_id = 13;
  //Optional value. If not provided it is assumed the from_branch or from_commit_id is located in the same repository
  optional string from_repository = 14;
  int32 log = 15;
  int32 max_message_length = 16;
  bytes message = 17;
  RpcMergeStrategy strategy = 18;
  bytes target_ref = 19;
  bytes to_branch = 20;
  string to_commit_id = 21;
}

/* Returns the result of performing the MergeRequest. */
message RpcMergeResponse {
  oneof response_oneof {
    RpcBranch branch = 1;
    RpcMergeConflicts conflicts = 2;
  }
}

/* Returns the result of performing the MergeRequest. */
message RpcMergeResponseFragment {
  oneof response_oneof {
    RpcRunMergeHooks run_merge_hooks = 2;
    RpcMergeResponse merge_response = 3;
  }
}

/* Supported merge strategies. */
enum RpcMergeStrategy {
  MERGE_STRATEGY_UNSPECIFIED = 0;
  MERGE_STRATEGY_NO_FF = 1;
  MERGE_STRATEGY_FF = 2;
  MERGE_STRATEGY_FF_ONLY = 3;
  MERGE_STRATEGY_REBASE_FF_ONLY = 4;
  MERGE_STRATEGY_REBASE_NO_FF = 5;
  MERGE_STRATEGY_SQUASH = 6;
  MERGE_STRATEGY_SQUASH_FF_ONLY = 7;
}

/* A fragment of a request for a rebase. The response type will be a RebaseResponseFragment.
   The rebase_request is used to start the rebase, for which the response will be run_rebase_hooks (to indicate that the
   client can run pre-update hooks).
   The update_ref is used to send the result from the pre-update hooks, and to start the ref update.
   The response if successful will include the updated Branch. */
message RpcRebaseFragment {
  oneof request_oneof {
    RpcRebaseRequest rebase_request = 1;
    RpcUpdateRef update_ref = 2;
  }
}

/* Requests to try a rebase or perform a rebase for the given parameters. */
message RpcRebaseRequest {
  string repository = 1;
  RpcGitTimeouts timeouts = 3;

  //Indicates whether a rebase is allowed to produce no new commits (and reset the branch to the upstream commit)
  //in the case when all of the branch's commits are discarded, or whether it is required to produce at least one commit.
  bool allow_empty = 10;
  bytes branch = 11;
  string commit_id = 12;
  RpcPerson committer = 13;
  bytes upstream = 14;
  optional string upstream_repository = 15;
}

/* Returns the result of performing the RebaseRequest. */
message RpcRebaseResponse {
  RpcBranch branch = 1;
}

message RpcRebaseResponseFragment {
  oneof response_oneof {
    RpcRunRebaseHooks run_rebase_hooks = 1;
    RpcRebaseResponse rebase_response = 2;
  }
}

message RpcResolveCommitsRequest {
  string repository = 1;
  RpcGitTimeouts timeouts = 3;

  repeated bytes commitishes = 10;
}

message RpcResolveCommitsResponse {
  //Protobuf maps don't support bytes for keys, so this has to use a list of entries instead.
  repeated RpcResolvedCommit resolved_commits = 1;
}

/* Describes an association between a commit-ish value and the commit ID it was resolved to. */
message RpcResolvedCommit {
  bytes commitish = 1;
  string commit_id = 2;
}

/* A fragment of a request for a revert. The response type will be a RevertResponseFragment.
   The revert_request is used to start the revert, for which the response will be run_revert_hooks (to indicate that the
   client can run pre-update hooks).
   The update_ref is used to send the result from the pre-update hooks, and to start the ref update.
   The response if successful will include the updated Branch. */
//@since 1.5
message RpcRevertFragment {
  oneof request_oneof {
    RpcRevertRequest revert_request = 1;
    RpcUpdateRef update_ref = 2;
  }
}

/* Describes a request to perform revert operation on a repository */
//@since 1.5
message RpcRevertRequest {
  string repository = 1;
  string commit_id = 2;
  optional int32 merged_commit_parent_number = 3;
  RpcPerson committer = 4;
  RpcBranch branch = 5;
  optional string target_branch = 6;
  RpcGitTimeouts timeouts = 7;
}

/* Describes a response for revert operation on a repository */
//@since 1.5
message RpcRevertResponse {
  RpcBranch branch = 1;
}

/* Describes a response fragment for the revert operation */
//@since 1.5
message RpcRevertResponseFragment {
  oneof response_oneof {
    RpcRunRevertHooks run_revert_hooks = 1;
    RpcRevertResponse revert_response = 2;
  }
}


/* Requests to run edit file hooks. */
message RpcRunEditFileHooks {
  //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 work tree, sandbox or quarantine environment has been set up to
  //stage the changes.
  string repository = 1;
  string commit_id = 2;
}

/* Requests to run merge hooks for the given merge. */
message RpcRunMergeHooks {
  //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 work tree, sandbox or quarantine environment has been set up to
  //stage the changes.
  string repository = 1;

  RpcBranch from_ref = 10;
  string merge_commit = 11;
  RpcBranch to_ref = 12;
}

/* Requests to run rebase hooks for the given rebase. */
message RpcRunRebaseHooks {
  //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 work tree, sandbox or quarantine environment has been set up to
  //stage the changes.
  string repository = 1;

  RpcBranch branch = 10;
  string commit_id = 11;
}

/* Requests to run revert hooks. */
//@since 1.5
message RpcRunRevertHooks {
  //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 work tree, sandbox or quarantine environment has been set up to
  //stage the changes.
  string repository = 1;
  string commit_id = 2;
}

message RpcTraverseCommitsRequest {
  string repository = 1;
  RpcGitTimeouts timeouts = 2;

  //Secondary repositories whose commits should be considered
  repeated string alternates = 3;

  //Include all refs
  bool all = 10;

  //Include refs/heads/*
  bool branches = 11;

  //Commits which may be identified by branch or tag name or by hash, which should be excluded from the results.
  //Note: Branch and tag names are always resolved against the primary repository.
  repeated bytes excludes = 12;

  //Whether or not to ignore missing commits
  bool ignore_missing = 13;

  //Commits which may be identified by branch or tag name or by hash, which should be included in the results.
  //When a commit is both included and excluded, it is excluded.
  //Note: Branch and tag names are always resolved against the primary repository.
  repeated bytes includes = 14;

  //Sort order to use for the commits
  RpcRevListOrder order = 15;

  //Include refs/tags/*
  bool tags = 16;
}

message RpcTraverseCommitsResponseFragment {
  repeated RpcMinimalCommit commits = 1;
}

message RpcTryMergeResponse {
  RpcMergeConflicts conflicts = 1;
}

message RpcTryRebaseResponse {
}

/* Requests to update the ref. */
message RpcUpdateRef {
}
