svp-client-0.2.0/.cargo_vcs_info.json0000644000000001500000000000100131130ustar { "git": { "sha1": "e917d6a0dd87f8b0a83741afc39b52459fef8fbe" }, "path_in_vcs": "svp-client" }svp-client-0.2.0/Cargo.toml0000644000000017730000000000100111250ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "svp-client" version = "0.2.0" authors = ["Jelmer Vernooij "] build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Client for the silver-platter protocol" readme = false license = "Apache-2.0" [lib] name = "svp_client" path = "src/lib.rs" [dependencies.log] version = ">=0.4" [dependencies.serde] version = "1" features = ["derive"] [dependencies.serde_json] version = "1" [dependencies.url] version = "2" features = ["serde"] svp-client-0.2.0/Cargo.toml.orig000064400000000000000000000005331046102023000145770ustar 00000000000000[package] name = "svp-client" version = "0.2.0" authors = ["Jelmer Vernooij "] edition = "2021" license = "Apache-2.0" description = "Client for the silver-platter protocol" [lib] [dependencies] log = ">=0.4" serde = { workspace = true, features = ["derive"] } serde_json = "1" url = { workspace = true, features = ["serde"] } svp-client-0.2.0/src/lib.rs000064400000000000000000000160551046102023000136210ustar 00000000000000//! # svp-client //! //! `svp-client` is a library to interact with the [SVP //! protocol](https://github.com/jelmer/silver-platter/blob/master/codemod-protocol.md), as supported by //! the `svp` command-line tool. use std::collections::HashMap; #[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)] /// Behaviour for updating the changelog. pub struct ChangelogBehaviour { #[serde(rename = "update")] /// Whether the changelog should be updated. pub update_changelog: bool, /// Explanation for the decision. pub explanation: String, } #[derive(Debug, serde::Serialize)] struct Failure { pub result_code: String, pub versions: HashMap, pub description: String, pub transient: Option, } impl std::fmt::Display for Failure { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}: {}", self.result_code, self.description) } } impl std::error::Error for Failure {} impl std::fmt::Display for Success { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "Success") } } #[derive(Debug, serde::Serialize)] struct DebianContext { pub changelog: Option, } #[derive(Debug, serde::Serialize)] struct Success { pub versions: HashMap, pub value: Option, pub context: Option, pub debian: Option, #[serde(rename = "target-branch-url")] pub target_branch_url: Option, #[serde(rename = "commit-message")] pub commit_message: Option, } /// Write a success to the SVP API fn write_svp_success(data: &Success) -> std::io::Result<()> { if enabled() { let f = std::fs::File::create(std::env::var("SVP_RESULT").unwrap()).unwrap(); Ok(serde_json::to_writer(f, data)?) } else { Ok(()) } } /// Write a failure to the SVP API fn write_svp_failure(data: &Failure) -> std::io::Result<()> { if enabled() { let f = std::fs::File::create(std::env::var("SVP_RESULT").unwrap()).unwrap(); Ok(serde_json::to_writer(f, data)?) } else { Ok(()) } } /// Report success pub fn report_success(versions: HashMap, value: Option, context: Option) where T: serde::Serialize, { write_svp_success(&Success { versions, value, context: context.map(|x| serde_json::to_value(x).unwrap()), debian: None, target_branch_url: None, commit_message: None, }) .unwrap(); } /// Report success with Debian-specific context pub fn report_success_debian( versions: HashMap, value: Option, context: Option, changelog: Option, ) where T: serde::Serialize, { write_svp_success(&Success { versions, value, context: context.map(|x| serde_json::to_value(x).unwrap()), debian: Some(DebianContext { changelog }), target_branch_url: None, commit_message: None, }) .unwrap(); } /// Report that there is nothing to do pub fn report_nothing_to_do( versions: HashMap, description: Option<&str>, hint: Option<&str>, ) -> ! { let description = description.unwrap_or("Nothing to do"); write_svp_failure(&Failure { result_code: "nothing-to-do".to_string(), versions, description: description.to_string(), transient: None, }) .unwrap(); log::error!("{}", description); if let Some(hint) = hint { log::info!("{}", hint); } std::process::exit(0); } /// Report a fatal error pub fn report_fatal( versions: HashMap, code: &str, description: &str, hint: Option<&str>, transient: Option, ) -> ! { write_svp_failure(&Failure { result_code: code.to_string(), versions, description: description.to_string(), transient, }) .unwrap(); log::error!("{}", description); if let Some(hint) = hint { log::info!("{}", hint); } std::process::exit(1); } /// Load the resume file if it exists pub fn load_resume() -> Option { if enabled() { if let Ok(resume_path) = std::env::var("SVP_RESUME") { let f = std::fs::File::open(resume_path).unwrap(); let resume: T = serde_json::from_reader(f).unwrap(); Some(resume) } else { None } } else { None } } /// Check if the SVP API is enabled pub fn enabled() -> bool { std::env::var("SVP_API").ok().as_deref() == Some("1") } /// A reporter for the SVP API pub struct Reporter { versions: HashMap, target_branch_url: Option, commit_message: Option, } impl Reporter { /// Create a new reporter pub fn new(versions: HashMap) -> Self { Self { versions, target_branch_url: None, commit_message: None, } } /// Check if the SVP API is enabled pub fn enabled(&self) -> bool { enabled() } /// Load the resume file if it exists pub fn load_resume(&self) -> Option { load_resume() } /// Set the target branch URL pub fn set_target_branch_url(&mut self, url: url::Url) { self.target_branch_url = Some(url); } /// Set the commit message pub fn set_commit_message(&mut self, message: String) { self.commit_message = Some(message); } /// Report success pub fn report_success(self, value: Option, context: Option) where T: serde::Serialize, { write_svp_success(&Success { versions: self.versions, value, context: context.map(|x| serde_json::to_value(x).unwrap()), debian: None, target_branch_url: self.target_branch_url, commit_message: self.commit_message, }) .unwrap(); } /// Report success with Debian-specific context pub fn report_success_debian( self, value: Option, context: Option, changelog: Option, ) where T: serde::Serialize, { write_svp_success(&Success { versions: self.versions, value, context: context.map(|x| serde_json::to_value(x).unwrap()), debian: Some(DebianContext { changelog }), target_branch_url: self.target_branch_url, commit_message: self.commit_message, }) .unwrap(); } /// Report that there is nothing to do pub fn report_nothing_to_do(self, description: Option<&str>, hint: Option<&str>) -> ! { report_nothing_to_do(self.versions, description, hint); } /// Report a fatal error pub fn report_fatal( self, code: &str, description: &str, hint: Option<&str>, transient: Option, ) -> ! { report_fatal(self.versions, code, description, hint, transient); } }