mirror of
https://seed.radicle.dev/rad:z6cFWeWpnZNHh9rUW8phgA3b5yGt.git
synced 2026-10-27 07:10:58 +08:00
The current `error::Error` type aggregated a lot of different error scenarios that were not for the actual repo actions, instead they would be for the domains that the repo actions would return. This is a reorganisation of those by localising error variants in their modules: * namespace::Error * commit::Error * glob::Error * adding `type Error` to ToCommit * adding `type Error` to Revision The main Error type now consists of these other Error types and lives in the `repo` module. It is re-exported at the top-level since RepositoryRef is the main interaction with the library. During this refactor, some reorganisation of functions was done as well: * Move `get_file` from `Commit` to `RepositoryRef` as `get_commit_file`. * Have a blanket implementation of `ToCommit` for any `Revision`, instead of repeating the implementations. Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com> X-Clacks-Overhead: GNU Terry Pratchett
216 lines
6.3 KiB
Rust
216 lines
6.3 KiB
Rust
// This file is part of radicle-surf
|
|
// <https://github.com/radicle-dev/radicle-surf>
|
|
//
|
|
// Copyright (C) 2019-2020 The Radicle Team <dev@radicle.xyz>
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License version 3 or
|
|
// later as published by the Free Software Foundation.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
//! ```
|
|
//! use nonempty::NonEmpty;
|
|
//! use radicle_surf::file_system::{Directory, File, Label, Path, SystemType};
|
|
//! use radicle_surf::file_system::unsound;
|
|
//! use radicle_surf::vcs::git::*;
|
|
//! use std::collections::HashMap;
|
|
//! use std::str::FromStr;
|
|
//! # use std::error::Error;
|
|
//!
|
|
//! # fn main() -> Result<(), Box<dyn Error>> {
|
|
//! let repo = Repository::new("./data/git-platinum")?;
|
|
//!
|
|
//! // Pin the browser to a parituclar commit.
|
|
//! let pin_commit = Oid::from_str("3873745c8f6ffb45c990eb23b491d4b4b6182f95")?;
|
|
//! let mut browser = Browser::new(&repo, Branch::local("master"))?;
|
|
//! browser.commit(pin_commit)?;
|
|
//!
|
|
//! let directory = browser.get_directory()?;
|
|
//! let mut directory_contents = directory.list_directory();
|
|
//! directory_contents.sort();
|
|
//!
|
|
//! assert_eq!(directory_contents, vec![
|
|
//! SystemType::file(unsound::label::new(".i-am-well-hidden")),
|
|
//! SystemType::file(unsound::label::new(".i-too-am-hidden")),
|
|
//! SystemType::file(unsound::label::new("README.md")),
|
|
//! SystemType::directory(unsound::label::new("bin")),
|
|
//! SystemType::directory(unsound::label::new("src")),
|
|
//! SystemType::directory(unsound::label::new("text")),
|
|
//! SystemType::directory(unsound::label::new("this")),
|
|
//! ]);
|
|
//!
|
|
//! // find src directory in the Git directory and the in-memory directory
|
|
//! let src_directory = directory
|
|
//! .find_directory(Path::new(unsound::label::new("src")))
|
|
//! .expect("failed to find src");
|
|
//! let mut src_directory_contents = src_directory.list_directory();
|
|
//! src_directory_contents.sort();
|
|
//!
|
|
//! assert_eq!(src_directory_contents, vec![
|
|
//! SystemType::file(unsound::label::new("Eval.hs")),
|
|
//! SystemType::file(unsound::label::new("Folder.svelte")),
|
|
//! SystemType::file(unsound::label::new("memory.rs")),
|
|
//! ]);
|
|
//! #
|
|
//! # Ok(())
|
|
//! # }
|
|
//! ```
|
|
|
|
use std::{convert::Infallible, str::FromStr};
|
|
|
|
// Re-export git2 as sub-module
|
|
pub use git2::{self, Error as Git2Error, Time};
|
|
use git_ref_format::{name::Components, Component, Qualified, RefString};
|
|
pub use radicle_git_ext::Oid;
|
|
|
|
mod repo;
|
|
pub use repo::{Error, Repository, RepositoryRef};
|
|
|
|
pub mod glob;
|
|
pub use glob::Glob;
|
|
|
|
mod history;
|
|
pub use history::History;
|
|
|
|
/// Provides the data for talking about branches.
|
|
pub mod branch;
|
|
pub use branch::{Branch, Local, Remote};
|
|
|
|
/// Provides the data for talking about tags.
|
|
pub mod tag;
|
|
pub use tag::Tag;
|
|
|
|
/// Provides the data for talking about commits.
|
|
pub mod commit;
|
|
pub use commit::{Author, Commit};
|
|
|
|
/// Provides the data for talking about namespaces.
|
|
pub mod namespace;
|
|
pub use namespace::Namespace;
|
|
|
|
/// Provides the data for talking about repository statistics.
|
|
pub mod stats;
|
|
pub use stats::Stats;
|
|
|
|
pub use crate::diff::Diff;
|
|
|
|
/// The signature of a commit
|
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub struct Signature(Vec<u8>);
|
|
|
|
impl From<git2::Buf> for Signature {
|
|
fn from(other: git2::Buf) -> Self {
|
|
Signature((*other).into())
|
|
}
|
|
}
|
|
|
|
/// Supports various ways to specify a revision used in Git.
|
|
pub trait Revision {
|
|
type Error: std::error::Error + Send + Sync + 'static;
|
|
|
|
/// Returns the object id of this revision in `repo`.
|
|
fn object_id(&self, repo: &RepositoryRef) -> Result<Oid, Self::Error>;
|
|
}
|
|
|
|
impl Revision for RefString {
|
|
type Error = git2::Error;
|
|
|
|
fn object_id(&self, repo: &RepositoryRef) -> Result<Oid, Self::Error> {
|
|
repo.repo_ref.refname_to_id(self.as_str()).map(Oid::from)
|
|
}
|
|
}
|
|
|
|
impl Revision for &RefString {
|
|
type Error = git2::Error;
|
|
|
|
fn object_id(&self, repo: &RepositoryRef) -> Result<Oid, Self::Error> {
|
|
repo.repo_ref.refname_to_id(self.as_str()).map(Oid::from)
|
|
}
|
|
}
|
|
|
|
impl Revision for Qualified<'_> {
|
|
type Error = git2::Error;
|
|
|
|
fn object_id(&self, repo: &RepositoryRef) -> Result<Oid, Self::Error> {
|
|
repo.repo_ref.refname_to_id(self.as_str()).map(Oid::from)
|
|
}
|
|
}
|
|
|
|
impl Revision for &Qualified<'_> {
|
|
type Error = git2::Error;
|
|
|
|
fn object_id(&self, repo: &RepositoryRef) -> Result<Oid, Self::Error> {
|
|
repo.repo_ref.refname_to_id(self.as_str()).map(Oid::from)
|
|
}
|
|
}
|
|
|
|
impl Revision for Oid {
|
|
type Error = Infallible;
|
|
|
|
fn object_id(&self, _repo: &RepositoryRef) -> Result<Oid, Self::Error> {
|
|
Ok(*self)
|
|
}
|
|
}
|
|
|
|
impl Revision for &str {
|
|
type Error = git2::Error;
|
|
|
|
fn object_id(&self, _repo: &RepositoryRef) -> Result<Oid, Self::Error> {
|
|
Oid::from_str(self).map(Oid::from)
|
|
}
|
|
}
|
|
|
|
impl Revision for &Branch {
|
|
type Error = Error;
|
|
|
|
fn object_id(&self, repo: &RepositoryRef) -> Result<Oid, Self::Error> {
|
|
let refname = repo.namespaced_refname(&self.refname())?;
|
|
Ok(repo.repo_ref.refname_to_id(&refname).map(Oid::from)?)
|
|
}
|
|
}
|
|
|
|
impl Revision for &Tag {
|
|
type Error = Infallible;
|
|
|
|
fn object_id(&self, _repo: &RepositoryRef) -> Result<Oid, Self::Error> {
|
|
Ok(self.id())
|
|
}
|
|
}
|
|
|
|
/// A common trait for anything that can convert to a `Commit`.
|
|
pub trait ToCommit {
|
|
type Error: std::error::Error + Send + Sync + 'static;
|
|
|
|
/// Converts to a commit in `repo`.
|
|
fn to_commit(self, repo: &RepositoryRef) -> Result<Commit, Self::Error>;
|
|
}
|
|
|
|
impl ToCommit for Commit {
|
|
type Error = Infallible;
|
|
|
|
fn to_commit(self, _repo: &RepositoryRef) -> Result<Commit, Self::Error> {
|
|
Ok(self)
|
|
}
|
|
}
|
|
|
|
impl<R: Revision> ToCommit for R {
|
|
type Error = Error;
|
|
|
|
fn to_commit(self, repo: &RepositoryRef) -> Result<Commit, Self::Error> {
|
|
let oid = repo.object_id(&self)?;
|
|
let commit = repo.repo_ref.find_commit(oid.into())?;
|
|
Ok(Commit::try_from(commit)?)
|
|
}
|
|
}
|
|
|
|
pub(crate) fn refstr_join<'a>(c: Component<'a>, cs: Components<'a>) -> RefString {
|
|
std::iter::once(c).chain(cs).collect::<RefString>()
|
|
}
|