|
|
# RhodeCode VCSServer provides access to different vcs backends via network.
|
|
|
# Copyright (C) 2014-2023 RhodeCode GmbH
|
|
|
#
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
|
# (at your option) any later version.
|
|
|
#
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
# GNU General Public License for more details.
|
|
|
#
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
# along with this program; if not, write to the Free Software Foundation,
|
|
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
|
|
"""
|
|
|
Adjustments to Mercurial
|
|
|
|
|
|
Intentionally kept separate from `hgcompat` and `hg`, so that these patches can
|
|
|
be applied without having to import the whole Mercurial machinery.
|
|
|
|
|
|
Imports are function local, so that just importing this module does not cause
|
|
|
side-effects other than these functions being defined.
|
|
|
"""
|
|
|
|
|
|
import logging
|
|
|
|
|
|
|
|
|
def patch_largefiles_capabilities():
|
|
|
"""
|
|
|
Patches the capabilities function in the largefiles extension.
|
|
|
"""
|
|
|
from vcsserver import hgcompat
|
|
|
lfproto = hgcompat.largefiles.proto
|
|
|
wrapper = _dynamic_capabilities_wrapper(
|
|
|
lfproto, hgcompat.extensions.extensions)
|
|
|
lfproto._capabilities = wrapper
|
|
|
|
|
|
|
|
|
def _dynamic_capabilities_wrapper(lfproto, extensions):
|
|
|
|
|
|
wrapped_capabilities = lfproto._capabilities
|
|
|
logger = logging.getLogger('vcsserver.hg')
|
|
|
|
|
|
def _dynamic_capabilities(orig, repo, proto):
|
|
|
"""
|
|
|
Adds dynamic behavior, so that the capability is only added if the
|
|
|
extension is enabled in the current ui object.
|
|
|
"""
|
|
|
if 'largefiles' in dict(extensions(repo.ui)):
|
|
|
logger.debug('Extension largefiles enabled')
|
|
|
calc_capabilities = wrapped_capabilities
|
|
|
return calc_capabilities(orig, repo, proto)
|
|
|
else:
|
|
|
logger.debug('Extension largefiles disabled')
|
|
|
return orig(repo, proto)
|
|
|
|
|
|
return _dynamic_capabilities
|
|
|
|
|
|
|
|
|
def patch_subrepo_type_mapping():
|
|
|
from collections import defaultdict
|
|
|
from .hgcompat import subrepo, subrepoutil
|
|
|
from vcsserver.exceptions import SubrepoMergeException
|
|
|
|
|
|
class NoOpSubrepo(subrepo.abstractsubrepo):
|
|
|
|
|
|
def __init__(self, ctx, path, *args, **kwargs):
|
|
|
"""Initialize abstractsubrepo part
|
|
|
|
|
|
``ctx`` is the context referring this subrepository in the
|
|
|
parent repository.
|
|
|
|
|
|
``path`` is the path to this subrepository as seen from
|
|
|
innermost repository.
|
|
|
"""
|
|
|
self.ui = ctx.repo().ui
|
|
|
self._ctx = ctx
|
|
|
self._path = path
|
|
|
|
|
|
def storeclean(self, path):
|
|
|
"""
|
|
|
returns true if the repository has not changed since it was last
|
|
|
cloned from or pushed to a given repository.
|
|
|
"""
|
|
|
return True
|
|
|
|
|
|
def dirty(self, ignoreupdate=False, missing=False):
|
|
|
"""returns true if the dirstate of the subrepo is dirty or does not
|
|
|
match current stored state. If ignoreupdate is true, only check
|
|
|
whether the subrepo has uncommitted changes in its dirstate.
|
|
|
"""
|
|
|
return False
|
|
|
|
|
|
def basestate(self):
|
|
|
"""current working directory base state, disregarding .hgsubstate
|
|
|
state and working directory modifications"""
|
|
|
substate = subrepoutil.state(self._ctx, self.ui)
|
|
|
file_system_path, rev, repotype = substate.get(self._path)
|
|
|
return rev
|
|
|
|
|
|
def remove(self):
|
|
|
"""remove the subrepo
|
|
|
|
|
|
(should verify the dirstate is not dirty first)
|
|
|
"""
|
|
|
pass
|
|
|
|
|
|
def get(self, state, overwrite=False):
|
|
|
"""run whatever commands are needed to put the subrepo into
|
|
|
this state
|
|
|
"""
|
|
|
pass
|
|
|
|
|
|
def merge(self, state):
|
|
|
"""merge currently-saved state with the new state."""
|
|
|
raise SubrepoMergeException()()
|
|
|
|
|
|
def push(self, opts):
|
|
|
"""perform whatever action is analogous to 'hg push'
|
|
|
|
|
|
This may be a no-op on some systems.
|
|
|
"""
|
|
|
pass
|
|
|
|
|
|
# Patch subrepo type mapping to always return our NoOpSubrepo class
|
|
|
# whenever a subrepo class is looked up.
|
|
|
subrepo.types = {
|
|
|
'hg': NoOpSubrepo,
|
|
|
'git': NoOpSubrepo,
|
|
|
'svn': NoOpSubrepo
|
|
|
}
|
|
|
|