Radish alpha
r
rad:z6cFWeWpnZNHh9rUW8phgA3b5yGt
Git libraries for Radicle
Radicle
Git
Merge remote-tracking branch 'origin/fix/serialize-tree'
Fintan Halpenny committed 3 years ago
commit 79a94721366490053e2d8ac1c1afa14fb0c25f09
parent 9df4291
8 files changed +173 -23
modified radicle-surf/src/diff.rs
@@ -238,23 +238,15 @@ impl Serialize for Line {

/// Either the modification of a single [`Line`], or just contextual
/// information.
-
#[cfg_attr(
-
    feature = "serde",
-
    derive(Serialize),
-
    serde(tag = "type", rename_all = "camelCase")
-
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Modification {
    /// A lines is an addition in a file.
-
    #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
    Addition(Addition),

    /// A lines is a deletion in a file.
-
    #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
    Deletion(Deletion),

    /// A contextual line in a file, i.e. there were no changes to the line.
-
    #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
    Context {
        line: Line,
        line_no_old: u32,
@@ -262,22 +254,96 @@ pub enum Modification {
    },
}

+
#[cfg(feature = "serde")]
+
impl Serialize for Modification {
+
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+
    where
+
        S: Serializer,
+
    {
+
        use serde::ser::SerializeMap as _;
+

+
        const NAME: &str = "Modification";
+
        const ADDITION: &str = "Addition";
+
        const DELETION: &str = "Deletion";
+
        const CONTEXT: &str = "Context";
+

+
        match self {
+
            Modification::Addition(addition) => {
+
                let mut map = serializer.serialize_map(Some(3))?;
+
                map.serialize_entry("line", &addition.line)?;
+
                map.serialize_entry("lineNo", &addition.line_no)?;
+
                map.serialize_entry("type", "addition")?;
+
                map.end()
+
            },
+
            Modification::Deletion(deletion) => {
+
                let mut map = serializer.serialize_map(Some(3))?;
+
                map.serialize_entry("line", &deletion.line)?;
+
                map.serialize_entry("lineNo", &deletion.line_no)?;
+
                map.serialize_entry("type", "deletion")?;
+
                map.end()
+
            },
+
            Modification::Context {
+
                line,
+
                line_no_old,
+
                line_no_new,
+
            } => {
+
                let mut map = serializer.serialize_map(Some(4))?;
+
                map.serialize_entry("line", line)?;
+
                map.serialize_entry("lineNoOld", line_no_old)?;
+
                map.serialize_entry("lineNoNew", line_no_new)?;
+
                map.serialize_entry("type", "context")?;
+
                map.end()
+
            },
+
        }
+
    }
+
}
+

/// A addition of a [`Line`] at the `line_no`.
-
#[cfg_attr(feature = "serde", derive(Serialize), serde(rename_all = "camelCase"))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Addition {
    pub line: Line,
    pub line_no: u32,
}

+
#[cfg(feature = "serde")]
+
impl Serialize for Addition {
+
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+
    where
+
        S: Serializer,
+
    {
+
        use serde::ser::SerializeStruct as _;
+

+
        let mut s = serializer.serialize_struct("Addition", 3)?;
+
        s.serialize_field("line", &self.line)?;
+
        s.serialize_field("lineNo", &self.line_no)?;
+
        s.serialize_field("type", "addition")?;
+
        s.end()
+
    }
+
}
+

/// A deletion of a [`Line`] at the `line_no`.
-
#[cfg_attr(feature = "serde", derive(Serialize), serde(rename_all = "camelCase"))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Deletion {
    pub line: Line,
    pub line_no: u32,
}

+
#[cfg(feature = "serde")]
+
impl Serialize for Deletion {
+
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+
    where
+
        S: Serializer,
+
    {
+
        use serde::ser::SerializeStruct as _;
+

+
        let mut s = serializer.serialize_struct("Deletion", 3)?;
+
        s.serialize_field("line", &self.line)?;
+
        s.serialize_field("lineNo", &self.line_no)?;
+
        s.serialize_field("type", "deletion")?;
+
        s.end()
+
    }
+
}
+

impl Modification {
    pub fn addition(line: impl Into<Line>, line_no: u32) -> Self {
        Self::Addition(Addition {
modified radicle-surf/src/file_system/directory.rs
@@ -352,10 +352,11 @@ impl Directory {

        let mut entries = BTreeMap::new();
        let mut error = None;
+
        let path = self.path();

        // Walks only the first level of entries.
-
        tree.walk(git2::TreeWalkMode::PreOrder, |path, entry| {
-
            match Entry::from_entry(entry, Path::new(path).to_path_buf()) {
+
        tree.walk(git2::TreeWalkMode::PreOrder, |_, entry| {
+
            match Entry::from_entry(entry, path.clone()) {
                Ok(Some(entry)) => match entry {
                    Entry::File(_) => {
                        entries.insert(entry.name().clone(), entry);
modified radicle-surf/src/source/commit.rs
@@ -47,7 +47,7 @@ pub struct Commit {
}

/// Representation of a code commit.
-
#[derive(Clone)]
+
#[derive(Clone, Debug)]
pub struct Header {
    /// Identifier of the commit in the form of a sha1 hash. Often referred to
    /// as oid or object id.
modified radicle-surf/src/source/object/blob.rs
@@ -103,7 +103,7 @@ impl Serialize for Blob {
        state.serialize_field("content", &self.content)?;
        state.serialize_field("lastCommit", &self.commit)?;
        state.serialize_field("name", &self.file.name())?;
-
        state.serialize_field("path", &self.file.location())?;
+
        state.serialize_field("path", &self.file.path())?;
        state.end()
    }
}
modified radicle-surf/src/source/object/tree.rs
@@ -33,6 +33,7 @@ use crate::{
};

/// Result of a directory listing, carries other trees and blobs.
+
#[derive(Clone, Debug)]
pub struct Tree {
    pub directory: Directory,
    pub commit: Option<commit::Header>,
@@ -95,7 +96,7 @@ impl Serialize for Tree {
        state.serialize_field("entries", &self.entries)?;
        state.serialize_field("lastCommit", &self.commit)?;
        state.serialize_field("name", &self.directory.name())?;
-
        state.serialize_field("path", &self.directory.location())?;
+
        state.serialize_field("path", &self.directory.path())?;
        state.end()
    }
}
@@ -126,14 +127,14 @@ impl Serialize for TreeEntry {
    {
        const FIELDS: usize = 4;
        let mut state = serializer.serialize_struct("TreeEntry", FIELDS)?;
-
        state.serialize_field("path", &self.entry.location())?;
+
        state.serialize_field("path", &self.entry.path())?;
        state.serialize_field("name", &self.entry.name())?;
        state.serialize_field("lastCommit", &None::<commit::Header>)?;
        state.serialize_field(
            "kind",
            match self.entry {
                directory::Entry::File(_) => "blob",
-
                directory::Entry::Directory(_) => "directory",
+
                directory::Entry::Directory(_) => "tree",
            },
        )?;
        state.end()
modified radicle-surf/t/src/git/diff.rs
@@ -5,11 +5,12 @@ use radicle_surf::{
    diff::{
        Added,
        Addition,
+
        Deleted,
+
        Deletion,
        Diff,
        EofNewLine,
        FileDiff,
        Hunk,
-
        Hunks,
        Line,
        Modification,
        Modified,
@@ -152,9 +153,26 @@ fn test_diff_serde() {
    let diff = Diff {
        added: vec![ Added {
            path: Path::new("LICENSE").to_path_buf(),
-
            diff: FileDiff::Plain { hunks: Hunks::default() }
+
            diff: FileDiff::Plain {
+
                hunks: vec![Hunk {
+
                    header: Line::from(b"@@ -0,0 +1,1".to_vec()),
+
                    lines: vec![
+
                        Addition { line: Line::from(b"MIT".to_vec()), line_no: 1 }
+
                    ]
+
                }].into()
+
            }
+
        }],
+
        deleted: vec![ Deleted {
+
            path: Path::new("DCO").to_path_buf(),
+
            diff: FileDiff::Plain {
+
                hunks: vec![Hunk {
+
                    header: Line::from(b"@@ -0,0 +1,1".to_vec()),
+
                    lines: vec![
+
                        Deletion { line: Line::from(b"TODO".to_vec()), line_no: 1 }
+
                    ]
+
                }].into()
+
            }
        }],
-
        deleted: vec![],
        moved: vec![ Moved {
            old_path: Path::new("CONTRIBUTING").to_path_buf(),
            new_path: Path::new("CONTRIBUTING.md").to_path_buf(),
@@ -184,12 +202,34 @@ fn test_diff_serde() {

    let eof: Option<u8> = None;
    let json = serde_json::json!({
-
        "added": [{"path": "LICENSE", "diff": {
+
        "added": [{
+
            "path": "LICENSE",
+
            "diff": {
+
                "type": "plain",
+
                "hunks": [{
+
                    "header": "@@ -0,0 +1,1",
+
                    "lines": [{
+
                        "line": "MIT",
+
                        "lineNo": 1,
+
                        "type": "addition",
+
                    }]
+
                }]
+
            },
+
        }],
+
        "deleted": [{
+
            "path": "DCO",
+
            "diff": {
                "type": "plain",
-
                "hunks": []
+
                "hunks": [{
+
                    "header": "@@ -0,0 +1,1",
+
                    "lines": [{
+
                        "line": "TODO",
+
                        "lineNo": 1,
+
                        "type": "deletion",
+
                    }]
+
                }]
            },
        }],
-
        "deleted": [],
        "moved": [{ "oldPath": "CONTRIBUTING", "newPath": "CONTRIBUTING.md" }],
        "copied": [],
        "modified": [{
modified radicle-surf/t/src/lib.rs
@@ -6,3 +6,6 @@ mod git;

#[cfg(test)]
mod file_system;
+

+
#[cfg(test)]
+
mod source;
added radicle-surf/t/src/source.rs
@@ -0,0 +1,39 @@
+
use std::path::Path;
+

+
use git_ref_format::refname;
+
use radicle_surf::{git::Repository, source};
+
use serde_json::json;
+

+
const GIT_PLATINUM: &str = "../data/git-platinum";
+

+
#[test]
+
fn tree_serialization() {
+
    let repo = Repository::open(GIT_PLATINUM).unwrap();
+
    let tree = source::Tree::new(
+
        &repo,
+
        &refname!("refs/heads/master"),
+
        Some(&Path::new("src")),
+
    )
+
    .unwrap();
+

+
    let expected = json!({
+
      "entries": [
+
        {
+
          "kind": "blob",
+
          "lastCommit": null,
+
          "name": "Eval.hs",
+
          "path": "src/Eval.hs"
+
        },
+
        {
+
          "kind": "blob",
+
          "lastCommit": null,
+
          "name": "memory.rs",
+
          "path": "src/memory.rs"
+
        }
+
      ],
+
      "lastCommit": null,
+
      "name": "src",
+
      "path": "src"
+
    });
+
    assert_eq!(serde_json::to_value(tree).unwrap(), expected)
+
}