Skip to content

Instantly share code, notes, and snippets.

@naoyat
Last active December 26, 2018 03:49
Show Gist options
  • Save naoyat/e4f012fda451ea816dd42885573ba482 to your computer and use it in GitHub Desktop.
Save naoyat/e4f012fda451ea816dd42885573ba482 to your computer and use it in GitHub Desktop.
Gitで実行可能バイナリファイルを排除する(すべての実行可能ファイルの名前を.gitignoreファイルに追加するスクリプトを書いた話) ref: https://qiita.com/naoya_t/items/159dc9a91eb0b27441c8
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
#
# add executable files to .gitignore in each directory (create if not exists)
#
from __future__ import print_function
import os
import re
import click
import six
def get_signature(path):
try:
with open(path, 'rb') as f:
data = f.read(4)
except Exception:
return False
if six.PY2:
data = [ord(x) for x in data]
return ''.join(['%02x' % x for x in data])
def is_ELF(signature):
return signature == '7f454c64'
def is_MachO(signature):
return bool(re.match(r'(cffaedfe|cefaedfe|feedface|feedfacf|cafebabe)', signature))
def parse_gitignore(gitignore_path):
with open(gitignore_path, 'r') as f:
lines = f.readlines()
tmp = []
for line in lines:
line = line.rstrip()
line = re.sub(r'#.*$', '', line)
line = re.sub(r'[ \t]*', '', line)
if line == '':
continue
if '.' in line:
line = line.replace('.', '\\.')
if '*' in line:
line = line.replace('*', '.*')
tmp.append(line)
exp = '^(' + '|'.join(tmp) + ')$'
return re.compile(exp)
def append_dry_run(path, files, redirect='>'):
if files:
print('%s %s' % (redirect, path))
for filename in files:
print(' + %s' % filename)
def append_actual(path, files, mode='a', verbose=False):
with open(path, mode) as f:
for filename in files:
if verbose:
print(' +', filename)
f.write(filename)
f.write('\n')
def add_files_to_gitignore(dir, files, gitignore='.gitignore', dry_run=False):
gitignore_path = os.path.join(dir, gitignore)
if os.path.exists(gitignore_path):
print(gitignore_path, 'exists')
rx = parse_gitignore(gitignore_path)
if dry_run:
print(rx.pattern)
to_be_appended = []
for filename in files:
if rx.match(filename):
print(' -', filename, '(already ignored)')
else:
print(' +', filename)
to_be_appended.append(filename)
else:
print(gitignore_path, 'does not exist')
to_be_appended = files
to_be_appended = sorted(list(to_be_appended))
if dry_run:
append_dry_run(gitignore_path, to_be_appended)
else:
append_actual(gitignore_path, to_be_appended, verbose=True)
def add_executable_files_to_gitignore(dir='.', put_together=False, use_path=False, dry_run=False):
executable_files = set()
for curDir, dirs, files in os.walk(dir):
print('[%s]' % curDir)
for file in files:
path = os.path.join(curDir, file)
if not os.access(path, os.X_OK):
continue
signature = get_signature(path)
if is_ELF(signature) or is_MachO(signature):
if put_together and use_path:
executable_files.add(path)
else:
executable_files.add(file)
if not put_together and executable_files:
add_files_to_gitignore(curDir, executable_files, dry_run=dry_run)
executable_files = set()
if put_together:
add_files_to_gitignore(dir, executable_files, dry_run=dry_run)
@click.command()
@click.argument('dir', type=click.Path(), default='.')
@click.option('--put-together', is_flag=True, default=False)
@click.option('--use-path', is_flag=True, default=False)
@click.option('--dry-run', is_flag=True, default=False)
def main(dir, put_together, use_path, dry_run):
add_executable_files_to_gitignore(dir, put_together=put_together, use_path=use_path, dry_run=dry_run)
if __name__ == '__main__':
main()
$ python add_executable_files_to_gitignore.py .
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment