1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
use anyhow::{Context, Result};
use alef::cli::dispatch;
use super::args::*;
use super::dispatch::DispatchContext;
use super::helpers::*;
pub(crate) fn handle(command: Commands, context: &DispatchContext) -> Result<Option<Commands>> {
let config_path = &context.config_path;
match command {
Commands::Publish { action } => {
let (_workspace, resolved) = load_config(config_path)?;
let crates_to_process = dispatch::select_crates(&resolved, &context.crate_filter)?;
let multi = dispatch::is_multi_crate(&crates_to_process);
match action {
PublishAction::Prepare {
lang,
target,
dry_run,
require_registry,
} => {
let rust_target = target
.as_deref()
.map(alef::publish::platform::RustTarget::parse)
.transpose()?;
for resolved_cfg in &crates_to_process {
let languages = resolve_languages(resolved_cfg, lang.as_deref())?;
if multi {
eprintln!(
"[{}] Preparing publish for: {}",
resolved_cfg.name,
format_languages(&languages)
);
} else {
eprintln!("Preparing publish for: {}", format_languages(&languages));
}
alef::publish::prepare(
resolved_cfg,
&languages,
rust_target.as_ref(),
dry_run,
require_registry,
)?;
}
println!("Prepare complete");
Ok(None)
}
PublishAction::Build {
lang,
target,
use_cross,
} => {
let rust_target = target
.as_deref()
.map(alef::publish::platform::RustTarget::parse)
.transpose()?;
for resolved_cfg in &crates_to_process {
let languages = resolve_languages(resolved_cfg, lang.as_deref())?;
if multi {
eprintln!(
"[{}] Building publish artifacts for: {}",
resolved_cfg.name,
format_languages(&languages)
);
} else {
eprintln!("Building publish artifacts for: {}", format_languages(&languages));
}
alef::publish::build(resolved_cfg, &languages, rust_target.as_ref(), use_cross)?;
}
println!("Build complete");
Ok(None)
}
PublishAction::Package {
lang,
target,
output,
version,
dry_run,
php_version,
php_ts,
php_libc,
windows_compiler,
} => {
let rust_target = target
.as_deref()
.map(alef::publish::platform::RustTarget::parse)
.transpose()?;
let output_dir = std::path::Path::new(&output);
for resolved_cfg in &crates_to_process {
let languages = resolve_languages(resolved_cfg, lang.as_deref())?;
let ver = version
.clone()
.or_else(|| resolved_cfg.resolved_version())
.context("could not determine version — set --version or version_from in alef.toml")?;
// Build PHP-specific options when any PHP language is in the list.
let needs_php = languages.contains(&alef::core::config::Language::Php);
let pie_opts: Option<alef::publish::package::php::PiePackageOptions<'_>> = if needs_php {
let php_ver = php_version
.as_deref()
.context("--php-version is required when packaging --lang php")?;
let ts_mode = alef::publish::package::php::TsMode::parse(&php_ts)?;
// Validate: Windows target requires --windows-compiler.
if let Some(ref rt) = rust_target {
if rt.os == alef::publish::platform::Os::Windows && windows_compiler.is_none() {
anyhow::bail!(
"--windows-compiler is required when packaging PHP for a Windows target"
);
}
}
Some(alef::publish::package::php::PiePackageOptions {
php_version: php_ver,
ts_mode,
debug_mode: alef::publish::package::php::DebugMode::NoDebug,
libc_override: php_libc.as_deref(),
windows_compiler: windows_compiler.as_deref(),
})
} else {
None
};
let pkg_options = alef::publish::PackageOptions { php: pie_opts };
if multi {
eprintln!(
"[{}] Packaging {} (v{ver}) for: {}",
resolved_cfg.name,
output_dir.display(),
format_languages(&languages)
);
} else {
eprintln!(
"Packaging {} (v{ver}) for: {}",
output_dir.display(),
format_languages(&languages)
);
}
alef::publish::package(
resolved_cfg,
&languages,
rust_target.as_ref(),
output_dir,
&ver,
dry_run,
&pkg_options,
)?;
}
println!("Package complete");
Ok(None)
}
PublishAction::Validate => {
let mut all_issues: Vec<String> = Vec::new();
for resolved_cfg in &crates_to_process {
let languages = resolve_languages(resolved_cfg, None)?;
let issues = alef::publish::validate(resolved_cfg, &languages)?;
all_issues.extend(issues);
}
if all_issues.is_empty() {
println!("All package manifests are consistent");
} else {
eprintln!("Validation issues:");
for issue in &all_issues {
eprintln!(" - {issue}");
}
anyhow::bail!("{} validation issue(s) found", all_issues.len());
}
Ok(None)
}
}
}
other => Ok(Some(other)),
}
}