Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/devbot/state.py
blob: 0335b0ca9928b3ebaa3f6eb7adeccf6fdf8f029f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import hashlib
import os
import json

from devbot import config

_BUILT_MODULES = "builtmodules"
_FULL_BUILD = "fullbuild"
_SYSTEM_CHECK = "syscheck"


def built_module_touch(module):
    built_modules = _load_state(_BUILT_MODULES, {})

    source_hash = _compute_mtime_hash(module.get_source_dir())
    built_modules[module.name] = {"source_hash": source_hash}

    _save_state(_BUILT_MODULES, built_modules)


def built_module_is_unchanged(module):
    built_modules = _load_state(_BUILT_MODULES, {})
    if module.name not in built_modules:
        return False

    built_module = built_modules[module.name]
    if "source_hash" not in built_module:
        return False

    old_source_hash = built_module["source_hash"]
    new_source_hash = _compute_mtime_hash(module.get_source_dir())

    return old_source_hash == new_source_hash


def system_check_is_unchanged():
    system_check = _load_state(_SYSTEM_CHECK)
    if not system_check or not "config_hash" in system_check:
        return False

    config_hash = _compute_mtime_hash(config.config_dir)

    return system_check["config_hash"] == config_hash


def system_check_touch():
    system_check = _load_state(_SYSTEM_CHECK, {})

    config_hash = _compute_mtime_hash(config.config_dir)
    system_check["config_hash"] = config_hash

    _save_state(_SYSTEM_CHECK, system_check)


def full_build_is_required():
    full_build = _load_state(_FULL_BUILD)
    if not full_build:
        return True

    return not (full_build["last"] == config.get_full_build())


def full_build_touch():
    full_build = _load_state(_FULL_BUILD, {})
    full_build["last"] = config.get_full_build()
    _save_state(_FULL_BUILD, full_build)


def clean(build_only=False):
    print("* Deleting state")

    names = [_BUILT_MODULES, _FULL_BUILD]
    if not build_only:
        names.append(_SYSTEM_CHECK)

    for name in names:
        try:
            os.unlink(_get_state_path(name))
        except OSError:
            pass


def _get_state_path(name):
    return os.path.join(config.build_state_dir, "%s.json" % name)


def _load_state(name, default=None):
    state = default

    try:
        with open(_get_state_path(name)) as f:
            state = json.load(f)
    except IOError:
        pass

    return state


def _save_state(name, state):
    with open(_get_state_path(name), "w+") as f:
        json.dump(state, f, indent=4)
        f.write('\n')


def _compute_mtime_hash(path):
    # For some reason if path is unicode we
    # get a 10x slow down for some directories
    path = str(path)

    data = ""
    for root, dirs, files in os.walk(path):
        for name in files:
            path = os.path.join(root, name)
            mtime = os.lstat(path).st_mtime
            data = "%s%s %s\n" % (data, mtime, path)

            if ".git" in dirs:
                dirs.remove(".git")

    return hashlib.sha256(data.encode('utf-8')).hexdigest()