syntax = "proto3";

package mesh.v1;

import "google/protobuf/timestamp.proto";
import "mesh/v1/git_model.proto";
import "mesh/v1/git_plumbing.proto";
import "mesh/v1/stream.proto";
import "mesh/v1/topology.proto";

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

message RpcListReflogsRequest {
  string repository = 1;
}

message RpcReflogsChunk {
  repeated RpcOsFile files = 1;
  bool more_responses = 2;
}

message RpcAnyRepository {
  oneof repository_oneof {
    string repository = 1;
    RpcRemoteRepository remote_repository = 2;
  }
}

/* Request to check if pull requests in a repository are in sync with Bitbucket */
message RpcBulkVerifyRepositoryIntegrityRequest {
  repeated RpcVerifyRepositoryRequest repository_requests = 1;
}

message RpcBulkVerifyRepositoryIntegrityResponse {
  repeated RpcRepositoryIntegrityIssue integrity_issues = 1;
}

  message RpcCreateRepositoryRequest {
  //The ID of the repository to create
  string repository = 1;
  RpcGitTimeouts timeouts = 5;

  //Optional field. If not provided, the system default will be used.
  optional bytes default_branch = 2;
  //Metadata stored in the repository config. This metadata should contain details such as the team, project and
  //slug that help a system administrator make the link between a repository on disk and the repository in database.
  map<string, string> metadata = 3;
  //Optional field. When set, the repository will be created as a fork of the origin repository and will be created
  //in the same partition on the same data store as the origin repository.
  optional string origin = 4;
}

message RpcCreateRepositoryResponse {
}

message RpcDeleteRepositoryRequest {
  string repository = 1;

  //Only required for Bitbucket Server repositories that are located in the shared home or additional data stores.
  //The hierarchy membership details are used to update the alternates on the forks, and to decide whether the
  //repository on disk can be safely deleted. Ignored for managed repositories.
  RpcHierarchyMembership hierarchy_membership = 2;
}

message RpcHierarchyMembership {
  //The repository's forks
  repeated string forks = 2;
  //Whether this repository is the only (remaining) fork of origin. Only provided if origin is also provided
  optional bool only_fork_of_origin = 5;
  //Whether the repository is the only (remaining) member of the hierarchy
  bool only_member = 3;
  //The repository's origin repository
  optional string origin = 4;
}

message RpcDeleteRepositoryResponse {
}

// Note that RpcFetchRequest does not support many of the git-fetch parameters that could also be provided directly
// through refspecs. Callers are expected to provide the refspec alternative. For instance, --tags can be replaced by
// the refs/tags/*:refs/tags/* refspec. Likewise, --force can be replaced by starting the relevant refspec(s) with
// a + sign. We're intentionally avoiding --tags because it interacts with --prune in subtle ways that can lead to
// unexpected results. By exclusively using refspecs to determine what to fetch, we aim to avoid these types of subtle
// errors.
message RpcFetchRequest {
  string repository = 1;
  RpcGitOptions options = 2;
  RpcGitTimeouts timeouts = 3;

  bool atomic = 14;
  //Disables "tag following", ensuring only explicitly-requested refs (potentially including tags) are updated.
  bool no_tags = 10;
  //Flag to remove all local refs matching one of the refspecs that do not exist in the source repository.
  bool prune = 11;
  repeated bytes refspecs = 12;
  //The repository to fetch from
  RpcAnyRepository source_repository = 13;
}

message RpcFetchResponseFragment {
  //List of ref IDs that failed to update for some reason, if any
  repeated bytes failed_ref_ids = 1;
  //List of ref updates, if any refs were updated
  repeated RpcRefUpdate ref_updates = 2;
}

message RpcGetDefaultBranchRequest {
  string repository = 1;
  RpcGitTimeouts timeouts = 2;
}

message RpcGetDefaultBranchResponse {
  bytes branch_id = 1;
}

message RpcListRefsRequest {
  string repository = 1;
}

//@since 1.3
message RpcGetRepositoriesRequest {
  //Partitions to filter results
  repeated string partitions = 1;

  //Range hints for pagination
  int32 limit = 2;
  int32 skip = 3;
}

//@since 1.3
message RpcGetRepositoriesResponseFragment {
  repeated RpcRepository repositories = 1;
}

message RpcGetRepositoryDetailsRequest {
  string repository = 1;
}

message RpcGetRepositoryDetailsResponse {
  bytes default_branch = 1;
  map<string, string> metadata = 2;
  bool transcode_enabled = 3;
}

message RpcGetRepositoryReplicaDetailsRequest {
  string repository = 1;
}

message RpcGetRepositoryReplicaDetailsResponse {
  RpcRepositoryReplicaDetails details = 1;
}

/* Request for determining the repository size. */
message RpcGetRepositorySizeRequest {
  string repository = 1;
  RpcGitTimeouts timeouts = 2;
}

/* Response for the repository size. */
message RpcGetRepositorySizeResponse {
  RpcRepositorySize size = 1;
  RpcRepositorySize shared_size = 2;
}

message RpcGetRepositoryStateRequest {
  string repository = 1;
  optional RpcRepairCapabilitiesAdvertisement capabilities = 2;
  //Flag that if set, triggers a recalculation from scratch of the hashes instead of returning a cached value
  bool no_cache = 3;
}

message RpcGetRepositoryStateResponse {
  optional string content_hash = 1;
  optional string last_transaction_id = 2;
  optional string metadata_hash = 3;
  RpcReplicaState state = 4;
  optional RpcRepairCapabilitiesAdvertisement capabilities = 5;
  uint64 version = 6;
}

/* Request for determining whether the repository is empty. */
message RpcIsRepositoryEmptyRequest {
  string repository = 1;
}

/* Response for whether the repository is empty. */
message RpcIsRepositoryEmptyResponse {
  bool empty = 1;
}

message RpcIsTranscodeEnabledRequest {
  string repository = 1;
}

message RpcIsTranscodeEnabledResponse {
  bool enabled = 1;
}

message RpcPrivateKeyCredentials {
  bytes private_key = 1;
  //Optional password for the private key
  bytes password = 2;
  bytes username = 3;
}

message RpcPushProgressFragment {
  repeated RpcProgressUpdate progress_updates = 1;
}

message RpcPushRequest {
  string repository = 1;
  RpcGitOptions options = 2;
  RpcGitTimeouts timeouts = 3;

  bool force = 11;
  bool prune = 12;
  repeated bytes refspecs = 13;
  RpcRemoteRepository target_repository = 14;
}

message RpcPushResponseFragment {
  oneof fragment_oneof {
    RpcPushProgressFragment progress_update = 1;
    RpcPushResultFragment result = 2;
  }
}

message RpcPushResultFragment {
  //List of ref IDs that failed to update for some reason, if any
  repeated bytes failed_ref_ids = 1;
  //List of ref updates, if any refs were updated
  repeated RpcRefUpdate ref_updates = 2;
}

message RpcRemoteRepository {
  //Optional. Should be provided if credentials are needed to access the remote repository
  oneof credentials_oneof {
    RpcUsernamePasswordCredentials username_password = 1;
    RpcPrivateKeyCredentials private_key = 2;
  }
  string url = 3;
}

message RpcRefsChunk {
  repeated RpcRef refs = 1;
  bool more_responses = 2;
}

message RpcGetReflogsRequest {
  string repository = 1;
  repeated bytes paths = 2;
}

message RpcReflogStart {
  bytes path = 1;
  bool not_found = 2;
}

message RpcRepairCapabilitiesAdvertisement {
  repeated string capabilities = 1;
}

message RpcRepairRequest {
  string repository = 1;
  optional string source_repository = 2;
}

message RpcRepairSourceFragment {
  oneof command_oneof {
    RpcRepairRequest repair_request = 1;
    RpcGetRepositoryStateResponse repository_state = 2;
    RpcGetRepositoryDetailsResponse repository_details = 3;
    RpcRefsChunk list_refs_chunk = 4;
    RpcReflogsChunk list_reflogs_chunk = 5;
    RpcReflogStart reflog_start = 6;
    RpcStreamChunk reflog_chunk = 7;
    RpcStreamChunk pack_chunk = 8;
  }
  //The logical timestamp of the repair source
  uint64 logical_timestamp = 10;
}

message RpcRepairSummary {
  google.protobuf.Timestamp timestamp = 1;
  RpcReplicaState source_state = 2;
  RpcReplicaState target_state = 3;
  uint64 version = 4;
}

message RpcRepairTargetFragment {
  oneof command_oneof {
    RpcGetRepositoryStateRequest get_repository_state = 2;
    RpcGetRepositoryDetailsRequest get_repository_details = 3;
    RpcListRefsRequest list_refs = 4;
    RpcListReflogsRequest list_reflogs = 5;
    RpcGetReflogsRequest get_reflogs = 6;
    RpcPackObjectsStdinFragment get_pack = 8;
    RpcRepairSummary summary = 9;
  }
  //The logical timestamp of the repair target
  uint64 logical_timestamp = 10;
}

//@since 1.3
message RpcRepository {
  string id = 1;
  optional uint64 version = 2;
}

//@since 1.2
message RpcRepositoryConsistencySummary {
  //The content hash that the repository should have.
  string content_hash = 1;
  //List of replica IDs that are consistent.
  repeated string consistent_replicas = 2;
  //List of replica IDs that are not at the expected version or hashes and are considered to be inconsistent.
  repeated string inconsistent_replicas = 3;
  //List of replica IDs that could not be checked because they are offline or otherwise unavailable.
  repeated string unavailable_replicas = 4;
  //The version of the repository.
  uint64 version = 5;
}

message RpcRepositoryIntegrityIssue {
  RepositoryIntegrityIssueType issue_type = 1;
  string repository = 2;
  repeated uint64 pull_request_ids = 3;
  //@since 1.1
  RpcRepositoryConsistencySummary repository_consistency_summary = 4;
}

enum RepositoryIntegrityIssueType {
  INTEGRITY_ISSUE_UNSPECIFIED = 0;
  INTEGRITY_ISSUE_MISSING_PRS = 1;
  INTEGRITY_ISSUE_EXTRA_PRS = 2;
}

message RpcRepositoryReplicaDetails {
  optional string content_hash = 1;
  optional string metadata_hash = 2;
  //The version replica_state refers to (e.g. INCONSISTENT with version x)
  optional uint64 observed_version = 3;
  RpcReplicaState replica_state = 4;
  //The version the replica is currently at (which may be lower than observed_version)
  optional uint64 version = 5;
}

message RpcRepositorySize {
  uint64 garbage_size = 1;
  uint64 in_pack_size = 2;
  uint64 loose_size = 3;
}

/* Request to schedule garbage collection with the given parameters. */
message RpcScheduleGarbageCollectionRequest {
  string repository = 1;

  //Indicates that only stale packs should be gc-d
  bool stale_only = 10;
  //Number of refs that have been added, useful hint for GC
  int32 added = 11;
  //Number of refs that have been deleted, useful hint for GC
  int32 deleted = 12;
  //Number of refs that have been updated, useful hint for GC
  int32 updated = 13;
}

/* Response for the garbage collection request. */
message RpcScheduleGarbageCollectionResponse {
}

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

  bytes branch_id = 10;
}

message RpcSetDefaultBranchResponse {
}

message RpcSetGarbageCollectionPausedRequest {
  string repository = 1;
  bool paused = 2;
  //Timeout to acquire garbage collection lock in seconds
  uint64 timeout = 3;
}

message RpcSetGarbageCollectionPausedResponse {
  bool result = 1;
}

message RpcSetMetadataRequest {
  string repository = 1;

  map<string, string> metadata = 10;
}

message RpcSetMetadataResponse {
}

message RpcSetTranscodeEnabledRequest {
  string repository = 1;
  bool enabled = 2;
}

message RpcSetTranscodeEnabledResponse {
}

message RpcUsernamePasswordCredentials {
  bytes password = 1;
  bytes username = 2;
}

message RpcVerifyRepositoryRequest {
  string repository = 1;
  //latest pull request id in this repository according to Bitbucket
  uint64 latest_pull_request_id = 2;
}

//@since 1.2
message RpcVerifyRepositoryConsistencyRequest {
  string repository = 1;
}

//@since 1.2
message RpcVerifyRepositoryConsistencyResponse {
  RpcRepositoryConsistencySummary summary = 1;
}
