1
0
mirror of https://github.com/chubin/cheat.sh.git synced 2026-06-20 21:26:44 +02:00
Files
cheat.sh/lib/adapter/git_adapter.py
T
2025-07-29 20:07:59 +02:00

169 lines
5.2 KiB
Python

"""
Implementation of `GitRepositoryAdapter`, adapter that is used to handle git repositories
"""
import glob
import os
from .adapter import Adapter # pylint: disable=relative-import
def _get_filenames(path):
return [os.path.split(topic)[1] for topic in glob.glob(path)]
class RepositoryAdapter(Adapter):
"""
Implements methods needed to handle standard
repository based adapters.
"""
def _get_list(self, prefix=None):
"""
List of files in the cheat sheets directory
with the extension removed
"""
answer = _get_filenames(
os.path.join(
self.local_repository_location(),
self._cheatsheet_files_prefix,
"*" + self._cheatsheet_files_extension,
)
)
ext = self._cheatsheet_files_extension
if ext:
answer = [
filename[: -len(ext)] for filename in answer if filename.endswith(ext)
]
return answer
def _get_page(self, topic, request_options=None):
filename = os.path.join(
self.local_repository_location(), self._cheatsheet_files_prefix, topic
)
if os.path.exists(filename) and not os.path.isdir(filename):
answer = self._format_page(open(filename, "r").read())
else:
# though it should not happen
answer = "%s:%s not found" % (str(self.__class__), topic)
return answer
class GitRepositoryAdapter(RepositoryAdapter): # pylint: disable=abstract-method
"""
Implements all methods needed to handle cache handling
for git-repository-based adapters
"""
@classmethod
def fetch_command(cls):
"""
Initial fetch of the repository.
Return cmdline that has to be executed to fetch the repository.
Skipping if `self._repository_url` is not specified
"""
if not cls._repository_url:
return None
if not cls._repository_url.startswith("https://github.com/"):
# in this case `fetch` has to be implemented
# in the distinct adapter subclass
raise RuntimeError(
"Do not known how to handle this repository: %s" % cls._repository_url
)
local_repository_dir = cls.local_repository_location()
if not local_repository_dir:
return None
return ["git", "clone", "--depth=1", cls._repository_url, local_repository_dir]
@classmethod
def update_command(cls):
"""
Update of the repository.
Return cmdline that has to be executed to update the repository
inside `local_repository_location()`.
"""
if not cls._repository_url:
return None
local_repository_dir = cls.local_repository_location()
if not local_repository_dir:
return None
if not cls._repository_url.startswith("https://github.com/"):
# in this case `update` has to be implemented
# in the distinct adapter subclass
raise RuntimeError(
"Do not known how to handle this repository: %s" % cls._repository_url
)
return ["git", "pull"]
@classmethod
def current_state_command(cls):
"""
Get current state of repository (current revision).
This is used to find what cache entries should be invalidated.
"""
if not cls._repository_url:
return None
local_repository_dir = cls.local_repository_location()
if not local_repository_dir:
return None
if not cls._repository_url.startswith("https://github.com/"):
# in this case `update` has to be implemented
# in the distinct adapter subclass
raise RuntimeError(
"Do not known how to handle this repository: %s" % cls._repository_url
)
return ["git", "rev-parse", "--short", "HEAD", "--"]
@classmethod
def save_state(cls, state):
"""
Save state `state` of the repository.
Must be called after the cache clean up.
"""
local_repository_dir = cls.local_repository_location()
state_filename = os.path.join(local_repository_dir, ".cached_revision")
open(state_filename, "wb").write(state)
@classmethod
def get_state(cls):
"""
Return the saved `state` of the repository.
If state cannot be read, return None
"""
local_repository_dir = cls.local_repository_location()
state_filename = os.path.join(local_repository_dir, ".cached_revision")
state = None
if os.path.exists(state_filename):
state = open(state_filename, "r").read()
return state
@classmethod
def get_updates_list_command(cls):
"""
Return list of updates since the last update whose id is saved as the repository state.
The list is used to invalidate the cache.
"""
current_state = cls.get_state()
if not current_state:
return ["git", "ls-tree", "--full-tree", "-r", "--name-only", "HEAD", "--"]
return ["git", "diff", "--name-only", current_state, "HEAD", "--"]