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))
|