new: template manifests and registry infrastructure
Split the Template trait into a data half and a logic half. Every
template is now declared by a manifest under data/templates/<id>/
(CLI id, wizard label, detection markers, Build-Depends, architecture,
rules dh line, rules-extra body, control source fields, gitignore
entries and static file bodies with {placeholder} substitution),
embedded through the TEMPLATE_SOURCES index and parsed once into the
registry; the order of the index is the wizard menu order and the
detection priority at once. The logic half is the slim TemplateHooks
trait (probe, post_write, file-body overrides merged over the manifest
bodies by path shadowing, Build-Depends/architecture amendments and
extra context values), registered per template as a HOOKS static: a
template without hooks needs zero Rust.
- TemplateId becomes a Copy wrapper of the stable CLI string; the
enum, its all/as_str/display_name/from_label matches and the old
statics array collapse into the registry accessors.
- rust's rules overrides move to data/templates/rust/rules.extra.tpl
with {locked}/{artifact} hook context; python's backend table,
meson/cmake's pkg-config opt-in, autotools' gettext and python's
C-extension hints become hook amendments over the manifest baseline.
- detect.rs drops its hardcoded marker cascade: the manifests'
detect.files drive detection in registry order, with the shell
single-script heuristic and the never-detected empty template kept
as the code special cases they are. License sniffing is untouched.
- The template tests port to manifest validation: registry coverage
and stable order, placeholder presence in the rendering context,
rules composition, the Build-Depends/architecture/dh-line table now
asserted against the manifest data, and the hook shadowing merge.
The static skeleton bodies of the shell/empty/makefile/go templates
stay in their Rust hooks for now; the next commit moves them into
their manifests.
This commit is contained in:
+25
-38
@@ -1,26 +1,28 @@
|
||||
//! The `go` template: a Go module built through dh-golang.
|
||||
//!
|
||||
//! The source stanza carries `XS-Go-Import-Path`, probed from the `module`
|
||||
//! line of `go.mod` when the packaged tree has one, defaulting to the
|
||||
//! package name (fresh skeletons embed the package name in their own
|
||||
//! `go.mod`).
|
||||
//! The source stanza carries `XS-Go-Import-Path`, declared as the
|
||||
//! `{go_import_path}` placeholder by the manifest and filled from the
|
||||
//! `module` line of `go.mod` when the packaged tree has one, defaulting to
|
||||
//! the package name (fresh skeletons embed the package name in their own
|
||||
//! `go.mod`). The module line is also the probe of an existing project; the
|
||||
//! skeleton bodies stay here until they move into the manifest's `files:`
|
||||
//! list.
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use super::{OutputFile, Template, source_dir_of};
|
||||
use crate::new::options::{NewOptions, TemplateId};
|
||||
use super::{OutputFile, ProbeResult, TemplateHooks, source_dir_of};
|
||||
use crate::new::options::NewOptions;
|
||||
|
||||
/// Go module (`go.mod`).
|
||||
pub struct Go;
|
||||
/// The logic half of the go template.
|
||||
pub struct Hooks;
|
||||
|
||||
impl Template for Go {
|
||||
fn id(&self) -> TemplateId {
|
||||
TemplateId::Go
|
||||
}
|
||||
/// The go template's hooks, registered in the template registry.
|
||||
pub static HOOKS: Hooks = Hooks;
|
||||
|
||||
impl TemplateHooks for Hooks {
|
||||
/// A stdlib-only `main.go` (no archive dependencies needed to build) and
|
||||
/// the matching `go.mod` whose module path is the package name.
|
||||
fn skeleton(&self, opts: &NewOptions) -> Vec<OutputFile> {
|
||||
fn skeleton_files(&self, opts: &NewOptions) -> Vec<OutputFile> {
|
||||
vec![
|
||||
OutputFile::new(
|
||||
"go.mod",
|
||||
@@ -49,36 +51,21 @@ impl Template for Go {
|
||||
]
|
||||
}
|
||||
|
||||
/// No extra debian/ files: dh-golang drives the build.
|
||||
fn debian(&self, _opts: &NewOptions) -> Vec<OutputFile> {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
fn build_depends(&self, _opts: &NewOptions) -> Vec<String> {
|
||||
vec!["golang-any".to_string(), "dh-golang".to_string()]
|
||||
}
|
||||
|
||||
fn architecture(&self, _opts: &NewOptions) -> &'static str {
|
||||
"any"
|
||||
}
|
||||
|
||||
fn rules_dh_line(&self) -> String {
|
||||
"dh $@ --buildsystem=golang".to_string()
|
||||
}
|
||||
|
||||
fn source_fields(&self, opts: &NewOptions) -> Vec<(String, String)> {
|
||||
vec![("XS-Go-Import-Path".to_string(), import_path(opts))]
|
||||
/// The `{go_import_path}` value of the manifest's `XS-Go-Import-Path`
|
||||
/// source field (see [`import_path`]).
|
||||
fn context(&self, opts: &NewOptions) -> Vec<(String, String)> {
|
||||
vec![("go_import_path".to_string(), import_path(opts))]
|
||||
}
|
||||
|
||||
/// Name (and default command) from the `module` line of `go.mod`: the
|
||||
/// last path segment is the conventional binary/package name.
|
||||
fn probe(&self, dir: &Path) -> Option<super::ProbeResult> {
|
||||
fn probe(&self, dir: &Path) -> Option<ProbeResult> {
|
||||
let module = read_module_line(dir)?;
|
||||
let name = module.rsplit('/').next()?.to_string();
|
||||
if name.is_empty() {
|
||||
return None;
|
||||
}
|
||||
Some(super::ProbeResult {
|
||||
Some(ProbeResult {
|
||||
name: Some(name.clone()),
|
||||
command: Some(name),
|
||||
..Default::default()
|
||||
@@ -114,13 +101,13 @@ fn read_module_line(dir: &Path) -> Option<String> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::new::options::{License, SourceDir};
|
||||
use crate::new::options::{License, SourceDir, TemplateId};
|
||||
use tempfile::tempdir;
|
||||
|
||||
fn opts(source_dir: SourceDir) -> NewOptions {
|
||||
NewOptions {
|
||||
name: "mytool".into(),
|
||||
template: TemplateId::Go,
|
||||
template: TemplateId::GO,
|
||||
source_dir,
|
||||
upstream_version: "0.1.0".into(),
|
||||
revision: 1,
|
||||
@@ -146,7 +133,7 @@ mod tests {
|
||||
#[test]
|
||||
fn go_template_shape() {
|
||||
let o = opts(SourceDir::Skeleton);
|
||||
let template = super::super::get(TemplateId::Go).unwrap();
|
||||
let template = super::super::get(TemplateId::GO).unwrap();
|
||||
|
||||
assert_eq!(template.architecture(&o), "any");
|
||||
assert_eq!(
|
||||
@@ -180,7 +167,7 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let template = super::super::get(TemplateId::Go).unwrap();
|
||||
let template = super::super::get(TemplateId::GO).unwrap();
|
||||
let probe = template.probe(dir.path()).expect("probe result");
|
||||
assert_eq!(probe.name.as_deref(), Some("mytool"));
|
||||
assert_eq!(probe.command.as_deref(), Some("mytool"));
|
||||
|
||||
Reference in New Issue
Block a user