/ src / api / json / commit.rs
commit.rs
 1  use std::path::Path;
 2  use std::str;
 3  
 4  use base64::{prelude::BASE64_STANDARD, Engine};
 5  use radicle_surf as surf;
 6  use serde_json::{json, Value};
 7  
 8  pub(crate) struct Commit<'a>(&'a surf::Commit);
 9  
10  impl<'a> Commit<'a> {
11      pub fn new(commit: &'a surf::Commit) -> Self {
12          Self(commit)
13      }
14  
15      pub fn as_json(&self) -> Value {
16          json!({
17              "id": self.0.id,
18              "author": {
19                  "name": self.0.author.name,
20                  "email": self.0.author.email
21              },
22              "summary": self.0.summary,
23              "description": self.0.description(),
24              "parents": self.0.parents,
25              "committer": {
26                  "name": self.0.committer.name,
27                  "email": self.0.committer.email,
28                  "time": self.0.committer.time.seconds()
29              }
30          })
31      }
32  }
33  
34  pub(crate) struct Blob<'a, T: AsRef<[u8]>>(&'a surf::blob::Blob<T>);
35  
36  impl<'a, T: AsRef<[u8]>> Blob<'a, T> {
37      pub fn new(blob: &'a surf::blob::Blob<T>) -> Self {
38          Self(blob)
39      }
40  
41      pub fn as_json(&self, path: &str) -> Value {
42          let content = match str::from_utf8(self.0.content()) {
43              Ok(s) => s.to_owned(),
44              Err(_) => BASE64_STANDARD.encode(self.0.content()),
45          };
46  
47          json!({
48              "binary": self.0.is_binary(),
49              "name": name_in_path(path),
50              "content": content,
51              "path": path,
52              "lastCommit": Commit(self.0.commit()).as_json()
53          })
54      }
55  }
56  
57  pub(crate) struct Tree<'a>(&'a surf::tree::Tree);
58  
59  impl<'a> Tree<'a> {
60      pub fn new(tree: &'a surf::tree::Tree) -> Self {
61          Self(tree)
62      }
63  
64      pub fn as_json(&self, path: &str) -> Value {
65          let prefix = Path::new(path);
66          let entries = self
67              .0
68              .entries()
69              .iter()
70              .map(|entry| {
71                  json!({
72                      "path": prefix.join(entry.name()),
73                      "oid": entry.object_id(),
74                      "name": entry.name(),
75                      "kind": match entry.entry() {
76                          surf::tree::EntryKind::Tree(_) => "tree",
77                          surf::tree::EntryKind::Blob(_) => "blob",
78                          surf::tree::EntryKind::Submodule { .. } => "submodule"
79                      },
80                  })
81              })
82              .collect::<Vec<_>>();
83  
84          json!({
85              "entries": &entries,
86              "lastCommit": Commit::new(self.0.commit()).as_json(),
87              "name": name_in_path(path),
88              "path": path,
89          })
90      }
91  }
92  
93  /// Returns the name part of a path string.
94  fn name_in_path(path: &str) -> &str {
95      match path.rsplit('/').next() {
96          Some(name) => name,
97          None => path,
98      }
99  }