def in_merge_conflict(tempdir_factory): path = make_consuming_repo(tempdir_factory, "script_hooks_repo") with cwd(path): cmd_output("touch", "dummy") cmd_output("git", "add", "dummy") cmd_output("git", "add", C.CONFIG_FILE) cmd_output("git", "commit", "-m", "Add config.") conflict_path = tempdir_factory.get() cmd_output("git", "clone", path, conflict_path) with cwd(conflict_path): cmd_output("git", "checkout", "origin/master", "-b", "foo") with io.open("conflict_file", "w") as conflict_file: conflict_file.write("herp\nderp\n") cmd_output("git", "add", "conflict_file") with io.open("foo_only_file", "w") as foo_only_file: foo_only_file.write("foo") cmd_output("git", "add", "foo_only_file") cmd_output("git", "commit", "-m", "conflict_file") cmd_output("git", "checkout", "origin/master", "-b", "bar") with io.open("conflict_file", "w") as conflict_file: conflict_file.write("harp\nddrp\n") cmd_output("git", "add", "conflict_file") with io.open("bar_only_file", "w") as bar_only_file: bar_only_file.write("bar") cmd_output("git", "add", "bar_only_file") cmd_output("git", "commit", "-m", "conflict_file") cmd_output("git", "merge", "foo", retcode=None) yield os.path.join(conflict_path)
def in_merge_conflict(tmpdir_factory): path = make_consuming_repo(tmpdir_factory, 'script_hooks_repo') with cwd(path): cmd_output('touch', 'dummy') cmd_output('git', 'add', 'dummy') cmd_output('git', 'add', C.CONFIG_FILE) cmd_output('git', 'commit', '-m', 'Add config.') conflict_path = tmpdir_factory.get() cmd_output('git', 'clone', path, conflict_path) with cwd(conflict_path): cmd_output('git', 'checkout', 'origin/master', '-b', 'foo') with io.open('conflict_file', 'w') as conflict_file: conflict_file.write('herp\nderp\n') cmd_output('git', 'add', 'conflict_file') with io.open('foo_only_file', 'w') as foo_only_file: foo_only_file.write('foo') cmd_output('git', 'add', 'foo_only_file') cmd_output('git', 'commit', '-m', 'conflict_file') cmd_output('git', 'checkout', 'origin/master', '-b', 'bar') with io.open('conflict_file', 'w') as conflict_file: conflict_file.write('harp\nddrp\n') cmd_output('git', 'add', 'conflict_file') with io.open('bar_only_file', 'w') as bar_only_file: bar_only_file.write('bar') cmd_output('git', 'add', 'bar_only_file') cmd_output('git', 'commit', '-m', 'conflict_file') cmd_output('git', 'merge', 'foo', retcode=None) yield os.path.join(conflict_path)
def in_conflicting_submodule(tempdir_factory): git_dir_1 = git_dir(tempdir_factory) git_dir_2 = git_dir(tempdir_factory) with cwd(git_dir_2): cmd_output('git', 'commit', '--allow-empty', '-m', 'init!') with cwd(git_dir_1): cmd_output('git', 'submodule', 'add', git_dir_2, 'sub') with cwd(os.path.join(git_dir_1, 'sub')): _make_conflict() yield
def in_merge_conflict(tempdir_factory): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): cmd_output('touch', 'dummy') cmd_output('git', 'add', 'dummy') cmd_output('git', 'commit', '-m', 'Add config.') conflict_path = tempdir_factory.get() cmd_output('git', 'clone', path, conflict_path) with cwd(conflict_path): _make_conflict() yield os.path.join(conflict_path)
def test_install_in_submodule_and_run(tempdir_factory): src_path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') parent_path = git_dir(tempdir_factory) with cwd(parent_path): cmd_output('git', 'submodule', 'add', src_path, 'sub') cmd_output('git', 'commit', '-m', 'foo') sub_pth = os.path.join(parent_path, 'sub') with cwd(sub_pth): assert install(Runner(sub_pth)) == 0 ret, output = _get_commit_output(tempdir_factory) assert ret == 0 assert NORMAL_PRE_COMMIT_RUN.match(output)
def test_hook_that_modifies_but_returns_zero( tempdir_factory, mock_out_store_directory, ): git_path = make_consuming_repo( tempdir_factory, 'modified_file_returns_zero_repo', ) with cwd(git_path): stage_a_file('bar.py') _test_run( git_path, {}, ( # The first should fail b'Failed', # With a modified file (default message + the hook's output) b'Files were modified by this hook. Additional output:\n\n' b'Modified: foo.py', # The next hook should pass despite the first modifying b'Passed', # The next hook should fail b'Failed', # bar.py was modified, but provides no additional output b'Files were modified by this hook.\n', ), 1, True, )
def test_lots_of_files(mock_out_store_directory, tempdir_factory): # windows xargs seems to have a bug, here's a regression test for # our workaround git_path = make_consuming_repo(tempdir_factory, 'python_hooks_repo') with cwd(git_path): # Override files so we run against them with modify_config() as config: config[0]['hooks'][0]['files'] = '' # Write a crap ton of files for i in range(400): filename = '{0}{1}'.format('a' * 100, i) open(filename, 'w').close() cmd_output('bash', '-c', 'git add .') install(Runner(git_path)) # Don't want to write to home directory env = dict(os.environ, PRE_COMMIT_HOME=tempdir_factory.get()) cmd_output( 'git', 'commit', '-m', 'Commit!', # git commit puts pre-commit to stderr stderr=subprocess.STDOUT, env=env, )
def test_environment_not_sourced(tmpdir_factory): path = make_consuming_repo(tmpdir_factory, 'script_hooks_repo') with cwd(path): # Patch the executable to simulate rming virtualenv with mock.patch.object(sys, 'executable', '/bin/false'): assert install(Runner(path)) == 0 # Use a specific homedir to ignore --user installs homedir = tmpdir_factory.get() # Need this so we can call git commit without sploding with io.open(os.path.join(homedir, '.gitconfig'), 'w') as gitconfig: gitconfig.write( '[user]\n' ' name = Travis CI\n' ' email = [email protected]\n' ) ret, stdout, stderr = cmd_output( 'git', 'commit', '--allow-empty', '-m', 'foo', env={'HOME': homedir}, retcode=None, ) assert ret == 1 assert stdout == '' assert stderr == ( '`pre-commit` not found. ' 'Did you forget to activate your virtualenv?\n' )
def clone_strategy(directory): cmd_output( 'git', 'clone', '--no-checkout', repo, directory, env=no_git_env(), ) with cwd(directory): cmd_output('git', 'reset', ref, '--hard', env=no_git_env())
def img_staged(tempdir_factory): path = git_dir(tempdir_factory) with cwd(path): img_filename = os.path.join(path, 'img.jpg') shutil.copy(get_resource_path('img1.jpg'), img_filename) cmd_output('git', 'add', 'img.jpg') yield auto_namedtuple(path=path, img_filename=img_filename)
def test_make_archive(tmpdir_factory): output_dir = tmpdir_factory.get() git_path = git_dir(tmpdir_factory) # Add a files to the git directory with cwd(git_path): cmd_output('touch', 'foo') cmd_output('git', 'add', '.') cmd_output('git', 'commit', '-m', 'foo') # We'll use this sha head_sha = get_head_sha('.') # And check that this file doesn't exist cmd_output('touch', 'bar') cmd_output('git', 'add', '.') cmd_output('git', 'commit', '-m', 'bar') # Do the thing archive_path = make_archives.make_archive( 'foo', git_path, head_sha, output_dir, ) assert archive_path == os.path.join(output_dir, 'foo.tar.gz') assert os.path.exists(archive_path) extract_dir = tmpdir_factory.get() # Extract the tar with tarfile_open(archive_path) as tf: tf.extractall(extract_dir) # Verify the contents of the tar assert os.path.exists(os.path.join(extract_dir, 'foo')) assert os.path.exists(os.path.join(extract_dir, 'foo', 'foo')) assert not os.path.exists(os.path.join(extract_dir, 'foo', '.git')) assert not os.path.exists(os.path.join(extract_dir, 'foo', 'bar'))
def clone(self, url, sha): """Clone the given url and checkout the specific sha.""" self.require_created() # Check if we already exist with sqlite3.connect(self.db_path) as db: result = db.execute( 'SELECT path FROM repos WHERE repo = ? AND ref = ?', [url, sha], ).fetchone() if result: return result[0] logger.info('Initializing environment for {0}.'.format(url)) dir = tempfile.mkdtemp(prefix='repo', dir=self.directory) with clean_path_on_failure(dir): cmd_output( 'git', 'clone', '--no-checkout', url, dir, env=no_git_env(), ) with cwd(dir): cmd_output('git', 'reset', sha, '--hard', env=no_git_env()) # Update our db with the created repo with sqlite3.connect(self.db_path) as db: db.execute( 'INSERT INTO repos (repo, ref, path) VALUES (?, ?, ?)', [url, sha, dir], ) return dir
def test_run_output_logfile( cap_out, tempdir_factory, mock_out_store_directory, ): expected_output = ( b'This is STDOUT output\n', b'This is STDERR output\n', ) git_path = make_consuming_repo(tempdir_factory, 'logfile_repo') with cwd(git_path): _test_run( cap_out, git_path, {}, expected_output, expected_ret=1, stage=True ) logfile_path = os.path.join(git_path, 'test.log') assert os.path.exists(logfile_path) with open(logfile_path, 'rb') as logfile: logfile_content = logfile.readlines() for expected_output_part in expected_output: assert expected_output_part in logfile_content
def test_installed_from_venv(tempdir_factory): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): install(Runner(path, C.CONFIG_FILE)) # No environment so pre-commit is not on the path when running! # Should still pick up the python from when we installed ret, output = _get_commit_output( tempdir_factory, env={ 'HOME': os.path.expanduser('~'), 'PATH': _path_without_us(), 'TERM': os.environ.get('TERM', ''), # Windows needs this to import `random` 'SYSTEMROOT': os.environ.get('SYSTEMROOT', ''), # Windows needs this to resolve executables 'PATHEXT': os.environ.get('PATHEXT', ''), # Git needs this to make a commit 'GIT_AUTHOR_NAME': os.environ['GIT_AUTHOR_NAME'], 'GIT_COMMITTER_NAME': os.environ['GIT_COMMITTER_NAME'], 'GIT_AUTHOR_EMAIL': os.environ['GIT_AUTHOR_EMAIL'], 'GIT_COMMITTER_EMAIL': os.environ['GIT_COMMITTER_EMAIL'], }, ) assert ret == 0 assert NORMAL_PRE_COMMIT_RUN.match(output)
def test_get_root_deeper(tempdir_factory): path = git_dir(tempdir_factory) foo_path = os.path.join(path, "foo") os.mkdir(foo_path) with cwd(foo_path): assert git.get_root() == path
def test_stdout_write_bug_py26( repo_with_failing_hook, mock_out_store_directory, tmpdir_factory, ): with cwd(repo_with_failing_hook): # Add bash hook on there again with io.open( '.pre-commit-config.yaml', 'a+', encoding='UTF-8', ) as config_file: config_file.write(' args: ["☃"]\n') cmd_output('git', 'add', '.pre-commit-config.yaml') stage_a_file() install(Runner(repo_with_failing_hook)) # Don't want to write to home directory env = dict(os.environ, PRE_COMMIT_HOME=tmpdir_factory.get()) # Have to use subprocess because pytest monkeypatches sys.stdout _, stdout, _ = cmd_output( 'git', 'commit', '-m', 'Commit!', # git commit puts pre-commit to stderr stderr=subprocess.STDOUT, env=env, retcode=None, ) assert 'UnicodeEncodeError' not in stdout # Doesn't actually happen, but a reasonable assertion assert 'UnicodeDecodeError' not in stdout
def test_environment_not_sourced(tempdir_factory): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): # Patch the executable to simulate rming virtualenv with mock.patch.object(sys, 'executable', '/bin/false'): assert install(Runner(path, C.CONFIG_FILE)) == 0 # Use a specific homedir to ignore --user installs homedir = tempdir_factory.get() ret, stdout, stderr = cmd_output( 'git', 'commit', '--allow-empty', '-m', 'foo', env={ 'HOME': homedir, 'PATH': _path_without_us(), # Git needs this to make a commit 'GIT_AUTHOR_NAME': os.environ['GIT_AUTHOR_NAME'], 'GIT_COMMITTER_NAME': os.environ['GIT_COMMITTER_NAME'], 'GIT_AUTHOR_EMAIL': os.environ['GIT_AUTHOR_EMAIL'], 'GIT_COMMITTER_EMAIL': os.environ['GIT_COMMITTER_EMAIL'], }, retcode=None, ) assert ret == 1 assert stdout == '' assert stderr == ( '`pre-commit` not found. ' 'Did you forget to activate your virtualenv?\n' )
def _test_sub_state(path, sha='sha1', status='A'): assert os.path.exists(path.sub_path) with cwd(path.sub_path): actual_sha = cmd_output('git', 'rev-parse', 'HEAD')[1].strip() assert actual_sha == getattr(path.submodule, sha) actual_status = get_short_git_status()['sub'] assert actual_status == status
def test_hook_install_failure(mock_out_store_directory, tempdir_factory): git_path = make_consuming_repo(tempdir_factory, 'not_installable_repo') with cwd(git_path): install(Runner(git_path)) # Don't want to write to home directory env = dict(os.environ, PRE_COMMIT_HOME=tempdir_factory.get()) _, stdout, _ = cmd_output( 'git', 'commit', '-m', 'Commit!', # git commit puts pre-commit to stderr stderr=subprocess.STDOUT, env=env, retcode=None, encoding=None, ) assert b'UnicodeDecodeError' not in stdout # Doesn't actually happen, but a reasonable assertion assert b'UnicodeEncodeError' not in stdout # Sanity check our output assert ( b'An unexpected error has occurred: CalledProcessError: ' in stdout ) assert '☃'.encode('UTF-8') + '²'.encode('latin1') in stdout
def test_autoupdate_old_revision_broken( tempdir_factory, in_tmpdir, mock_out_store_directory, ): """In $FUTURE_VERSION, hooks.yaml will no longer be supported. This asserts that when that day comes, pre-commit will be able to autoupdate despite not being able to read hooks.yaml in that repository. """ path = make_repo(tempdir_factory, 'python_hooks_repo') config = make_config_from_repo(path, check=False) with cwd(path): cmd_output('git', 'mv', C.MANIFEST_FILE, 'nope.yaml') cmd_output('git', 'commit', '-m', 'simulate old repo') # Assume this is the revision the user's old repository was at rev = get_head_sha(path) cmd_output('git', 'mv', 'nope.yaml', C.MANIFEST_FILE) cmd_output('git', 'commit', '-m', 'move hooks file') update_rev = get_head_sha(path) config['sha'] = rev write_config('.', config) before = open(C.CONFIG_FILE).read() ret = autoupdate(Runner('.', C.CONFIG_FILE), tags_only=False) after = open(C.CONFIG_FILE).read() assert ret == 0 assert before != after assert update_rev in after
def test_clone(store, tempdir_factory, log_info_mock): path = git_dir(tempdir_factory) with cwd(path): cmd_output('git', 'commit', '--allow-empty', '-m', 'foo') sha = get_head_sha(path) cmd_output('git', 'commit', '--allow-empty', '-m', 'bar') ret = store.clone(path, sha) # Should have printed some stuff assert log_info_mock.call_args_list[0][0][0].startswith( 'Initializing environment for ' ) # Should return a directory inside of the store assert os.path.exists(ret) assert ret.startswith(store.directory) # Directory should start with `repo` _, dirname = os.path.split(ret) assert dirname.startswith('repo') # Should be checked out to the sha we specified assert get_head_sha(ret) == sha # Assert there's an entry in the sqlite db for this with sqlite3.connect(store.db_path) as db: path, = db.execute( 'SELECT path from repos WHERE repo = ? and ref = ?', [path, sha], ).fetchone() assert path == ret
def make_repo(tempdir_factory, repo_source): path = git_dir(tempdir_factory) copy_tree_to_path(get_resource_path(repo_source), path) with cwd(path): cmd_output('git', 'add', '.') cmd_output('git', 'commit', '-m', 'Add hooks') return path
def test_pcre_hook_matching(tempdir_factory, store): path = git_dir(tempdir_factory) with cwd(path): with io.open("herp", "w") as herp: herp.write("\nherpfoo'bard\n") with io.open("derp", "w") as derp: derp.write("[INFO] information yo\n") _test_hook_repo( tempdir_factory, store, "pcre_hooks_repo", "regex-with-quotes", ["herp", "derp"], b"herp:2:herpfoo'bard\n", expected_return_code=123, ) _test_hook_repo( tempdir_factory, store, "pcre_hooks_repo", "other-regex", ["herp", "derp"], b"derp:1:[INFO] information yo\n", expected_return_code=123, )
def test_get_root_deeper(tempdir_factory): path = git_dir(tempdir_factory) foo_path = os.path.join(path, 'foo') os.mkdir(foo_path) with cwd(foo_path): assert os.path.normcase(git.get_root()) == os.path.normcase(path)
def _update_repository(repo_config, runner): """Updates a repository to the tip of `master`. If the repository cannot be updated because a hook that is configured does not exist in `master`, this raises a RepositoryCannotBeUpdatedError Args: repo_config - A config for a repository """ repo = Repository.create(repo_config, runner.store) with cwd(repo.repo_path_getter.repo_path): cmd_output('git', 'fetch') head_sha = cmd_output('git', 'rev-parse', 'origin/master')[1].strip() # Don't bother trying to update if our sha is the same if head_sha == repo_config['sha']: return repo_config # Construct a new config with the head sha new_config = OrderedDict(repo_config) new_config['sha'] = head_sha new_repo = Repository.create(new_config, runner.store) # See if any of our hooks were deleted with the new commits hooks = set(hook_id for hook_id, _ in repo.hooks) hooks_missing = hooks - (hooks & set(new_repo.manifest.hooks.keys())) if hooks_missing: raise RepositoryCannotBeUpdatedError( 'Cannot update because the tip of master is missing these hooks:\n' '{0}'.format(', '.join(sorted(hooks_missing))) ) return new_config
def make_archive(name, repo, ref, destdir): """Makes an archive of a repository in the given destdir. :param text name: Name to give the archive. For instance foo. The file that is created will be called foo.tar.gz. :param text repo: Repository to clone. :param text ref: Tag/SHA/branch to check out. :param text destdir: Directory to place archives in. """ output_path = os.path.join(destdir, name + '.tar.gz') with tmpdir() as tempdir: # Clone the repository to the temporary directory cmd_output('git', 'clone', repo, tempdir) with cwd(tempdir): cmd_output('git', 'checkout', ref) # We don't want the '.git' directory # It adds a bunch of size to the archive and we don't use it at # runtime rmtree(os.path.join(tempdir, '.git')) with tarfile.open(five.n(output_path), 'w|gz') as tf: tf.add(tempdir, name) return output_path
def submodule_with_commits(tempdir_factory): path = git_dir(tempdir_factory) with cwd(path): cmd_output('git', 'commit', '--allow-empty', '-m', 'foo') sha1 = cmd_output('git', 'rev-parse', 'HEAD')[1].strip() cmd_output('git', 'commit', '--allow-empty', '-m', 'bar') sha2 = cmd_output('git', 'rev-parse', 'HEAD')[1].strip() yield auto_namedtuple(path=path, sha1=sha1, sha2=sha2)
def foo_staged(tempdir_factory): path = git_dir(tempdir_factory) with cwd(path): with io.open('foo', 'w') as foo_file: foo_file.write(FOO_CONTENTS) cmd_output('git', 'add', 'foo') foo_filename = os.path.join(path, 'foo') yield auto_namedtuple(path=path, foo_filename=foo_filename)
def test_install_pre_commit_and_run(tempdir_factory): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): assert install(Runner(path, C.CONFIG_FILE)) == 0 ret, output = _get_commit_output(tempdir_factory) assert ret == 0 assert NORMAL_PRE_COMMIT_RUN.match(output)
def _do_run(repo, args, environ={}): runner = Runner(repo) write_mock = mock.Mock() write_fn = functools.partial(sys_stdout_write_wrapper, stream=write_mock) with cwd(runner.git_root): # replicates Runner.create behaviour ret = run(runner, args, write=write_fn, environ=environ) printed = get_write_mock_output(write_mock) return ret, printed
def test_failing_hooks_returns_nonzero(tempdir_factory): path = make_consuming_repo(tempdir_factory, 'failing_hook_repo') with cwd(path): assert install(Runner(path, C.CONFIG_FILE)) == 0 ret, output = _get_commit_output(tempdir_factory) assert ret == 1 assert FAILING_PRE_COMMIT_RUN.match(output)
def test_arbitrary_bytes_hook( cap_out, tempdir_factory, mock_out_store_directory, ): git_path = make_consuming_repo(tempdir_factory, 'arbitrary_bytes_repo') with cwd(git_path): _test_run(cap_out, git_path, {}, (b'\xe2\x98\x83\xb2\n', ), 1, True)
def test_install_overwrite_no_existing_hooks(tempdir_factory): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): assert install(Runner(path, C.CONFIG_FILE), overwrite=True) == 0 ret, output = _get_commit_output(tempdir_factory) assert ret == 0 assert NORMAL_PRE_COMMIT_RUN.match(output)
def test_cwd_of_hook(tempdir_factory, store): # Note: this doubles as a test for `system` hooks path = git_dir(tempdir_factory) with cwd(path): _test_hook_repo( tempdir_factory, store, 'prints_cwd_repo', 'prints_cwd', ['-L'], _norm_pwd(path) + b'\n', )
def test_install_overwrite_no_existing_hooks(tmpdir_factory): path = make_consuming_repo(tmpdir_factory, 'script_hooks_repo') with cwd(path): assert install(Runner(path), overwrite=True) == 0 ret, output = _get_commit_output(tmpdir_factory) assert ret == 0 assert NORMAL_PRE_COMMIT_RUN.match(output)
def test_cwd_of_hook(tmpdir_factory, store): # Note: this doubles as a test for `system` hooks path = git_dir(tmpdir_factory) with cwd(path): _test_hook_repo( tmpdir_factory, store, 'prints_cwd_repo', 'prints_cwd', ['-L'], _norm_pwd(path) + '\n', )
def test_install_pre_commit_and_run(tmpdir_factory): path = make_consuming_repo(tmpdir_factory, 'script_hooks_repo') with cwd(path): assert install(Runner(path)) == 0 ret, output = _get_commit_output(tmpdir_factory) assert ret == 0 assert NORMAL_PRE_COMMIT_RUN.match(output)
def test_failing_hooks_returns_nonzero(tmpdir_factory): path = make_consuming_repo(tmpdir_factory, 'failing_hook_repo') with cwd(path): assert install(Runner(path)) == 0 ret, output = _get_commit_output(tmpdir_factory) assert ret == 1 assert FAILING_PRE_COMMIT_RUN.match(output)
def test_get_staged_files_deleted(tempdir_factory): path = git_dir(tempdir_factory) with cwd(path): open('test', 'a').close() cmd_output('git', 'add', 'test') cmd_output('git', 'commit', '-m', 'foo', '--allow-empty') cmd_output('git', 'rm', '--cached', 'test') assert git.get_staged_files() == []
def make_consuming_repo(tmpdir_factory, repo_source): path = make_repo(tmpdir_factory, repo_source) config = make_config_from_repo(path) git_path = git_dir(tmpdir_factory) write_config(git_path, config) with cwd(git_path): cmd_output('git', 'add', C.CONFIG_FILE) cmd_output('git', 'commit', '-m', 'Add hooks config') return git_path
def test_install_idempotent(tmpdir_factory): path = make_consuming_repo(tmpdir_factory, 'script_hooks_repo') with cwd(path): assert install(Runner(path)) == 0 assert install(Runner(path)) == 0 ret, output = _get_commit_output(tmpdir_factory) assert ret == 0 assert NORMAL_PRE_COMMIT_RUN.match(output)
def test_python_hook_weird_setup_cfg(tempdir_factory, store): path = git_dir(tempdir_factory) with cwd(path): with io.open('setup.cfg', 'w') as setup_cfg: setup_cfg.write('[install]\ninstall_scripts=/usr/sbin\n') _test_hook_repo( tempdir_factory, store, 'python_hooks_repo', 'foo', [os.devnull], b"['" + five.to_bytes(os.devnull) + b"']\nHello World\n")
def test_unicode_merge_commit_message(tempdir_factory): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): assert install(Runner(path, C.CONFIG_FILE)) == 0 cmd_output('git', 'checkout', 'master', '-b', 'foo') cmd_output('git', 'commit', '--allow-empty', '-m', 'branch2') cmd_output('git', 'checkout', 'master') cmd_output('git', 'merge', 'foo', '--no-ff', '--no-commit', '-m', '☃') # Used to crash cmd_output('git', 'commit', '--no-edit')
def test_files_running_subdir( repo_with_passing_hook, mock_out_store_directory, tempdir_factory, ): with cwd(repo_with_passing_hook): install(Runner(repo_with_passing_hook, C.CONFIG_FILE)) os.mkdir('subdir') open('subdir/foo.py', 'w').close() cmd_output('git', 'add', 'subdir/foo.py') with cwd('subdir'): # Use subprocess to demonstrate behaviour in main _, stdout, _ = cmd_output_mocked_pre_commit_home( sys.executable, '-m', 'pre_commit.main', 'run', '-v', # Files relative to where we are (#339) '--files', 'foo.py', tempdir_factory=tempdir_factory, ) assert 'subdir/foo.py'.replace('/', os.sep) in stdout
def test_install_disallow_mising_config(tempdir_factory): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): runner = Runner(path, C.CONFIG_FILE) remove_config_from_repo(path) assert install(runner, overwrite=True, skip_on_missing_conf=False) == 0 ret, output = _get_commit_output(tempdir_factory) assert ret == 1
def test_get_hook_path(tmpdir_factory): path = git_dir(tmpdir_factory) with cwd(path): runner = Runner(path) expected_paths = (os.path.join(path, '.git/hooks/pre-commit'), os.path.join(path, '.git/hooks/pre-commit.legacy')) assert expected_paths == get_hook_path(runner, 'pre-commit') expected_paths = (os.path.join(path, '.git/hooks/pre-push'), os.path.join(path, '.git/hooks/pre-push.legacy')) assert expected_paths == get_hook_path(runner, 'pre-push')
def test_pre_push_integration_empty_push(tempdir_factory): upstream = make_consuming_repo(tempdir_factory, 'script_hooks_repo') path = tempdir_factory.get() cmd_output('git', 'clone', upstream, path) with cwd(path): install(Runner(path, C.CONFIG_FILE), hook_type='pre-push') _get_push_output(tempdir_factory) retc, output = _get_push_output(tempdir_factory) assert output == 'Everything up-to-date\n' assert retc == 0
def test_install_pre_commit_and_run_custom_path(tempdir_factory): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): cmd_output('git', 'mv', C.CONFIG_FILE, 'custom-config.yaml') cmd_output('git', 'commit', '-m', 'move pre-commit config') assert install(Runner(path, 'custom-config.yaml')) == 0 ret, output = _get_commit_output(tempdir_factory) assert ret == 0 assert NORMAL_PRE_COMMIT_RUN.match(output)
def clone_strategy(directory): cmd_output( 'git', 'clone', '--no-checkout', repo, directory, env=no_git_env(), ) with cwd(directory): cmd_output('git', 'reset', ref, '--hard', env=no_git_env()) cmd_output( 'git', 'submodule', 'update', '--init', '--recursive', env=no_git_env(), )
def test_pcre_hook_case_insensitive_option(tempdir_factory, store): path = git_dir(tempdir_factory) with cwd(path): with io.open('herp', 'w') as herp: herp.write('FoOoOoObar\n') _test_hook_repo( tempdir_factory, store, 'pcre_hooks_repo', 'regex-with-grep-args', ['herp'], b'herp:1:FoOoOoObar\n', expected_return_code=1, )
def test_uninstall_doesnt_remove_not_our_hooks(tmpdir_factory): path = git_dir(tmpdir_factory) with cwd(path): runner = Runner(path) with io.open(runner.pre_commit_path, 'w') as pre_commit_file: pre_commit_file.write('#!/usr/bin/env bash\necho 1\n') make_executable(runner.pre_commit_path) assert uninstall(runner) == 0 assert os.path.exists(runner.pre_commit_path)
def test_really_long_file_paths(tempdir_factory, store): base_path = tempdir_factory.get() really_long_path = os.path.join(base_path, 'really_long' * 10) cmd_output('git', 'init', really_long_path) path = make_repo(tempdir_factory, 'python_hooks_repo') config = make_config_from_repo(path) with cwd(really_long_path): repo = Repository.create(config, store) repo.require_installed()
def test_expected_fatal_error_no_git_repo( tempdir_factory, cap_out, mock_out_store_directory, ): with cwd(tempdir_factory.get()): with pytest.raises(PreCommitSystemExit): main.main([]) assert cap_out.get() == ( 'An error has occurred: FatalError: git failed. ' 'Is it installed, and are you in a Git repository directory?\n' 'Check the log at ~/.pre-commit/pre-commit.log\n' )
def test_types_hook_repository( cap_out, tempdir_factory, mock_out_store_directory, ): git_path = make_consuming_repo(tempdir_factory, 'types_repo') with cwd(git_path): stage_a_file('bar.py') stage_a_file('bar.notpy') ret, printed = _do_run(cap_out, git_path, _get_opts()) assert ret == 1 assert b'bar.py' in printed assert b'bar.notpy' not in printed
def test_create_changes_to_git_root(tempdir_factory): path = git_dir(tempdir_factory) with cwd(path): # Change into some directory, create should set to root foo_path = os.path.join(path, 'foo') os.mkdir(foo_path) os.chdir(foo_path) assert os.getcwd() != path runner = Runner.create(C.CONFIG_FILE) assert os.path.normcase(runner.git_root) == os.path.normcase(path) assert os.path.normcase(os.getcwd()) == os.path.normcase(path)
def test_create_changes_to_git_root(tmpdir_factory): path = git_dir(tmpdir_factory) with cwd(path): # Change into some directory, create should set to root foo_path = os.path.join(path, 'foo') os.mkdir(foo_path) os.chdir(foo_path) assert os.getcwd() != path runner = Runner.create() assert runner.git_root == path assert os.getcwd() == path
def test_pre_push_integration_accepted(tmpdir_factory): upstream = make_consuming_repo(tmpdir_factory, 'script_hooks_repo') path = tmpdir_factory.get() cmd_output('git', 'clone', upstream, path) with cwd(path): install(Runner(path), hook_type='pre-push') assert _get_commit_output(tmpdir_factory)[0] == 0 retc, output = _get_push_output(tmpdir_factory) assert retc == 0 assert 'Bash hook' in output assert 'Passed' in output
def out_of_date_repo(tempdir_factory): path = make_repo(tempdir_factory, 'python_hooks_repo') original_sha = git.head_sha(path) # Make a commit with cwd(path): cmd_output('git', 'commit', '--allow-empty', '-m', 'foo') head_sha = git.head_sha(path) yield auto_namedtuple( path=path, original_sha=original_sha, head_sha=head_sha, )
def test_install_hooks_command(tempdir_factory, mock_out_store_directory): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): runner = Runner(path, C.CONFIG_FILE) install(runner) install_hooks(runner) ret, output = _get_commit_output( tempdir_factory, pre_commit_home=mock_out_store_directory, ) assert ret == 0 assert PRE_INSTALLED.match(output)