repo2docker/repo2docker/contentproviders/git.py

67 wiersze
2.5 KiB
Python
Czysty Zwykły widok Historia

import subprocess
2018-02-18 12:41:22 +00:00
import sys
from .base import ContentProvider, ContentProviderException
2018-02-18 12:41:22 +00:00
from ..utils import execute_cmd, check_ref
2018-02-18 12:41:22 +00:00
class Git(ContentProvider):
"""Provide contents of a remote git repository."""
def detect(self, source, ref=None, extra_args=None):
# Git is our content provider of last resort. This is to maintain the
# old behaviour when git and local directories were the only supported
# content providers. This means that this content provider will always
# match. The downside is that the call to `fetch()` later on might fail
return {"repo": source, "ref": ref}
2018-02-18 12:41:22 +00:00
def fetch(self, spec, output_dir, yield_output=False):
repo = spec["repo"]
ref = spec.get("ref", None)
2018-02-18 12:41:22 +00:00
# make a, possibly shallow, clone of the remote repository
try:
cmd = ["git", "clone", "--recursive"]
2018-02-18 12:41:22 +00:00
if ref is None:
cmd.extend(["--depth", "1"])
2018-02-18 12:41:22 +00:00
cmd.extend([repo, output_dir])
for line in execute_cmd(cmd, capture=yield_output):
yield line
2018-02-18 12:41:22 +00:00
except subprocess.CalledProcessError as e:
2018-02-18 12:41:22 +00:00
msg = "Failed to clone repository from {repo}.".format(repo=repo)
raise ContentProviderException(msg) from e
# check out the specific ref given by the user
if ref is not None:
hash = check_ref(ref, output_dir)
if hash is None:
self.log.error(
"Failed to check out ref %s", ref, extra=dict(phase="failed")
)
raise ValueError("Failed to check out ref {}".format(ref))
2018-02-18 12:41:22 +00:00
# If the hash is resolved above, we should be able to reset to it
for line in execute_cmd(
["git", "reset", "--hard", hash], cwd=output_dir, capture=yield_output
):
2018-02-18 12:41:22 +00:00
yield line
# ensure that git submodules are initialised and updated
for line in execute_cmd(
["git", "submodule", "update", "--init", "--recursive"],
cwd=output_dir,
capture=yield_output,
):
yield line
cmd = ["git", "rev-parse", "HEAD"]
sha1 = subprocess.Popen(cmd, stdout=subprocess.PIPE, cwd=output_dir)
self._sha1 = sha1.stdout.read().decode().strip()
@property
def content_id(self):
"""A unique ID to represent the version of the content.
Uses the first seven characters of the git commit ID of the repository.
"""
return self._sha1[:7]