pub mod apt;
pub mod debcommit;
pub mod directory;
pub mod error;
pub mod import_dsc;
pub mod merge_upstream;
pub mod release;
pub mod upstream;
pub mod vcs_up_to_date;
pub const DEFAULT_BUILD_DIR: &str = "../build-area";
pub const DEFAULT_ORIG_DIR: &str = "..";
pub const DEFAULT_RESULT_DIR: &str = "..";
use crate::branch::PyBranch;
use crate::debian::error::Error as DebianError;
use crate::error::Error;
use crate::tree::PyTree;
use crate::workingtree::PyWorkingTree;
use std::collections::HashMap;
use std::path::PathBuf;
use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;
use pyo3::types::PyDict;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Vendor {
Debian,
Ubuntu,
Kali,
}
impl std::fmt::Display for Vendor {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Vendor::Debian => write!(f, "debian"),
Vendor::Ubuntu => write!(f, "ubuntu"),
Vendor::Kali => write!(f, "kali"),
}
}
}
impl std::str::FromStr for Vendor {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"debian" => Ok(Vendor::Debian),
"ubuntu" => Ok(Vendor::Ubuntu),
"kali" => Ok(Vendor::Kali),
_ => Err(format!("Invalid vendor: {}", s)),
}
}
}
impl<'a, 'py> FromPyObject<'a, 'py> for Vendor {
type Error = PyErr;
fn extract(ob: Borrowed<'a, 'py, PyAny>) -> PyResult<Self> {
let vendor = ob.extract::<String>()?;
match vendor.as_str() {
"debian" => Ok(Vendor::Debian),
"ubuntu" => Ok(Vendor::Ubuntu),
"kali" => Ok(Vendor::Kali),
_ => Err(PyValueError::new_err((format!(
"Invalid vendor: {}",
vendor
),))),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, std::hash::Hash, Default)]
pub enum VersionKind {
#[default]
Auto,
Snapshot,
Release,
}
impl std::str::FromStr for VersionKind {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"auto" => Ok(VersionKind::Auto),
"snapshot" => Ok(VersionKind::Snapshot),
"release" => Ok(VersionKind::Release),
_ => Err(format!("Invalid version kind: {}", s)),
}
}
}
impl<'py> IntoPyObject<'py> for VersionKind {
type Target = PyAny;
type Output = Bound<'py, PyAny>;
type Error = PyErr;
fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
let s = match self {
VersionKind::Auto => "auto",
VersionKind::Snapshot => "snapshot",
VersionKind::Release => "release",
};
Ok(s.into_pyobject(py)?.into_any())
}
}
impl std::fmt::Display for VersionKind {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
VersionKind::Auto => write!(f, "auto"),
VersionKind::Snapshot => write!(f, "snapshot"),
VersionKind::Release => write!(f, "release"),
}
}
}
impl<'a, 'py> FromPyObject<'a, 'py> for VersionKind {
type Error = PyErr;
fn extract(ob: Borrowed<'a, 'py, PyAny>) -> PyResult<Self> {
let kind = ob.extract::<String>()?;
match kind.as_str() {
"auto" => Ok(VersionKind::Auto),
"snapshot" => Ok(VersionKind::Snapshot),
"release" => Ok(VersionKind::Release),
_ => Err(PyValueError::new_err((format!(
"Invalid version kind: {}",
kind
),))),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, std::hash::Hash)]
pub enum TarballKind {
Orig,
Additional(String),
}
impl serde::ser::Serialize for TarballKind {
fn serialize<S: serde::ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
TarballKind::Orig => serializer.serialize_none(),
TarballKind::Additional(kind) => serializer.serialize_some(kind),
}
}
}
impl<'a> serde::de::Deserialize<'a> for TarballKind {
fn deserialize<D: serde::de::Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
let kind = Option::<String>::deserialize(deserializer)?;
Ok(kind.into())
}
}
impl From<Option<String>> for TarballKind {
fn from(kind: Option<String>) -> Self {
match kind {
Some(kind) => TarballKind::Additional(kind),
None => TarballKind::Orig,
}
}
}
impl From<TarballKind> for Option<String> {
fn from(kind: TarballKind) -> Self {
match kind {
TarballKind::Orig => None,
TarballKind::Additional(kind) => Some(kind),
}
}
}
impl<'a, 'py> FromPyObject<'a, 'py> for TarballKind {
type Error = PyErr;
fn extract(ob: Borrowed<'a, 'py, PyAny>) -> PyResult<Self> {
let kind = ob.extract::<Option<String>>()?;
Ok(kind.into())
}
}
impl<'py> IntoPyObject<'py> for TarballKind {
type Target = PyAny;
type Output = Bound<'py, PyAny>;
type Error = PyErr;
fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
let o: Option<String> = self.into();
Ok(o.into_pyobject(py)?.into_any())
}
}
pub fn build_helper(
local_tree: &dyn PyWorkingTree,
subpath: &std::path::Path,
branch: &dyn PyBranch,
target_dir: &std::path::Path,
builder: &str,
guess_upstream_branch_url: bool,
apt_repo: Option<&dyn apt::Apt>,
) -> Result<HashMap<String, PathBuf>, DebianError> {
Python::attach(|py| -> PyResult<HashMap<String, PathBuf>> {
let locals = PyDict::new(py);
locals.set_item("local_tree", local_tree.to_object(py))?;
locals.set_item("subpath", subpath.to_string_lossy().to_string())?;
locals.set_item("branch", branch.to_object(py))?;
locals.set_item("target_dir", target_dir.to_string_lossy().to_string())?;
locals.set_item("builder", builder)?;
locals.set_item("guess_upstream_branch_url", guess_upstream_branch_url)?;
if let Some(apt_repo) = apt_repo {
locals.set_item("apt", apt_repo.as_pyobject())?;
}
py.import("breezy.plugins.debian.cmds")?
.call_method1("_build_helper", (locals,))?
.extract()
})
.map_err(DebianError::from)
}
pub fn tree_debian_tag_name(
tree: &dyn PyTree,
branch: &dyn PyBranch,
subpath: Option<&std::path::Path>,
vendor: Option<Vendor>,
) -> Result<String, Error> {
Python::attach(|py| {
let result = py.import("breezy.plugins.debian")?.call_method1(
"tree_debian_tag_name",
(
tree.to_object(py),
branch.to_object(py),
subpath,
vendor.map(|v| v.to_string()),
),
)?;
Ok(result.extract()?)
})
}
pub fn suite_to_distribution(suite: &str) -> Option<Vendor> {
Python::attach(|py| -> PyResult<Option<Vendor>> {
let result = py
.import("breezy.plugins.debian.util")?
.call_method1("suite_to_distribution", (suite,))?;
result.extract()
})
.unwrap()
}