1+ from __future__ import absolute_import
12from __future__ import unicode_literals
23
34import hashlib
45import os
56
7+ from pre_commit import five
68from pre_commit .languages import helpers
79from pre_commit .util import clean_path_on_failure
810from pre_commit .util import mkdirp
911from pre_commit .xargs import xargs
1012
1113
1214ENVIRONMENT_DIR = 'docker'
15+ PRE_COMMIT_LABEL = 'PRE_COMMIT'
1316
1417
1518def md5 (s ):
16- m = hashlib .md5 ()
17- m .update (s )
18- return m .hexdigest ()
19+ return five .to_text (hashlib .md5 (s ).hexdigest ())
1920
2021
2122def docker_tag (repo_cmd_runner ):
@@ -24,39 +25,62 @@ def docker_tag(repo_cmd_runner):
2425 ).lower ()
2526
2627
28+ def docker_is_running ():
29+ return xargs (('docker' ,), ['ps' ])[0 ] == 0
30+
31+
32+ def assert_docker_available ():
33+ assert docker_is_running (), (
34+ 'Docker is either not running or not configured in this environment'
35+ )
36+
37+
38+ def build_docker_image (repo_cmd_runner ):
39+ cmd = (
40+ 'docker' , 'build' , '--pull' ,
41+ '--tag' , docker_tag (repo_cmd_runner ),
42+ '--label' , PRE_COMMIT_LABEL ,
43+ '.'
44+ )
45+ helpers .run_setup_cmd (repo_cmd_runner , cmd )
46+
47+
2748def install_environment (
2849 repo_cmd_runner ,
2950 version = 'default' ,
3051 additional_dependencies = (),
3152):
32- assert repo_cmd_runner .exists ('Dockerfile' )
33- # I don't know of anybody trying to juggle multiple docker installations
34- # so this seems sufficient
53+ assert repo_cmd_runner .exists ('Dockerfile' ), (
54+ 'No Dockerfile was found in the hook repository'
55+ )
56+ assert version == 'default' , (
57+ 'Pre-commit does not support language_version for docker '
58+ )
59+ assert_docker_available ()
60+
3561 directory = helpers .environment_dir (ENVIRONMENT_DIR , 'default' )
3662 mkdirp (os .path .join (repo_cmd_runner .path (), directory ))
3763
38- cmd = (
39- 'docker' , 'build' , '--pull' ,
40- '--tag' , docker_tag (repo_cmd_runner ),
41- '.'
42- )
43-
4464 # Docker doesn't really have relevant disk environment, but pre-commit
4565 # still needs to cleanup it's state files on failure
4666 env_dir = repo_cmd_runner .path (directory )
4767 with clean_path_on_failure (env_dir ):
48- helpers . run_setup_cmd (repo_cmd_runner , cmd )
68+ build_docker_image (repo_cmd_runner )
4969
5070
5171def run_hook (repo_cmd_runner , hook , file_args ):
72+ assert_docker_available ()
73+ # Rebuild the docker image in case it has gone missing, as many people do
74+ # automated cleanup of docker images.
75+ build_docker_image (repo_cmd_runner )
76+ # the docker lib doesn't return stdout on non-zero exit codes,
77+ # so we run the container directly on the command line
5278 cmd = (
5379 'docker' , 'run' ,
54- '-t ' ,
80+ '--rm ' ,
5581 '-v' , '{}:/src' .format (os .getcwd ()),
5682 '--workdir' , '/src' ,
83+ '--entrypoint' , hook ['entry' ],
5784 docker_tag (repo_cmd_runner )
5885 )
59-
60- return xargs (
61- cmd + (hook ['entry' ],) + tuple (hook ['args' ]), file_args ,
62- )
86+ return xargs (cmd + tuple (hook ['args' ]), file_args )
0 commit comments