use std::path::PathBuf;
use time::OffsetDateTime;
pub struct Session {
pub(crate) repo: gix::Repository,
pub(crate) store: crate::db::Store,
pub(crate) namespace: String,
pub(crate) email: String,
pub(crate) name: String,
pub(crate) timestamp_override: Option<i64>,
}
impl Session {
pub fn discover() -> crate::error::Result<Self> {
let repo = crate::git_utils::discover_repo()?;
Self::from_repo(repo)
}
pub fn open(directory: impl Into<PathBuf>) -> crate::error::Result<Self> {
Self::from_repo(gix::open(directory).map_err(|err| crate::error::Error::Git(err.into()))?)
}
#[must_use]
pub fn with_timestamp(mut self, timestamp_ms: i64) -> Self {
self.timestamp_override = Some(timestamp_ms);
self
}
pub(crate) fn now(&self) -> i64 {
self.timestamp_override
.unwrap_or_else(|| OffsetDateTime::now_utc().unix_timestamp_nanos() as i64 / 1_000_000)
}
fn from_repo(repo: gix::Repository) -> crate::error::Result<Self> {
let db_path = crate::git_utils::db_path(&repo)?;
let email = crate::git_utils::get_email(&repo)?;
let name = crate::git_utils::get_name(&repo)?;
let namespace = crate::git_utils::get_namespace(&repo)?;
let store = crate::db::Store::open_with_repo(&db_path, repo.clone())?;
Ok(Self {
repo,
store,
namespace,
email,
name,
timestamp_override: None,
})
}
#[cfg(feature = "internal")]
pub fn store(&self) -> &crate::db::Store {
&self.store
}
#[cfg(feature = "internal")]
pub fn repo(&self) -> &gix::Repository {
&self.repo
}
pub fn namespace(&self) -> &str {
&self.namespace
}
pub fn email(&self) -> &str {
&self.email
}
pub fn name(&self) -> &str {
&self.name
}
pub(crate) fn local_ref(&self) -> String {
format!("refs/{}/local/main", self.namespace)
}
pub(crate) fn destination_ref(&self, destination: &str) -> String {
format!("refs/{}/local/{}", self.namespace, destination)
}
pub fn target(
&self,
target: &crate::types::Target,
) -> crate::session_handle::SessionTargetHandle<'_> {
crate::session_handle::SessionTargetHandle::new(self, target.clone())
}
pub fn resolve_target(
&self,
target: &crate::types::Target,
) -> crate::error::Result<crate::types::Target> {
target.resolve(&self.repo)
}
pub fn resolve_remote(&self, remote: Option<&str>) -> crate::error::Result<String> {
crate::git_utils::resolve_meta_remote(&self.repo, remote)
}
pub(crate) fn index_history(
&self,
tip_oid: gix::ObjectId,
old_tip: Option<gix::ObjectId>,
) -> crate::error::Result<usize> {
crate::sync::insert_promisor_entries(&self.repo, &self.store, tip_oid, old_tip)
}
pub fn serialize(&self) -> crate::error::Result<crate::serialize::SerializeOutput> {
crate::serialize::run(self, self.now(), false)
}
pub fn serialize_with_progress(
&self,
progress: impl FnMut(crate::serialize::SerializeProgress),
) -> crate::error::Result<crate::serialize::SerializeOutput> {
crate::serialize::run_with_progress(self, self.now(), false, progress)
}
pub fn serialize_full(&self) -> crate::error::Result<crate::serialize::SerializeOutput> {
crate::serialize::run(self, self.now(), true)
}
pub fn serialize_full_with_progress(
&self,
progress: impl FnMut(crate::serialize::SerializeProgress),
) -> crate::error::Result<crate::serialize::SerializeOutput> {
crate::serialize::run_with_progress(self, self.now(), true, progress)
}
pub fn materialize(
&self,
remote: Option<&str>,
) -> crate::error::Result<crate::materialize::MaterializeOutput> {
crate::materialize::run(self, remote, self.now())
}
pub fn pull(&self, remote: Option<&str>) -> crate::error::Result<crate::pull::PullOutput> {
crate::pull::run(self, remote, self.now())
}
pub fn push_once(&self, remote: Option<&str>) -> crate::error::Result<crate::push::PushOutput> {
crate::push::push_once(self, remote, self.now())
}
pub fn push_once_with_progress(
&self,
remote: Option<&str>,
progress: impl FnMut(crate::push::PushProgress),
) -> crate::error::Result<crate::push::PushOutput> {
crate::push::push_once_with_progress(self, remote, self.now(), progress)
}
pub fn resolve_push_conflict(&self, remote: Option<&str>) -> crate::error::Result<()> {
crate::push::resolve_push_conflict(self, remote, self.now())
}
pub fn resolve_push_conflict_with_progress(
&self,
remote: Option<&str>,
progress: impl FnMut(crate::push::PushProgress),
) -> crate::error::Result<()> {
crate::push::resolve_push_conflict_with_progress(self, remote, self.now(), progress)
}
}