/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/dirty_tracker.py

  • Committer: Jelmer Vernooij
  • Date: 2020-07-27 19:24:18 UTC
  • mto: (7490.40.77 work)
  • mto: This revision was merged to the branch mainline in revision 7520.
  • Revision ID: jelmer@jelmer.uk-20200727192418-g72o6nm01wvvery9
Add a workspace module.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python3
 
2
# Copyright (C) 2019 Jelmer Vernooij
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
17
 
 
18
"""Track whether a particular directory structure is dirty."""
 
19
 
 
20
import os
 
21
from pyinotify import (
 
22
    WatchManager,
 
23
    IN_CREATE,
 
24
    IN_CLOSE_WRITE,
 
25
    IN_Q_OVERFLOW,
 
26
    IN_DELETE,
 
27
    IN_MOVED_TO,
 
28
    IN_MOVED_FROM,
 
29
    IN_ATTRIB,
 
30
    ProcessEvent,
 
31
    Notifier,
 
32
    Event,
 
33
    )
 
34
 
 
35
 
 
36
MASK = (
 
37
    IN_CLOSE_WRITE | IN_DELETE | IN_Q_OVERFLOW | IN_MOVED_TO | IN_MOVED_FROM |
 
38
    IN_ATTRIB)
 
39
 
 
40
 
 
41
class _Process(ProcessEvent):
 
42
 
 
43
    def my_init(self):
 
44
        self.paths = set()
 
45
        self.created = set()
 
46
 
 
47
    def process_default(self, event):
 
48
        path = os.path.join(event.path, event.name)
 
49
        if event.mask & IN_CREATE:
 
50
            self.created.add(path)
 
51
        self.paths.add(path)
 
52
        if event.mask & IN_DELETE and path in self.created:
 
53
            self.paths.remove(path)
 
54
            self.created.remove(path)
 
55
 
 
56
 
 
57
class DirtyTracker(object):
 
58
 
 
59
    def __init__(self, tree, subpath='.'):
 
60
        self._tree = tree
 
61
        self._wm = WatchManager()
 
62
        self._process = _Process()
 
63
        self._notifier = Notifier(self._wm, self._process)
 
64
        self._notifier.coalesce_events(True)
 
65
 
 
66
        def check_excluded(p):
 
67
            return tree.is_control_filename(tree.relpath(p))
 
68
        self._wdd = self._wm.add_watch(
 
69
            tree.abspath(subpath), MASK, rec=True, auto_add=True,
 
70
            exclude_filter=check_excluded)
 
71
 
 
72
    def _process_pending(self):
 
73
        if self._notifier.check_events(timeout=0):
 
74
            self._notifier.read_events()
 
75
        self._notifier.process_events()
 
76
 
 
77
    def __del__(self):
 
78
        self._notifier.stop()
 
79
 
 
80
    def mark_clean(self):
 
81
        self._process_pending()
 
82
        self._process.paths.clear()
 
83
        self._process.created.clear()
 
84
 
 
85
    def is_dirty(self):
 
86
        self._process_pending()
 
87
        return bool(self._process.paths)
 
88
 
 
89
    def paths(self):
 
90
        self._process_pending()
 
91
        return self._process.paths
 
92
 
 
93
    def relpaths(self):
 
94
        return set(self._tree.relpath(p) for p in self.paths())