Radish alpha
r
rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5
Radicle web interface
Radicle
Git
radicle-explorer radicle-httpd src api json commit.rs
use std::path::Path;
use std::str;

use base64::{prelude::BASE64_STANDARD, Engine};
use radicle_surf as surf;
use serde_json::{json, Value};

pub(crate) struct Commit<'a>(&'a surf::Commit);

impl<'a> Commit<'a> {
    pub fn new(commit: &'a surf::Commit) -> Self {
        Self(commit)
    }

    pub fn as_json(&self) -> Value {
        json!({
            "id": self.0.id,
            "author": {
                "name": self.0.author.name,
                "email": self.0.author.email
            },
            "summary": self.0.summary,
            "description": self.0.description(),
            "parents": self.0.parents,
            "committer": {
                "name": self.0.committer.name,
                "email": self.0.committer.email,
                "time": self.0.committer.time.seconds()
            }
        })
    }
}

pub(crate) struct Blob<'a, T: AsRef<[u8]>>(&'a surf::blob::Blob<T>);

impl<'a, T: AsRef<[u8]>> Blob<'a, T> {
    pub fn new(blob: &'a surf::blob::Blob<T>) -> Self {
        Self(blob)
    }

    pub fn as_json(&self, path: &str) -> Value {
        let content = match str::from_utf8(self.0.content()) {
            Ok(s) => s.to_owned(),
            Err(_) => BASE64_STANDARD.encode(self.0.content()),
        };

        json!({
            "binary": self.0.is_binary(),
            "name": name_in_path(path),
            "content": content,
            "path": path,
            "lastCommit": Commit(self.0.commit()).as_json()
        })
    }
}

pub(crate) struct Tree<'a>(&'a surf::tree::Tree);

impl<'a> Tree<'a> {
    pub fn new(tree: &'a surf::tree::Tree) -> Self {
        Self(tree)
    }

    pub fn as_json(&self, path: &str) -> Value {
        let prefix = Path::new(path);
        let entries = self
            .0
            .entries()
            .iter()
            .map(|entry| {
                json!({
                    "path": prefix.join(entry.name()),
                    "oid": entry.object_id(),
                    "name": entry.name(),
                    "kind": match entry.entry() {
                        surf::tree::EntryKind::Tree(_) => "tree",
                        surf::tree::EntryKind::Blob(_) => "blob",
                        surf::tree::EntryKind::Submodule { .. } => "submodule"
                    },
                })
            })
            .collect::<Vec<_>>();

        json!({
            "entries": &entries,
            "lastCommit": Commit::new(self.0.commit()).as_json(),
            "name": name_in_path(path),
            "path": path,
        })
    }
}

/// Returns the name part of a path string.
fn name_in_path(path: &str) -> &str {
    match path.rsplit('/').next() {
        Some(name) => name,
        None => path,
    }
}