syntax = "proto3";

package gitaly;

import "google/protobuf/duration.proto";

option go_package = "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v16/internal/gitaly/vendored/gitalypb";

// AccessCheckError is an error returned by GitLab's `/internal/allowed`
// endpoint.
message AccessCheckError {
  // ErrorMessage is the error message as returned by the endpoint.
  string error_message = 1;
  // Protocol is the protocol used.
  string protocol = 2;
  // UserId is the user ID as which changes had been pushed.
  string user_id = 3;
  // Changes is the set of changes which have failed the access check.
  bytes changes = 4;
}

// IndexError is an error returned when an operation fails to due a conflict with
// the repository index.
message IndexError {
  // ErrorType is the type of error encountered on the index operation.
  enum ErrorType {
    // ERROR_TYPE_UNSPECIFIED is the default error type and should never be set.
    ERROR_TYPE_UNSPECIFIED = 0;
    // ERROR_TYPE_EMPTY_PATH indicates an empty path was provided by the caller.
    ERROR_TYPE_EMPTY_PATH = 1;
    // ERROR_TYPE_INVALID_PATH indicates a path either contained '.git', or was
    // incorrectly formated, e.g. invalid://file/path.
    ERROR_TYPE_INVALID_PATH = 2;
    // ERROR_TYPE_DIRECTORY_EXISTS indicates the directory being created already exists.
    ERROR_TYPE_DIRECTORY_EXISTS = 3;
    // ERROR_TYPE_DIRECTORY_TRAVERSAL indicates the path contains a directory traversal
    // sequence.
    ERROR_TYPE_DIRECTORY_TRAVERSAL = 4;
    // ERROR_TYPE_FILE_EXISTS indicates the file being created already exists.
    ERROR_TYPE_FILE_EXISTS = 5;
    // ERROR_TYPE_FILE_NOT_FOUND indicates the file being updated does not exist.
    ERROR_TYPE_FILE_NOT_FOUND = 6;
  };

  // Path is the file or directory path that triggered the error.
  bytes path = 1;
  // ErrorType is the type of index error that occurred.
  ErrorType error_type = 2;
}

// InvalidRefFormatError is an error returned when refs have an invalid format.
message InvalidRefFormatError {
  // Refs are the offending refs with invalid formats.
  repeated bytes refs = 2;
}

// NotAncestorError is an error returned when parent_revision is not an ancestor
// of the child_revision.
message NotAncestorError {
  // ParentRevision is the revision checked against ChildRevision for whether it
  // is an ancestor of ChildRevision
  bytes parent_revision = 1;
  // ChildRevision is the revision checked against ParentRevision for whether
  // it is a descendent of ChildRevision.
  bytes child_revision = 2;
}

// ChangesAlreadyAppliedError is an error returned when the operation would
// have resulted in no changes because these changes have already been applied.
message ChangesAlreadyAppliedError {
}

// MergeConflictError is an error returned in the case when merging two commits
// fails due to a merge conflict.
message MergeConflictError {
  // ConflictingFiles is the set of files which have been conflicting. If this
  // field is empty, then there has still been a merge conflict, but it wasn't
  // able to determine which files have been conflicting.
  repeated bytes conflicting_files = 1;
  // ConflictingCommitIds is the set of commit IDs that caused the conflict. In the general case,
  // this should be set to two commit IDs.
  repeated string conflicting_commit_ids = 2;
}

// ReferencesLockedError is an error returned when an ref update fails because
// the references have already been locked by another process.
message ReferencesLockedError {
  // Refs are the references that could not be locked.
  repeated bytes refs = 1;
}

// ReferenceExistsError is an error returned when a reference that ought not to exist does exist
// already.
message ReferenceExistsError {
  // ReferenceName is the name of the reference that exists already.
  bytes reference_name = 1;
  // Oid is the object ID of the reference that preexists already.
  string oid = 2;
}

// ReferenceNotFoundError is an error retruned when a reference that ought to exist does not exist.
message ReferenceNotFoundError {
  // ReferenceName is the name of the reference that does not exist.
  bytes reference_name = 1;
}

// ReferenceUpdateError is an error returned when updating a reference has
// failed.
message ReferenceUpdateError {
  // ReferenceName is the name of the reference that failed to be updated.
  bytes reference_name = 1;
  // OldOid is the object ID the reference should have pointed to before the update.
  string old_oid = 2;
  // NewOid is the object ID the reference should have pointed to after the update.
  string new_oid = 3;
}

// ResolveRevisionError is an error returned when resolving a specific revision
// has failed.
message ResolveRevisionError {
  // Revision is the name of the revision that was tried to be resolved.
  bytes revision = 1;
}

// LimitError is an error returned when Gitaly enforces request limits.
message LimitError {
  // ErrorMessage provides context into why a limit was enforced.
  string error_message = 1;
  // RetryAfter provides the duration after which a retry is safe.
  // 0 indicates non-retryable.
  google.protobuf.Duration retry_after = 2;
}

// CustomHookError is an error returned when Gitaly executes a custom hook and the hook returns
// a non-zero return code.
message CustomHookError {
  // HookType is the type of the hook that has been running. Please consult githooks(5) for more
  // information about the specific types.
  enum HookType {
    // HOOK_TYPE_UNSPECIFIED is the default hook type and should never be set.
    HOOK_TYPE_UNSPECIFIED = 0;
    // HOOK_TYPE_PRERECEIVE is executed after all changes have been written into a temporary staging
    // directory, but before any references in the repository have been updated. It is executed with
    // all references that are about to be updated at once. If this hook exits, then no references
    // will have been updated in the repository and staged objects will have been discarded.
    HOOK_TYPE_PRERECEIVE = 1;
    // HOOK_TYPE_UPDATE is executed after the pre-receive hook. It is executed per reference that is
    // about to be updated and can be used to reject only a subset of reference updates. If this
    // hook error is raised then a subset of references may have already been updated.
    HOOK_TYPE_UPDATE = 2;
    // HOOK_TYPE_POSTRECEIVE is executed after objects have been migrated into the repository and
    // after references have been updated. An error in this hook will not impact the changes
    // anymore as everything has already been persisted.
    HOOK_TYPE_POSTRECEIVE = 3;
  };

  // Stdout is the standard output of the hook that has failed, if any. Data may be truncated.
  bytes stdout = 1;
  // Stderr is the standard error of the hook that has failed, if any. Data may be truncated.
  bytes stderr = 2;
  // HookType is the type of the hook.
  HookType hook_type = 3;
}
