changed()   C
last analyzed

Complexity

Conditions 7

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
c 1
b 0
f 0
dl 0
loc 25
rs 5.5
1
# -*- coding: utf-8 -*-
2
"""Check if contents of directory has changed.
3
"""
4
from __future__ import print_function
5
import argparse
6
import os
7
import hashlib
8
from .listfiles import list_files
9
from .path import Path
10
11
12
def digest(dirname, glob=None):
13
    """Returns the md5 digest of all interesting files (or glob) in `dirname`.
14
    """
15
    md5 = hashlib.md5()
16
    if glob is None:
17
        fnames = [fname for _, fname in list_files(Path(dirname))]
18
        for fname in sorted(fnames):
19
            fname = os.path.join(dirname, fname)
20
            md5.update(open(fname, 'rb').read())
21
    else:
22
        fnames = Path(dirname).glob(glob)
23
        for fname in sorted(fnames):
24
            md5.update(fname.open('rb').read())
25
    return md5.hexdigest()
26
27
28
def changed(dirname, filename='.md5', args=None, glob=None):
29
    """Has `glob` changed in `dirname`
30
31
    Args:
32
        dirname: directory to measure
33
        filename: filename to store checksum
34
    """
35
    root = Path(dirname)
36
    if not root.exists():
37
        # if dirname doesn't exist it is changed (by definition)
38
        return True
39
40
    cachefile = root / filename
41
    current_digest = cachefile.open().read() if cachefile.exists() else ""
42
    
43
    _digest = digest(dirname, glob=glob)
44
    if args and args.verbose:  # pragma: nocover
45
        print("md5:", _digest)
46
    has_changed = current_digest != _digest
47
48
    if has_changed:
49
        with open(os.path.join(dirname, filename), 'w') as fp:
50
            fp.write(_digest)
51
52
    return has_changed
53
54
55
class Directory(Path):
56
    """A path that is a directory.
57
    """
58
    def changed(self, filename='.md5', glob=None):
59
        """Are any of the files matched by ``glob`` changed?
60
        """
61
        if glob is not None:
62
            filename += '.glob-' + ''.join(ch.lower()
63
                                           for ch in glob if ch.isalpha())
64
        return changed(self, filename, glob=glob)
65
66
67
def main():  # pragma: nocover
68
    """Return exit code of zero iff directory is not changed.
69
    """
70
    p = argparse.ArgumentParser()
71
    p.add_argument(
72
        'directory',
73
        help="Directory to check"
74
    )
75
    p.add_argument(
76
        '--verbose', '-v', action='store_true',
77
        help="increase verbosity"
78
    )
79
    args = p.parse_args()
80
81
    import sys
82
    _changed = changed(sys.argv[1], args=args)
83
    sys.exit(_changed)
84
85
86
if __name__ == "__main__":  # pragma: nocover
87
    main()
88