mirror of
https://github.com/clockworklabs/SpacetimeDB.git
synced 2026-05-10 01:30:37 -04:00
[bfops/translate-script]: WIP
This commit is contained in:
@@ -91,123 +91,6 @@ fn check_global_json_policy() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn overlay_unity_meta_skeleton(pkg_id: &str) -> Result<()> {
|
||||
let skeleton_base = Path::new("sdks/csharp/unity-meta-skeleton~");
|
||||
let skeleton_root = skeleton_base.join(pkg_id);
|
||||
if !skeleton_root.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let pkg_root = Path::new("sdks/csharp/packages").join(pkg_id);
|
||||
if !pkg_root.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Copy spacetimedb.<pkg>.meta
|
||||
let pkg_root_meta = skeleton_base.join(format!("{pkg_id}.meta"));
|
||||
if pkg_root_meta.exists()
|
||||
&& let Some(parent) = pkg_root.parent()
|
||||
{
|
||||
let pkg_meta_dst = parent.join(format!("{pkg_id}.meta"));
|
||||
fs::copy(&pkg_root_meta, &pkg_meta_dst)?;
|
||||
}
|
||||
|
||||
let versioned_dir = match find_only_subdir(&pkg_root) {
|
||||
Ok(dir) => dir,
|
||||
Err(err) => {
|
||||
log::info!("Skipping Unity meta overlay for {pkg_id}: could not locate restored version dir: {err}");
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
// If version.meta exists under the skeleton package, rename it to match the restored version dir.
|
||||
let version_meta_template = skeleton_root.join("version.meta");
|
||||
if version_meta_template.exists()
|
||||
&& let Some(parent) = versioned_dir.parent()
|
||||
{
|
||||
let version_name = versioned_dir
|
||||
.file_name()
|
||||
.expect("versioned directory should have a file name");
|
||||
let version_meta_dst = parent.join(format!("{}.meta", version_name.to_string_lossy()));
|
||||
fs::copy(&version_meta_template, &version_meta_dst)?;
|
||||
}
|
||||
|
||||
copy_overlay_dir(&skeleton_root, &versioned_dir)
|
||||
}
|
||||
|
||||
fn clear_restored_package_dirs(pkg_id: &str) -> Result<()> {
|
||||
let pkg_root = Path::new("sdks/csharp/packages").join(pkg_id);
|
||||
if !pkg_root.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fs::remove_dir_all(&pkg_root)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn find_only_subdir(dir: &Path) -> Result<PathBuf> {
|
||||
let mut subdirs: Vec<PathBuf> = vec![];
|
||||
|
||||
for entry in fs::read_dir(dir)? {
|
||||
let entry = entry?;
|
||||
if entry.file_type()?.is_dir() {
|
||||
subdirs.push(entry.path());
|
||||
}
|
||||
}
|
||||
|
||||
match subdirs.as_slice() {
|
||||
[] => Err(anyhow::anyhow!(
|
||||
"Could not find a restored versioned directory under {}",
|
||||
dir.display()
|
||||
)),
|
||||
[only] => Ok(only.clone()),
|
||||
_ => Err(anyhow::anyhow!(
|
||||
"Expected exactly one restored versioned directory under {}, found {}",
|
||||
dir.display(),
|
||||
subdirs.len()
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn copy_overlay_dir(src: &Path, dst: &Path) -> Result<()> {
|
||||
if !src.exists() {
|
||||
bail!("Skeleton directory does not exist: {}", src.display());
|
||||
}
|
||||
if !dst.exists() {
|
||||
bail!("Destination directory does not exist: {}", dst.display());
|
||||
}
|
||||
|
||||
for entry in fs::read_dir(src)? {
|
||||
let entry = entry?;
|
||||
let src_path = entry.path();
|
||||
let dst_path = dst.join(entry.file_name());
|
||||
if entry.file_type()?.is_dir() {
|
||||
if dst_path.exists() {
|
||||
copy_overlay_dir(&src_path, &dst_path)?;
|
||||
}
|
||||
} else {
|
||||
if src_path.extension() == Some(OsStr::new("meta")) {
|
||||
let asset_path = dst_path
|
||||
.parent()
|
||||
.expect("dst_path should have a parent")
|
||||
.join(dst_path.file_stem().expect(".meta file should have a file stem"));
|
||||
|
||||
if asset_path.exists() {
|
||||
fs::copy(&src_path, &dst_path)?;
|
||||
} else if dst_path.exists() {
|
||||
fs::remove_file(&dst_path)?;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
fs::copy(&src_path, &dst_path)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum CiCmd {
|
||||
/// Runs tests
|
||||
@@ -225,12 +108,6 @@ enum CiCmd {
|
||||
///
|
||||
/// Runs tests for the codegen crate and builds a test module with the wasm bindings.
|
||||
WasmBindings,
|
||||
/// Builds and packs C# DLLs and NuGet packages for local Unity workflows
|
||||
///
|
||||
/// Packs the in-repo C# NuGet packages and restores the C# SDK to populate `sdks/csharp/packages/**`.
|
||||
/// Then overlays Unity `.meta` skeleton files from `sdks/csharp/unity-meta-skeleton~/**` onto the restored
|
||||
/// versioned package directory, so Unity can associate stable meta files with the most recently built package.
|
||||
Dlls,
|
||||
/// Runs smoketests
|
||||
///
|
||||
/// Executes the smoketests suite with some default exclusions.
|
||||
@@ -308,84 +185,6 @@ fn tracked_rs_files_under(path: &str) -> Result<Vec<PathBuf>> {
|
||||
.collect())
|
||||
}
|
||||
|
||||
fn run_dlls() -> Result<()> {
|
||||
ensure_repo_root()?;
|
||||
|
||||
cmd!(
|
||||
"dotnet",
|
||||
"pack",
|
||||
"crates/bindings-csharp/BSATN.Runtime",
|
||||
"-c",
|
||||
"Release"
|
||||
)
|
||||
.run()?;
|
||||
cmd!("dotnet", "pack", "crates/bindings-csharp/Runtime", "-c", "Release").run()?;
|
||||
|
||||
let repo_root = env::current_dir()?;
|
||||
let bsatn_source = repo_root.join("crates/bindings-csharp/BSATN.Runtime/bin/Release");
|
||||
let runtime_source = repo_root.join("crates/bindings-csharp/Runtime/bin/Release");
|
||||
|
||||
let nuget_config_dir = tempfile::tempdir()?;
|
||||
let nuget_config_path = nuget_config_dir.path().join("nuget.config");
|
||||
let nuget_config_contents = format!(
|
||||
r#"<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="Local SpacetimeDB.BSATN.Runtime" value="{}" />
|
||||
<add key="Local SpacetimeDB.Runtime" value="{}" />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
<packageSourceMapping>
|
||||
<packageSource key="Local SpacetimeDB.BSATN.Runtime">
|
||||
<package pattern="SpacetimeDB.BSATN.Runtime" />
|
||||
</packageSource>
|
||||
<packageSource key="Local SpacetimeDB.Runtime">
|
||||
<package pattern="SpacetimeDB.Runtime" />
|
||||
</packageSource>
|
||||
<packageSource key="nuget.org">
|
||||
<package pattern="*" />
|
||||
</packageSource>
|
||||
</packageSourceMapping>
|
||||
</configuration>
|
||||
"#,
|
||||
bsatn_source.display(),
|
||||
runtime_source.display(),
|
||||
);
|
||||
fs::write(&nuget_config_path, nuget_config_contents)?;
|
||||
|
||||
let nuget_config_path_str = nuget_config_path.to_string_lossy().to_string();
|
||||
|
||||
clear_restored_package_dirs("spacetimedb.bsatn.runtime")?;
|
||||
clear_restored_package_dirs("spacetimedb.runtime")?;
|
||||
|
||||
cmd!(
|
||||
"dotnet",
|
||||
"restore",
|
||||
"SpacetimeDB.ClientSDK.csproj",
|
||||
"--configfile",
|
||||
&nuget_config_path_str,
|
||||
)
|
||||
.dir("sdks/csharp")
|
||||
.run()?;
|
||||
|
||||
overlay_unity_meta_skeleton("spacetimedb.bsatn.runtime")?;
|
||||
overlay_unity_meta_skeleton("spacetimedb.runtime")?;
|
||||
|
||||
cmd!(
|
||||
"dotnet",
|
||||
"pack",
|
||||
"SpacetimeDB.ClientSDK.csproj",
|
||||
"-c",
|
||||
"Release",
|
||||
"--no-restore"
|
||||
)
|
||||
.dir("sdks/csharp")
|
||||
.run()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_publish_checks() -> Result<()> {
|
||||
cmd!("bash", "-lc", "test -d venv || python3 -m venv venv").run()?;
|
||||
cmd!("venv/bin/pip3", "install", "argparse", "toml").run()?;
|
||||
@@ -622,10 +421,6 @@ fn main() -> Result<()> {
|
||||
cmd!(cli_path, "build", "--module-path", "modules/module-test",).run()?;
|
||||
}
|
||||
|
||||
Some(CiCmd::Dlls) => {
|
||||
run_dlls()?;
|
||||
}
|
||||
|
||||
Some(CiCmd::Smoketests(args)) => {
|
||||
ensure_repo_root()?;
|
||||
smoketest::run(args)?;
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
#![allow(clippy::disallowed_macros)]
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use duct::cmd;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub fn workspace_dir() -> PathBuf {
|
||||
Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.ancestors()
|
||||
.nth(2)
|
||||
.expect("tools/csharp-tools should be two levels below the workspace root")
|
||||
.to_path_buf()
|
||||
}
|
||||
|
||||
pub fn sdk_dir() -> PathBuf {
|
||||
workspace_dir().join("sdks/csharp")
|
||||
}
|
||||
|
||||
fn cli_manifest() -> PathBuf {
|
||||
workspace_dir().join("crates/cli/Cargo.toml")
|
||||
}
|
||||
|
||||
fn standalone_manifest() -> PathBuf {
|
||||
workspace_dir().join("crates/standalone/Cargo.toml")
|
||||
}
|
||||
|
||||
fn path_arg(path: &Path) -> String {
|
||||
path.to_string_lossy().into_owned()
|
||||
}
|
||||
|
||||
fn canonicalize_existing(path: &Path) -> Result<PathBuf> {
|
||||
path.canonicalize()
|
||||
.with_context(|| format!("failed to canonicalize {}", path.display()))
|
||||
}
|
||||
|
||||
fn render_nuget_config(bsatn_source: &Path, runtime_source: &Path) -> String {
|
||||
format!(
|
||||
r#"<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<!-- Experimental NuGet feed for Microsoft.DotNet.ILCompiler.LLVM packages -->
|
||||
<add key="dotnet-experimental" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json" />
|
||||
<!-- Local NuGet repositories -->
|
||||
<add key="Local SpacetimeDB.BSATN.Runtime" value="{}" />
|
||||
<!-- We need to override the module runtime as well because the examples use it -->
|
||||
<add key="Local SpacetimeDB.Runtime" value="{}" />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
<packageSourceMapping>
|
||||
<!-- Ensure that SpacetimeDB.BSATN.Runtime is used from the local folder. -->
|
||||
<!-- Otherwise we risk an outdated version being quietly pulled from NuGet for testing. -->
|
||||
<packageSource key="Local SpacetimeDB.BSATN.Runtime">
|
||||
<package pattern="SpacetimeDB.BSATN.Runtime" />
|
||||
</packageSource>
|
||||
<packageSource key="Local SpacetimeDB.Runtime">
|
||||
<package pattern="SpacetimeDB.Runtime" />
|
||||
</packageSource>
|
||||
<!-- Experimental packages for NativeAOT-LLVM compilation -->
|
||||
<packageSource key="dotnet-experimental">
|
||||
<package pattern="Microsoft.DotNet.ILCompiler.LLVM" />
|
||||
<package pattern="runtime.*" />
|
||||
</packageSource>
|
||||
<!-- Fallback for other packages (e.g. test deps). -->
|
||||
<packageSource key="nuget.org">
|
||||
<package pattern="*" />
|
||||
</packageSource>
|
||||
</packageSourceMapping>
|
||||
</configuration>
|
||||
"#,
|
||||
bsatn_source.display(),
|
||||
runtime_source.display(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn write_persistent_nuget_configs(spacetimedb_repo_path: Option<&Path>) -> Result<()> {
|
||||
let spacetimedb_repo_path = match spacetimedb_repo_path {
|
||||
Some(path) => canonicalize_existing(path)?,
|
||||
None => workspace_dir(),
|
||||
};
|
||||
|
||||
let sdk_config = sdk_dir().join("NuGet.Config");
|
||||
let sdk_config_contents = render_nuget_config(
|
||||
&spacetimedb_repo_path.join("crates/bindings-csharp/BSATN.Runtime/bin/Release"),
|
||||
&spacetimedb_repo_path.join("crates/bindings-csharp/Runtime/bin/Release"),
|
||||
);
|
||||
fs::write(&sdk_config, sdk_config_contents).with_context(|| format!("failed to write {}", sdk_config.display()))?;
|
||||
|
||||
let repo_config = spacetimedb_repo_path.join("NuGet.Config");
|
||||
let repo_config_contents = render_nuget_config(
|
||||
Path::new("crates/bindings-csharp/BSATN.Runtime/bin/Release"),
|
||||
Path::new("crates/bindings-csharp/Runtime/bin/Release"),
|
||||
);
|
||||
fs::write(&repo_config, repo_config_contents)
|
||||
.with_context(|| format!("failed to write {}", repo_config.display()))?;
|
||||
|
||||
println!("Wrote {} contents:", sdk_config.display());
|
||||
print!("{}", fs::read_to_string(&sdk_config)?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remove_obj_tilde_children(parent: &Path) -> Result<()> {
|
||||
if !parent.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
for entry in fs::read_dir(parent)? {
|
||||
let entry = entry?;
|
||||
if entry.file_type()?.is_dir() {
|
||||
let obj_tilde = entry.path().join("obj~");
|
||||
if obj_tilde.exists() {
|
||||
fs::remove_dir_all(&obj_tilde).with_context(|| format!("failed to remove {}", obj_tilde.display()))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn clean_procedure_obj_tilde_dirs() -> Result<()> {
|
||||
let procedure_client = sdk_dir().join("examples~/regression-tests/procedure-client");
|
||||
println!("Cleanup obj~ folders generated in {}", procedure_client.display());
|
||||
remove_obj_tilde_children(&procedure_client)?;
|
||||
remove_obj_tilde_children(&procedure_client.join("module_bindings"))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run_regression_tests() -> Result<()> {
|
||||
let sdk = sdk_dir();
|
||||
let workspace = workspace_dir();
|
||||
let server_url = env::var("SPACETIMEDB_SERVER_URL").unwrap_or_else(|_| "local".to_string());
|
||||
|
||||
cmd!("cargo", "regen", "csharp", "regression-tests").run()?;
|
||||
|
||||
cmd!("cargo", "build", "--manifest-path", path_arg(&standalone_manifest())).run()?;
|
||||
|
||||
cmd!(
|
||||
"cargo",
|
||||
"run",
|
||||
"--manifest-path",
|
||||
path_arg(&cli_manifest()),
|
||||
"--",
|
||||
"publish",
|
||||
"-c",
|
||||
"-y",
|
||||
"--server",
|
||||
&server_url,
|
||||
"-p",
|
||||
path_arg(&sdk.join("examples~/regression-tests/server")),
|
||||
"btree-repro",
|
||||
)
|
||||
.run()?;
|
||||
cmd!(
|
||||
"cargo",
|
||||
"run",
|
||||
"--manifest-path",
|
||||
path_arg(&cli_manifest()),
|
||||
"--",
|
||||
"publish",
|
||||
"-c",
|
||||
"-y",
|
||||
"--server",
|
||||
&server_url,
|
||||
"-p",
|
||||
path_arg(&sdk.join("examples~/regression-tests/republishing/server-initial")),
|
||||
"republish-test",
|
||||
)
|
||||
.run()?;
|
||||
cmd!(
|
||||
"cargo",
|
||||
"run",
|
||||
"--manifest-path",
|
||||
path_arg(&cli_manifest()),
|
||||
"--",
|
||||
"call",
|
||||
"--server",
|
||||
&server_url,
|
||||
"republish-test",
|
||||
"insert",
|
||||
"1",
|
||||
)
|
||||
.run()?;
|
||||
cmd!(
|
||||
"cargo",
|
||||
"run",
|
||||
"--manifest-path",
|
||||
path_arg(&cli_manifest()),
|
||||
"--",
|
||||
"publish",
|
||||
"--server",
|
||||
&server_url,
|
||||
"-p",
|
||||
path_arg(&sdk.join("examples~/regression-tests/republishing/server-republish")),
|
||||
"--break-clients",
|
||||
"republish-test",
|
||||
)
|
||||
.run()?;
|
||||
cmd!(
|
||||
"cargo",
|
||||
"run",
|
||||
"--manifest-path",
|
||||
path_arg(&cli_manifest()),
|
||||
"--",
|
||||
"call",
|
||||
"--server",
|
||||
&server_url,
|
||||
"republish-test",
|
||||
"insert",
|
||||
"2",
|
||||
)
|
||||
.run()?;
|
||||
|
||||
clean_procedure_obj_tilde_dirs()?;
|
||||
|
||||
cmd!(
|
||||
"cargo",
|
||||
"run",
|
||||
"--manifest-path",
|
||||
path_arg(&cli_manifest()),
|
||||
"--",
|
||||
"publish",
|
||||
"-c",
|
||||
"-y",
|
||||
"--server",
|
||||
&server_url,
|
||||
"-p",
|
||||
path_arg(&workspace.join("modules/sdk-test-procedure")),
|
||||
"procedure-tests",
|
||||
)
|
||||
.run()?;
|
||||
|
||||
cmd!("dotnet", "run", "-c", "Debug")
|
||||
.dir(sdk.join("examples~/regression-tests/client"))
|
||||
.run()?;
|
||||
cmd!("dotnet", "run", "-c", "Debug")
|
||||
.dir(sdk.join("examples~/regression-tests/republishing/client"))
|
||||
.run()?;
|
||||
cmd!("dotnet", "run", "-c", "Debug")
|
||||
.dir(sdk.join("examples~/regression-tests/procedure-client"))
|
||||
.run()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
use anyhow::Result;
|
||||
use clap::{Parser, Subcommand};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(name = "csharp-tools", bin_name = "cargo csharp", about = "C# SDK maintenance tasks")]
|
||||
struct Cli {
|
||||
#[command(subcommand)]
|
||||
command: Command,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Command {
|
||||
/// Write NuGet.Config files that point at local SpacetimeDB C# packages.
|
||||
WriteNugetConfig {
|
||||
/// Path to the SpacetimeDB repository whose C# packages should be used.
|
||||
spacetimedb_repo_path: Option<PathBuf>,
|
||||
},
|
||||
/// Run the C# regression test workflow against a running local SpacetimeDB instance.
|
||||
RunRegressionTests,
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let cli = Cli::parse();
|
||||
|
||||
match cli.command {
|
||||
Command::WriteNugetConfig { spacetimedb_repo_path } => {
|
||||
csharp_tools::write_persistent_nuget_configs(spacetimedb_repo_path.as_deref())?;
|
||||
}
|
||||
Command::RunRegressionTests => {
|
||||
csharp_tools::run_regression_tests()?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
#![allow(clippy::disallowed_macros)]
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use duct::cmd;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
const BSATN_PACKAGE_ID: &str = "spacetimedb.bsatn.runtime";
|
||||
const RUNTIME_PACKAGE_ID: &str = "spacetimedb.runtime";
|
||||
|
||||
fn workspace_dir() -> PathBuf {
|
||||
Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.ancestors()
|
||||
.nth(2)
|
||||
.expect("tools/regen should be two levels below the workspace root")
|
||||
.to_path_buf()
|
||||
}
|
||||
|
||||
fn sdk_dir() -> PathBuf {
|
||||
workspace_dir().join("sdks/csharp")
|
||||
}
|
||||
|
||||
fn cli_manifest() -> PathBuf {
|
||||
workspace_dir().join("crates/cli/Cargo.toml")
|
||||
}
|
||||
|
||||
fn standalone_manifest() -> PathBuf {
|
||||
workspace_dir().join("crates/standalone/Cargo.toml")
|
||||
}
|
||||
|
||||
fn path_arg(path: &Path) -> String {
|
||||
path.to_string_lossy().into_owned()
|
||||
}
|
||||
|
||||
fn render_nuget_config(bsatn_source: &Path, runtime_source: &Path) -> String {
|
||||
format!(
|
||||
r#"<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<!-- Experimental NuGet feed for Microsoft.DotNet.ILCompiler.LLVM packages -->
|
||||
<add key="dotnet-experimental" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json" />
|
||||
<!-- Local NuGet repositories -->
|
||||
<add key="Local SpacetimeDB.BSATN.Runtime" value="{}" />
|
||||
<!-- We need to override the module runtime as well because the examples use it -->
|
||||
<add key="Local SpacetimeDB.Runtime" value="{}" />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
<packageSourceMapping>
|
||||
<!-- Ensure that SpacetimeDB.BSATN.Runtime is used from the local folder. -->
|
||||
<!-- Otherwise we risk an outdated version being quietly pulled from NuGet for testing. -->
|
||||
<packageSource key="Local SpacetimeDB.BSATN.Runtime">
|
||||
<package pattern="SpacetimeDB.BSATN.Runtime" />
|
||||
</packageSource>
|
||||
<packageSource key="Local SpacetimeDB.Runtime">
|
||||
<package pattern="SpacetimeDB.Runtime" />
|
||||
</packageSource>
|
||||
<!-- Experimental packages for NativeAOT-LLVM compilation -->
|
||||
<packageSource key="dotnet-experimental">
|
||||
<package pattern="Microsoft.DotNet.ILCompiler.LLVM" />
|
||||
<package pattern="runtime.*" />
|
||||
</packageSource>
|
||||
<!-- Fallback for other packages (e.g. test deps). -->
|
||||
<packageSource key="nuget.org">
|
||||
<package pattern="*" />
|
||||
</packageSource>
|
||||
</packageSourceMapping>
|
||||
</configuration>
|
||||
"#,
|
||||
bsatn_source.display(),
|
||||
runtime_source.display(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn regen_regression_tests() -> Result<()> {
|
||||
let sdk = sdk_dir();
|
||||
let workspace = workspace_dir();
|
||||
|
||||
cmd!("cargo", "build", "--manifest-path", path_arg(&standalone_manifest())).run()?;
|
||||
|
||||
cmd!(
|
||||
"cargo",
|
||||
"run",
|
||||
"--manifest-path",
|
||||
path_arg(&cli_manifest()),
|
||||
"--",
|
||||
"generate",
|
||||
"-y",
|
||||
"-l",
|
||||
"csharp",
|
||||
"-o",
|
||||
path_arg(&sdk.join("examples~/regression-tests/client/module_bindings")),
|
||||
"--module-path",
|
||||
path_arg(&sdk.join("examples~/regression-tests/server")),
|
||||
)
|
||||
.run()?;
|
||||
cmd!(
|
||||
"cargo",
|
||||
"run",
|
||||
"--manifest-path",
|
||||
path_arg(&cli_manifest()),
|
||||
"--",
|
||||
"generate",
|
||||
"-y",
|
||||
"-l",
|
||||
"csharp",
|
||||
"-o",
|
||||
path_arg(&sdk.join("examples~/regression-tests/republishing/client/module_bindings")),
|
||||
"--module-path",
|
||||
path_arg(&sdk.join("examples~/regression-tests/republishing/server-republish")),
|
||||
)
|
||||
.run()?;
|
||||
cmd!(
|
||||
"cargo",
|
||||
"run",
|
||||
"--manifest-path",
|
||||
path_arg(&cli_manifest()),
|
||||
"--",
|
||||
"generate",
|
||||
"-y",
|
||||
"-l",
|
||||
"csharp",
|
||||
"-o",
|
||||
path_arg(&sdk.join("examples~/regression-tests/procedure-client/module_bindings")),
|
||||
"--module-path",
|
||||
path_arg(&workspace.join("modules/sdk-test-procedure")),
|
||||
)
|
||||
.run()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn overlay_unity_meta_skeleton(pkg_id: &str) -> Result<()> {
|
||||
let sdk = sdk_dir();
|
||||
let skeleton_base = sdk.join("unity-meta-skeleton~");
|
||||
let skeleton_root = skeleton_base.join(pkg_id);
|
||||
if !skeleton_root.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let pkg_root = sdk.join("packages").join(pkg_id);
|
||||
if !pkg_root.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let pkg_root_meta = skeleton_base.join(format!("{pkg_id}.meta"));
|
||||
if pkg_root_meta.exists()
|
||||
&& let Some(parent) = pkg_root.parent()
|
||||
{
|
||||
let pkg_meta_dst = parent.join(format!("{pkg_id}.meta"));
|
||||
fs::copy(&pkg_root_meta, &pkg_meta_dst)?;
|
||||
}
|
||||
|
||||
let versioned_dir = match find_only_subdir(&pkg_root) {
|
||||
Ok(dir) => dir,
|
||||
Err(err) => {
|
||||
eprintln!("Skipping Unity meta overlay for {pkg_id}: could not locate restored version dir: {err}");
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
let version_meta_template = skeleton_root.join("version.meta");
|
||||
if version_meta_template.exists()
|
||||
&& let Some(parent) = versioned_dir.parent()
|
||||
{
|
||||
let version_name = versioned_dir
|
||||
.file_name()
|
||||
.expect("versioned directory should have a file name");
|
||||
let version_meta_dst = parent.join(format!("{}.meta", version_name.to_string_lossy()));
|
||||
fs::copy(&version_meta_template, &version_meta_dst)?;
|
||||
}
|
||||
|
||||
copy_overlay_dir(&skeleton_root, &versioned_dir)
|
||||
}
|
||||
|
||||
fn clear_restored_package_dirs(pkg_id: &str) -> Result<()> {
|
||||
let pkg_root = sdk_dir().join("packages").join(pkg_id);
|
||||
if pkg_root.exists() {
|
||||
fs::remove_dir_all(&pkg_root)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn find_only_subdir(dir: &Path) -> Result<PathBuf> {
|
||||
let mut subdirs = vec![];
|
||||
|
||||
for entry in fs::read_dir(dir)? {
|
||||
let entry = entry?;
|
||||
if entry.file_type()?.is_dir() {
|
||||
subdirs.push(entry.path());
|
||||
}
|
||||
}
|
||||
|
||||
match subdirs.as_slice() {
|
||||
[] => bail!("Could not find a restored versioned directory under {}", dir.display()),
|
||||
[only] => Ok(only.clone()),
|
||||
_ => bail!(
|
||||
"Expected exactly one restored versioned directory under {}, found {}",
|
||||
dir.display(),
|
||||
subdirs.len()
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn copy_overlay_dir(src: &Path, dst: &Path) -> Result<()> {
|
||||
if !src.exists() {
|
||||
bail!("Skeleton directory does not exist: {}", src.display());
|
||||
}
|
||||
if !dst.exists() {
|
||||
bail!("Destination directory does not exist: {}", dst.display());
|
||||
}
|
||||
|
||||
for entry in fs::read_dir(src)? {
|
||||
let entry = entry?;
|
||||
let src_path = entry.path();
|
||||
let dst_path = dst.join(entry.file_name());
|
||||
if entry.file_type()?.is_dir() {
|
||||
if dst_path.exists() {
|
||||
copy_overlay_dir(&src_path, &dst_path)?;
|
||||
}
|
||||
} else {
|
||||
if src_path.extension().is_some_and(|ext| ext == "meta") {
|
||||
let asset_path = dst_path
|
||||
.parent()
|
||||
.expect("dst_path should have a parent")
|
||||
.join(dst_path.file_stem().expect(".meta file should have a file stem"));
|
||||
|
||||
if asset_path.exists() {
|
||||
fs::copy(&src_path, &dst_path)?;
|
||||
} else if dst_path.exists() {
|
||||
fs::remove_file(&dst_path)?;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
fs::copy(&src_path, &dst_path)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn regen_dlls() -> Result<()> {
|
||||
let workspace = workspace_dir();
|
||||
let sdk = sdk_dir();
|
||||
|
||||
cmd!(
|
||||
"dotnet",
|
||||
"pack",
|
||||
workspace.join("crates/bindings-csharp/BSATN.Runtime"),
|
||||
"-c",
|
||||
"Release"
|
||||
)
|
||||
.run()?;
|
||||
cmd!(
|
||||
"dotnet",
|
||||
"pack",
|
||||
workspace.join("crates/bindings-csharp/Runtime"),
|
||||
"-c",
|
||||
"Release"
|
||||
)
|
||||
.run()?;
|
||||
|
||||
let nuget_config_dir = tempfile::tempdir()?;
|
||||
let nuget_config_path = nuget_config_dir.path().join("nuget.config");
|
||||
fs::write(
|
||||
&nuget_config_path,
|
||||
render_nuget_config(
|
||||
&workspace.join("crates/bindings-csharp/BSATN.Runtime/bin/Release"),
|
||||
&workspace.join("crates/bindings-csharp/Runtime/bin/Release"),
|
||||
),
|
||||
)?;
|
||||
|
||||
clear_restored_package_dirs(BSATN_PACKAGE_ID)?;
|
||||
clear_restored_package_dirs(RUNTIME_PACKAGE_ID)?;
|
||||
|
||||
cmd!(
|
||||
"dotnet",
|
||||
"restore",
|
||||
"SpacetimeDB.ClientSDK.csproj",
|
||||
"--configfile",
|
||||
path_arg(&nuget_config_path),
|
||||
)
|
||||
.dir(&sdk)
|
||||
.run()?;
|
||||
|
||||
overlay_unity_meta_skeleton(BSATN_PACKAGE_ID)?;
|
||||
overlay_unity_meta_skeleton(RUNTIME_PACKAGE_ID)?;
|
||||
|
||||
cmd!(
|
||||
"dotnet",
|
||||
"pack",
|
||||
"SpacetimeDB.ClientSDK.csproj",
|
||||
"-c",
|
||||
"Release",
|
||||
"--no-restore"
|
||||
)
|
||||
.dir(&sdk)
|
||||
.run()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
use anyhow::Result;
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
mod csharp;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(name = "regen", bin_name = "cargo regen", about = "Regenerate checked-in artifacts")]
|
||||
struct Cli {
|
||||
#[command(subcommand)]
|
||||
command: Command,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Command {
|
||||
/// Regenerate C# SDK artifacts.
|
||||
Csharp {
|
||||
#[command(subcommand)]
|
||||
command: CsharpCommand,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum CsharpCommand {
|
||||
/// Regenerate C# regression test bindings.
|
||||
RegressionTests,
|
||||
/// Regenerate C# DLL and NuGet package artifacts for Unity workflows.
|
||||
Dlls,
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let cli = Cli::parse();
|
||||
|
||||
match cli.command {
|
||||
Command::Csharp { command } => match command {
|
||||
CsharpCommand::RegressionTests => csharp::regen_regression_tests()?,
|
||||
CsharpCommand::Dlls => csharp::regen_dlls()?,
|
||||
},
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user