Switch to using context manager for cleanup
MODIFY
repo2docker/app.py
repo2docker/app.py
@@ -11,26 +11,25 @@ import json
import os
import time
import logging
-import uuid
-import shutil
import argparse
import tempfile
from pythonjsonlogger import jsonlogger
import escapism
-from traitlets.config import Application, LoggingConfigurable
-from traitlets import Type, Bool, Unicode, Dict, List, default, Tuple
+from traitlets.config import Application
+from traitlets import Unicode, List, default, Tuple
import docker
from docker.utils import kwargs_from_env
import subprocess
from .detectors import (
- BuildPack, PythonBuildPack, DockerBuildPack, LegacyBinderDockerBuildPack,
+ PythonBuildPack, DockerBuildPack, LegacyBinderDockerBuildPack,
CondaBuildPack, JuliaBuildPack, Python2BuildPack, BaseImage
)
from .utils import execute_cmd
+from .utils import maybe_cleanup
from . import __version__
@@ -54,12 +53,13 @@ class Repo2Docker(Application):
return logging.INFO
git_workdir = Unicode(
- tempfile.mkdtemp(prefix='repo2docker'),
+ None,
config=True,
help="""
Working directory to check out git repositories to.
- Should be somewhere ephemeral, such as /tmp
+ The default is to use the system's temporary directory. Should be
+ somewhere ephemeral, such as /tmp.
"""
)
@@ -248,7 +248,6 @@ class Repo2Docker(Application):
self.run_cmd = args.cmd
-
def push_image(self):
client = docker.APIClient(version='auto', **kwargs_from_env())
# Build a progress setup for each layer, and only emit per-layer info every 1.5s
@@ -315,8 +314,16 @@ class Repo2Docker(Application):
def start(self):
if self.repo_type == 'local':
checkout_path = self.repo
+ else:
+ if self.git_workdir is None:
+ checkout_path = tempfile.mkdtemp(prefix='repo2docker')
else:
checkout_path = self.git_workdir
+
+ # keep as much as possible in the context manager to make sure we
+ # cleanup if things go wrong
+ with maybe_cleanup(checkout_path, self.cleanup_checkout):
+ if self.repo_type == 'remote':
self.fetch(
self.repo,
self.ref,
@@ -332,23 +339,25 @@ class Repo2Docker(Application):
picked_buildpack = bp
break
- self.log.debug(picked_buildpack.render(), extra=dict(phase='building'))
+ self.log.debug(picked_buildpack.render(),
+ extra=dict(phase='building'))
if self.build:
- self.log.info('Using %s builder\n', bp.name, extra=dict(phase='building'))
+ self.log.info('Using %s builder\n', bp.name,
+ extra=dict(phase='building'))
for l in picked_buildpack.build(self.output_image_spec):
if 'stream' in l:
- self.log.info(l['stream'], extra=dict(phase='building'))
+ self.log.info(l['stream'],
+ extra=dict(phase='building'))
elif 'error' in l:
self.log.info(l['error'], extra=dict(phase='failure'))
sys.exit(1)
elif 'status' in l:
- self.log.info('Fetching base image...\r', extra=dict(phase='building'))
+ self.log.info('Fetching base image...\r',
+ extra=dict(phase='building'))
else:
- self.log.info(json.dumps(l), extra=dict(phase='building'))
-
- if self.cleanup_checkout:
- shutil.rmtree(checkout_path, ignore_errors=True)
+ self.log.info(json.dumps(l),
+ extra=dict(phase='building'))
if self.push:
self.push_image()

MODIFY
repo2docker/utils.py
repo2docker/utils.py
+from contextlib import contextmanager
from functools import partial
+import shutil
import subprocess
+
def execute_cmd(cmd, capture=False, **kwargs):
"""
Call given command, yielding output line by line if capture=True
@@ -41,3 +44,10 @@ def execute_cmd(cmd, capture=False, **kwargs):
ret = proc.wait()
if ret != 0:
raise subprocess.CalledProcessError(ret, cmd)
+
+
+@contextmanager
+def maybe_cleanup(path, cleanup=False):
+ yield
+ if cleanup:
+ shutil.rmtree(path, ignore_errors=True)

Switch to using context manager for cleanup