# requirements.py - objects and functions related to repository requirements
#
# Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.

from __future__ import annotations

import typing

if typing.TYPE_CHECKING:
    from typing import (
        Final,
    )
    from .interfaces.types import (
        RequirementSetT,
        RequirementT,
    )

# obsolete experimental requirements:
#  - manifestv2: An experimental new manifest format that allowed
#    for stem compression of long paths. Experiment ended up not
#    being successful (repository sizes went up due to worse delta
#    chains), and the code was deleted in 4.6.

GENERALDELTA_REQUIREMENT: Final[RequirementT] = b'generaldelta'
DOTENCODE_REQUIREMENT: Final[RequirementT] = b'dotencode'
PLAIN_ENCODE_REQUIREMENT: Final[
    RequirementT
] = b"exp-very-fragile-and-unsafe-plain-store-encoding"
STORE_REQUIREMENT: Final[RequirementT] = b'store'
FNCACHE_REQUIREMENT: Final[RequirementT] = b'fncache'
FILEINDEXV1_REQUIREMENT: Final[RequirementT] = b'fileindex-v1'

DIRSTATE_TRACKED_HINT_V1: Final[RequirementT] = b'dirstate-tracked-key-v1'
DIRSTATE_V2_REQUIREMENT: Final[RequirementT] = b'dirstate-v2'

# When narrowing is finalized and no longer subject to format changes,
# we should move this to just "narrow" or similar.
NARROW_REQUIREMENT: Final[RequirementT] = b'narrowhg-experimental'

# Enables sparse working directory usage
SPARSE_REQUIREMENT: Final[RequirementT] = b'exp-sparse'

# Some file revision might be stored in a `lfs` remote store. See the `lfs`
# extension for details.
LFS_REQUIREMENT: Final[RequirementT] = b'lfs'

# Enables the internal phase which is used to hide changesets instead
# of stripping them
INTERNAL_PHASE_REQUIREMENT: Final[RequirementT] = b'internal-phase-2'

# Enables the internal phase which is used to hide changesets instead
# of stripping them
ARCHIVED_PHASE_REQUIREMENT: Final[RequirementT] = b'exp-archived-phase'

# Stores manifest in Tree structure
TREEMANIFEST_REQUIREMENT: Final[RequirementT] = b'treemanifest'

REVLOGV1_REQUIREMENT: Final[RequirementT] = b'revlogv1'

# allow using ZSTD as compression engine for revlog content
REVLOG_COMPRESSION_ZSTD: Final[RequirementT] = b'revlog-compression-zstd'

# Increment the sub-version when the revlog v2 format changes to lock out old
# clients.
CHANGELOGV2_REQUIREMENT: Final[RequirementT] = b'exp-changelog-v2'

# Increment the sub-version when the revlog v2 format changes to lock out old
# clients.
REVLOGV2_REQUIREMENT: Final[RequirementT] = b'exp-revlogv2.2'

# A repository with the sparserevlog feature will have delta chains that
# can spread over a larger span. Sparse reading cuts these large spans into
# pieces, so that each piece isn't too big.
# Without the sparserevlog capability, reading from the repository could use
# huge amounts of memory, because the whole span would be read at once,
# including all the intermediate revisions that aren't pertinent for the chain.
# This is why once a repository has enabled sparse-read, it becomes required.
SPARSEREVLOG_REQUIREMENT: Final[RequirementT] = b'sparserevlog'

# revlogs holds information about their delta. Especially, snapshot are
# explicitly flag as such.
DELTA_INFO_REQUIREMENT: Final[RequirementT] = b'delta-info-revlog'

# A repository with the the copies-sidedata-changeset requirement will store
# copies related information in changeset's sidedata.
COPIESSDC_REQUIREMENT: Final[RequirementT] = b'exp-copies-sidedata-changeset'

# The repository use persistent nodemap for the changelog and the manifest.
NODEMAP_REQUIREMENT: Final[RequirementT] = b'persistent-nodemap'

# Denotes that the current repository is a share
SHARED_REQUIREMENT: Final[RequirementT] = b'shared'

# Denotes that current repository is a share and the shared source path is
# relative to the current repository root path
RELATIVE_SHARED_REQUIREMENT: Final[RequirementT] = b'relshared'

# A repository with share implemented safely. The repository has different
# store and working copy requirements i.e. both `.hg/requires` and
# `.hg/store/requires` are present.
SHARESAFE_REQUIREMENT: Final[RequirementT] = b'share-safe'

# Bookmarks must be stored in the `store` part of the repository and will be
# share accross shares
BOOKMARKS_IN_STORE_REQUIREMENT: Final[RequirementT] = b'bookmarksinstore'

# List of requirements which are working directory specific
# These requirements cannot be shared between repositories if they
# share the same store
# * sparse is a working directory specific functionality and hence working
#   directory specific requirement
# * SHARED_REQUIREMENT and RELATIVE_SHARED_REQUIREMENT are requirements which
#   represents that the current working copy/repository shares store of another
#   repo. Hence both of them should be stored in working copy
# * SHARESAFE_REQUIREMENT needs to be stored in working dir to mark that rest of
#   the requirements are stored in store's requires
# * DIRSTATE_V2_REQUIREMENT affects .hg/dirstate, of which there is one per
#   working directory.
WORKING_DIR_REQUIREMENTS: Final[RequirementSetT] = {
    SPARSE_REQUIREMENT,
    SHARED_REQUIREMENT,
    RELATIVE_SHARED_REQUIREMENT,
    SHARESAFE_REQUIREMENT,
    DIRSTATE_TRACKED_HINT_V1,
    DIRSTATE_V2_REQUIREMENT,
}

# List of requirement that do not impact "stream-clone" (and hardlink clone) and
# can be ignored in such case.
#
# requirements in this list can be safely altered during stream-clone.
STREAM_IGNORABLE_REQUIREMENTS: Final[
    RequirementSetT
] = WORKING_DIR_REQUIREMENTS | {
    DOTENCODE_REQUIREMENT,  # abstracted by the vfs layer
    PLAIN_ENCODE_REQUIREMENT,  # abstracted by the vfs layer
    FNCACHE_REQUIREMENT,  # abstracted by the vfs layer
    FILEINDEXV1_REQUIREMENT,  # abstracted by the vfs layer
    STORE_REQUIREMENT,  # abstracted by the vfs layer
    NODEMAP_REQUIREMENT,  # Have some special logic to handle that case
}
