1+ import os
2+ import sys
3+
14import pytest
25
6+ from pre_commit_hooks import check_executables_have_shebangs
37from pre_commit_hooks .check_executables_have_shebangs import main
8+ from pre_commit_hooks .util import cmd_output
9+
10+ skip_win32 = pytest .mark .skipif (
11+ sys .platform == 'win32' ,
12+ reason = "non-git checks aren't relevant on windows" ,
13+ )
414
515
16+ @skip_win32 # pragma: win32 no cover
617@pytest .mark .parametrize (
718 'content' , (
819 b'#!/bin/bash\n hello world\n ' ,
@@ -17,14 +28,14 @@ def test_has_shebang(content, tmpdir):
1728 assert main ((path .strpath ,)) == 0
1829
1930
31+ @skip_win32 # pragma: win32 no cover
2032@pytest .mark .parametrize (
2133 'content' , (
2234 b'' ,
2335 b' #!python\n ' ,
2436 b'\n #!python\n ' ,
2537 b'python\n ' ,
2638 '☃' .encode (),
27-
2839 ),
2940)
3041def test_bad_shebang (content , tmpdir , capsys ):
@@ -33,3 +44,67 @@ def test_bad_shebang(content, tmpdir, capsys):
3344 assert main ((path .strpath ,)) == 1
3445 _ , stderr = capsys .readouterr ()
3546 assert stderr .startswith (f'{ path } : marked executable but' )
47+
48+
49+ def test_check_git_filemode_passing (tmpdir ):
50+ with tmpdir .as_cwd ():
51+ cmd_output ('git' , 'init' , '.' )
52+
53+ f = tmpdir .join ('f' )
54+ f .write ('#!/usr/bin/env bash' )
55+ f_path = str (f )
56+ cmd_output ('chmod' , '+x' , f_path )
57+ cmd_output ('git' , 'add' , f_path )
58+ cmd_output ('git' , 'update-index' , '--chmod=+x' , f_path )
59+
60+ g = tmpdir .join ('g' ).ensure ()
61+ g_path = str (g )
62+ cmd_output ('git' , 'add' , g_path )
63+
64+ # this is potentially a problem, but not something the script intends
65+ # to check for -- we're only making sure that things that are
66+ # executable have shebangs
67+ h = tmpdir .join ('h' )
68+ h .write ('#!/usr/bin/env bash' )
69+ h_path = str (h )
70+ cmd_output ('git' , 'add' , h_path )
71+
72+ files = (f_path , g_path , h_path )
73+ assert check_executables_have_shebangs ._check_git_filemode (files ) == 0
74+
75+
76+ def test_check_git_filemode_failing (tmpdir ):
77+ with tmpdir .as_cwd ():
78+ cmd_output ('git' , 'init' , '.' )
79+
80+ f = tmpdir .join ('f' ).ensure ()
81+ f_path = str (f )
82+ cmd_output ('chmod' , '+x' , f_path )
83+ cmd_output ('git' , 'add' , f_path )
84+ cmd_output ('git' , 'update-index' , '--chmod=+x' , f_path )
85+
86+ files = (f_path ,)
87+ assert check_executables_have_shebangs ._check_git_filemode (files ) == 1
88+
89+
90+ @pytest .mark .parametrize (
91+ ('content' , 'mode' , 'expected' ),
92+ (
93+ pytest .param ('#!python' , '+x' , 0 , id = 'shebang with executable' ),
94+ pytest .param ('#!python' , '-x' , 0 , id = 'shebang without executable' ),
95+ pytest .param ('' , '+x' , 1 , id = 'no shebang with executable' ),
96+ pytest .param ('' , '-x' , 0 , id = 'no shebang without executable' ),
97+ ),
98+ )
99+ def test_git_executable_shebang (temp_git_dir , content , mode , expected ):
100+ with temp_git_dir .as_cwd ():
101+ path = temp_git_dir .join ('path' )
102+ path .write (content )
103+ cmd_output ('git' , 'add' , str (path ))
104+ cmd_output ('chmod' , mode , str (path ))
105+ cmd_output ('git' , 'update-index' , f'--chmod={ mode } ' , str (path ))
106+
107+ # simulate how identify choses that something is executable
108+ filenames = [path for path in [str (path )] if os .access (path , os .X_OK )]
109+
110+ assert main (filenames ) == expected
0 commit comments