syntax = "proto3";

package gitaly;

import "google/protobuf/duration.proto";

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

// AccessCheckError is an error returned by GitLab's `/internal/allowed`
// endpoint.
message AccessCheckError {
  // error_message is the error message as returned by the endpoint.
  string error_message = 1;
  // protocol is the protocol used.
  string protocol = 2;
  // user_id 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 formatted, 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;
  // error_type 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 {
  // parent_revision is the revision checked against ChildRevision for whether it
  // is an ancestor of ChildRevision
  bytes parent_revision = 1;
  // child_revision 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 {
  // conflicting_files 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;
  // conflicting_commit_ids 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 {
  // reference_name 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 returned when a reference that ought to exist does not exist.
message ReferenceNotFoundError {
  // reference_name is the name of the reference that does not exist.
  bytes reference_name = 1;
}

// ReferenceStateMismatchError is an error returned when updating a reference fails because its pointing to a different
// object ID than expected.
message ReferenceStateMismatchError {
  // reference_name is the name of the reference that was failed to update.
  bytes reference_name = 1;
  // expected_object_id is the object ID that the reference was expected to point to but didn't.
  bytes expected_object_id = 2;
  // actual_object_id is the object ID that the reference actually pointed to at the time when it was tried to be
  // updated.
  bytes actual_object_id = 3;
}

// ReferenceUpdateError is an error returned when updating a reference has
// failed.
message ReferenceUpdateError {
  // reference_name is the name of the reference that failed to be updated.
  bytes reference_name = 1;
  // old_oid is the object ID the reference should have pointed to before the update.
  string old_oid = 2;
  // new_oid 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 {
  // error_message provides context into why a limit was enforced.
  string error_message = 1;
  // retry_after 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;
  // hook_type is the type of the hook.
  HookType hook_type = 3;
}

// PathError is an error returned when there is an issue with the path provided.
message PathError {
  // ErrorType is the type of error encountered.
  enum ErrorType {
    // ERROR_TYPE_UNSPECIFIED is the default error type and should never be set.
    ERROR_TYPE_UNSPECIFIED = 0;
    // ERROR_TYPE_EMPTY_PATH is the error type when the provided path is empty.
    ERROR_TYPE_EMPTY_PATH = 1;
    // ERROR_TYPE_RELATIVE_PATH_ESCAPES_REPOSITORY is the error type when there are
    // traversing components found in the path and it either escapes the repository or is not
    // supported by the RPC.
    ERROR_TYPE_RELATIVE_PATH_ESCAPES_REPOSITORY = 2;
    // ERROR_TYPE_ABSOLUTE_PATH is the error type when an absolute path is provided
    // while a relative path was expected.
    ERROR_TYPE_ABSOLUTE_PATH = 3;
    // ERROR_TYPE_LONG_PATH is the error type when the path is too long.
    ERROR_TYPE_LONG_PATH = 4;
  };

  // path is the file or directory path that triggered the error. The path may be
  // truncated due to size limits.
  bytes path = 1;
  // error_type is the type of path error that occurred.
  ErrorType error_type = 2;
}

// PathNotFoundError is an error returned when a given path cannot be found.
message PathNotFoundError {
  // path is the path that could not be found.
  bytes path = 1;
}

// AmbiguousReferenceError is an error returned when an reference is unknown.
message AmbiguousReferenceError {
  // reference is the reference passed to the git command.
  bytes reference = 1;
}
// BadObjectError is an error returned when git cannot find a valid object based on its id.
message BadObjectError {
  // bad_oid is the bad object id passed to the git command.
  bytes bad_oid = 1;
}

// InvalidRevisionRange is an error returned when the range given to the git log command is invalid.
message InvalidRevisionRange {
  // range is the commit range passed to git log command.
  bytes range = 1;
}

