30 lines
1.6 KiB
Python
30 lines
1.6 KiB
Python
"""Public metadata-only Git checkouts, without credentials or project hooks."""
|
|
import os
|
|
import subprocess
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
|
|
def checkout_metadata(url,destination,patterns,branch='master'):
|
|
destination=Path(destination)
|
|
destination.parent.mkdir(parents=True,exist_ok=True)
|
|
env=dict(os.environ,GIT_TERMINAL_PROMPT='0',GIT_LFS_SKIP_SMUDGE='1')
|
|
def git(*args):
|
|
result=subprocess.run(['git','-c','credential.helper=','-c','http.extraHeader=','-c','core.hooksPath=/dev/null','-c','core.deltaBaseCacheLimit=32m',*args],env=env,capture_output=True,text=True,timeout=900)
|
|
if result.returncode:
|
|
raise RuntimeError('Metadata checkout failed: '+result.stderr[-500:])
|
|
return result.stdout.strip()
|
|
if not destination.exists():
|
|
with tempfile.TemporaryDirectory(prefix='metadata-clone-',dir=destination.parent) as tmp:
|
|
stage=Path(tmp)/'repo'
|
|
git('clone','--filter=blob:none','--depth','1','--single-branch','--branch',branch,'--no-checkout',url,str(stage))
|
|
git('-C',str(stage),'sparse-checkout','set','--no-cone',*patterns)
|
|
git('-C',str(stage),'checkout',branch)
|
|
stage.rename(destination)
|
|
else:
|
|
if git('-C',str(destination),'status','--porcelain'):
|
|
raise RuntimeError('Metadata checkout has local changes; refusing to overwrite')
|
|
git('-C',str(destination),'fetch','--filter=blob:none','--depth','1','origin',branch)
|
|
git('-C',str(destination),'checkout','--detach','FETCH_HEAD')
|
|
return git('-C',str(destination),'rev-parse','HEAD')
|