vivacity-core 0.8.0

Manifests, content hash, platform checks, dist fetching, content-addressed store and installation for vivacity
Documentation
//! Emulation of the `symfony/runtime` plugin (plan r2): the plugin only
//! generates `vendor/autoload_runtime.php` at autoload dump time. The template
//! below is the observed output of the real plugin (symfony-demo fixture,
//! default options); the drift test (ignored by default, slow) regenerates
//! the reference through a real `composer install` with plugins.
//!
//! If the root composer.json customises `extra.runtime`, we are outside the
//! default emulation, so the scope detector routes to the fallback.

use crate::error::{Error, Result};
use serde_json::Value;
use std::path::Path;

pub const AUTOLOAD_RUNTIME_TEMPLATE: &str = r#"<?php

// autoload_runtime.php @generated by Symfony Runtime

if (true === (require_once __DIR__.'/autoload.php') || empty($_SERVER['SCRIPT_FILENAME'])) {
    return;
}

$app = require $_SERVER['SCRIPT_FILENAME'];

if (!is_object($app)) {
    throw new TypeError(sprintf('Invalid return value: callable object expected, "%s" returned from "%s".', get_debug_type($app), $_SERVER['SCRIPT_FILENAME']));
}

if (is_string($_SERVER['APP_RUNTIME_OPTIONS'] ??= $_ENV['APP_RUNTIME_OPTIONS'] ?? [])) {
    $_SERVER['APP_RUNTIME_OPTIONS'] = json_decode($_SERVER['APP_RUNTIME_OPTIONS'], true, 512, JSON_THROW_ON_ERROR);
}
$_SERVER['APP_RUNTIME'] ??= $_ENV['APP_RUNTIME'] ?? 'Symfony\\Component\\Runtime\\SymfonyRuntime';
$runtime = new $_SERVER['APP_RUNTIME']($_SERVER['APP_RUNTIME_OPTIONS'] += [
  'project_dir' => dirname(__DIR__, 1),
]);

[$app, $args] = $runtime
    ->getResolver($app)
    ->resolve();

$app = $app(...$args);

exit(
    $runtime
        ->getRunner($app)
        ->run()
);
"#;

/// Non-empty `extra.runtime` means options we do not emulate in v1.
pub fn has_custom_runtime_options(root_manifest: &Value) -> bool {
    root_manifest
        .get("extra")
        .and_then(|e| e.get("runtime"))
        .and_then(Value::as_object)
        .is_some_and(|o| !o.is_empty())
}

pub fn write_stub(vendor_dir: &Path) -> Result<()> {
    let path = vendor_dir.join("autoload_runtime.php");
    let tmp = vendor_dir.join(".autoload_runtime.php.vivacity-tmp");
    std::fs::write(&tmp, AUTOLOAD_RUNTIME_TEMPLATE).map_err(Error::io(&tmp))?;
    std::fs::rename(&tmp, &path).map_err(Error::io(&path))?;
    Ok(())
}