Radish alpha
r
rad:z6cFWeWpnZNHh9rUW8phgA3b5yGt
Git libraries for Radicle
Radicle
Git
Merge remote-tracking branch 'han/fix-ci2'
Fintan Halpenny committed 3 years ago
commit b3d23d2019f0944ad1222c898331ccd10b758020
parent 32902d0
11 files changed +64 -80
modified .github/workflows/ci.yaml
@@ -85,10 +85,13 @@ jobs:
        with:
          fetch-depth: 0
      # The 'main' branch is needed for radicle-surf vcs::git::tests::test_submodule_failure,
-
      # however actions/checkout uses the init.defaultBranch 'master' at this moment.
-
      # We will improve the test soon to remove this need.
-
      - run: git branch -f main  # -f in case of running against 'main' branch.
-
      - run: git branch -u origin/main main
+
      # however actions/checkout uses the init.defaultBranch 'master' at this moment, even if
+
      # the repo does not use 'master' branch. We create 'main' branch as needed for the test.
+
      #
+
      # awk magic: create 'main' branch only if not exist yet.
+
      #  END: do things at the end of the input.
+
      #  NR: Number of Records in the input.
+
      - run: git branch --list main | awk 'END { if (NR == 0) system("git branch main; git branch -u origin/main main"); }'
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
@@ -120,8 +123,7 @@ jobs:
      - uses: actions/checkout@master
        with:
          fetch-depth: 0
-
      - run: git branch -f main
-
      - run: git branch -u origin/main main
+
      - run: git branch --list main | awk 'END { if (NR == 0) system("git branch main; git branch -u origin/main main"); }'
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
modified radicle-surf/examples/diff.rs
@@ -17,11 +17,11 @@

extern crate radicle_surf;

-
use std::{env::Args, time::Instant};
+
use std::{env::Args, str::FromStr, time::Instant};

-
use git2::Oid;
use nonempty::NonEmpty;

+
use radicle_git_ext::Oid;
use radicle_surf::{
    diff::Diff,
    file_system::Directory,
modified radicle-surf/src/commit.rs
@@ -33,6 +33,8 @@ use crate::{
    vcs::git::{self, BranchName, Browser, Rev},
};

+
use radicle_git_ext::Oid;
+

/// Commit statistics.
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[derive(Clone)]
@@ -62,7 +64,7 @@ pub struct Commit {
pub struct Header {
    /// Identifier of the commit in the form of a sha1 hash. Often referred to
    /// as oid or object id.
-
    pub sha1: git2::Oid,
+
    pub sha1: Oid,
    /// The author of the commit.
    pub author: Person,
    /// The summary of the commit message body.
@@ -139,7 +141,7 @@ pub struct Commits {
///
/// Will return [`Error`] if the project doesn't exist or the surf interaction
/// fails.
-
pub fn commit(browser: &mut Browser<'_>, sha1: git2::Oid) -> Result<Commit, Error> {
+
pub fn commit(browser: &mut Browser<'_>, sha1: Oid) -> Result<Commit, Error> {
    browser.commit(sha1)?;

    let history = browser.get();
@@ -215,7 +217,7 @@ pub fn commit(browser: &mut Browser<'_>, sha1: git2::Oid) -> Result<Commit, Erro
///
/// Will return [`Error`] if the project doesn't exist or the surf interaction
/// fails.
-
pub fn header(browser: &mut Browser<'_>, sha1: git2::Oid) -> Result<Header, Error> {
+
pub fn header(browser: &mut Browser<'_>, sha1: Oid) -> Result<Header, Error> {
    browser.commit(sha1)?;

    let history = browser.get();
modified radicle-surf/src/revision.rs
@@ -94,10 +94,7 @@ where
                },
                None => git::Branch::local(&name).into(),
            }),
-
            Revision::Sha { sha } => {
-
                let oid: git2::Oid = sha.into();
-
                Ok(oid.into())
-
            },
+
            Revision::Sha { sha } => Ok(sha.into()),
        }
    }
}
modified radicle-surf/src/vcs/git.rs
@@ -21,6 +21,7 @@
//! 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>> {
@@ -63,7 +64,8 @@
//! ```

// Re-export git2 as sub-module
-
pub use git2::{self, Error as Git2Error, Oid, Time};
+
pub use git2::{self, Error as Git2Error, Time};
+
pub use radicle_git_ext::Oid;

/// Provides ways of selecting a particular reference/revision.
mod reference;
@@ -387,6 +389,7 @@ impl<'a> Browser<'a> {
    /// use nonempty::NonEmpty;
    /// use radicle_surf::vcs::History;
    /// use radicle_surf::vcs::git::{TagName, Branch, Browser, Oid, Repository};
+
    /// use std::str::FromStr;
    /// # use std::error::Error;
    ///
    /// # fn main() -> Result<(), Box<dyn Error>> {
@@ -646,6 +649,7 @@ impl<'a> Browser<'a> {
    /// ```
    /// use radicle_surf::vcs::git::{Branch, RefScope, Browser, Namespace, Oid, Repository, Tag, TagName, Author, Time};
    /// use std::convert::TryFrom;
+
    /// use std::str::FromStr;
    /// # use std::error::Error;
    ///
    /// # fn main() -> Result<(), Box<dyn Error>> {
@@ -915,6 +919,7 @@ impl<'a> Browser<'a> {
    ///
    /// ```
    /// use radicle_surf::vcs::git::{Branch, Browser, Repository, Oid, error};
+
    /// use std::str::FromStr;
    /// # use std::error::Error;
    ///
    /// # fn main() -> Result<(), Box<dyn Error>> {
@@ -967,6 +972,7 @@ impl<'a> Browser<'a> {
    /// ```
    /// use radicle_surf::vcs::git::{Browser, Repository, Branch, BranchName, Namespace, Oid};
    /// use std::convert::TryFrom;
+
    /// use std::str::FromStr;
    /// # use std::error::Error;
    ///
    /// # fn main() -> Result<(), Box<dyn Error>> {
@@ -1017,7 +1023,7 @@ impl<'a> Browser<'a> {
    /// ```
    pub fn revision_branches(&self, rev: impl Into<Rev>) -> Result<Vec<Branch>, Error> {
        let commit = self.repository.rev_to_commit(&rev.into())?;
-
        self.repository.revision_branches(&commit.id())
+
        self.repository.revision_branches(&commit.id().into())
    }

    /// Get the [`Stats`] of the underlying [`Repository`].
@@ -1078,7 +1084,7 @@ impl<'a> Browser<'a> {
            Error,
        > = Ok(HashMap::new());

-
        let commit = repo.find_commit(commit.id)?;
+
        let commit = repo.find_commit(commit.id.into())?;
        let tree = commit.as_object().peel_to_tree()?;

        tree.walk(
@@ -1117,8 +1123,8 @@ impl<'a> Browser<'a> {
    ///
    /// See [`git2::Repository::merge_base`] for details.
    pub fn merge_base(&self, one: Oid, two: Oid) -> Result<Option<Oid>, Error> {
-
        match self.repository.repo_ref.merge_base(one, two) {
-
            Ok(merge_base) => Ok(Some(merge_base)),
+
        match self.repository.repo_ref.merge_base(one.into(), two.into()) {
+
            Ok(merge_base) => Ok(Some(merge_base.into())),
            Err(err) => {
                if err.code() == git2::ErrorCode::NotFound {
                    Ok(None)
@@ -1317,6 +1323,7 @@ mod tests {
    #[cfg(test)]
    mod rev {
        use super::{Branch, Browser, Error, Oid, Repository, TagName};
+
        use std::str::FromStr;

        // **FIXME**: This seems to break occasionally on
        // buildkite. For some reason the commit
@@ -1440,6 +1447,7 @@ mod tests {
            file_system::{unsound, Path},
            vcs::git::{Branch, Browser, Oid, Repository},
        };
+
        use std::str::FromStr;

        #[test]
        fn readme_missing_and_memory() {
@@ -1571,6 +1579,7 @@ mod tests {
    #[cfg(test)]
    mod diff {
        use crate::{diff::*, vcs::git::*};
+
        use std::str::FromStr;

        #[test]
        fn test_initial_diff() -> Result<(), Error> {
@@ -1579,7 +1588,7 @@ mod tests {

            let oid = Oid::from_str("d3464e33d75c75c99bfb90fa2e9d16efc0b7d0e3")?;
            let repo = Repository::new("./data/git-platinum")?;
-
            let commit = repo.0.find_commit(oid).unwrap();
+
            let commit = repo.0.find_commit(oid.into()).unwrap();

            assert!(commit.parents().count() == 0);
            assert!(commit.parent(0).is_err());
@@ -1617,13 +1626,15 @@ mod tests {
            let repo = Repository::new("./data/git-platinum")?;
            let commit = repo
                .0
-
                .find_commit(Oid::from_str("80bacafba303bf0cdf6142921f430ff265f25095")?)
+
                .find_commit(git2::Oid::from_str(
+
                    "80bacafba303bf0cdf6142921f430ff265f25095",
+
                )?)
                .unwrap();
            let parent = commit.parent(0)?;

            let bro = Browser::new(&repo, Branch::local("master"))?;

-
            let diff = bro.diff(parent.id(), commit.id())?;
+
            let diff = bro.diff(parent.id().into(), commit.id().into())?;

            let expected_diff = Diff {
                created: vec![],
modified radicle-surf/src/vcs/git/commit.rs
@@ -16,7 +16,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use crate::vcs::git::error::Error;
-
use git2::Oid;
+
use radicle_git_ext::Oid;
use std::{convert::TryFrom, str};

#[cfg(feature = "serialize")]
@@ -92,9 +92,7 @@ impl<'repo> TryFrom<git2::Signature<'repo>> for Author {
#[cfg_attr(feature = "serialize", derive(Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Commit {
-
    // TODO: Replace git2::Oid with git_ext::Oid (https://github.com/radicle-dev/radicle-git/issues/5)
-
    /// Object ID of the Commit, i.e. the SHA1 digest.
-
    #[cfg_attr(feature = "serialize", serde(deserialize_with = "deserialize_oid"))]
+
    /// Object Id
    pub id: Oid,
    /// The author of the commit.
    pub author: Author,
@@ -105,7 +103,6 @@ pub struct Commit {
    /// The summary message of the commit.
    pub summary: String,
    /// The parents of this commit.
-
    #[cfg_attr(feature = "serialize", serde(deserialize_with = "deserialize_vec_oid"))]
    pub parents: Vec<Oid>,
}

@@ -146,44 +143,18 @@ impl Serialize for Commit {
    }
}

-
#[cfg(feature = "serialize")]
-
fn deserialize_oid<'de, D>(deserializer: D) -> Result<Oid, D::Error>
-
where
-
    D: Deserializer<'de>,
-
{
-
    let oid: &str = Deserialize::deserialize(deserializer)?;
-
    Oid::from_str(oid).map_err(|_| {
-
        serde::de::Error::invalid_type(
-
            serde::de::Unexpected::Str(oid),
-
            &"a SHA1 hash not longer than 40 hex characters",
-
        )
-
    })
-
}
-

-
#[cfg(feature = "serialize")]
-
fn deserialize_vec_oid<'de, D>(deserializer: D) -> Result<Vec<Oid>, D::Error>
-
where
-
    D: Deserializer<'de>,
-
{
-
    let oids: Vec<&str> = Deserialize::deserialize(deserializer)?;
-
    oids.iter()
-
        .map(|key| Oid::from_str(key))
-
        .collect::<Result<Vec<Oid>, _>>()
-
        .map_err(de::Error::custom)
-
}
-

impl<'repo> TryFrom<git2::Commit<'repo>> for Commit {
    type Error = Error;

    fn try_from(commit: git2::Commit) -> Result<Self, Self::Error> {
-
        let id = commit.id();
+
        let id = commit.id().into();
        let author = Author::try_from(commit.author())?;
        let committer = Author::try_from(commit.committer())?;
        let message_raw = commit.message_bytes();
        let message = str::from_utf8(message_raw)?.into();
        let summary_raw = commit.summary_bytes().ok_or(Error::MissingSummary)?;
        let summary = str::from_utf8(summary_raw)?.into();
-
        let parents = commit.parent_ids().collect();
+
        let parents = commit.parent_ids().map(|oid| oid.into()).collect();

        Ok(Commit {
            id,
@@ -199,8 +170,8 @@ impl<'repo> TryFrom<git2::Commit<'repo>> for Commit {
#[cfg(feature = "serialize")]
#[cfg(test)]
pub mod tests {
-
    use git2::Oid;
    use proptest::prelude::*;
+
    use radicle_git_ext::Oid;
    use test_helpers::roundtrip;

    use super::{Author, Commit};
modified radicle-surf/src/vcs/git/namespace.rs
@@ -16,8 +16,8 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use crate::vcs::git::error::Error;
-
pub use git2::Oid;
use nonempty::NonEmpty;
+
pub use radicle_git_ext::Oid;
use std::{convert::TryFrom, fmt, str};

/// A `Namespace` value allows us to switch the git namespace of
modified radicle-surf/src/vcs/git/reference.rs
@@ -20,7 +20,7 @@ use std::{fmt, str};
use thiserror::Error;

use crate::vcs::git::{repo::RepositoryRef, BranchName, Namespace, TagName};
-

+
use radicle_git_ext::Oid;
pub(super) mod glob;

/// A revision within the repository.
@@ -29,7 +29,7 @@ pub enum Rev {
    /// A reference to a branch or tag.
    Ref(Ref),
    /// A particular commit identifier.
-
    Oid(git2::Oid),
+
    Oid(Oid),
}

impl<R> From<R> for Rev
@@ -41,8 +41,8 @@ where
    }
}

-
impl From<git2::Oid> for Rev {
-
    fn from(other: git2::Oid) -> Self {
+
impl From<Oid> for Rev {
+
    fn from(other: Oid) -> Self {
        Self::Oid(other)
    }
}
modified radicle-surf/src/vcs/git/repo.rs
@@ -33,8 +33,8 @@ use crate::{
        Vcs,
    },
};
-
use git2::Oid;
use nonempty::NonEmpty;
+
use radicle_git_ext::Oid;
use std::{collections::HashSet, convert::TryFrom, str};

/// This is for flagging to the `file_history` function that it should
@@ -156,24 +156,24 @@ impl<'a> RepositoryRef<'a> {

    /// Get the [`Diff`] between two commits.
    pub fn diff(&self, from: Oid, to: Oid) -> Result<Diff, Error> {
-
        self.diff_commits(None, Some(from), to)
+
        self.diff_commits(None, Some(from.into()), to.into())
            .and_then(|diff| Diff::try_from(diff).map_err(Error::from))
    }

    /// Get the [`Diff`] of a commit with no parents.
    pub fn initial_diff(&self, oid: Oid) -> Result<Diff, Error> {
-
        self.diff_commits(None, None, oid)
+
        self.diff_commits(None, None, oid.into())
            .and_then(|diff| Diff::try_from(diff).map_err(Error::from))
    }

    /// Parse an [`Oid`] from the given string.
    pub fn oid(&self, oid: &str) -> Result<Oid, Error> {
-
        Ok(self.repo_ref.revparse_single(oid)?.id())
+
        Ok(self.repo_ref.revparse_single(oid)?.id().into())
    }

    pub(super) fn rev_to_commit(&self, rev: &Rev) -> Result<git2::Commit, Error> {
        match rev {
-
            Rev::Oid(oid) => Ok(self.repo_ref.find_commit(*oid)?),
+
            Rev::Oid(oid) => Ok(self.repo_ref.find_commit((*oid).into())?),
            Rev::Ref(reference) => Ok(reference.find_ref(self)?.peel_to_commit()?),
        }
    }
@@ -184,7 +184,7 @@ impl<'a> RepositoryRef<'a> {

    /// Get a particular `Commit`.
    pub(super) fn get_commit(&self, oid: Oid) -> Result<git2::Commit<'a>, Error> {
-
        let commit = self.repo_ref.find_commit(oid)?;
+
        let commit = self.repo_ref.find_commit(oid.into())?;
        Ok(commit)
    }

@@ -214,7 +214,7 @@ impl<'a> RepositoryRef<'a> {
        for commit_result_id in revwalk {
            // The revwalk iter returns results so
            // we unpack these and push them to the history
-
            let commit_id: Oid = commit_result_id?;
+
            let commit_id = commit_result_id?;

            // Skip the head commit since we have processed it
            if commit_id == head_id {
@@ -278,10 +278,11 @@ impl<'a> RepositoryRef<'a> {
    }

    fn reachable_from(&self, reference: &git2::Reference, oid: &Oid) -> Result<bool, Error> {
+
        let git2_oid = (*oid).into();
        let other = reference.peel_to_commit()?.id();
-
        let is_descendant = self.repo_ref.graph_descendant_of(other, *oid)?;
+
        let is_descendant = self.repo_ref.graph_descendant_of(other, git2_oid)?;

-
        Ok(other == *oid || is_descendant)
+
        Ok(other == git2_oid || is_descendant)
    }

    /// Get the history of the file system where the head of the [`NonEmpty`] is
@@ -296,10 +297,10 @@ impl<'a> RepositoryRef<'a> {
        let mut commits = vec![];

        // Set the revwalk to the head commit
-
        revwalk.push(commit.id)?;
+
        revwalk.push(commit.id.into())?;

        for commit in revwalk {
-
            let parent_id: Oid = commit?;
+
            let parent_id = commit?;
            let parent = self.repo_ref.find_commit(parent_id)?;
            let paths = self.diff_commit_and_parents(path, &parent)?;
            if let Some(_path) = paths {
@@ -333,8 +334,8 @@ impl<'a> RepositoryRef<'a> {
    fn diff_commits(
        &self,
        path: Option<&file_system::Path>,
-
        from: Option<Oid>,
-
        to: Oid,
+
        from: Option<git2::Oid>,
+
        to: git2::Oid,
    ) -> Result<git2::Diff, Error> {
        let new_tree = self.repo_ref.find_commit(to)?.tree()?;
        let old_tree = from.map_or(Ok(None), |oid| {
modified radicle-surf/src/vcs/git/stats.rs
@@ -15,7 +15,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

-
pub use git2::Oid;
+
pub use radicle_git_ext::Oid;

#[cfg(feature = "serialize")]
use serde::Serialize;
modified radicle-surf/src/vcs/git/tag.rs
@@ -16,7 +16,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use crate::vcs::git::{self, error::Error, reference::Ref, Author};
-
use git2::Oid;
+
use radicle_git_ext::Oid;
use std::{convert::TryFrom, fmt, str};

/// A newtype wrapper over `String` to separate out the fact that a caller wants
@@ -112,9 +112,9 @@ impl<'repo> TryFrom<git2::Tag<'repo>> for Tag {
    type Error = str::Utf8Error;

    fn try_from(tag: git2::Tag) -> Result<Self, Self::Error> {
-
        let id = tag.id();
+
        let id = tag.id().into();

-
        let target_id = tag.target_id();
+
        let target_id = tag.target_id().into();

        let name = TagName::try_from(tag.name_bytes())?;

@@ -163,7 +163,7 @@ impl<'repo> TryFrom<git2::Reference<'repo>> for Tag {
                {
                    let commit = reference.peel_to_commit()?;
                    Ok(Tag::Light {
-
                        id: commit.id(),
+
                        id: commit.id().into(),
                        name,
                        remote,
                    })