~paul-mcspadden/computer-janitor/bug-726616

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
# Copyright (C) 2008, 2009, 2010  Canonical, Ltd.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""Cruft whitelists."""

from __future__ import absolute_import, unicode_literals

__metaclass__ = type
__all__ = [
    'Whitelist',
    ]


import os


DEFAULT_WHITELIST_DIRS = ['/etc/computer-janitor.d']


def whitelist_files(directories):
    """A generator of white list file names.

    File names are absolute, and all will end in '.whitelist'.

    :param directories: The directories to scan.
    :type directory: sequence of strings
    """
    for directory in directories:
        try:
            for filename in os.listdir(directory):
                if filename.endswith('.whitelist'):
                    yield os.path.abspath(os.path.join(directory, filename))
        except OSError:
            # Just ignore the directory if we can't read it.
            pass


class Whitelist:
    """A cruft whitelister."""

    def __init__(self, whitelist_dirs=None):
        """Scan directories for whitelist files.

        Each directory in `whitelist_dirs` is scanned for files ending in
        '.whitelist'.  When such a file is found, it is parsed.  All blank
        lines and lines beginning with '#' are ignored.  All other lines name
        a piece of cruft that should not be cleaned up.  The names are of the
        format 'prefix:cruftname' as defined by
        `computerjanitor.cruft.Cruft.get_name()`.

        :param whitelist_dirs: An alternative list of directories to scan for
            '.whitelist' files.  If not given `/etc/computer-janitor.d` is
            scanned.
        :type whitelist_dirs: A sequence of strings.
        """
        self.whitelist = set()
        if whitelist_dirs is None:
            whitelist_dirs = DEFAULT_WHITELIST_DIRS
        for whitelist_file in whitelist_files(whitelist_dirs):
            with open(whitelist_file) as fp:
                for line in fp:
                    line = line.strip()
                    if len(line) > 0 and not line.startswith('#'):
                        self.whitelist.add(line)

    def is_whitelisted(self, cruft):
        """Is the cruft whitelisted?

        :param cruft: A piece of cruft.
        :type cruft: `computerjanitor.cruft.Cruft`
        :return: True if the cruft is whitelisted; specifically, if
            `cruft.get_name()` appears in the list of whitelisted cruft.
        :rtype: boolean
        """
        return cruft.get_name() in self.whitelist