|
3 | 3 | import shutil |
4 | 4 | from pathlib import Path |
5 | 5 | import tempfile |
| 6 | +import xmltodict |
6 | 7 |
|
7 | 8 | import smoketests |
8 | 9 | from .. import Smoketest, STDB_DIR, run_cmd, TEMPLATE_CARGO_TOML |
@@ -43,17 +44,57 @@ def _parse_quickstart(doc_path: Path, language: str) -> str: |
43 | 44 | # So we could have a different db for each language |
44 | 45 | return "\n".join(blocks).replace("quickstart-chat", f"quickstart-chat-{language}") + end |
45 | 46 |
|
46 | | - |
47 | | -def _dotnet_add_package(project_path: Path, package_name: str, source_path: Path): |
48 | | - """Add a local NuGet package to a .NET project""" |
49 | | - sources = run_cmd("dotnet", "nuget", "list", "source", cwd=project_path, capture_stderr=True) |
50 | | - # Is the source already added? |
51 | | - if package_name in sources: |
52 | | - run_cmd("dotnet", "nuget", "remove", "source", package_name, cwd=project_path, capture_stderr=True) |
53 | | - run_cmd("dotnet", "nuget", "add", "source", source_path, "--name", package_name, cwd=project_path, |
54 | | - capture_stderr=True) |
55 | | - run_cmd("dotnet", "add", "package", package_name, cwd=project_path, capture_stderr=True) |
56 | | - |
| 47 | +def load_nuget_config(p: Path): |
| 48 | + if p.exists(): |
| 49 | + with p.open("rb") as f: |
| 50 | + return xmltodict.parse(f.read(), force_list=["add", "packageSource", "package"]) |
| 51 | + return {} |
| 52 | + |
| 53 | +def save_nuget_config(p: Path, doc: dict): |
| 54 | + # Write back (pretty, UTF-8, no BOM) |
| 55 | + xml = xmltodict.unparse(doc, pretty=True) |
| 56 | + p.write_text(xml, encoding="utf-8") |
| 57 | + |
| 58 | +def add_source(doc: dict, *, key: str, path: str) -> None: |
| 59 | + cfg = doc.setdefault("configuration", {}) |
| 60 | + sources = cfg.setdefault("packageSources", {}) |
| 61 | + source_entries = sources.setdefault("add", []) |
| 62 | + source = {"@key": key, "@value": path} |
| 63 | + source_entries.append(source) |
| 64 | + |
| 65 | +def add_mapping(doc: dict, *, key: str, pattern: str) -> None: |
| 66 | + cfg = doc.setdefault("configuration", {}) |
| 67 | + |
| 68 | + psm = cfg.setdefault("packageSourceMapping", {}) |
| 69 | + mapping_sources = psm.setdefault("packageSource", []) |
| 70 | + |
| 71 | + # Find or create the target <packageSource key="..."> |
| 72 | + target = next((s for s in mapping_sources if s.get("@key") == key), None) |
| 73 | + if target is None: |
| 74 | + target = {"@key": key, "package": []} |
| 75 | + mapping_sources.append(target) |
| 76 | + |
| 77 | + pkgs = target.setdefault("package", []) |
| 78 | + |
| 79 | + existing = {pkg.get("@pattern") for pkg in pkgs if "@pattern" in pkg} |
| 80 | + if pattern not in existing: |
| 81 | + pkgs.append({"@pattern": pattern}) |
| 82 | + |
| 83 | +def override_nuget_package(*, project_dir: Path, package: str, source_dir: Path, build_subdir: str): |
| 84 | + """Override nuget config to use a local NuGet package on a .NET project""" |
| 85 | + # Make sure the local package is built |
| 86 | + run_cmd("dotnet", "pack", cwd=source_dir) |
| 87 | + |
| 88 | + p = Path(project_dir) / "nuget.config" |
| 89 | + doc = load_nuget_config(p) |
| 90 | + add_source(doc, key=package, path=source_dir/build_subdir) |
| 91 | + add_mapping(doc, key=package, pattern=package) |
| 92 | + # Fallback for other packages |
| 93 | + add_mapping(doc, key="nuget.org", pattern="*") |
| 94 | + save_nuget_config(p, doc) |
| 95 | + |
| 96 | + # Clear any caches for nuget packages |
| 97 | + run_cmd("dotnet", "nuget", "locals", "--clear", "all", capture_stderr=True) |
57 | 98 |
|
58 | 99 | class BaseQuickstart(Smoketest): |
59 | 100 | AUTOPUBLISH = False |
@@ -246,11 +287,27 @@ def project_init(self, path: Path): |
246 | 287 | run_cmd("dotnet", "new", "console", "--name", "QuickstartChatClient", "--output", path, capture_stderr=True) |
247 | 288 |
|
248 | 289 | def sdk_setup(self, path: Path): |
249 | | - _dotnet_add_package(path, "SpacetimeDB.ClientSDK", (STDB_DIR / "sdks/csharp").absolute()) |
| 290 | + override_nuget_package( |
| 291 | + project_dir=STDB_DIR/"sdks/csharp", |
| 292 | + package="SpacetimeDB.BSATN.Runtime", |
| 293 | + source_dir=(STDB_DIR / "crates/bindings-csharp/BSATN.Runtime").absolute(), |
| 294 | + build_subdir="bin/Release" |
| 295 | + ) |
| 296 | + override_nuget_package( |
| 297 | + project_dir=path, |
| 298 | + package="SpacetimeDB.ClientSDK", |
| 299 | + source_dir=(STDB_DIR / "sdks/csharp").absolute(), |
| 300 | + build_subdir="bin~/Release" |
| 301 | + ) |
| 302 | + run_cmd("dotnet", "add", "package", "SpacetimeDB.ClientSDK", cwd=path, capture_stderr=True) |
250 | 303 |
|
251 | 304 | def server_postprocess(self, server_path: Path): |
252 | | - _dotnet_add_package(server_path, "SpacetimeDB.Runtime", |
253 | | - (STDB_DIR / "crates/bindings-csharp/Runtime").absolute()) |
| 305 | + override_nuget_package( |
| 306 | + project_dir=server_path, |
| 307 | + package="SpacetimeDB.Runtime", |
| 308 | + source_dir=(STDB_DIR / "crates/bindings-csharp/Runtime").absolute(), |
| 309 | + build_subdir="bin/Release" |
| 310 | + ) |
254 | 311 |
|
255 | 312 | def test_quickstart(self): |
256 | 313 | """Run the C# quickstart guides for server and client.""" |
|
0 commit comments