JavaScript is disabled, refresh for a better experience. ambee/giterated

ambee/giterated

Git repository hosting, collaboration, and discovery for the Fediverse.

Add docs

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨51aad53

⁨src/model/repository.rs⁩ - ⁨5309⁩ bytes
Raw
1 use std::str::FromStr;
2
3 use serde::{Deserialize, Serialize};
4
5 use super::{instance::Instance, user::User};
6
7 /// A repository, defined by the instance it exists on along with
8 /// its owner and name.
9 ///
10 /// # Textual Format
11 /// A repository's textual reference is defined as:
12 ///
13 /// `{owner: User}/{name: String}@{instance: Instance}`
14 ///
15 /// # Examples
16 /// For the repository named `foo` owned by `barson:giterated.dev` on the instance
17 /// `giterated.dev`, the following [`Repository`] initialization would
18 /// be valid:
19 ///
20 /// ```
21 /// let repository = Repository {
22 /// owner: User::from_str("barson:giterated.dev").unwrap(),
23 /// name: String::from("foo"),
24 /// instance: Instance::from_str("giterated.dev").unwrap()
25 /// };
26 ///
27 /// // This is correct
28 /// assert_eq!(Repository::from_str("barson:giterated.dev/[email protected]").unwrap(), repository);
29 /// ```
30 #[derive(Hash, Clone, Serialize, Deserialize)]
31 pub struct Repository {
32 pub owner: User,
33 pub name: String,
34 /// Instance the repository is on
35 pub instance: Instance,
36 }
37
38 impl ToString for Repository {
39 fn to_string(&self) -> String {
40 format!("{}/{}@{}", self.owner, self.name, self.instance.to_string())
41 }
42 }
43
44 impl FromStr for Repository {
45 type Err = ();
46
47 fn from_str(s: &str) -> Result<Self, Self::Err> {
48 let mut by_ampersand = s.split('@');
49 let mut path_split = by_ampersand.next().unwrap().split('/');
50
51 let instance = Instance::from_str(by_ampersand.next().unwrap()).unwrap();
52 let owner = User::from_str(path_split.next().unwrap()).unwrap();
53 let name = path_split.next().unwrap().to_string();
54
55 Ok(Self {
56 instance,
57 owner,
58 name,
59 })
60 }
61 }
62
63 /// Visibility of the repository to the general eye
64 #[derive(Debug, Hash, Serialize, Deserialize, Clone, sqlx::Type)]
65 #[sqlx(type_name = "visibility", rename_all = "lowercase")]
66 pub enum RepositoryVisibility {
67 Public,
68 Unlisted,
69 Private,
70 }
71
72 #[derive(Clone, Debug, Serialize, Deserialize)]
73 pub struct RepositoryView {
74 /// Name of the repository
75 ///
76 /// This is different than the [`Repository`] name,
77 /// which may be a path.
78 pub name: String,
79 /// Owner of the Repository
80 pub owner: User,
81 /// Repository description
82 pub description: Option<String>,
83 /// Repository visibility
84 pub visibility: RepositoryVisibility,
85 /// Default branch of the repository
86 pub default_branch: String,
87 /// Last commit made to the repository
88 pub latest_commit: Option<Commit>,
89 /// Revision of the displayed tree
90 pub tree_rev: Option<String>,
91 /// Repository tree
92 pub tree: Vec<RepositoryTreeEntry>,
93 }
94
95 #[derive(Debug, Clone, Serialize, Deserialize)]
96 pub enum RepositoryObjectType {
97 Tree,
98 Blob,
99 }
100
101 /// Stored info for our tree entries
102 #[derive(Debug, Clone, Serialize, Deserialize)]
103 pub struct RepositoryTreeEntry {
104 /// Name of the tree/blob
105 pub name: String,
106 /// Type of the tree entry
107 pub object_type: RepositoryObjectType,
108 /// Git supplies us with the mode at all times, and people like it displayed.
109 pub mode: i32,
110 /// File size
111 pub size: Option<usize>,
112 /// Last commit made to the tree/blob
113 pub last_commit: Option<Commit>,
114 }
115
116 impl RepositoryTreeEntry {
117 // I love you Emilia <3
118 pub fn new(name: &str, object_type: RepositoryObjectType, mode: i32) -> Self {
119 Self {
120 name: name.to_string(),
121 object_type,
122 mode,
123 size: None,
124 last_commit: None,
125 }
126 }
127 }
128
129 #[derive(Debug, Clone, Serialize, Deserialize)]
130 pub struct RepositoryTreeEntryWithCommit {
131 pub tree_entry: RepositoryTreeEntry,
132 pub commit: Commit,
133 }
134
135 /// Info about a git commit
136 #[derive(Debug, Clone, Serialize, Deserialize)]
137 pub struct Commit {
138 /// Unique commit ID
139 pub oid: String,
140 /// Full commit message
141 pub message: Option<String>,
142 /// Who created the commit
143 pub author: CommitSignature,
144 /// Who committed the commit
145 pub committer: CommitSignature,
146 /// Time when the commit happened
147 pub time: chrono::NaiveDateTime,
148 }
149
150 /// Gets all info from [`git2::Commit`] for easy use
151 impl From<git2::Commit<'_>> for Commit {
152 fn from(commit: git2::Commit<'_>) -> Self {
153 Self {
154 oid: commit.id().to_string(),
155 message: commit.message().map(|message| message.to_string()),
156 author: commit.author().into(),
157 committer: commit.committer().into(),
158 time: chrono::NaiveDateTime::from_timestamp_opt(commit.time().seconds(), 0).unwrap(),
159 }
160 }
161 }
162
163 /// Git commit signature
164 #[derive(Debug, Clone, Serialize, Deserialize)]
165 pub struct CommitSignature {
166 pub name: Option<String>,
167 pub email: Option<String>,
168 pub time: chrono::NaiveDateTime,
169 }
170
171 /// Converts the signature from git2 into something usable without explicit lifetimes.
172 impl From<git2::Signature<'_>> for CommitSignature {
173 fn from(signature: git2::Signature<'_>) -> Self {
174 Self {
175 name: signature.name().map(|name| name.to_string()),
176 email: signature.email().map(|email| email.to_string()),
177 time: chrono::NaiveDateTime::from_timestamp_opt(signature.when().seconds(), 0).unwrap(),
178 }
179 }
180 }
181