new: port the shell, empty, makefile and go templates to manifests
Move the four templates' static file bodies into .tpl files under
data/templates/<id>/, referenced by their manifests' files: lists —
the shell skeleton script (executable, {command}-named) with its
skeleton-only debian/install mapping, the empty template's stub README,
the makefile hello.c/Makefile skeleton with its skeleton-only install
mapping, and go's go.mod/main.go skeleton (the go directive of go.mod
stays a literal: nothing about it is answer-derived).
The empty template ends up hookless — zero Rust, its registry entry
points at no hooks — and src/new/templates/empty.rs is deleted. The
shell and go hooks shrink to their probes (plus go's {go_import_path}
context value); the makefile hooks keep only the existing-tree hint
probing the packaged Makefile for a phony install: target, since that
heuristic reads the tree and cannot be data.
This commit is contained in:
@@ -0,0 +1 @@
|
||||
{name} - empty base tree scaffolded by `pkh new`; there is intentionally no upstream build system here.
|
||||
@@ -1,6 +1,9 @@
|
||||
## The `empty` template: a metapackage (non-empty Depends list) or an
|
||||
## empty base package with no build system at all — pure `dh $@` plumbing
|
||||
## as a starting point for hand-written rules.
|
||||
## as a starting point for hand-written rules. Pure data: no hooks, the
|
||||
## metapackage Depends payload travels in the wizard answers, and the
|
||||
## only upstream file is the stub README marking the tree as
|
||||
## intentionally empty.
|
||||
##
|
||||
## Schema: see src/new/templates/mod.rs.
|
||||
|
||||
@@ -11,4 +14,6 @@ detect:
|
||||
build_depends: []
|
||||
architecture: all
|
||||
rules_dh_line: "dh $@"
|
||||
files: []
|
||||
files:
|
||||
- path: README
|
||||
template: README.tpl
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
module {name}
|
||||
|
||||
go 1.21
|
||||
@@ -0,0 +1,8 @@
|
||||
// Placeholder for {name}, generated by `pkh new`.
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println("Hello from {command}!")
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
## The `go` template: a Go module built through dh-golang. The logic half
|
||||
## — the go.mod module-line probe and the `{go_import_path}` value below —
|
||||
## lives in src/new/templates/go.rs.
|
||||
## lives in src/new/templates/go.rs; the skeleton bodies are static data
|
||||
## (the `go` directive of go.mod stays a literal: nothing about it is
|
||||
## answer-derived, so it has no {placeholder}).
|
||||
##
|
||||
## Schema: see src/new/templates/mod.rs.
|
||||
|
||||
@@ -15,4 +17,8 @@ architecture: any
|
||||
rules_dh_line: "dh $@ --buildsystem=golang"
|
||||
source_fields:
|
||||
XS-Go-Import-Path: "{go_import_path}"
|
||||
files: []
|
||||
files:
|
||||
- path: go.mod
|
||||
template: go.mod.tpl
|
||||
- path: main.go
|
||||
template: main.go.tpl
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
CC ?= cc
|
||||
CFLAGS ?= -O2 -Wall -Wextra
|
||||
PREFIX ?= /usr
|
||||
|
||||
all: {command}
|
||||
|
||||
{command}: hello.c
|
||||
$(CC) $(CFLAGS) -o $@ hello.c
|
||||
|
||||
install: {command}
|
||||
install -Dm755 {command} $(DESTDIR)$(PREFIX)/bin/{command}
|
||||
|
||||
clean:
|
||||
rm -f {command}
|
||||
|
||||
.PHONY: all install clean
|
||||
@@ -0,0 +1,8 @@
|
||||
#include <stdio.h>
|
||||
|
||||
/* Placeholder for {name}, generated by `pkh new`. */
|
||||
int main(void)
|
||||
{
|
||||
printf("Hello from {command}!\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{command} usr/bin/{command}
|
||||
@@ -2,7 +2,11 @@
|
||||
## debhelper's makefile buildsystem runs `make` for the build and
|
||||
## `make install DESTDIR=...` when the Makefile carries an `install:`
|
||||
## target (missing targets are skipped gracefully), so plain `dh $@`
|
||||
## plumbing is enough here.
|
||||
## plumbing is enough here. The phony-install hint of
|
||||
## src/new/templates/makefile.rs (whether dh_auto_install will run
|
||||
## `make install` for an existing tree) is the only logic; the skeleton
|
||||
## bodies below are static data (the install mapping is rendered for
|
||||
## skeletons only, whose phony install target is known by construction).
|
||||
##
|
||||
## Schema: see src/new/templates/mod.rs.
|
||||
|
||||
@@ -14,4 +18,11 @@ build_depends:
|
||||
- build-essential
|
||||
architecture: any
|
||||
rules_dh_line: "dh $@"
|
||||
files: []
|
||||
files:
|
||||
- path: hello.c
|
||||
template: hello.c.tpl
|
||||
- path: Makefile
|
||||
template: Makefile.tpl
|
||||
- path: debian/install
|
||||
template: install.tpl
|
||||
skeleton_only: true
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{command}.sh usr/bin/{command}
|
||||
@@ -2,7 +2,10 @@
|
||||
## /usr/bin with plain `dh $@` plumbing. Detection is not marker-based: the
|
||||
## single-script heuristic of src/new/detect.rs (a lone *.sh or shebang
|
||||
## file) maps here. The probe pre-filling the wizard answers from the
|
||||
## script file name lives in src/new/templates/shell.rs.
|
||||
## script file name lives in src/new/templates/shell.rs; everything else
|
||||
## is the data below (the skeleton script is executable, the install
|
||||
## mapping exists for skeletons only — packaging an existing tree leaves
|
||||
## the mapping to the user).
|
||||
##
|
||||
## Schema: see src/new/templates/mod.rs.
|
||||
|
||||
@@ -13,4 +16,10 @@ detect:
|
||||
build_depends: []
|
||||
architecture: all
|
||||
rules_dh_line: "dh $@"
|
||||
files: []
|
||||
files:
|
||||
- path: "{command}.sh"
|
||||
template: script.tpl
|
||||
executable: true
|
||||
- path: debian/install
|
||||
template: install.tpl
|
||||
skeleton_only: true
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
# Placeholder for {name}, generated by `pkh new`.
|
||||
echo "Hello from {command}!"
|
||||
@@ -1,84 +0,0 @@
|
||||
//! The `empty` template: a metapackage or an empty base package with no
|
||||
//! build system at all.
|
||||
//!
|
||||
//! One template with two flavors: a non-empty `Depends` list selects the
|
||||
//! **metapackage** flavor (the canonical `Architecture: all`, nothing
|
||||
//! compiled, the Depends list *is* the payload shape), while an empty list
|
||||
//! selects the **empty base** — pure `dh $@` plumbing as a starting point
|
||||
//! for hand-written rules. Both flavors are pure manifest data except for
|
||||
//! the stub `README` of the skeleton, which lives here until its static
|
||||
//! body moves into the manifest's `files:` list.
|
||||
|
||||
use super::{OutputFile, TemplateHooks};
|
||||
use crate::new::options::NewOptions;
|
||||
|
||||
/// The logic half of the empty template.
|
||||
pub struct Hooks;
|
||||
|
||||
/// The empty template's hooks, registered in the template registry.
|
||||
pub static HOOKS: Hooks = Hooks;
|
||||
|
||||
impl TemplateHooks for Hooks {
|
||||
/// No upstream files beyond a stub `README` marking the tree as
|
||||
/// intentionally empty.
|
||||
fn skeleton_files(&self, opts: &NewOptions) -> Vec<OutputFile> {
|
||||
vec![OutputFile::new(
|
||||
"README",
|
||||
format!(
|
||||
"{} - empty base tree scaffolded by `pkh new`; there is \
|
||||
intentionally no upstream build system here.\n",
|
||||
opts.name
|
||||
),
|
||||
)]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::new::options::{License, SourceDir, TemplateId};
|
||||
|
||||
fn opts(depends: Vec<String>) -> NewOptions {
|
||||
NewOptions {
|
||||
name: "metapkg".into(),
|
||||
template: TemplateId::EMPTY,
|
||||
source_dir: SourceDir::Skeleton,
|
||||
upstream_version: "0.1.0".into(),
|
||||
revision: 1,
|
||||
summary: "A metapackage".into(),
|
||||
long_description: "A metapackage".into(),
|
||||
homepage: None,
|
||||
license: License::Custom("unknown".into()),
|
||||
command: "ignored".into(),
|
||||
maintainer: ("Jane".into(), "jane@example.com".into()),
|
||||
dist: "debian".into(),
|
||||
series: "sid".into(),
|
||||
release: false,
|
||||
depends,
|
||||
source_format: crate::new::options::SourceFormat::Quilt,
|
||||
orig: Some(crate::new::options::OrigOrigin::Snapshot),
|
||||
git: true,
|
||||
autopkgtest: false,
|
||||
pkg_config: false,
|
||||
watch: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_template_shape() {
|
||||
let template = super::super::get(TemplateId::EMPTY).unwrap();
|
||||
|
||||
// Metapackage flavor: the depends list travels in the options.
|
||||
let o = opts(vec!["hello".into(), "hello-data (>= 1.0)".into()]);
|
||||
assert!(template.debian(&o).is_empty());
|
||||
assert_eq!(template.architecture(&o), "all");
|
||||
assert!(template.build_depends(&o).is_empty());
|
||||
assert!(template.rules_extra(&o).is_empty());
|
||||
|
||||
let skeleton = template.skeleton(&o);
|
||||
assert_eq!(skeleton.len(), 1);
|
||||
assert_eq!(skeleton[0].path, "README");
|
||||
assert!(!skeleton[0].executable);
|
||||
assert!(skeleton[0].contents.contains("metapkg"));
|
||||
}
|
||||
}
|
||||
+9
-39
@@ -1,16 +1,16 @@
|
||||
//! The `go` template: a Go module built through dh-golang.
|
||||
//!
|
||||
//! 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.
|
||||
//! The skeleton bodies (`go.mod`, `main.go`) are manifest data
|
||||
//! (`data/templates/go/manifest.yml`); the source stanza carries
|
||||
//! `XS-Go-Import-Path`, declared as the `{go_import_path}` placeholder by
|
||||
//! the manifest and filled here 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.
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use super::{OutputFile, ProbeResult, TemplateHooks, source_dir_of};
|
||||
use super::{ProbeResult, TemplateHooks, source_dir_of};
|
||||
use crate::new::options::NewOptions;
|
||||
|
||||
/// The logic half of the go template.
|
||||
@@ -20,37 +20,6 @@ pub struct Hooks;
|
||||
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_files(&self, opts: &NewOptions) -> Vec<OutputFile> {
|
||||
vec![
|
||||
OutputFile::new(
|
||||
"go.mod",
|
||||
format!(
|
||||
"module {name}\n\
|
||||
\n\
|
||||
go 1.21\n",
|
||||
name = opts.name,
|
||||
),
|
||||
),
|
||||
OutputFile::new(
|
||||
"main.go",
|
||||
format!(
|
||||
"// Placeholder for {name}, generated by `pkh new`.\n\
|
||||
package main\n\
|
||||
\n\
|
||||
import \"fmt\"\n\
|
||||
\n\
|
||||
func main() {{\n\
|
||||
\tfmt.Println(\"Hello from {command}!\")\n\
|
||||
}}\n",
|
||||
name = opts.name,
|
||||
command = opts.command,
|
||||
),
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
/// 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)> {
|
||||
@@ -143,6 +112,7 @@ mod tests {
|
||||
assert_eq!(template.rules_dh_line(), "dh $@ --buildsystem=golang");
|
||||
assert!(template.debian(&o).is_empty());
|
||||
|
||||
// The skeleton bodies are manifest data now.
|
||||
let skeleton = template.skeleton(&o);
|
||||
assert!(
|
||||
skeleton
|
||||
|
||||
@@ -3,16 +3,17 @@
|
||||
//! debhelper's makefile buildsystem runs `make` for the build and `make
|
||||
//! install DESTDIR=...` when the Makefile carries an `install:` target
|
||||
//! (missing targets are skipped gracefully), so plain `dh $@` plumbing is
|
||||
//! enough here. The metadata is manifest data; the logic half here is the
|
||||
//! phony-`install:` heuristic advising the user whether `dh_auto_install`
|
||||
//! will run `make install`, plus (until their bodies move into the
|
||||
//! manifest's `files:` list) the `hello.c`/`Makefile` skeleton and its
|
||||
//! `debian/install` mapping.
|
||||
//! enough here. Everything is manifest data
|
||||
//! (`data/templates/makefile/manifest.yml`: the `hello.c`/`Makefile`
|
||||
//! skeleton and the skeleton-only `debian/install` mapping) except the
|
||||
//! hint logged here for an existing tree, which probes its Makefile for a
|
||||
//! phony `install:` target to tell whether `dh_auto_install` will run
|
||||
//! `make install` (a skeleton's target is known by construction, so
|
||||
//! skeletons need no code).
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use super::meson::hello_c;
|
||||
use super::{OutputFile, TemplateHooks, source_dir_of};
|
||||
use super::TemplateHooks;
|
||||
use crate::new::options::{NewOptions, SourceDir};
|
||||
|
||||
/// The logic half of the makefile template.
|
||||
@@ -22,53 +23,18 @@ pub struct Hooks;
|
||||
pub static HOOKS: Hooks = Hooks;
|
||||
|
||||
impl TemplateHooks for Hooks {
|
||||
/// A `hello.c` plus a `Makefile` with `all`/`install`/`clean` targets;
|
||||
/// `install` honors `DESTDIR` and copies the binary to
|
||||
/// `$(DESTDIR)/usr/bin/`.
|
||||
fn skeleton_files(&self, opts: &NewOptions) -> Vec<OutputFile> {
|
||||
vec![
|
||||
hello_c(opts),
|
||||
OutputFile::new(
|
||||
"Makefile",
|
||||
format!(
|
||||
"CC ?= cc\n\
|
||||
CFLAGS ?= -O2 -Wall -Wextra\n\
|
||||
PREFIX ?= /usr\n\
|
||||
\n\
|
||||
all: {command}\n\
|
||||
\n\
|
||||
{command}: hello.c\n\
|
||||
\t$(CC) $(CFLAGS) -o $@ hello.c\n\
|
||||
\n\
|
||||
install: {command}\n\
|
||||
\tinstall -Dm755 {command} $(DESTDIR)$(PREFIX)/bin/{command}\n\
|
||||
\n\
|
||||
clean:\n\
|
||||
\trm -f {command}\n\
|
||||
\n\
|
||||
.PHONY: all install clean\n",
|
||||
command = opts.command,
|
||||
),
|
||||
),
|
||||
]
|
||||
/// No files of its own: the manifest carries the skeleton-only
|
||||
/// `debian/install` mapping. When packaging an existing tree, probe
|
||||
/// its Makefile for a phony `install:` target and say which install
|
||||
/// step `dh_auto_install` will take (no `debian/install` is emitted
|
||||
/// there — the source-relative mapping of an unknown artifact is only
|
||||
/// the project's to write, and `make install` already ran).
|
||||
fn debian_files(&self, opts: &NewOptions) -> Vec<super::OutputFile> {
|
||||
if matches!(opts.source_dir, SourceDir::Skeleton) {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
/// `debian/install` mapping the built binary into `/usr/bin`, generated
|
||||
/// only when the packaged Makefile carries a phony `install:` target:
|
||||
/// for skeletons that is known by construction; when packaging an
|
||||
/// existing tree the Makefile is probed instead (no `debian/install` is
|
||||
/// emitted there — the source-relative mapping of an unknown artifact is
|
||||
/// only the project's to write, and `make install` already ran).
|
||||
fn debian_files(&self, opts: &NewOptions) -> Vec<OutputFile> {
|
||||
match &opts.source_dir {
|
||||
SourceDir::Skeleton => {
|
||||
vec![OutputFile::new(
|
||||
"debian/install",
|
||||
format!("{} usr/bin/{}\n", opts.command, opts.command),
|
||||
)]
|
||||
}
|
||||
_ => {
|
||||
if let Some(dir) = source_dir_of(opts)
|
||||
let dir = super::source_dir_of(opts);
|
||||
if let Some(dir) = dir.as_deref()
|
||||
&& phony_install_target(&dir.join("Makefile")).is_some()
|
||||
{
|
||||
log::info!(
|
||||
@@ -84,8 +50,6 @@ impl TemplateHooks for Hooks {
|
||||
}
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The name of the phony `install:` target of the Makefile at `path`, when
|
||||
@@ -157,8 +121,8 @@ mod tests {
|
||||
assert_eq!(template.rules_dh_line(), "dh $@");
|
||||
assert!(template.rules_extra(&o).is_empty());
|
||||
|
||||
// Skeleton: hello.c + Makefile with all/install/clean, and the
|
||||
// phony install target maps to debian/install.
|
||||
// Skeleton (manifest data): hello.c + Makefile with all/install/clean
|
||||
// targets, and the phony install target maps to debian/install.
|
||||
let skeleton = template.skeleton(&o);
|
||||
assert!(skeleton.iter().any(|f| f.path == "hello.c"));
|
||||
let makefile = skeleton
|
||||
@@ -183,7 +147,7 @@ mod tests {
|
||||
assert_eq!(debian[0].path, "debian/install");
|
||||
assert_eq!(debian[0].contents, "mytool usr/bin/mytool\n");
|
||||
|
||||
// Existing tree: nothing is emitted (probe log only).
|
||||
// Existing tree: nothing is emitted (the probe log only).
|
||||
let o = opts(SourceDir::Here);
|
||||
assert!(template.debian(&o).is_empty());
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
|
||||
pub mod autotools;
|
||||
pub mod cmake;
|
||||
pub mod empty;
|
||||
pub mod go;
|
||||
pub mod makefile;
|
||||
pub mod meson;
|
||||
@@ -370,26 +369,61 @@ static TEMPLATE_SOURCES: &[TemplateSources] = &[
|
||||
TemplateSources {
|
||||
id: TemplateId::GO,
|
||||
manifest: include_str!("../../../data/templates/go/manifest.yml"),
|
||||
tpls: &[],
|
||||
tpls: &[
|
||||
(
|
||||
"go.mod.tpl",
|
||||
include_str!("../../../data/templates/go/go.mod.tpl"),
|
||||
),
|
||||
(
|
||||
"main.go.tpl",
|
||||
include_str!("../../../data/templates/go/main.go.tpl"),
|
||||
),
|
||||
],
|
||||
hooks: Some(&go::HOOKS),
|
||||
},
|
||||
TemplateSources {
|
||||
id: TemplateId::SHELL,
|
||||
manifest: include_str!("../../../data/templates/shell/manifest.yml"),
|
||||
tpls: &[],
|
||||
tpls: &[
|
||||
(
|
||||
"script.tpl",
|
||||
include_str!("../../../data/templates/shell/script.tpl"),
|
||||
),
|
||||
(
|
||||
"install.tpl",
|
||||
include_str!("../../../data/templates/shell/install.tpl"),
|
||||
),
|
||||
],
|
||||
hooks: Some(&shell::HOOKS),
|
||||
},
|
||||
TemplateSources {
|
||||
id: TemplateId::MAKEFILE,
|
||||
manifest: include_str!("../../../data/templates/makefile/manifest.yml"),
|
||||
tpls: &[],
|
||||
tpls: &[
|
||||
(
|
||||
"hello.c.tpl",
|
||||
include_str!("../../../data/templates/makefile/hello.c.tpl"),
|
||||
),
|
||||
(
|
||||
"Makefile.tpl",
|
||||
include_str!("../../../data/templates/makefile/Makefile.tpl"),
|
||||
),
|
||||
(
|
||||
"install.tpl",
|
||||
include_str!("../../../data/templates/makefile/install.tpl"),
|
||||
),
|
||||
],
|
||||
hooks: Some(&makefile::HOOKS),
|
||||
},
|
||||
TemplateSources {
|
||||
id: TemplateId::EMPTY,
|
||||
manifest: include_str!("../../../data/templates/empty/manifest.yml"),
|
||||
tpls: &[],
|
||||
hooks: Some(&empty::HOOKS),
|
||||
tpls: &[(
|
||||
"README.tpl",
|
||||
include_str!("../../../data/templates/empty/README.tpl"),
|
||||
)],
|
||||
// Pure data: the empty template ships without any logic half.
|
||||
hooks: None,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -897,8 +931,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn probe_defaults_to_none() {
|
||||
// The empty and shell templates alike: the root directory is no
|
||||
// single-script project.
|
||||
// Hookless (empty) and probe-carrying (shell) templates alike: the
|
||||
// root directory is no single-script project.
|
||||
assert!(
|
||||
get(TemplateId::EMPTY)
|
||||
.unwrap()
|
||||
@@ -988,6 +1022,22 @@ mod tests {
|
||||
assert_eq!(files[2].contents, "extra");
|
||||
}
|
||||
|
||||
/// The empty template is pure data: a stub `README` skeleton, no extra
|
||||
/// debian/ files (the metapackage `Depends` payload travels in the
|
||||
/// options, not in the template).
|
||||
#[test]
|
||||
fn empty_template_shape() {
|
||||
let o = opts(TemplateId::EMPTY);
|
||||
let template = get(TemplateId::EMPTY).unwrap();
|
||||
assert!(template.debian(&o).is_empty());
|
||||
assert!(template.build_depends(&o).is_empty());
|
||||
let skeleton = template.skeleton(&o);
|
||||
assert_eq!(skeleton.len(), 1);
|
||||
assert_eq!(skeleton[0].path, "README");
|
||||
assert!(!skeleton[0].executable);
|
||||
assert!(skeleton[0].contents.contains("mytool"));
|
||||
}
|
||||
|
||||
/// Only the rust template contributes root `.gitignore` entries of its
|
||||
/// own — exactly the vendoring pair, unconditionally (its vendoring
|
||||
/// hook runs in every mode); every other template contributes nothing.
|
||||
|
||||
+21
-39
@@ -1,17 +1,17 @@
|
||||
//! The `shell` template: a single interpreted script installed to
|
||||
//! `/usr/bin` with plain `dh $@` plumbing.
|
||||
//!
|
||||
//! The data half lives in `data/templates/shell/manifest.yml`; the logic
|
||||
//! half here is the single-script probe pre-filling the wizard answers from
|
||||
//! the script file name (the same heuristic [`crate::new::detect`] bases
|
||||
//! its shell detection on) plus, for now, the skeleton script and its
|
||||
//! skeleton-only `debian/install` mapping (the manifest `files:` list takes
|
||||
//! those over once their bodies are static data).
|
||||
//! Everything except the probe is manifest data
|
||||
//! (`data/templates/shell/manifest.yml`: the skeleton script, its
|
||||
//! skeleton-only `debian/install` mapping, the plain `dh $@` plumbing).
|
||||
//! The logic half here pre-fills the wizard answers from the file name of
|
||||
//! the single top-level script — the same heuristic [`crate::new::detect`]
|
||||
//! bases its shell detection on.
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use super::{OutputFile, ProbeResult, TemplateHooks};
|
||||
use crate::new::options::{self, NewOptions, SourceDir};
|
||||
use super::{ProbeResult, TemplateHooks};
|
||||
use crate::new::options;
|
||||
|
||||
/// The logic half of the shell template.
|
||||
pub struct Hooks;
|
||||
@@ -20,34 +20,6 @@ pub struct Hooks;
|
||||
pub static HOOKS: Hooks = Hooks;
|
||||
|
||||
impl TemplateHooks for Hooks {
|
||||
/// A minimal executable script named after the command, with a `#!/bin/sh`
|
||||
/// shebang and an `echo` placeholder.
|
||||
fn skeleton_files(&self, opts: &NewOptions) -> Vec<OutputFile> {
|
||||
vec![OutputFile::executable(
|
||||
format!("{}.sh", opts.command),
|
||||
format!(
|
||||
"#!/bin/sh\n# Placeholder for {}, generated by `pkh new`.\n\
|
||||
echo \"Hello from {}!\"\n",
|
||||
opts.name, opts.command
|
||||
),
|
||||
)]
|
||||
}
|
||||
|
||||
/// `debian/install` mapping the script into `/usr/bin/<command>`
|
||||
/// (debian/install renames when the destination carries a file name).
|
||||
/// Only for the skeleton mode: when packaging an existing tree the
|
||||
/// generated mapping would reference the non-existent skeleton script,
|
||||
/// so the user writes their own install file instead.
|
||||
fn debian_files(&self, opts: &NewOptions) -> Vec<OutputFile> {
|
||||
if !matches!(opts.source_dir, SourceDir::Skeleton) {
|
||||
return Vec::new();
|
||||
}
|
||||
vec![OutputFile::new(
|
||||
"debian/install",
|
||||
format!("{}.sh usr/bin/{}\n", opts.command, opts.command),
|
||||
)]
|
||||
}
|
||||
|
||||
/// The file name of the single top-level script (sanitized) pre-fills the
|
||||
/// package name and command questions.
|
||||
fn probe(&self, dir: &Path) -> Option<ProbeResult> {
|
||||
@@ -64,12 +36,11 @@ impl TemplateHooks for Hooks {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::new::options::{License, SourceDir, TemplateId};
|
||||
use tempfile::tempdir;
|
||||
|
||||
fn opts() -> NewOptions {
|
||||
NewOptions {
|
||||
fn opts() -> crate::new::options::NewOptions {
|
||||
crate::new::options::NewOptions {
|
||||
name: "mytool".into(),
|
||||
template: TemplateId::SHELL,
|
||||
source_dir: SourceDir::Skeleton,
|
||||
@@ -103,16 +74,27 @@ mod tests {
|
||||
assert!(template.build_depends(&o).is_empty());
|
||||
assert!(template.rules_extra(&o).is_empty());
|
||||
|
||||
// The skeleton bodies are manifest data now: the executable script
|
||||
// and its skeleton-only install mapping.
|
||||
let skeleton = template.skeleton(&o);
|
||||
assert_eq!(skeleton.len(), 1);
|
||||
assert_eq!(skeleton[0].path, "mytool.sh");
|
||||
assert!(skeleton[0].executable);
|
||||
assert!(skeleton[0].contents.starts_with("#!/bin/sh\n"));
|
||||
assert!(skeleton[0].contents.contains("echo \"Hello from mytool!\""));
|
||||
|
||||
let debian = template.debian(&o);
|
||||
assert_eq!(debian.len(), 1);
|
||||
assert_eq!(debian[0].path, "debian/install");
|
||||
assert_eq!(debian[0].contents, "mytool.sh usr/bin/mytool\n");
|
||||
|
||||
// Packaging an existing tree: no install mapping is generated (it
|
||||
// would reference the non-existent skeleton script).
|
||||
let existing = crate::new::options::NewOptions {
|
||||
source_dir: SourceDir::Here,
|
||||
..opts()
|
||||
};
|
||||
assert!(template.debian(&existing).is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user