()
| 152 | |
| 153 | |
| 154 | def main() -> None: |
| 155 | parser = argparse.ArgumentParser() |
| 156 | parser.add_argument("--verbose", action="store_true", default=False, help="Increase verbosity") |
| 157 | parser.add_argument("--sqlite", action="store_true", default=False, help="Use a sqlite cache") |
| 158 | parser.add_argument( |
| 159 | "--num-shards", type=int, default=SQLITE_NUM_SHARDS, help=argparse.SUPPRESS |
| 160 | ) |
| 161 | parser.add_argument("input_dir1", help="Input directory for the original cache") |
| 162 | parser.add_argument("input_dir2", help="Input directory for the target cache") |
| 163 | parser.add_argument("output", help="Output file with the diff from original cache") |
| 164 | args = parser.parse_args() |
| 165 | |
| 166 | cache1 = make_cache(args.input_dir1, args.sqlite, num_shards=args.num_shards) |
| 167 | cache2 = make_cache(args.input_dir2, args.sqlite, num_shards=args.num_shards) |
| 168 | |
| 169 | type_misses: dict[str, int] = defaultdict(int) |
| 170 | type_hits: dict[str, int] = defaultdict(int) |
| 171 | |
| 172 | updates: dict[str, str | None] = {} |
| 173 | |
| 174 | deps1: dict[str, set[str]] = {} |
| 175 | deps2: dict[str, set[str]] = {} |
| 176 | |
| 177 | misses = hits = 0 |
| 178 | cache1_all = list(cache1.list_all()) |
| 179 | for s in cache1_all: |
| 180 | obj1 = load(cache1, s) |
| 181 | try: |
| 182 | obj2 = load(cache2, s) |
| 183 | except FileNotFoundError: |
| 184 | obj2 = None |
| 185 | |
| 186 | typ = s.split(".")[-2] |
| 187 | if obj1 != obj2: |
| 188 | misses += 1 |
| 189 | type_misses[typ] += 1 |
| 190 | |
| 191 | # Collect the dependencies instead of including them directly in the diff |
| 192 | # so we can produce a much smaller direct diff of them. |
| 193 | if ".deps." not in s: |
| 194 | if obj2 is not None: |
| 195 | updates[s] = encode_for_diff(s, obj2) |
| 196 | else: |
| 197 | updates[s] = None |
| 198 | elif obj2: |
| 199 | # This is a deps file, with json data |
| 200 | assert ".deps." in s |
| 201 | merge_deps(deps1, obj1) |
| 202 | merge_deps(deps2, obj2) |
| 203 | else: |
| 204 | hits += 1 |
| 205 | type_hits[typ] += 1 |
| 206 | |
| 207 | cache1_all_set = set(cache1_all) |
| 208 | for s in cache2.list_all(): |
| 209 | if s not in cache1_all_set: |
| 210 | raw = cache2.read(s) |
| 211 | if s.endswith(".ff"): |
no test coverage detected
searching dependent graphs…