Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def read_version():
'pyyaml~=6.0',
'rich>=14',
'requests==2.31.0', # Docker SDK breaks on 2.32.0
'filelock==3.29.7',
'repo_library @ git+https://github.com/rdkcentral/sc-repo-library.git@master',
'git_flow_library @ git+https://github.com/rdkcentral/sc-git-flow-library.git@master',
'sc_manifest_parser @ git+https://github.com/rdkcentral/sc-manifest-parser.git@main'
Expand Down
41 changes: 39 additions & 2 deletions src/sc/clone/cloners/repo_cloner.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
import shutil
import subprocess
import sys
import time

from filelock import FileLock, Timeout
from pydantic import BaseModel

from .cloner import Cloner, RefType
Expand All @@ -29,6 +31,8 @@
logger = logging.getLogger(__name__)

REPO_CACHE_DIR = Path.home() / ".caches"
CACHE_LOCK_PATH = REPO_CACHE_DIR / ".lock"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be better to call the lock .sc_lock. I doubt we'll ever re-use the cache in the future, but alwaty nicer to know where the lock came from.

CACHE_MAX_WAIT = 600

class RepoClonerConfig(BaseModel):
"""
Expand Down Expand Up @@ -74,8 +78,42 @@ def clone(self, directory: Path):
- Parses the manifest to retrieve projects.
- Initializes GitFlow for all unlocked projects.
"""
reference = self._cache() if self.config.cache else None
if self.config.cache:
self._clone_with_cache(directory)
else:
self._clone(directory)

def _clone_with_cache(self, directory: Path):
REPO_CACHE_DIR.mkdir(exist_ok=True)

started = time.monotonic()
lock = FileLock(CACHE_LOCK_PATH)

logger.info("Acquiring cache lock.")
while True:
try:
lock.acquire(timeout=20)
break
except Timeout:
waited = int(time.monotonic() - started)
if waited < CACHE_MAX_WAIT:
logger.info(
f"Cache is in use by another process, waited {waited} seconds..."
)
Comment thread
BenjiMilan marked this conversation as resolved.
else:
logger.error(
f"Cache remained locked past the set wait time of {CACHE_MAX_WAIT} seconds."
)
sys.exit(1)
Comment on lines +89 to +107

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure old SC would clear the lock if you reached the 5 min timeout. We should probably do that. Also does this library handle the lock if it was there since before the start of the sc process, like when a clone gets killed halfway through and the lock is never cleared. Then the user tries to clone again?

logger.info("Cache lock acquired.")

try:
reference = self._cache()
self._clone(directory, reference)
finally:
lock.release()

def _clone(self, directory: Path, reference: Path | None = None):
self._init_repo(directory=directory, reference=reference)
RepoLibrary.sync(
directory,
Expand All @@ -95,7 +133,6 @@ def _cache(self) -> Path:
Returns:
Path: The directory of the mirrored cache.
"""
REPO_CACHE_DIR.mkdir(exist_ok=True)
manifest_hostname = self._get_manifest_hostname(self.config.uri)
host_cache_dir = Path(REPO_CACHE_DIR / manifest_hostname)
host_cache_dir.mkdir(exist_ok=True)
Expand Down