shared-context-engineering 0.3.3

Shared Context Engineering CLI
use sha2::{Digest, Sha256};
use std::{
    env,
    fmt::Write,
    fs,
    io::{self, Write as IoWrite},
    path::{Path, PathBuf},
};

const TARGETS: &[TargetSpec] = &[
    TargetSpec {
        const_name: "OPENCODE_EMBEDDED_ASSETS",
        relative_root: "assets/generated/config/opencode",
        allow_dead_code: false,
    },
    TargetSpec {
        const_name: "CLAUDE_EMBEDDED_ASSETS",
        relative_root: "assets/generated/config/claude",
        allow_dead_code: false,
    },
    TargetSpec {
        const_name: "PI_EMBEDDED_ASSETS",
        relative_root: "assets/generated/config/pi",
        allow_dead_code: false,
    },
    TargetSpec {
        const_name: "HOOK_EMBEDDED_ASSETS",
        relative_root: "assets/hooks",
        allow_dead_code: false,
    },
];

const MIGRATIONS_ROOT: &str = "migrations";
const GENERATED_MIGRATIONS_PATH: &str = "src/generated_migrations.rs";

struct TargetSpec {
    const_name: &'static str,
    relative_root: &'static str,
    allow_dead_code: bool,
}

fn main() {
    if let Err(error) = generate_embedded_asset_manifest() {
        panic!("failed to generate setup embedded asset manifest: {error}");
    }

    if let Err(error) = generate_migration_manifest() {
        panic!("failed to generate embedded migration manifest: {error}");
    }

    emit_git_commit();
    emit_repo_version();
}

fn generate_migration_manifest() -> io::Result<()> {
    println!("cargo:rerun-if-changed=build.rs");

    let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").map_err(|e| invalid_data(&e))?);
    let migrations_root = manifest_dir.join(MIGRATIONS_ROOT);
    let destination_path = manifest_dir.join(GENERATED_MIGRATIONS_PATH);

    println!("cargo:rerun-if-changed={}", migrations_root.display());

    let mut databases = collect_migration_databases(&migrations_root)?;
    databases.sort_unstable_by(|a, b| a.directory_name.cmp(&b.directory_name));

    let mut output = String::new();
    output.push_str("// @generated by build.rs; do not edit by hand.\n");
    output.push_str("#![allow(dead_code)]\n\n");

    for database in &databases {
        output.push_str("#[rustfmt::skip]\n");
        output.push_str("pub static ");
        output.push_str(&database.const_name);
        output.push_str(": &[(&str, &str)] = &[\n");

        for migration in &database.migrations {
            println!(
                "cargo:rerun-if-changed={}",
                migration.absolute_path.display()
            );
            writeln!(
                output,
                "    (\"{}\", include_str!(\"{}\")),",
                escape_for_rust_string(&migration.id),
                escape_for_rust_string(&migration.include_path),
            )
            .expect("writing to String buffer should never fail");
        }

        output.push_str("];\n\n");
    }

    let trimmed = format!("{}\n", output.trim_end());
    write_if_changed(&destination_path, trimmed.as_bytes())
}

fn emit_git_commit() {
    // Commit embedding is release-only: the flake sets SCE_GIT_COMMIT solely on
    // the release package derivation. Ordinary native builds, `cargo test`,
    // Clippy, fmt, and other checks leave it unset so they stay cache-reusable
    // across commits. When absent, the app falls back to "unknown" via
    // `option_env!`. Deliberately no `git rev-parse` fallback and no
    // `.git/HEAD` / `.git/packed-refs` rerun watches.
    println!("cargo:rerun-if-env-changed=SCE_GIT_COMMIT");

    if let Ok(commit) = env::var("SCE_GIT_COMMIT") {
        let commit = commit.trim();
        if !commit.is_empty() {
            println!("cargo:rustc-env=SCE_GIT_COMMIT={commit}");
        }
    }
}

fn emit_repo_version() {
    let manifest_dir = match env::var("CARGO_MANIFEST_DIR") {
        Ok(value) => PathBuf::from(value),
        Err(_) => return,
    };

    let repository_root = match manifest_dir.parent() {
        Some(path) => path.to_path_buf(),
        None => return,
    };

    let version_path = repository_root.join(".version");
    println!("cargo:rerun-if-changed={}", version_path.display());

    let Ok(bytes) = fs::read(&version_path) else {
        return;
    };

    let version = String::from_utf8_lossy(&bytes);
    let version = version.trim();
    if !version.is_empty() {
        println!("cargo:rustc-env=SCE_VERSION={version}");
    }
}

fn generate_embedded_asset_manifest() -> io::Result<()> {
    let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").map_err(|e| invalid_data(&e))?);
    let out_dir = PathBuf::from(env::var("OUT_DIR").map_err(|e| invalid_data(&e))?);
    let destination_path = out_dir.join("setup_embedded_assets.rs");

    let mut output = String::new();

    for target in TARGETS {
        let source_root = manifest_dir.join(target.relative_root);
        println!("cargo:rerun-if-changed={}", source_root.display());

        let mut files = Vec::new();
        collect_files(&source_root, &source_root, &mut files)?;
        files.sort_unstable_by(|a, b| a.relative_path.cmp(&b.relative_path));

        if target.allow_dead_code {
            output.push_str("#[allow(dead_code)]\n");
        }
        writeln!(
            output,
            "pub static {}: &[EmbeddedAsset] = &[",
            target.const_name
        )
        .expect("writing to String buffer should never fail");

        for file in &files {
            println!("cargo:rerun-if-changed={}", file.absolute_path.display());
            let bytes = fs::read(&file.absolute_path)?;
            let sha256 = compute_sha256(&bytes);
            let include_path = format!("{}/{}", target.relative_root, file.relative_path);
            writeln!(
                output,
                "    EmbeddedAsset {{ relative_path: \"{}\", \
                 bytes: include_bytes!(concat!(env!(\"CARGO_MANIFEST_DIR\"), \"/{}\")), \
                 sha256: {} }},",
                escape_for_rust_string(&file.relative_path),
                escape_for_rust_string(&include_path),
                format_byte_literal("[", &sha256),
            )
            .expect("writing to String buffer should never fail");
        }

        output.push_str("];\n\n");
    }

    let mut output_file = fs::File::create(destination_path)?;
    output_file.write_all(output.as_bytes())
}

#[derive(Debug)]
struct MigrationDatabase {
    directory_name: String,
    const_name: String,
    migrations: Vec<MigrationFile>,
}

#[derive(Debug)]
struct MigrationFile {
    absolute_path: PathBuf,
    id: String,
    include_path: String,
    sort_prefix: u64,
}

fn collect_migration_databases(migrations_root: &Path) -> io::Result<Vec<MigrationDatabase>> {
    let mut databases = Vec::new();

    for entry in fs::read_dir(migrations_root)? {
        let entry = entry?;

        if !entry.file_type()?.is_dir() {
            continue;
        }

        let directory_path = entry.path();
        let directory_name = entry
            .file_name()
            .to_str()
            .ok_or_else(|| invalid_data(&"non-UTF-8 migration directory names are not supported"))?
            .to_owned();

        println!("cargo:rerun-if-changed={}", directory_path.display());

        let mut migrations = collect_migration_files(&directory_name, &directory_path)?;
        migrations.sort_unstable_by(|a, b| {
            a.sort_prefix
                .cmp(&b.sort_prefix)
                .then_with(|| a.id.cmp(&b.id))
        });

        databases.push(MigrationDatabase {
            const_name: migration_const_name(&directory_name)?,
            directory_name,
            migrations,
        });
    }

    Ok(databases)
}

fn collect_migration_files(
    directory_name: &str,
    directory_path: &Path,
) -> io::Result<Vec<MigrationFile>> {
    let mut migrations = Vec::new();

    for entry in fs::read_dir(directory_path)? {
        let entry = entry?;
        let path = entry.path();

        if entry.file_type()?.is_dir()
            || path.extension().and_then(|value| value.to_str()) != Some("sql")
        {
            continue;
        }

        let id = path
            .file_stem()
            .and_then(|value| value.to_str())
            .ok_or_else(|| invalid_data(&"non-UTF-8 migration filenames are not supported"))?
            .to_owned();

        migrations.push(MigrationFile {
            absolute_path: path,
            include_path: format!("../{MIGRATIONS_ROOT}/{directory_name}/{id}.sql"),
            sort_prefix: migration_sort_prefix(&id)?,
            id,
        });
    }

    Ok(migrations)
}

fn migration_sort_prefix(id: &str) -> io::Result<u64> {
    let prefix = id
        .split_once('_')
        .map(|(prefix, _)| prefix)
        .ok_or_else(|| invalid_data(&format!("migration filename '{id}' must contain '_'")))?;

    if prefix.is_empty() || !prefix.chars().all(|character| character.is_ascii_digit()) {
        return Err(invalid_data(&format!(
            "migration filename '{id}' must start with a numeric prefix"
        )));
    }

    prefix.parse::<u64>().map_err(|error| invalid_data(&error))
}

fn migration_const_name(directory_name: &str) -> io::Result<String> {
    let mut const_name = String::new();

    for character in directory_name.chars() {
        if character.is_ascii_alphanumeric() {
            const_name.push(character.to_ascii_uppercase());
        } else if character == '-' || character == '_' {
            const_name.push('_');
        } else {
            return Err(invalid_data(&format!(
                "migration directory '{directory_name}' contains unsupported character '{character}'"
            )));
        }
    }

    if const_name.is_empty() {
        return Err(invalid_data(&"migration directory name cannot be empty"));
    }

    const_name.push_str("_MIGRATIONS");
    Ok(const_name)
}

#[derive(Debug)]
struct SourceFile {
    absolute_path: PathBuf,
    relative_path: String,
}

fn collect_files(
    base_root: &Path,
    current_dir: &Path,
    output: &mut Vec<SourceFile>,
) -> io::Result<()> {
    for entry in fs::read_dir(current_dir)? {
        let entry = entry?;
        let path = entry.path();

        if entry.file_type()?.is_dir() {
            collect_files(base_root, &path, output)?;
            continue;
        }

        let relative_path = path
            .strip_prefix(base_root)
            .map_err(|_| invalid_data(&"failed to strip source root from file path"))?;

        let relative_path = normalize_relative_path(relative_path)?;

        output.push(SourceFile {
            absolute_path: path,
            relative_path,
        });
    }

    Ok(())
}

fn normalize_relative_path(path: &Path) -> io::Result<String> {
    let normalized = path
        .to_str()
        .ok_or_else(|| invalid_data(&"non-UTF-8 config paths are not supported"))?
        .replace('\\', "/");

    if normalized.is_empty() {
        return Err(invalid_data(&"relative path cannot be empty"));
    }

    if normalized.starts_with('/') {
        return Err(invalid_data(&"relative path must not start with '/'"));
    }

    Ok(normalized)
}

fn escape_for_rust_string(value: &str) -> String {
    value.replace('\\', "\\\\").replace('"', "\\\"")
}

fn compute_sha256(bytes: &[u8]) -> [u8; 32] {
    let digest = Sha256::digest(bytes);
    digest.into()
}

fn format_byte_literal(prefix: &str, bytes: &[u8]) -> String {
    format!(
        "{prefix}{}]",
        bytes
            .iter()
            .map(|byte| format!("0x{byte:02x}"))
            .collect::<Vec<_>>()
            .join(", ")
    )
}

fn write_if_changed(path: &Path, bytes: &[u8]) -> io::Result<()> {
    if fs::read(path).is_ok_and(|existing| existing == bytes) {
        return Ok(());
    }

    fs::write(path, bytes)
}

fn invalid_data<E: ToString>(error: &E) -> io::Error {
    io::Error::new(io::ErrorKind::InvalidData, error.to_string())
}