Coverage for src/ansible_sign/checksum/differ/base.py: 92%
28 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-07-02 14:12 +0000
« prev ^ index » next coverage.py v7.9.1, created at 2025-07-02 14:12 +0000
1import os
2from pathlib import PurePath
5class ChecksumFileExistenceDiffer:
6 """
7 When checking checksum files, it can be important to ensure not only that
8 the files listed have correct hashes, but that no files were added that
9 are not listed.
11 This is particularly important in situations where files might get
12 "wildcard-included" -- whereby an extra file slipping in could present a
13 security risk.
15 This class, and subclasses of it, provide an implementation that
16 ChecksumFileValidator instances can use to list all "interesting" files that
17 should be listed in the checksum file.
18 """
20 # These are tuples of path elements, compared to the path's parts (as
21 # presented by pathlib).
22 ignored_paths = set([
23 ".ansible-sign",
24 ".ansible-sign/**",
25 ])
27 # Files that get added to the manifest in list_files() even if not
28 # explicitly found by gather_files()
29 always_added_files = set()
31 # When gathering files, any warnings we encounter can be propagated up.
32 # This is a place to store them.
33 warnings = set()
35 def __init__(self, root):
36 self.root = root
38 def gather_files(self, verifying=False):
39 return set()
41 def list_files(self, verifying):
42 """
43 Return a (sorted, normalized) list of files.
45 Individual differs can implement logic based on whether we are
46 using this to generate a manifest or to verify one, and 'verifying'
47 is what is used to toggle this logic.
48 """
49 gathered = self.gather_files(verifying=verifying)
50 files = set(os.path.normpath(f) for f in gathered)
52 for path in files.copy():
53 for ignored_path in self.ignored_paths:
54 if PurePath(path).match(ignored_path):
55 files.remove(path)
57 for path in self.always_added_files:
58 if not os.path.exists(os.path.join(self.root, path)): 58 ↛ 59line 58 didn't jump to line 59 because the condition on line 58 was never true
59 raise FileNotFoundError(path)
60 files.add(path)
62 return sorted(files)
64 def compare_filelist(self, checksum_paths):
65 """
66 Given a set of paths (from a checksum file), see if files have since
67 been added or removed from the root directory and any deeper
68 directories.
70 The given set of paths is used as the source of truth and additions
71 and deletions are list with respect to it.
72 """
74 real_paths = set(self.list_files(verifying=True))
75 out = {}
76 out["added"] = sorted(real_paths - checksum_paths)
77 out["removed"] = sorted(checksum_paths - real_paths)
78 return out