blob: f6425965547c85f7b41edb93dd428df6e5cac605 [file] [log] [blame]
Abhishek Pandit-Subedib75bd562021-02-25 15:32:22 -08001#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# Copyright 2021 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6""" This script cleans up the vendor directory.
7"""
Abhishek Pandit-Subedi5065a0f2021-06-13 20:38:55 +00008import hashlib
Abhishek Pandit-Subedib75bd562021-02-25 15:32:22 -08009import json
10import os
11import pathlib
Abhishek Pandit-Subedi5065a0f2021-06-13 20:38:55 +000012import subprocess
13
14
15def _rerun_checksums(package_path):
16 """Re-run checksums for given package.
17
18 Writes resulting checksums to $package_path/.cargo-checksum.json.
19 """
20 hashes = {}
21 checksum_path = os.path.join(package_path, '.cargo-checksum.json')
22 if not pathlib.Path(checksum_path).is_file():
23 return False
24
25 with open(checksum_path, 'r') as fread:
26 contents = json.load(fread)
27
28 for root, _, files in os.walk(package_path, topdown=True):
29 for f in files:
30 # Don't checksum an existing checksum file
31 if f == ".cargo-checksum.json":
32 continue
33
34 file_path = os.path.join(root, f)
35 with open(file_path, 'rb') as frb:
36 m = hashlib.sha256()
37 m.update(frb.read())
38 d = m.hexdigest()
39
40 # Key is relative to the package path so strip from beginning
41 key = os.path.relpath(file_path, package_path)
42 hashes[key] = d
43
44 if hashes:
45 print("{} regenerated {} hashes".format(package_path, len(hashes.keys())))
46 contents['files'] = hashes
47
48 with open(checksum_path, 'w') as fwrite:
49 json.dump(contents, fwrite)
50
51 return True
Abhishek Pandit-Subedib75bd562021-02-25 15:32:22 -080052
53
54def _remove_OWNERS_checksum(root):
55 """ Delete all OWNERS files from the checksum file.
56
Abhishek Pandit-Subedi5065a0f2021-06-13 20:38:55 +000057 Args:
58 root: Root directory for the vendored crate.
Abhishek Pandit-Subedib75bd562021-02-25 15:32:22 -080059
Abhishek Pandit-Subedi5065a0f2021-06-13 20:38:55 +000060 Returns:
61 True if OWNERS was found and cleaned up. Otherwise False.
62 """
Abhishek Pandit-Subedib75bd562021-02-25 15:32:22 -080063 checksum_path = os.path.join(root, '.cargo-checksum.json')
64 if not pathlib.Path(checksum_path).is_file():
65 return False
66
67 with open(checksum_path, 'r') as fread:
68 contents = json.load(fread)
69
70 del_keys = []
71 for cfile in contents['files']:
72 if 'OWNERS' in cfile:
73 del_keys.append(cfile)
74
75 for key in del_keys:
76 del contents['files'][key]
77
78 if del_keys:
79 print('{} deleted: {}'.format(root, del_keys))
80 with open(checksum_path, 'w') as fwrite:
81 json.dump(contents, fwrite)
82
83 return bool(del_keys)
84
85
86def cleanup_owners(vendor_path):
87 """ Remove owners checksums from the vendor directory.
88
Abhishek Pandit-Subedi5065a0f2021-06-13 20:38:55 +000089 We currently do not check in the OWNERS files from vendored crates because
90 they interfere with the find-owners functionality in gerrit. This cleanup
91 simply finds all instances of "OWNERS" in the checksum files within and
92 removes them.
Abhishek Pandit-Subedib75bd562021-02-25 15:32:22 -080093
Abhishek Pandit-Subedi5065a0f2021-06-13 20:38:55 +000094 Args:
95 vendor_path: Absolute path to vendor directory.
96 """
Abhishek Pandit-Subedib75bd562021-02-25 15:32:22 -080097 deps_cleaned = []
98 for root, dirs, _ in os.walk(vendor_path):
99 for d in dirs:
100 removed = _remove_OWNERS_checksum(os.path.join(root, d))
101 if removed:
102 deps_cleaned.append(d)
103
104 if deps_cleaned:
105 print('Cleanup owners:\n {}'.format("\n".join(deps_cleaned)))
106
107
Abhishek Pandit-Subedi5065a0f2021-06-13 20:38:55 +0000108def apply_single_patch(patch, workdir):
109 """Apply a single patch and return whether it was successful.
110
111 Returns:
112 True if successful. False otherwise.
113 """
114 print("-- Applying {}".format(patch))
115 proc = subprocess.run(["patch", "-p1", "-i", patch], cwd=workdir)
116 return proc.returncode == 0
117
118
119def apply_patches(patches_path, vendor_path):
120 """Finds patches and applies them to sub-folders in the vendored crates.
121
122 Args:
123 patches_path: Path to folder with patches. Expect all patches to be one
124 level down (matching the crate name).
125 vendor_path: Root path to vendored crates directory.
126 """
127 checksums_for = {}
128
129 # Don't bother running if patches directory is empty
130 if not pathlib.Path(patches_path).is_dir():
131 return
132
133 # Look for all patches and apply them
134 for d in os.listdir(patches_path):
135 dir_path = os.path.join(patches_path, d)
136
137 # We don't process patches in root dir
138 if not os.path.isdir(dir_path):
139 continue
140
141 for patch in os.listdir(os.path.join(dir_path)):
142 file_path = os.path.join(dir_path, patch)
143
144 # Skip if not a patch file
145 if not os.path.isfile(file_path) or not patch.endswith(".patch"):
146 continue
147
148 # If there are any patches, queue checksums for that folder.
149 checksums_for[d] = True
150
151 # Apply the patch. Exit from patch loop if patching failed.
152 success = apply_single_patch(file_path,
153 os.path.join(vendor_path, d))
154 if not success:
155 print("Failed to apply patch: {}".format(patch))
156 break
157
158
159 # Re-run checksums for all modified packages since we applied patches.
160 for key in checksums_for.keys():
161 _rerun_checksums(os.path.join(vendor_path, key))
162
163
Abhishek Pandit-Subedib75bd562021-02-25 15:32:22 -0800164def main():
165 current_path = pathlib.Path(__file__).parent.absolute()
Abhishek Pandit-Subedi5065a0f2021-06-13 20:38:55 +0000166 patches = os.path.join(current_path, "patches")
167 vendor = os.path.join(current_path, "vendor")
Abhishek Pandit-Subedib75bd562021-02-25 15:32:22 -0800168
Abhishek Pandit-Subedi5065a0f2021-06-13 20:38:55 +0000169 # Order matters here:
170 # - Apply patches (also re-calculates checksums)
171 # - Cleanup any owners files (otherwise, git check-in or checksums are
172 # unhappy)
173 apply_patches(patches, vendor)
174 cleanup_owners(vendor)
Abhishek Pandit-Subedib75bd562021-02-25 15:32:22 -0800175
176
177if __name__ == '__main__':
178 main()