Completed
Push — master ( 4ecf0c...8e8e85 )
by Bjorn
01:03
created

main()   B

Complexity

Conditions 4

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 4
c 2
b 0
f 0
dl 0
loc 22
rs 8.9197
1
# -*- coding: utf-8 -*-
2
"""List interesting files.
3
"""
4
import argparse
5
import os
6
from hashlib import md5
7
from .path import Path
8
9
SKIPFILE_NAME = '.skipfile'
10
11
12
def read_skipfile(dirname='.', defaults=None):
13
    """The .skipfile should contain one entry per line,
14
       listing files/directories that should be skipped by
15
       :func:`list_files`.
16
    """
17
    if defaults is None:
18
        defaults = ['Makefile', 'make.bat', 'atlassian-ide-plugin.xml']
19
    try:
20
        return defaults + open(
21
            os.path.join(dirname, SKIPFILE_NAME)
22
        ).read().splitlines()
23
    except IOError:
24
        return defaults
25
26
27
def list_files(dirname='.', digest=True):
28
    """Yield (digest, fname) tuples for all interesting files
29
       in `dirname`.
30
    """
31
    skipdirs = ['__pycache__', '.git', '.svn', 'htmlcov', 'dist', 'build',
32
                '.idea', 'tasks', 'static', 'media', 'data', 'migrations',
33
                '.doctrees', '_static', 'node_modules', 'external',
34
                'jobs', 'tryout', 'tmp', '_coverage',
35
               ]
36
    skipexts = ['.pyc', '~', '.svg', '.txt', '.TTF', '.tmp', '.errmail',
37
                '.email', '.bat', '.dll', '.exe', '.Dll', '.jpg', '.gif',
38
                '.png', '.ico', '.db', '.md5']
39
    dirname = str(dirname)
40
    skipfiles = read_skipfile(dirname)
41
42
    def clean_dirs(directories):
43
        """Remove directories that should be skipped.
44
        """
45
        for d in directories:
46
            if d.endswith('.egg-info'):
47
                directories.remove(d)
48
        for d in skipdirs:
49
            if d in directories:
50
                directories.remove(d)
51
52
    def keep_file(filename, filepath):
53
        """Returns False if the file should be skipped.
54
        """
55
        if filename.startswith('.'):
56
            return False
57
        if filepath in skipfiles:
58
            return False
59
        for ext in skipexts:
60
            if filename.endswith(ext):
61
                return False
62
        return True
63
64
    for root, dirs, files in os.walk(os.path.abspath(dirname)):
65
        clean_dirs(dirs)
66
        for fname in files:
67
            relpth = os.path.relpath(
68
                os.path.join(root, fname),
69
                dirname
70
            ).replace('\\', '/')
71
72
            parts = Path(relpth).parts()
73
            if not keep_file(fname, relpth) or \
74
                    any(p.startswith('.') for p in parts):
75
                continue
76
77
            pth = os.path.join(dirname, relpth)
78
            if digest:
79
                yield md5(open(pth).read()).hexdigest(), relpth
80
            else:
81
                yield relpth
82
83
84
def main():  # pragma: nocover
85
    """Print checksum and file name for all files in the directory.
86
    """
87
    p = argparse.ArgumentParser(add_help="Recursively list interesting files.")
88
    p.add_argument(
89
        'directory', nargs="?", default="",
90
        help="The directory to process (current dir if omitted)."
91
    )
92
    p.add_argument(
93
        '--verbose', '-v', action='store_true',
94
        help="Increase verbosity."
95
    )
96
97
    args = p.parse_args()
98
    args.curdir = os.getcwd()
99
    if not args.directory:
100
        args.direcotry = args.curdir
101
    if args.verbose:
102
        print args
103
104
    for chsm, fname in list_files(args.directory):
105
        print chsm, fname
106
107
108
if __name__ == "__main__":  # pragma: nocover
109
    main()
110