new: add pkh put, a native dput replacement for PPA uploads

Upload built source packages over SFTP with host-key verification
(Launchpad fingerprints pinned in host_keys.yml, ask-to-accept
otherwise), Launchpad account discovery (git config lp.user), and
pre-flight checks the upload queue itself never does: changes file
discovery/validation, PPA existence via the Launchpad API, target
series validity, and debian/control Section validity (sections
bundled in distro_info.yml). Upload log prevents duplicate uploads
unless --force.
This commit is contained in:
2026-09-16 21:38:53 +02:00
parent 9228ff448b
commit f27d27ea99
13 changed files with 2023 additions and 97 deletions
+38
View File
@@ -164,6 +164,13 @@ fn main() {
.about("Build the source package (into a .dsc)")
.arg(arg!(--verbose "Show raw tool output instead of the live build view").required(false)),
)
.subcommand(
Command::new("put")
.about("Upload the built source package to a PPA")
.arg(arg!(--ppa <ppa> "Upload to a PPA (format: user/ppa_name)"))
.arg(arg!([changes] "Explicit .changes file to upload (default: the one built from this package, next to the source tree)").required(false))
.arg(arg!(--force "Upload even if this exact .changes file was already uploaded to the target")),
)
.subcommand(
Command::new("deb")
.about("Build the source package into binary package (.deb)")
@@ -470,6 +477,37 @@ fn main() {
std::process::exit(1);
}
}
Some(("put", sub_matches)) => {
let cwd = current_dir_or_exit();
let ppa = sub_matches.get_one::<String>("ppa").map(|s| s.as_str());
let changes = sub_matches
.get_one::<String>("changes")
.map(std::path::PathBuf::from);
let force = sub_matches
.get_one::<bool>("force")
.copied()
.unwrap_or(false);
// Only PPA targets are implemented for now
let Some(ppa) = ppa else {
error!(
"pkh put needs a target: pass --ppa user/ppa_name \
(archive uploads are not supported yet)"
);
std::process::exit(1);
};
let options = pkh::put::PutOptions {
ppa: ppa.to_string(),
changes,
force,
cwd,
};
if let Err(e) = rt.block_on(async { pkh::put::put(&options, &multi).await }) {
error!("{}", e);
std::process::exit(1);
}
}
Some(("deb", sub_matches)) => {
let cwd = current_dir_or_exit();
let series = sub_matches.get_one::<String>("series").map(|s| s.as_str());