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

ambee/giterated

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

Changes

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨0b2a26d

Showing ⁨⁨11⁩ changed files⁩ with ⁨⁨338⁩ insertions⁩ and ⁨⁨24⁩ deletions⁩

.gitignore

View file
@@ -1,3 +1,4 @@
1 1 /target
2 2 .idea
3 3 .env
4 Giterated.toml
4 \ No newline at end of file

Cargo.lock

View file
@@ -99,6 +99,12 @@ dependencies = [
99 99
100 100 [[package]]
101 101 name = "base64"
102 version = "0.13.1"
103 source = "registry+https://github.com/rust-lang/crates.io-index"
104 checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
105
106 [[package]]
107 name = "base64"
102 108 version = "0.21.3"
103 109 source = "registry+https://github.com/rust-lang/crates.io-index"
104 110 checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53"
@@ -178,7 +184,7 @@ dependencies = [
178 184 "js-sys",
179 185 "num-traits",
180 186 "serde",
181 "time",
187 "time 0.1.45",
182 188 "wasm-bindgen",
183 189 "winapi",
184 190 ]
@@ -276,6 +282,12 @@ dependencies = [
276 282 ]
277 283
278 284 [[package]]
285 name = "deranged"
286 version = "0.3.8"
287 source = "registry+https://github.com/rust-lang/crates.io-index"
288 checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946"
289
290 [[package]]
279 291 name = "digest"
280 292 version = "0.10.7"
281 293 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -529,12 +541,15 @@ dependencies = [
529 541 "chrono",
530 542 "futures-util",
531 543 "git2",
544 "jsonwebtoken",
545 "log",
532 546 "serde",
533 547 "serde_json",
534 548 "sqlx",
535 549 "thiserror",
536 550 "tokio",
537 551 "tokio-tungstenite",
552 "toml",
538 553 "tracing",
539 554 "tracing-subscriber",
540 555 ]
@@ -700,6 +715,20 @@ dependencies = [
700 715 ]
701 716
702 717 [[package]]
718 name = "jsonwebtoken"
719 version = "8.3.0"
720 source = "registry+https://github.com/rust-lang/crates.io-index"
721 checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378"
722 dependencies = [
723 "base64 0.21.3",
724 "pem",
725 "ring",
726 "serde",
727 "serde_json",
728 "simple_asn1",
729 ]
730
731 [[package]]
703 732 name = "lazy_static"
704 733 version = "1.4.0"
705 734 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -873,6 +902,17 @@ dependencies = [
873 902 ]
874 903
875 904 [[package]]
905 name = "num-bigint"
906 version = "0.4.4"
907 source = "registry+https://github.com/rust-lang/crates.io-index"
908 checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
909 dependencies = [
910 "autocfg",
911 "num-integer",
912 "num-traits",
913 ]
914
915 [[package]]
876 916 name = "num-bigint-dig"
877 917 version = "0.8.4"
878 918 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1025,6 +1065,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1025 1065 checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
1026 1066
1027 1067 [[package]]
1068 name = "pem"
1069 version = "1.1.1"
1070 source = "registry+https://github.com/rust-lang/crates.io-index"
1071 checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8"
1072 dependencies = [
1073 "base64 0.13.1",
1074 ]
1075
1076 [[package]]
1028 1077 name = "pem-rfc7468"
1029 1078 version = "0.7.0"
1030 1079 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1162,6 +1211,21 @@ dependencies = [
1162 1211 ]
1163 1212
1164 1213 [[package]]
1214 name = "ring"
1215 version = "0.16.20"
1216 source = "registry+https://github.com/rust-lang/crates.io-index"
1217 checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
1218 dependencies = [
1219 "cc",
1220 "libc",
1221 "once_cell",
1222 "spin 0.5.2",
1223 "untrusted",
1224 "web-sys",
1225 "winapi",
1226 ]
1227
1228 [[package]]
1165 1229 name = "rsa"
1166 1230 version = "0.9.2"
1167 1231 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1278,6 +1342,15 @@ dependencies = [
1278 1342 ]
1279 1343
1280 1344 [[package]]
1345 name = "serde_spanned"
1346 version = "0.6.3"
1347 source = "registry+https://github.com/rust-lang/crates.io-index"
1348 checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186"
1349 dependencies = [
1350 "serde",
1351 ]
1352
1353 [[package]]
1281 1354 name = "sha1"
1282 1355 version = "0.10.5"
1283 1356 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1328,6 +1401,18 @@ dependencies = [
1328 1401 ]
1329 1402
1330 1403 [[package]]
1404 name = "simple_asn1"
1405 version = "0.6.2"
1406 source = "registry+https://github.com/rust-lang/crates.io-index"
1407 checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085"
1408 dependencies = [
1409 "num-bigint",
1410 "num-traits",
1411 "thiserror",
1412 "time 0.3.28",
1413 ]
1414
1415 [[package]]
1331 1416 name = "slab"
1332 1417 version = "0.4.9"
1333 1418 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1489,7 +1574,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1489 1574 checksum = "8ca69bf415b93b60b80dc8fda3cb4ef52b2336614d8da2de5456cc942a110482"
1490 1575 dependencies = [
1491 1576 "atoi",
1492 "base64",
1577 "base64 0.21.3",
1493 1578 "bitflags 2.4.0",
1494 1579 "byteorder",
1495 1580 "bytes",
@@ -1532,7 +1617,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1532 1617 checksum = "a0db2df1b8731c3651e204629dd55e52adbae0462fa1bdcbed56a2302c18181e"
1533 1618 dependencies = [
1534 1619 "atoi",
1535 "base64",
1620 "base64 0.21.3",
1536 1621 "bitflags 2.4.0",
1537 1622 "byteorder",
1538 1623 "chrono",
@@ -1681,6 +1766,34 @@ dependencies = [
1681 1766 ]
1682 1767
1683 1768 [[package]]
1769 name = "time"
1770 version = "0.3.28"
1771 source = "registry+https://github.com/rust-lang/crates.io-index"
1772 checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48"
1773 dependencies = [
1774 "deranged",
1775 "itoa",
1776 "serde",
1777 "time-core",
1778 "time-macros",
1779 ]
1780
1781 [[package]]
1782 name = "time-core"
1783 version = "0.1.1"
1784 source = "registry+https://github.com/rust-lang/crates.io-index"
1785 checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
1786
1787 [[package]]
1788 name = "time-macros"
1789 version = "0.2.14"
1790 source = "registry+https://github.com/rust-lang/crates.io-index"
1791 checksum = "1a942f44339478ef67935ab2bbaec2fb0322496cf3cbe84b261e06ac3814c572"
1792 dependencies = [
1793 "time-core",
1794 ]
1795
1796 [[package]]
1684 1797 name = "tinyvec"
1685 1798 version = "1.6.0"
1686 1799 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1749,6 +1862,40 @@ dependencies = [
1749 1862 ]
1750 1863
1751 1864 [[package]]
1865 name = "toml"
1866 version = "0.7.6"
1867 source = "registry+https://github.com/rust-lang/crates.io-index"
1868 checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542"
1869 dependencies = [
1870 "serde",
1871 "serde_spanned",
1872 "toml_datetime",
1873 "toml_edit",
1874 ]
1875
1876 [[package]]
1877 name = "toml_datetime"
1878 version = "0.6.3"
1879 source = "registry+https://github.com/rust-lang/crates.io-index"
1880 checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
1881 dependencies = [
1882 "serde",
1883 ]
1884
1885 [[package]]
1886 name = "toml_edit"
1887 version = "0.19.14"
1888 source = "registry+https://github.com/rust-lang/crates.io-index"
1889 checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a"
1890 dependencies = [
1891 "indexmap",
1892 "serde",
1893 "serde_spanned",
1894 "toml_datetime",
1895 "winnow",
1896 ]
1897
1898 [[package]]
1752 1899 name = "tracing"
1753 1900 version = "0.1.37"
1754 1901 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1866,6 +2013,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1866 2013 checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
1867 2014
1868 2015 [[package]]
2016 name = "untrusted"
2017 version = "0.7.1"
2018 source = "registry+https://github.com/rust-lang/crates.io-index"
2019 checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
2020
2021 [[package]]
1869 2022 name = "url"
1870 2023 version = "2.4.0"
1871 2024 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1967,6 +2120,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1967 2120 checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
1968 2121
1969 2122 [[package]]
2123 name = "web-sys"
2124 version = "0.3.64"
2125 source = "registry+https://github.com/rust-lang/crates.io-index"
2126 checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
2127 dependencies = [
2128 "js-sys",
2129 "wasm-bindgen",
2130 ]
2131
2132 [[package]]
1970 2133 name = "whoami"
1971 2134 version = "1.4.1"
1972 2135 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2070,6 +2233,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2070 2233 checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
2071 2234
2072 2235 [[package]]
2236 name = "winnow"
2237 version = "0.5.15"
2238 source = "registry+https://github.com/rust-lang/crates.io-index"
2239 checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc"
2240 dependencies = [
2241 "memchr",
2242 ]
2243
2244 [[package]]
2073 2245 name = "zeroize"
2074 2246 version = "1.6.0"
2075 2247 source = "registry+https://github.com/rust-lang/crates.io-index"

Cargo.toml

View file
@@ -13,6 +13,10 @@ futures-util = "*"
13 13 serde = { version = "1", features = [ "derive" ]}
14 14 serde_json = "1.0"
15 15 tracing-subscriber = "0.3"
16 jsonwebtoken = { version = "*", features = ["use_pem"]}
17 log = "*"
18
19 toml = { version = "0.7" }
16 20
17 21 chrono = { version = "0.4", features = [ "serde" ] }
18 22 async-trait = "0.1"

src/authentication.rs

View file
@@ -0,0 +1,76 @@
1 use std::{error::Error, time::SystemTime};
2
3 use chrono::Duration;
4 use jsonwebtoken::{encode, Algorithm, EncodingKey};
5 use serde::{Deserialize, Serialize};
6 use tokio::{fs::File, io::AsyncReadExt};
7 use toml::Table;
8
9 use crate::{
10 messages::authentication::{AuthenticationTokenRequest, AuthenticationTokenResponse},
11 model::{instance::Instance, user::User},
12 };
13
14 #[derive(Debug, Serialize, Deserialize)]
15 struct UserTokenMetadata {
16 user: User,
17 generated_for: Instance,
18 exp: u64,
19 }
20
21 pub struct AuthenticationTokenGranter {
22 pub config: Table,
23 }
24
25 impl AuthenticationTokenGranter {
26 pub async fn token_request(
27 &mut self,
28 request: AuthenticationTokenRequest,
29 ) -> Result<AuthenticationTokenResponse, Box<dyn Error + Send>> {
30 let secret_key = self.config["authentication"]["secret_key"]
31 .as_str()
32 .unwrap();
33 let private_key = {
34 let mut file = File::open(self.config["keys"]["private"].as_str().unwrap())
35 .await
36 .unwrap();
37
38 let mut key = vec![];
39 file.read_to_end(&mut key).await.unwrap();
40
41 key
42 };
43
44 if request.secret_key != secret_key {
45 error!("Incorrect secret key!");
46
47 panic!()
48 }
49
50 let encoding_key = EncodingKey::from_rsa_pem(&private_key).unwrap();
51
52 let claims = UserTokenMetadata {
53 user: User {
54 username: String::from("ambee"),
55 instance: Instance {
56 url: String::from("giterated.dev"),
57 },
58 },
59 generated_for: Instance {
60 url: String::from("giterated.dev"),
61 },
62 exp: (SystemTime::UNIX_EPOCH.elapsed().unwrap()
63 + std::time::Duration::from_secs(24 * 60 * 60))
64 .as_secs(),
65 };
66
67 let token = encode(
68 &jsonwebtoken::Header::new(Algorithm::RS256),
69 &claims,
70 &encoding_key,
71 )
72 .unwrap();
73
74 Ok(AuthenticationTokenResponse { token })
75 }
76 }

src/backend/git.rs

View file
@@ -151,7 +151,7 @@ impl GitBackend {
151 151 }
152 152
153 153 // Delete the repository from the database
154 return match sqlx::query!(
154 match sqlx::query!(
155 155 "DELETE FROM repositories WHERE instance_url = $1 AND username = $2 AND name = $3",
156 156 instance_url,
157 157 username,
@@ -162,7 +162,7 @@ impl GitBackend {
162 162 {
163 163 Ok(deleted) => Ok(deleted.rows_affected()),
164 164 Err(err) => Err(GitBackendError::FailedDeletingFromDatabase(err)),
165 };
165 }
166 166 }
167 167
168 168 // TODO: Find where this fits
@@ -197,7 +197,7 @@ impl GitBackend {
197 197 let current_path = dd.new_file().path().unwrap();
198 198
199 199 // Path or directory
200 if current_path.eq(Path::new(&path)) || current_path.starts_with(&path) {
200 if current_path.eq(Path::new(&path)) || current_path.starts_with(path) {
201 201 return Ok(commit.into());
202 202 }
203 203 }
@@ -215,7 +215,7 @@ impl RepositoryBackend for GitBackend {
215 215 request: &CreateRepositoryRequest,
216 216 ) -> Result<CreateRepositoryResponse, Box<dyn Error + Send>> {
217 217 // Check if repository already exists in the database
218 if let Ok(repository) = self
218 if let Ok(_repository) = self
219 219 .find_by_instance_username_name(
220 220 request.owner.instance.url.as_str(),
221 221 request.owner.username.as_str(),
@@ -304,7 +304,7 @@ impl RepositoryBackend for GitBackend {
304 304
305 305 if !repository.can_user_view_repository(
306 306 request.owner.instance.url.as_str(),
307 Some(&request.owner.username.as_str()),
307 Some(request.owner.username.as_str()),
308 308 ) {
309 309 return Err(Box::new(GitBackendError::RepositoryNotFound {
310 310 instance_url: request.owner.instance.url.clone(),
@@ -361,7 +361,7 @@ impl RepositoryBackend for GitBackend {
361 361 let mut current_path = rev_name.replace("refs/heads/", "");
362 362
363 363 // Get the commit tree
364 let mut git_tree = if let Some(path) = &request.path {
364 let git_tree = if let Some(path) = &request.path {
365 365 // Add it to our full path string
366 366 current_path.push_str(format!("/{}", path).as_str());
367 367 // Get the specified path, return an error if it wasn't found.
@@ -400,7 +400,7 @@ impl RepositoryBackend for GitBackend {
400 400 }
401 401
402 402 // Could possibly be done better
403 let path = if let Some(path) = current_path.split_once("/") {
403 let path = if let Some(path) = current_path.split_once('/') {
404 404 format!("{}/{}", path.1, entry.name().unwrap())
405 405 } else {
406 406 entry.name().unwrap().to_string()

src/connection.rs

View file
@@ -12,6 +12,7 @@ use tokio::{
12 12 use tokio_tungstenite::{tungstenite::Message, WebSocketStream};
13 13
14 14 use crate::{
15 authentication::AuthenticationTokenGranter,
15 16 backend::{IssuesBackend, RepositoryBackend},
16 17 handshake::{HandshakeFinalize, HandshakeMessage, HandshakeResponse},
17 18 listener::Listeners,
@@ -54,6 +55,7 @@ pub async fn connection_worker(
54 55 listeners: Arc<Mutex<Listeners>>,
55 56 connections: Arc<Mutex<Connections>>,
56 57 backend: Arc<Mutex<dyn RepositoryBackend + Send>>,
58 auth_granter: Arc<Mutex<AuthenticationTokenGranter>>,
57 59 addr: SocketAddr,
58 60 ) {
59 61 let mut handshaked = false;
@@ -183,7 +185,7 @@ pub async fn connection_worker(
183 185 RepositoryMessageKind::Request(request) => match request {
184 186 RepositoryRequest::CreateRepository(request) => {
185 187 let mut backend = backend.lock().await;
186 let response = backend.create_repository(request);
188 let response = backend.create_repository(request).await;
187 189
188 190 let response = match response {
189 191 Ok(response) => response,
@@ -241,7 +243,7 @@ pub async fn connection_worker(
241 243 }
242 244 RepositoryRequest::RepositoryInfo(request) => {
243 245 let mut backend = backend.lock().await;
244 let response = backend.repository_info(request);
246 let response = backend.repository_info(request).await;
245 247
246 248 let response = match response {
247 249 Ok(response) => response,

src/lib.rs

View file
@@ -1,3 +1,4 @@
1 pub mod authentication;
1 2 pub mod backend;
2 3 pub mod connection;
3 4 pub mod handshake;

src/main.rs

View file
@@ -2,16 +2,20 @@ use std::{error::Error, net::SocketAddr, sync::Arc};
2 2
3 3 use connection::{connection_worker, Connections, RawConnection};
4 4 use giterated_daemon::{
5 authentication::AuthenticationTokenGranter,
5 6 backend::{git::GitBackend, RepositoryBackend},
6 7 connection, listener,
7 8 };
8 9 use listener::Listeners;
10 use sqlx::{postgres::PgConnectOptions, ConnectOptions, PgPool};
9 11 use tokio::{
10 io::{AsyncRead, AsyncWrite},
12 fs::File,
13 io::{AsyncRead, AsyncReadExt, AsyncWrite},
11 14 net::{TcpListener, TcpStream},
12 15 sync::Mutex,
13 16 };
14 17 use tokio_tungstenite::{accept_async, WebSocketStream};
18 use toml::Table;
15 19
16 20 #[macro_use]
17 21 extern crate tracing;
@@ -19,10 +23,36 @@ extern crate tracing;
19 23 #[tokio::main]
20 24 async fn main() -> Result<(), Box<dyn Error>> {
21 25 tracing_subscriber::fmt::init();
22 let mut listener = TcpListener::bind("127.0.0.1:8080").await?;
26 let mut listener = TcpListener::bind("0.0.0.0:7270").await?;
23 27 let connections: Arc<Mutex<Connections>> = Arc::default();
24 28 let listeners: Arc<Mutex<Listeners>> = Arc::default();
25 let backend: Arc<Mutex<dyn RepositoryBackend + Send>> = Arc::new(Mutex::new(GitBackend::new()));
29 let config: Table = {
30 let mut file = File::open("Giterated.toml").await?;
31 let mut text = String::new();
32 file.read_to_string(&mut text).await?;
33 text.parse()?
34 };
35 let db_conn_options = PgConnectOptions::new()
36 .host(config["postgres"]["host"].as_str().unwrap())
37 .port(config["postgres"]["port"].as_integer().unwrap() as u16)
38 .database(config["postgres"]["database"].as_str().unwrap())
39 .username(config["postgres"]["user"].as_str().unwrap())
40 .password(config["postgres"]["password"].as_str().unwrap())
41 .log_statements(log::LevelFilter::Off)
42 .to_owned();
43 let db_pool = PgPool::connect_with(db_conn_options).await?;
44
45 let repository_backend: Arc<Mutex<dyn RepositoryBackend + Send>> = Arc::new(Mutex::new({
46 let foo: GitBackend = GitBackend {
47 pg_pool: db_pool,
48 repository_folder: String::from("/tmp/foo"),
49 };
50 foo
51 }));
52
53 let token_granter = Arc::new(Mutex::new(AuthenticationTokenGranter {
54 config: config.clone(),
55 }));
26 56
27 57 loop {
28 58 let stream = accept_stream(&mut listener).await;
@@ -57,7 +87,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
57 87 connection,
58 88 listeners.clone(),
59 89 connections.clone(),
60 backend.clone(),
90 repository_backend.clone(),
91 token_granter.clone(),
61 92 address,
62 93 )),
63 94 };

src/messages/authentication.rs

View file
@@ -0,0 +1,29 @@
1 use serde::{Deserialize, Serialize};
2
3 #[derive(Clone, Serialize, Deserialize)]
4 pub enum AuthenticationMessage {
5 Request(AuthenticationRequest),
6 Response(AuthenticationResponse),
7 }
8
9 #[derive(Clone, Serialize, Deserialize)]
10 pub enum AuthenticationRequest {
11 AuthenticationToken(AuthenticationTokenRequest),
12 }
13
14 #[derive(Clone, Serialize, Deserialize)]
15 pub enum AuthenticationResponse {
16 AuthenticationToken(AuthenticationTokenResponse),
17 }
18
19 #[derive(Clone, Serialize, Deserialize)]
20 pub struct AuthenticationTokenRequest {
21 pub secret_key: String,
22 pub username: String,
23 pub password: String,
24 }
25
26 #[derive(Clone, Serialize, Deserialize)]
27 pub struct AuthenticationTokenResponse {
28 pub token: String,
29 }

src/messages/mod.rs

View file
@@ -2,8 +2,9 @@ use serde::{Deserialize, Serialize};
2 2
3 3 use crate::handshake::HandshakeMessage;
4 4
5 use self::repository::RepositoryMessage;
5 use self::{authentication::AuthenticationMessage, repository::RepositoryMessage};
6 6
7 pub mod authentication;
7 8 pub mod issues;
8 9 pub mod repository;
9 10 pub mod user;
@@ -12,4 +13,5 @@ pub mod user;
12 13 pub enum MessageKind {
13 14 Handshake(HandshakeMessage),
14 15 Repository(RepositoryMessage),
16 Authentication(AuthenticationMessage),
15 17 }

src/model/repository.rs

View file
@@ -101,9 +101,7 @@ impl From<git2::Commit<'_>> for Commit {
101 101 fn from(commit: git2::Commit<'_>) -> Self {
102 102 Self {
103 103 oid: commit.id().to_string(),
104 message: commit
105 .message()
106 .map_or(None, |message| Some(message.to_string())),
104 message: commit.message().map(|message| message.to_string()),
107 105 author: commit.author().into(),
108 106 committer: commit.committer().into(),
109 107 time: chrono::NaiveDateTime::from_timestamp_opt(commit.time().seconds(), 0).unwrap(),
@@ -123,10 +121,8 @@ pub struct CommitSignature {
123 121 impl From<git2::Signature<'_>> for CommitSignature {
124 122 fn from(signature: git2::Signature<'_>) -> Self {
125 123 Self {
126 name: signature.name().map_or(None, |name| Some(name.to_string())),
127 email: signature
128 .email()
129 .map_or(None, |email| Some(email.to_string())),
124 name: signature.name().map(|name| name.to_string()),
125 email: signature.email().map(|email| email.to_string()),
130 126 time: chrono::NaiveDateTime::from_timestamp_opt(signature.when().seconds(), 0).unwrap(),
131 127 }
132 128 }