[WIP] base contentproviders commit
Very much a WIP, but some thougts on how we can support more
than just git.
ADD
repo2docker/contentproviders/__init__.py
repo2docker/contentproviders/__init__.py
ADD
repo2docker/contentproviders/base.py
+"""
+Base classes for repo2docker ContentProviders
+
+ContentProviders accept a `spec` of various kinds, and
+provide the contents from the spec to a given output directory.
+"""
+class ContentProviderException(Exception):
+ """Exception raised when a ContentProvider can not provide content
+ """
+ pass
+
+class ContentProvider:
+ kind = ""
+
+ def provide(self, spec, output_dir, yield_output=False):
+ """Provide the contents of given spec to output_dir
+
+ This is a generator, and so should be yielded from or iterated over.
+
+ Arguments:
+ spec -- Dict / String specification understood by this ContentProvider
+ output_dir {string} -- Path to output directory (must already exist)
+ yield_output {bool} -- If True, return output line by line. If not, output just goes to stdout.
+ """
+ raise NotImplementedError()
+

ADD
repo2docker/contentproviders/git.py
+import subprocess
+
+from .base import ContentProvider, ContentProviderException
+from ..utils import execute_cmd
+
+class GitContentProvider(ContentProvider):
+ """Provides contents of a git repository (optionally at a given ref)
+ """
+ kind = "git"
+
+ def provide(self, spec, output_dir, yield_output=False):
+ url = spec['url']
+ ref = spec.get('ref', None)
+ try:
+ for line in execute_cmd(['git', 'clone', url, output_dir],
+ capture=yield_output):
+ yield line
+ except subprocess.CalledProcessError as e:
+ raise ContentProviderException("Failed to clone repository!") from e
+
+ if ref:
+ try:
+ for line in execute_cmd(['git', 'reset', '--hard', ref],
+ cwd=output_dir,
+ capture=yield_output):
+ yield line
+ except subprocess.CalledProcessError:
+ raise ContentProviderException("Failed to checkout ref {}!".format(ref)) from e

ADD
tests/contentproviders/test_git.py
+from contextlib import contextmanager
+import shutil
+import os
+import subprocess
+from tempfile import TemporaryDirectory
+from repo2docker.contentproviders.git import GitContentProvider
+
+
+@contextmanager
+def git_repo():
+ """
+ Makes a dummy git repo in which user can perform git operations
+
+ Should be used as a contextmanager, it will delete directory when done
+ """
+
+ with TemporaryDirectory() as gitdir:
+ subprocess.check_call(['git', 'init'], cwd=gitdir)
+
+ yield gitdir
+
+def test_clone():
+ """Test simple git clone to a target dir
+ """
+ with git_repo() as upstream:
+ with open(os.path.join(upstream, 'test'), 'w') as f:
+ f.write("Hello")
+
+ subprocess.check_call(['git', 'add', 'test'], cwd=upstream)
+ subprocess.check_call(['git', 'commit', '-m', 'Test commit'], cwd=upstream)
+
+ with TemporaryDirectory() as clone_dir:
+ spec = {
+ 'url': upstream
+ }
+ for _ in GitContentProvider().provide(spec, clone_dir, False):
+ pass
+ assert os.path.exists(os.path.join(clone_dir, 'test'))

[WIP] base contentproviders commit

Very much a WIP, but some thougts on how we can support more
than just git.