|
29 | 29 | import changeset_detect as cd |
30 | 30 |
|
31 | 31 |
|
32 | | -def make_meta(packages, deps, workspace_root="/ws"): |
| 32 | +def make_meta(packages, deps, workspace_root="/ws", publish=None): |
33 | 33 | """Build a fake `cargo metadata` document. |
34 | 34 |
|
35 | 35 | packages: {name -> relative dir} |
36 | 36 | deps: {name -> [dependency names]} |
| 37 | + publish: {name -> publish value}, mirroring cargo metadata's `publish` |
| 38 | + field (`[]` for `publish = false`, a list for restricted |
| 39 | + registries). Names omitted here get no `publish` key, i.e. the |
| 40 | + default publishable-to-any-registry state. |
37 | 41 | """ |
38 | | - return { |
39 | | - "workspace_root": workspace_root, |
40 | | - "packages": [ |
41 | | - { |
42 | | - "name": name, |
43 | | - "manifest_path": f"{workspace_root}/{rel}/Cargo.toml", |
44 | | - "dependencies": [{"name": d} for d in deps.get(name, [])], |
45 | | - } |
46 | | - for name, rel in packages.items() |
47 | | - ], |
48 | | - } |
| 42 | + publish = publish or {} |
| 43 | + pkgs = [] |
| 44 | + for name, rel in packages.items(): |
| 45 | + entry = { |
| 46 | + "name": name, |
| 47 | + "manifest_path": f"{workspace_root}/{rel}/Cargo.toml", |
| 48 | + "dependencies": [{"name": d} for d in deps.get(name, [])], |
| 49 | + } |
| 50 | + if name in publish: |
| 51 | + entry["publish"] = publish[name] |
| 52 | + pkgs.append(entry) |
| 53 | + return {"workspace_root": workspace_root, "packages": pkgs} |
49 | 54 |
|
50 | 55 |
|
51 | 56 | # A small synthetic workspace: |
@@ -220,6 +225,48 @@ def test_changeset_content_prefills_missing(self): |
220 | 225 | self.assertNotIn("a-sys", r["changeset_content"]) |
221 | 226 |
|
222 | 227 |
|
| 228 | +class TestReconcile(unittest.TestCase): |
| 229 | + def test_publishable_crate_missing_from_knope_is_unmanaged(self): |
| 230 | + # Both crates are publishable (no `publish` key); only `a` is in knope. |
| 231 | + meta = make_meta({"a": "a", "b": "b"}, {}) |
| 232 | + unmanaged, stale = cd.reconcile_knope_config(meta, {"a"}) |
| 233 | + self.assertEqual(unmanaged, ["b"]) |
| 234 | + self.assertEqual(stale, []) |
| 235 | + |
| 236 | + def test_publish_false_crate_not_required_in_knope(self): |
| 237 | + # An example crate (publish = false) need not be knope-managed. |
| 238 | + meta = make_meta({"a": "a", "ex": "examples/ex"}, {}, publish={"ex": []}) |
| 239 | + unmanaged, stale = cd.reconcile_knope_config(meta, {"a"}) |
| 240 | + self.assertEqual(unmanaged, []) |
| 241 | + self.assertEqual(stale, []) |
| 242 | + |
| 243 | + def test_publish_false_crate_may_still_be_knope_managed(self): |
| 244 | + # e.g. livekit-ffi: publish = false but released via CI, so it's in |
| 245 | + # knope. This must not be flagged as stale. |
| 246 | + meta = make_meta({"ffi": "ffi"}, {}, publish={"ffi": []}) |
| 247 | + unmanaged, stale = cd.reconcile_knope_config(meta, {"ffi"}) |
| 248 | + self.assertEqual(unmanaged, []) |
| 249 | + self.assertEqual(stale, []) |
| 250 | + |
| 251 | + def test_restricted_registry_is_still_publishable(self): |
| 252 | + meta = make_meta({"a": "a"}, {}, publish={"a": ["crates-io"]}) |
| 253 | + unmanaged, stale = cd.reconcile_knope_config(meta, set()) |
| 254 | + self.assertEqual(unmanaged, ["a"]) |
| 255 | + self.assertEqual(stale, []) |
| 256 | + |
| 257 | + def test_stale_knope_entry_with_no_matching_crate(self): |
| 258 | + meta = make_meta({"a": "a"}, {}) |
| 259 | + unmanaged, stale = cd.reconcile_knope_config(meta, {"a", "ghost"}) |
| 260 | + self.assertEqual(unmanaged, []) |
| 261 | + self.assertEqual(stale, ["ghost"]) |
| 262 | + |
| 263 | + def test_both_directions_at_once(self): |
| 264 | + meta = make_meta({"a": "a", "b": "b"}, {}) |
| 265 | + unmanaged, stale = cd.reconcile_knope_config(meta, {"a", "ghost"}) |
| 266 | + self.assertEqual(unmanaged, ["b"]) |
| 267 | + self.assertEqual(stale, ["ghost"]) |
| 268 | + |
| 269 | + |
223 | 270 | class TestBuildChangesetContent(unittest.TestCase): |
224 | 271 | def test_deterministic_with_explicit_metadata(self): |
225 | 272 | content = cd.build_changeset_content( |
|
0 commit comments