aboutsummaryrefslogtreecommitdiff
blob: 1dcc99ad7999c74c341397c4b19946aaf8d0396a (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
import os
import pathlib

from snakeoil.osutils import pjoin

from .. import addons, base, results, sources
from ..packages import RawCPV
from ..utils import is_binary
from . import GentooRepoCheck, RepoCheck


class BinaryFile(results.Error):
    """Binary file found in the repository."""

    def __init__(self, path):
        super().__init__()
        self.path = path

    @property
    def desc(self):
        return f"binary file found in repository: {self.path!r}"


class RepoDirCheck(GentooRepoCheck, RepoCheck):
    """Scan all files in the repository for issues."""

    _source = (sources.EmptySource, (base.repo_scope,))
    required_addons = (addons.git.GitAddon,)
    known_results = frozenset([BinaryFile])

    # repo root level directories that are ignored
    ignored_root_dirs = frozenset([".git"])

    def __init__(self, *args, git_addon):
        super().__init__(*args)
        self.gitignored = git_addon.gitignored
        self.repo = self.options.target_repo
        self.ignored_paths = {pjoin(self.repo.location, x) for x in self.ignored_root_dirs}
        self.dirs = [self.repo.location]

    def finish(self):
        while self.dirs:
            for entry in os.scandir(self.dirs.pop()):
                if entry.is_dir(follow_symlinks=False):
                    if entry.path in self.ignored_paths or self.gitignored(entry.path):
                        continue
                    self.dirs.append(entry.path)
                elif is_binary(entry.path):
                    if not self.gitignored(entry.path):
                        rel_path = entry.path[len(self.repo.location) + 1 :]
                        yield BinaryFile(rel_path)


class EmptyCategoryDir(results.CategoryResult, results.Error):
    """Empty category directory in the repository."""

    scope = base.repo_scope

    @property
    def desc(self):
        return f"empty category directory: {self.category}"


class EmptyPackageDir(results.PackageResult, results.Error):
    """Empty package directory in the repository."""

    scope = base.repo_scope

    @property
    def desc(self):
        return f"empty package directory: {self.category}/{self.package}"


class EmptyDirsCheck(GentooRepoCheck, RepoCheck):
    """Scan for empty category or package directories."""

    _source = (sources.EmptySource, (base.repo_scope,))
    known_results = frozenset({EmptyCategoryDir, EmptyPackageDir})

    def __init__(self, *args):
        super().__init__(*args)
        self.repo = self.options.target_repo

    def finish(self):
        for cat, pkgs in sorted(self.repo.packages.items()):
            # ignore entries in profiles/categories with nonexistent dirs
            if not pkgs and cat in self.repo.category_dirs:
                yield EmptyCategoryDir(pkg=RawCPV(cat, None, None))
                continue
            for pkg in sorted(pkgs):
                if not self.repo.versions[(cat, pkg)]:
                    yield EmptyPackageDir(pkg=RawCPV(cat, pkg, None))


class CategoryIsNotDirectory(results.CategoryResult, results.Error):
    """A category was found that exists but isn't a directory."""

    scope = base.repo_scope

    @property
    def desc(self):
        return f"category on disk exists and is not a directory: {self.category}"


class RepositoryCategories(RepoCheck):
    """Scan for fundamental category issues in the repository layout"""

    _source = (sources.EmptySource, (base.repo_scope,))
    known_results = frozenset({CategoryIsNotDirectory})

    def finish(self):
        repo = self.options.target_repo
        repo_p = pathlib.Path(repo.location)
        for category in repo.categories:
            p = repo_p / category
            if p.exists() and not p.is_dir():
                yield CategoryIsNotDirectory(pkg=RawCPV(category, None, None))