#![deny(missing_docs)]
#![allow(unexpected_cfgs)]
#![allow(clippy::result_large_err)]
pub mod bazaar;
pub mod branch;
pub mod clean_tree;
pub mod commit;
pub mod config;
pub mod controldir;
pub mod cvs;
pub mod darcs;
pub mod delta;
pub mod diff;
#[cfg(feature = "dirty-tracker")]
pub mod dirty_tracker;
pub mod error;
pub mod export;
pub mod foreign;
pub mod forge;
pub mod fossil;
pub mod git;
pub mod github;
pub mod gitlab;
pub mod gpg;
pub mod graph;
pub mod groupcompress;
pub mod hooks;
pub mod interrepository;
pub mod intertree;
pub mod knit;
#[cfg(feature = "launchpad")]
pub mod launchpad;
pub mod location;
pub mod lock;
pub mod mercurial;
pub mod merge;
pub mod osutils;
pub mod patches;
pub mod plugin;
pub mod prelude;
pub mod rename_map;
pub mod repository;
pub mod revisionid;
pub mod search;
pub mod status;
pub mod subversion;
pub mod tags;
pub mod testing;
pub mod transform;
pub mod transport;
pub mod tree;
pub mod tsort;
pub mod ui;
pub mod urlutils;
pub mod version;
pub mod versionedfiles;
pub mod weave;
pub mod workingtree;
pub mod workspace;
#[cfg(feature = "debian")]
pub mod debian;
pub use branch::Branch;
pub use controldir::{ControlDir, Prober};
pub use forge::{get_forge, Forge, MergeProposal, MergeProposalStatus};
pub use lock::Lock;
use pyo3::exceptions::PyImportError;
use pyo3::prelude::*;
pub use revisionid::RevisionId;
pub use transport::{get_transport, Transport};
pub use tree::{RevisionTree, Tree, WorkingTree};
pub use urlutils::{join_segment_parameters, split_segment_parameters};
pub use workspace::reset_tree;
pub fn init_git() {
pyo3::Python::attach(|py| {
py.import("breezy.git").unwrap();
})
}
pub fn init_bzr() {
pyo3::Python::attach(|py| {
py.import("breezy.bzr").unwrap();
})
}
#[cfg(feature = "auto-initialize")]
#[ctor::ctor]
fn ensure_initialized() {
init();
}
const MINIMUM_VERSION: (usize, usize, usize) = (3, 3, 6);
#[derive(Debug, Clone)]
pub enum BreezyInitError {
NotInstalled,
VersionTooOld {
installed: (usize, usize, usize),
required: (usize, usize, usize),
},
Other(String),
}
impl std::fmt::Display for BreezyInitError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
BreezyInitError::NotInstalled => {
write!(f, "Breezy is not installed. Please install Breezy first.")
}
BreezyInitError::VersionTooOld {
installed,
required,
} => write!(
f,
"Breezy version {}.{}.{} is too old, please upgrade to at least {}.{}.{}.",
installed.0, installed.1, installed.2, required.0, required.1, required.2
),
BreezyInitError::Other(e) => write!(f, "{}", e),
}
}
}
impl std::error::Error for BreezyInitError {}
static INIT_BREEZY: std::sync::OnceLock<std::result::Result<(), BreezyInitError>> =
std::sync::OnceLock::new();
fn do_init() -> std::result::Result<(), BreezyInitError> {
pyo3::Python::initialize();
let (major, minor, micro) = pyo3::Python::attach(|py| match py.import("breezy") {
Ok(breezy) => {
let (major, minor, micro, _releaselevel, _serial): (
usize,
usize,
usize,
String,
usize,
) = breezy.getattr("version_info").unwrap().extract().unwrap();
Ok((major, minor, micro))
}
Err(e) => {
if e.is_instance_of::<PyImportError>(py) {
Err(BreezyInitError::NotInstalled)
} else {
Err(BreezyInitError::Other(e.to_string()))
}
}
})?;
if (major, minor, micro) < MINIMUM_VERSION {
return Err(BreezyInitError::VersionTooOld {
installed: (major, minor, micro),
required: MINIMUM_VERSION,
});
}
if major >= 4 {
log::warn!("Support for Breezy 4.0 is experimental and incomplete.");
}
init_git();
init_bzr();
pyo3::Python::attach(|py| {
let m = py.import("breezy.controldir").unwrap();
let f = m.getattr("ControlDirFormat").unwrap();
f.call_method0("known_formats").unwrap();
});
pyo3::Python::attach(|py| {
let m = py.import("breezy.config").unwrap();
m.call_method0("GlobalStack").unwrap();
m.call_method1("LocationStack", ("file:///",)).unwrap();
});
Ok(())
}
pub fn try_init() -> std::result::Result<(), BreezyInitError> {
INIT_BREEZY.get_or_init(do_init).clone()
}
pub fn init() {
try_init().unwrap();
}
pub type Result<R> = std::result::Result<R, crate::error::Error>;