fmt, clippy
This commit is contained in:
+21
-8
@@ -6,7 +6,7 @@ use std::collections::{HashMap, HashSet, VecDeque};
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use crate::debian::checksums::FileChecksums;
|
use crate::debian::checksums::FileChecksums;
|
||||||
use crate::debian::control::{parse_paragraphs, write_paragraph, Paragraph};
|
use crate::debian::control::{Paragraph, parse_paragraphs, write_paragraph};
|
||||||
|
|
||||||
/// One installed package relevant for dependency resolution.
|
/// One installed package relevant for dependency resolution.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -52,13 +52,20 @@ impl StatusDb {
|
|||||||
};
|
};
|
||||||
let arch = para.get("Architecture").unwrap_or("").to_string();
|
let arch = para.get("Architecture").unwrap_or("").to_string();
|
||||||
if let (Some(version), false) = (para.get("Version"), arch.is_empty()) {
|
if let (Some(version), false) = (para.get("Version"), arch.is_empty()) {
|
||||||
db.pkgs.entry(package.to_string()).or_default().push(InstalledPkg {
|
db.pkgs
|
||||||
version: version.to_string(),
|
.entry(package.to_string())
|
||||||
arch: arch.clone(),
|
.or_default()
|
||||||
});
|
.push(InstalledPkg {
|
||||||
|
version: version.to_string(),
|
||||||
|
arch: arch.clone(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if para.get("Essential").map(|v| v.eq_ignore_ascii_case("yes")).unwrap_or(false) {
|
if para
|
||||||
|
.get("Essential")
|
||||||
|
.map(|v| v.eq_ignore_ascii_case("yes"))
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
db.essential.push(package.to_string());
|
db.essential.push(package.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,7 +298,10 @@ pub fn render_buildinfo(input: &BuildInfoInput) -> Paragraph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Serialize and atomically write a `.buildinfo` file.
|
/// Serialize and atomically write a `.buildinfo` file.
|
||||||
pub fn save_buildinfo(path: &Path, paragraph: &Paragraph) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn save_buildinfo(
|
||||||
|
path: &Path,
|
||||||
|
paragraph: &Paragraph,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let tmp = path.with_extension("new");
|
let tmp = path.with_extension("new");
|
||||||
std::fs::write(&tmp, write_paragraph(paragraph))
|
std::fs::write(&tmp, write_paragraph(paragraph))
|
||||||
.map_err(|e| format!("cannot write '{}': {}", tmp.display(), e))?;
|
.map_err(|e| format!("cannot write '{}': {}", tmp.display(), e))?;
|
||||||
@@ -366,7 +376,10 @@ Architecture: amd64
|
|||||||
#[test]
|
#[test]
|
||||||
fn wrap_binary_field() {
|
fn wrap_binary_field() {
|
||||||
assert_eq!(wrap_long("abc"), "abc");
|
assert_eq!(wrap_long("abc"), "abc");
|
||||||
let long = (0..500).map(|i| i.to_string()).collect::<Vec<_>>().join(" ");
|
let long = (0..500)
|
||||||
|
.map(|i| i.to_string())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(" ");
|
||||||
let wrapped = wrap_long(&long);
|
let wrapped = wrap_long(&long);
|
||||||
assert!(wrapped.contains('\n'));
|
assert!(wrapped.contains('\n'));
|
||||||
for line in wrapped.lines() {
|
for line in wrapped.lines() {
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ impl BuildType {
|
|||||||
|
|
||||||
/// The architecture suffix used in artifact file names:
|
/// The architecture suffix used in artifact file names:
|
||||||
/// host arch, `all` or `source`.
|
/// host arch, `all` or `source`.
|
||||||
pub fn arch_suffix<'a>(self, host_arch: &'a str) -> &'a str {
|
pub fn arch_suffix(self, host_arch: &str) -> &str {
|
||||||
if self.has_any(ARCH_DEP) {
|
if self.has_any(ARCH_DEP) {
|
||||||
host_arch
|
host_arch
|
||||||
} else if self.has_any(ARCH_INDEP) {
|
} else if self.has_any(ARCH_INDEP) {
|
||||||
@@ -133,7 +133,10 @@ mod tests {
|
|||||||
fn parse_options() {
|
fn parse_options() {
|
||||||
assert_eq!(BuildType::from_options("full").unwrap(), FULL);
|
assert_eq!(BuildType::from_options("full").unwrap(), FULL);
|
||||||
assert_eq!(BuildType::from_options("source").unwrap(), SOURCE);
|
assert_eq!(BuildType::from_options("source").unwrap(), SOURCE);
|
||||||
assert_eq!(BuildType::from_options("source,any").unwrap(), SOURCE_ARCH_DEP);
|
assert_eq!(
|
||||||
|
BuildType::from_options("source,any").unwrap(),
|
||||||
|
SOURCE_ARCH_DEP
|
||||||
|
);
|
||||||
assert_eq!(BuildType::from_options("any,all").unwrap(), BINARY);
|
assert_eq!(BuildType::from_options("any,all").unwrap(), BINARY);
|
||||||
assert!(BuildType::from_options("bogus").is_err());
|
assert!(BuildType::from_options("bogus").is_err());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use crate::debian::checksums::FileChecksums;
|
use crate::debian::checksums::FileChecksums;
|
||||||
use crate::debian::control::{write_paragraph, Paragraph};
|
use crate::debian::control::{Paragraph, write_paragraph};
|
||||||
use crate::debian::files::FilesList;
|
use crate::debian::files::FilesList;
|
||||||
|
|
||||||
/// Everything needed to render a `.changes` file.
|
/// Everything needed to render a `.changes` file.
|
||||||
@@ -165,7 +165,10 @@ mod tests {
|
|||||||
"verylongpkgname - short (udeb)"
|
"verylongpkgname - short (udeb)"
|
||||||
);
|
);
|
||||||
let long_summary = "x".repeat(100);
|
let long_summary = "x".repeat(100);
|
||||||
assert_eq!(format_description("p", "deb", &long_summary).len(), 10 + 3 + 65);
|
assert_eq!(
|
||||||
|
format_description("p", "deb", &long_summary).len(),
|
||||||
|
10 + 3 + 65
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -230,7 +233,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
files_value,
|
files_value,
|
||||||
"\n<md5> 8 utils optional pkg_1.0.dsc"
|
"\n<md5> 8 utils optional pkg_1.0.dsc"
|
||||||
.replace("<md5>", &files_value.split_whitespace().next().unwrap_or(""))
|
.replace("<md5>", files_value.split_whitespace().next().unwrap_or(""))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-11
@@ -54,14 +54,12 @@ pub fn arch_env(host_arch: Option<&str>) -> Result<BTreeMap<String, String>, Str
|
|||||||
cmd.args(["--host-arch", arch]);
|
cmd.args(["--host-arch", arch]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let output = cmd
|
let output = cmd.output().map_err(|e| {
|
||||||
.output()
|
format!(
|
||||||
.map_err(|e| {
|
"failed to run 'dpkg-architecture': {}. Is 'dpkg-dev' installed?",
|
||||||
format!(
|
e
|
||||||
"failed to run 'dpkg-architecture': {}. Is 'dpkg-dev' installed?",
|
)
|
||||||
e
|
})?;
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
@@ -83,8 +81,7 @@ pub fn arch_env(host_arch: Option<&str>) -> Result<BTreeMap<String, String>, Str
|
|||||||
/// Read the current vendor name from `/etc/dpkg/origins/default`
|
/// Read the current vendor name from `/etc/dpkg/origins/default`
|
||||||
/// (its `Vendor:` or `Origin:` field), defaulting to `"debian"`.
|
/// (its `Vendor:` or `Origin:` field), defaulting to `"debian"`.
|
||||||
pub fn current_vendor() -> String {
|
pub fn current_vendor() -> String {
|
||||||
read_vendor_from(Path::new("/etc/dpkg/origins/default"))
|
read_vendor_from(Path::new("/etc/dpkg/origins/default")).unwrap_or_else(|| "debian".to_string())
|
||||||
.unwrap_or_else(|| "debian".to_string())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_vendor_from(path: &Path) -> Option<String> {
|
fn read_vendor_from(path: &Path) -> Option<String> {
|
||||||
@@ -289,7 +286,7 @@ mod tests {
|
|||||||
let env = build_env(1787392800, 16, &[]);
|
let env = build_env(1787392800, 16, &[]);
|
||||||
assert_eq!(env.get("SOURCE_DATE_EPOCH").unwrap(), "1787392800");
|
assert_eq!(env.get("SOURCE_DATE_EPOCH").unwrap(), "1787392800");
|
||||||
assert_eq!(env.get("DEB_BUILD_OPTIONS").unwrap(), "parallel=16");
|
assert_eq!(env.get("DEB_BUILD_OPTIONS").unwrap(), "parallel=16");
|
||||||
assert!(env.get("DEB_BUILD_PROFILES").is_none());
|
assert!(!env.contains_key("DEB_BUILD_PROFILES"));
|
||||||
|
|
||||||
let env = build_env(1, 4, &["nodoc".to_string(), "cross".to_string()]);
|
let env = build_env(1, 4, &["nodoc".to_string(), "cross".to_string()]);
|
||||||
assert_eq!(env.get("DEB_BUILD_PROFILES").unwrap(), "nodoc,cross");
|
assert_eq!(env.get("DEB_BUILD_PROFILES").unwrap(), "nodoc,cross");
|
||||||
|
|||||||
+17
-4
@@ -17,7 +17,7 @@ use std::path::{Path, PathBuf};
|
|||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
use crate::debian::{
|
use crate::debian::{
|
||||||
parse_paragraphs, ChecksumEntry, ControlInfo, FileChecksums, FilesEntry, FilesList,
|
ChecksumEntry, ControlInfo, FileChecksums, FilesEntry, FilesList, parse_paragraphs,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Options for a native source-package build.
|
/// Options for a native source-package build.
|
||||||
@@ -151,7 +151,10 @@ pub fn run_source_build(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("failed to check for GPG key: {}, building without signing", e);
|
log::warn!(
|
||||||
|
"failed to check for GPG key: {}, building without signing",
|
||||||
|
e
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,7 +170,12 @@ pub fn run_source_build(
|
|||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// 5. dpkg-source lifecycle: before-build + source build
|
// 5. dpkg-source lifecycle: before-build + source build
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
run_command(cwd, "dpkg-source", &["-I", "-i", "--before-build", "."], &pipeline_env)?;
|
run_command(
|
||||||
|
cwd,
|
||||||
|
"dpkg-source",
|
||||||
|
&["-I", "-i", "--before-build", "."],
|
||||||
|
&pipeline_env,
|
||||||
|
)?;
|
||||||
run_command(cwd, "dpkg-source", &["-I", "-i", "-b", "."], &pipeline_env)?;
|
run_command(cwd, "dpkg-source", &["-I", "-i", "-b", "."], &pipeline_env)?;
|
||||||
|
|
||||||
if !dsc_path.exists() {
|
if !dsc_path.exists() {
|
||||||
@@ -333,7 +341,12 @@ pub fn run_source_build(
|
|||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// 8. dpkg-source after-build (unapplies quilt patches it applied)
|
// 8. dpkg-source after-build (unapplies quilt patches it applied)
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
run_command(cwd, "dpkg-source", &["-I", "-i", "--after-build", "."], &pipeline_env)?;
|
run_command(
|
||||||
|
cwd,
|
||||||
|
"dpkg-source",
|
||||||
|
&["-I", "-i", "--after-build", "."],
|
||||||
|
&pipeline_env,
|
||||||
|
)?;
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// 9. Signing cascade: dsc -> buildinfo -> changes
|
// 9. Signing cascade: dsc -> buildinfo -> changes
|
||||||
|
|||||||
@@ -56,9 +56,13 @@ pub fn parse_changelog_entry(path: &Path) -> Result<ChangelogEntry, Box<dyn std:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let open = header
|
let open = header.find('(').ok_or_else(|| {
|
||||||
.find('(')
|
format!(
|
||||||
.ok_or_else(|| format!("invalid changelog header in '{}': {}", path.display(), header))?;
|
"invalid changelog header in '{}': {}",
|
||||||
|
path.display(),
|
||||||
|
header
|
||||||
|
)
|
||||||
|
})?;
|
||||||
let close = header[open..]
|
let close = header[open..]
|
||||||
.find(')')
|
.find(')')
|
||||||
.ok_or_else(|| format!("unbalanced parenthesis in changelog header '{}'", header))?;
|
.ok_or_else(|| format!("unbalanced parenthesis in changelog header '{}'", header))?;
|
||||||
|
|||||||
+25
-11
@@ -90,17 +90,16 @@ pub fn parse_paragraphs(input: &str) -> Vec<Paragraph> {
|
|||||||
// Continuation line
|
// Continuation line
|
||||||
if line.starts_with(' ') || line.starts_with('\t') {
|
if line.starts_with(' ') || line.starts_with('\t') {
|
||||||
let content = line.strip_prefix(' ').unwrap_or(line);
|
let content = line.strip_prefix(' ').unwrap_or(line);
|
||||||
if let Some(field) = &last_field {
|
if let Some(field) = &last_field
|
||||||
if let Some((_, v)) = current
|
&& let Some((_, v)) = current
|
||||||
.fields
|
.fields
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.rev()
|
.rev()
|
||||||
.find(|(k, _)| k.eq_ignore_ascii_case(field))
|
.find(|(k, _)| k.eq_ignore_ascii_case(field))
|
||||||
{
|
{
|
||||||
v.push('\n');
|
v.push('\n');
|
||||||
v.push_str(content);
|
v.push_str(content);
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Continuation without a preceding field line: skip it (malformed)
|
// Continuation without a preceding field line: skip it (malformed)
|
||||||
continue;
|
continue;
|
||||||
@@ -174,7 +173,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn parse_multiline_and_comments() {
|
fn parse_multiline_and_comments() {
|
||||||
let input = "# a comment\nDescription: short\n long description\n" //
|
let input = "# a comment\nDescription: short\n long description\n" //
|
||||||
.to_string() //
|
.to_string()
|
||||||
+ " spanning lines\n\nPackage: x\n";
|
+ " spanning lines\n\nPackage: x\n";
|
||||||
let paras = parse_paragraphs(&input);
|
let paras = parse_paragraphs(&input);
|
||||||
assert_eq!(paras.len(), 2);
|
assert_eq!(paras.len(), 2);
|
||||||
@@ -190,7 +189,10 @@ mod tests {
|
|||||||
let mut p = Paragraph::new();
|
let mut p = Paragraph::new();
|
||||||
p.set("Description", value);
|
p.set("Description", value);
|
||||||
let text = write_paragraph(&p);
|
let text = write_paragraph(&p);
|
||||||
assert_eq!(text, "Description: short\n long description\n spanning lines\n");
|
assert_eq!(
|
||||||
|
text,
|
||||||
|
"Description: short\n long description\n spanning lines\n"
|
||||||
|
);
|
||||||
let reparsed = parse_paragraphs(&text);
|
let reparsed = parse_paragraphs(&text);
|
||||||
assert_eq!(reparsed[0].get("Description"), Some(value));
|
assert_eq!(reparsed[0].get("Description"), Some(value));
|
||||||
}
|
}
|
||||||
@@ -228,12 +230,15 @@ impl ControlInfo {
|
|||||||
pub fn parse(path: &Path) -> Result<ControlInfo, Box<dyn std::error::Error>> {
|
pub fn parse(path: &Path) -> Result<ControlInfo, Box<dyn std::error::Error>> {
|
||||||
let content = std::fs::read_to_string(path)
|
let content = std::fs::read_to_string(path)
|
||||||
.map_err(|e| format!("failed to read control file '{}': {}", path.display(), e))?;
|
.map_err(|e| format!("failed to read control file '{}': {}", path.display(), e))?;
|
||||||
Self::from_str(&content)
|
content
|
||||||
|
.parse::<ControlInfo>()
|
||||||
.map_err(|e| format!("invalid control file '{}': {}", path.display(), e).into())
|
.map_err(|e| format!("invalid control file '{}': {}", path.display(), e).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse control content from a string.
|
/// Parse control content from a string.
|
||||||
pub fn from_str(content: &str) -> Result<ControlInfo, String> {
|
///
|
||||||
|
/// Prefer [`std::str::FromStr`] (`"...".parse::<ControlInfo>()`).
|
||||||
|
pub fn parse_content(content: &str) -> Result<ControlInfo, String> {
|
||||||
let paragraphs = parse_paragraphs(content);
|
let paragraphs = parse_paragraphs(content);
|
||||||
let mut iter = paragraphs.into_iter();
|
let mut iter = paragraphs.into_iter();
|
||||||
let source = iter
|
let source = iter
|
||||||
@@ -267,9 +272,18 @@ impl ControlInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::str::FromStr for ControlInfo {
|
||||||
|
type Err = String;
|
||||||
|
|
||||||
|
fn from_str(content: &str) -> Result<Self, Self::Err> {
|
||||||
|
ControlInfo::parse_content(content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod control_info_tests {
|
mod control_info_tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn control_parsing() {
|
fn control_parsing() {
|
||||||
|
|||||||
+10
-3
@@ -61,8 +61,11 @@ pub fn parse_filename(name: &str) -> Option<FilesEntry> {
|
|||||||
if let Some(dot) = rest.rfind('.') {
|
if let Some(dot) = rest.rfind('.') {
|
||||||
let arch = &rest[..dot];
|
let arch = &rest[..dot];
|
||||||
let ptype = &rest[dot + 1..];
|
let ptype = &rest[dot + 1..];
|
||||||
let valid = |s: &str| !s.is_empty()
|
let valid = |s: &str| {
|
||||||
&& s.chars().all(|c| c.is_ascii_alphanumeric() || "-+.:~".contains(c));
|
!s.is_empty()
|
||||||
|
&& s.chars()
|
||||||
|
.all(|c| c.is_ascii_alphanumeric() || "-+.:~".contains(c))
|
||||||
|
};
|
||||||
if valid(pkg) && valid(version) && valid(arch) && valid(ptype) {
|
if valid(pkg) && valid(version) && valid(arch) && valid(ptype) {
|
||||||
return Some(FilesEntry {
|
return Some(FilesEntry {
|
||||||
filename: name.to_string(),
|
filename: name.to_string(),
|
||||||
@@ -128,7 +131,11 @@ impl FilesList {
|
|||||||
return Err(format!("badly formed line in '{}': {}", path.display(), line).into());
|
return Err(format!("badly formed line in '{}': {}", path.display(), line).into());
|
||||||
}
|
}
|
||||||
let mut entry = parse_filename(tokens[0]).ok_or_else(|| {
|
let mut entry = parse_filename(tokens[0]).ok_or_else(|| {
|
||||||
format!("badly formed file name in '{}': {}", path.display(), tokens[0])
|
format!(
|
||||||
|
"badly formed file name in '{}': {}",
|
||||||
|
path.display(),
|
||||||
|
tokens[0]
|
||||||
|
)
|
||||||
})?;
|
})?;
|
||||||
entry.section = tokens[1].to_string();
|
entry.section = tokens[1].to_string();
|
||||||
entry.priority = tokens[2].to_string();
|
entry.priority = tokens[2].to_string();
|
||||||
|
|||||||
+2
-2
@@ -15,8 +15,8 @@ pub mod control;
|
|||||||
pub mod files;
|
pub mod files;
|
||||||
pub mod version;
|
pub mod version;
|
||||||
|
|
||||||
pub use changelog::{parse_changelog_entry, ChangelogEntry};
|
pub use changelog::{ChangelogEntry, parse_changelog_entry};
|
||||||
pub use checksums::{Entry as ChecksumEntry, FileChecksums};
|
pub use checksums::{Entry as ChecksumEntry, FileChecksums};
|
||||||
pub use control::{parse_paragraphs, write_paragraph, ControlInfo, Paragraph};
|
pub use control::{ControlInfo, Paragraph, parse_paragraphs, write_paragraph};
|
||||||
pub use files::{FilesEntry, FilesList};
|
pub use files::{FilesEntry, FilesList};
|
||||||
pub use version::DebianVersion;
|
pub use version::DebianVersion;
|
||||||
|
|||||||
+2
-2
@@ -9,11 +9,11 @@ pub mod apt;
|
|||||||
pub mod build;
|
pub mod build;
|
||||||
/// Parse or edit a Debian changelog of a source package
|
/// Parse or edit a Debian changelog of a source package
|
||||||
pub mod changelog;
|
pub mod changelog;
|
||||||
|
/// Build a Debian package into a binary (.deb)
|
||||||
|
pub mod deb;
|
||||||
/// Reusable Debian format primitives (control/deb822, checksums, versions,
|
/// Reusable Debian format primitives (control/deb822, checksums, versions,
|
||||||
/// changelog entries, artifact registries)
|
/// changelog entries, artifact registries)
|
||||||
pub mod debian;
|
pub mod debian;
|
||||||
/// Build a Debian package into a binary (.deb)
|
|
||||||
pub mod deb;
|
|
||||||
/// Obtain general information about distribution, series, etc
|
/// Obtain general information about distribution, series, etc
|
||||||
pub mod distro_info;
|
pub mod distro_info;
|
||||||
/// Obtain information about one or multiple packages
|
/// Obtain information about one or multiple packages
|
||||||
|
|||||||
+5
-7
@@ -46,9 +46,7 @@ pub fn find_signing_key_for_email(
|
|||||||
pub fn validate_key_id(keyid: &str) -> Result<(), Box<dyn Error>> {
|
pub fn validate_key_id(keyid: &str) -> Result<(), Box<dyn Error>> {
|
||||||
let len = keyid.len();
|
let len = keyid.len();
|
||||||
if len <= 8 {
|
if len <= 8 {
|
||||||
return Err(
|
return Err("short OpenPGP key IDs are broken; use a key fingerprint instead".into());
|
||||||
"short OpenPGP key IDs are broken; use a key fingerprint instead".into(),
|
|
||||||
);
|
|
||||||
} else if len <= 16 {
|
} else if len <= 16 {
|
||||||
log::warn!(
|
log::warn!(
|
||||||
"long OpenPGP key IDs are strongly discouraged; \
|
"long OpenPGP key IDs are strongly discouraged; \
|
||||||
@@ -65,10 +63,10 @@ pub fn validate_key_id(keyid: &str) -> Result<(), Box<dyn Error>> {
|
|||||||
fn find_secret_key(ctx: &mut Context, keyid: &str) -> Result<Option<gpgme::Key>, Box<dyn Error>> {
|
fn find_secret_key(ctx: &mut Context, keyid: &str) -> Result<Option<gpgme::Key>, Box<dyn Error>> {
|
||||||
for key_result in ctx.secret_keys()? {
|
for key_result in ctx.secret_keys()? {
|
||||||
let key = key_result?;
|
let key = key_result?;
|
||||||
if let Ok(fingerprint) = key.fingerprint() {
|
if let Ok(fingerprint) = key.fingerprint()
|
||||||
if fingerprint.ends_with(keyid) {
|
&& fingerprint.ends_with(keyid)
|
||||||
return Ok(Some(key));
|
{
|
||||||
}
|
return Ok(Some(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
|||||||
Reference in New Issue
Block a user