refactor sessions mod

This commit is contained in:
Nikita Galaiko 2023-02-20 10:17:44 +01:00
parent 0562bcae5d
commit 137f73848f
No known key found for this signature in database
GPG Key ID: EBAB54E845BA519D
7 changed files with 120 additions and 94 deletions

View File

@ -82,7 +82,7 @@ fn init(
Some(session) => session,
None => sessions::Session::from_head(git_repository, project)?,
};
sessions::flush_session(git_repository, user, project, &mut current_session)?;
current_session.flush(git_repository, user, project)?;
Ok(())
} else {
Err(error).with_context(|| {

View File

@ -0,0 +1,30 @@
use anyhow::{anyhow, Result};
use serde::Serialize;
#[derive(Debug, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Activity {
#[serde(rename = "type")]
pub activity_type: String,
pub timestamp: u64,
pub message: String,
}
pub fn parse_reflog_line(line: &str) -> Result<Activity> {
match line.split("\t").collect::<Vec<&str>>()[..] {
[meta, message] => {
let meta_parts = meta.split_whitespace().collect::<Vec<&str>>();
let timestamp = meta_parts[meta_parts.len() - 2].parse::<u64>()?;
match message.split(": ").collect::<Vec<&str>>()[..] {
[entry_type, msg] => Ok(Activity {
activity_type: entry_type.to_string(),
message: msg.to_string(),
timestamp,
}),
_ => Err(anyhow!("failed to parse reflog line: {}", line)),
}
}
_ => Err(anyhow!("failed to parse reflog line: {}", line)),
}
}

View File

@ -0,0 +1,49 @@
use super::activity::{parse_reflog_line, Activity};
#[test]
fn test_parse_reflog_line() {
let test_cases = vec![
(
"9ea641990993cb60c7d89c41606f6b457adb9681 3f2657e0d1eae57f58d7734aae10310a861de8e8 Nikita Galaiko <nikita@galaiko.rocks> 1676275740 +0100 commit: try sturdy mac dev certificate",
Activity{ activity_type: "commit".to_string(), timestamp: 1676275740, message: "try sturdy mac dev certificate".to_string() }
),
(
"999bc2f0194ea001f71ba65b5422a742b5e66d9f bb98b5411d597fdede63053c190260a38d459ecb Nikita Galaiko <nikita@galaiko.rocks> 1675428111 +0100 checkout: moving from production-build to master",
Activity{ activity_type: "checkout".to_string(), timestamp: 1675428111, message: "moving from production-build to master".to_string() },
),
(
"0000000000000000000000000000000000000000 9aa96f488fbdb8f7b15151d9d2e47690d3b21b46 Nikita Galaiko <nikita@galaiko.rocks> 1675176957 +0100 commit (initial): simple tauri example",
Activity{ activity_type: "commit (initial)".to_string(), timestamp: 1675176957, message: "simple tauri example".to_string() },
),
(
"d083bb9213fc5e0bb6d07c2c6c1eae5be483be25 dc870a80fddb843583baa36cb637c5c820b1e863 Nikita Galaiko <nikita@galaiko.rocks> 1675425613 +0100 commit (amend): build app with github actions",
Activity{ activity_type: "commit (amend)".to_string(), timestamp: 1675425613, message: "build app with github actions".to_string() },
),
(
"2843be38a72ac8418c7e5c5630cba3c4803916d1 fbb7a9356484b948bde4c7ee9fdeb6439edff8c0 Nikita Galaiko <nikita@galaiko.rocks> 1676274883 +0100 pull: Fast-forward",
Activity{ activity_type: "pull".to_string(), timestamp: 1676274883, message: "Fast-forward".to_string() },
),
(
"3f2657e0d1eae57f58d7734aae10310a861de8e8 3f2657e0d1eae57f58d7734aae10310a861de8e8 Nikita Galaiko <nikita@galaiko.rocks> 1676277401 +0100 reset: moving to HEAD",
Activity{ activity_type: "reset".to_string() , timestamp: 1676277401, message: "moving to HEAD".to_string() },
),
(
"9a831ba2fa07aa6a399bbb498e8effd913cec2e0 add94e65594e4c240b0f6b03973a3be3ff594306 Nikita Galaiko <nikita@galaiko.rocks> 1676039997 +0100 pull --rebase (start): checkout add94e65594e4c240b0f6b03973a3be3ff594306",
Activity{ activity_type: "pull --rebase (start)".to_string(), timestamp: 1676039997, message: "checkout add94e65594e4c240b0f6b03973a3be3ff594306".to_string() },
),
(
"add94e65594e4c240b0f6b03973a3be3ff594306 bcc93167c068649868aa3df4999ba154468a62b5 Nikita Galaiko <nikita@galaiko.rocks> 1676039997 +0100 pull --rebase (pick): make app run in background",
Activity{ activity_type: "pull --rebase (pick)".to_string(), timestamp: 1676039997, message: "make app run in background".to_string() },
),
(
"bcc93167c068649868aa3df4999ba154468a62b5 bcc93167c068649868aa3df4999ba154468a62b5 Nikita Galaiko <nikita@galaiko.rocks> 1676039997 +0100 pull --rebase (finish): returning to refs/heads/master",
Activity{ activity_type: "pull --rebase (finish)".to_string(), timestamp: 1676039997, message: "returning to refs/heads/master".to_string() },
)
];
for (line, expected) in test_cases {
let actual = parse_reflog_line(line);
assert!(actual.is_ok());
assert_eq!(actual.unwrap(), expected);
}
}

View File

@ -0,0 +1,7 @@
mod activity;
mod sessions;
pub use sessions::{get, list, list_files, Session};
#[cfg(test)]
mod activity_tests;

View File

@ -1,3 +1,4 @@
use super::activity;
use crate::{fs, projects, users};
use anyhow::{anyhow, Context, Result};
use filetime::FileTime;
@ -33,35 +34,7 @@ pub struct Session {
// if hash is not set, the session is not saved aka current
pub hash: Option<String>,
pub meta: Meta,
pub activity: Vec<Activity>,
}
#[derive(Debug, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Activity {
#[serde(rename = "type")]
pub activity_type: String,
pub timestamp: u64,
pub message: String,
}
fn parse_reflog_line(line: &str) -> Result<Activity> {
match line.split("\t").collect::<Vec<&str>>()[..] {
[meta, message] => {
let meta_parts = meta.split_whitespace().collect::<Vec<&str>>();
let timestamp = meta_parts[meta_parts.len() - 2].parse::<u64>()?;
match message.split(": ").collect::<Vec<&str>>()[..] {
[entry_type, msg] => Ok(Activity {
activity_type: entry_type.to_string(),
message: msg.to_string(),
timestamp,
}),
_ => Err(anyhow!("failed to parse reflog line: {}", line)),
}
}
_ => Err(anyhow!("failed to parse reflog line: {}", line)),
}
pub activity: Vec<activity::Activity>,
}
impl Session {
@ -110,9 +83,9 @@ impl Session {
})?;
let activity = reflog
.lines()
.filter_map(|line| parse_reflog_line(line).ok())
.filter_map(|line| activity::parse_reflog_line(line).ok())
.filter(|activity| activity.timestamp >= start_ts)
.collect::<Vec<Activity>>();
.collect::<Vec<activity::Activity>>();
let id_path = meta_path.join("id");
let id = std::fs::read_to_string(id_path.clone())
@ -149,7 +122,7 @@ impl Session {
},
activity: vec![],
};
create_session(project, &session)?;
create(project, &session)?;
Ok(session)
}
@ -175,9 +148,9 @@ impl Session {
})?;
let activity = reflog
.lines()
.filter_map(|line| parse_reflog_line(line).ok())
.filter_map(|line| activity::parse_reflog_line(line).ok())
.filter(|activity| activity.timestamp >= start_ts)
.collect::<Vec<Activity>>();
.collect::<Vec<activity::Activity>>();
Ok(Session {
id: read_as_string(repo, &tree, Path::new("session/meta/id")).with_context(|| {
@ -215,9 +188,22 @@ impl Session {
activity,
})
}
pub fn update(&self, project: &projects::Project) -> Result<()> {
update(project, self)
}
pub fn flush(
&mut self,
repo: &git2::Repository,
user: &Option<users::User>,
project: &projects::Project,
) -> Result<()> {
flush(repo, user, project, self)
}
}
fn write_session(session_path: &Path, session: &Session) -> Result<()> {
fn write(session_path: &Path, session: &Session) -> Result<()> {
if session.hash.is_some() {
return Err(anyhow!("cannot write session that is not current"));
}
@ -270,27 +256,27 @@ fn write_session(session_path: &Path, session: &Session) -> Result<()> {
Ok(())
}
pub fn update_session(project: &projects::Project, session: &Session) -> Result<()> {
fn update(project: &projects::Project, session: &Session) -> Result<()> {
let session_path = project.session_path();
log::debug!("{}: Updating current session", session_path.display());
if session_path.exists() {
write_session(&session_path, session)
write(&session_path, session)
} else {
Err(anyhow!("session does not exist"))
}
}
pub fn create_session(project: &projects::Project, session: &Session) -> Result<()> {
fn create(project: &projects::Project, session: &Session) -> Result<()> {
let session_path = project.session_path();
log::debug!("{}: Creating current session", session_path.display());
if session_path.exists() {
Err(anyhow!("session already exists"))
} else {
write_session(&session_path, session)
write(&session_path, session)
}
}
fn delete_session(project: &projects::Project) -> Result<()> {
fn delete(project: &projects::Project) -> Result<()> {
let session_path = project.session_path();
log::debug!("{}: Deleting current session", session_path.display());
if session_path.exists() {
@ -428,55 +414,7 @@ pub fn list_files(
Ok(files)
}
#[test]
fn test_parse_reflog_line() {
let test_cases = vec![
(
"9ea641990993cb60c7d89c41606f6b457adb9681 3f2657e0d1eae57f58d7734aae10310a861de8e8 Nikita Galaiko <nikita@galaiko.rocks> 1676275740 +0100 commit: try sturdy mac dev certificate",
Activity{ activity_type: "commit".to_string(), timestamp: 1676275740, message: "try sturdy mac dev certificate".to_string() }
),
(
"999bc2f0194ea001f71ba65b5422a742b5e66d9f bb98b5411d597fdede63053c190260a38d459ecb Nikita Galaiko <nikita@galaiko.rocks> 1675428111 +0100 checkout: moving from production-build to master",
Activity{ activity_type: "checkout".to_string(), timestamp: 1675428111, message: "moving from production-build to master".to_string() },
),
(
"0000000000000000000000000000000000000000 9aa96f488fbdb8f7b15151d9d2e47690d3b21b46 Nikita Galaiko <nikita@galaiko.rocks> 1675176957 +0100 commit (initial): simple tauri example",
Activity{ activity_type: "commit (initial)".to_string(), timestamp: 1675176957, message: "simple tauri example".to_string() },
),
(
"d083bb9213fc5e0bb6d07c2c6c1eae5be483be25 dc870a80fddb843583baa36cb637c5c820b1e863 Nikita Galaiko <nikita@galaiko.rocks> 1675425613 +0100 commit (amend): build app with github actions",
Activity{ activity_type: "commit (amend)".to_string(), timestamp: 1675425613, message: "build app with github actions".to_string() },
),
(
"2843be38a72ac8418c7e5c5630cba3c4803916d1 fbb7a9356484b948bde4c7ee9fdeb6439edff8c0 Nikita Galaiko <nikita@galaiko.rocks> 1676274883 +0100 pull: Fast-forward",
Activity{ activity_type: "pull".to_string(), timestamp: 1676274883, message: "Fast-forward".to_string() },
),
(
"3f2657e0d1eae57f58d7734aae10310a861de8e8 3f2657e0d1eae57f58d7734aae10310a861de8e8 Nikita Galaiko <nikita@galaiko.rocks> 1676277401 +0100 reset: moving to HEAD",
Activity{ activity_type: "reset".to_string() , timestamp: 1676277401, message: "moving to HEAD".to_string() },
),
(
"9a831ba2fa07aa6a399bbb498e8effd913cec2e0 add94e65594e4c240b0f6b03973a3be3ff594306 Nikita Galaiko <nikita@galaiko.rocks> 1676039997 +0100 pull --rebase (start): checkout add94e65594e4c240b0f6b03973a3be3ff594306",
Activity{ activity_type: "pull --rebase (start)".to_string(), timestamp: 1676039997, message: "checkout add94e65594e4c240b0f6b03973a3be3ff594306".to_string() },
),
(
"add94e65594e4c240b0f6b03973a3be3ff594306 bcc93167c068649868aa3df4999ba154468a62b5 Nikita Galaiko <nikita@galaiko.rocks> 1676039997 +0100 pull --rebase (pick): make app run in background",
Activity{ activity_type: "pull --rebase (pick)".to_string(), timestamp: 1676039997, message: "make app run in background".to_string() },
),
(
"bcc93167c068649868aa3df4999ba154468a62b5 bcc93167c068649868aa3df4999ba154468a62b5 Nikita Galaiko <nikita@galaiko.rocks> 1676039997 +0100 pull --rebase (finish): returning to refs/heads/master",
Activity{ activity_type: "pull --rebase (finish)".to_string(), timestamp: 1676039997, message: "returning to refs/heads/master".to_string() },
)
];
for (line, expected) in test_cases {
let actual = parse_reflog_line(line);
assert!(actual.is_ok());
assert_eq!(actual.unwrap(), expected);
}
}
pub fn flush_session(
fn flush(
repo: &git2::Repository,
user: &Option<users::User>,
project: &projects::Project,
@ -540,7 +478,7 @@ pub fn flush_session(
commit_oid
);
session.hash = Some(commit_oid.to_string());
delete_session(project).with_context(|| format!("failed to delete session"))?;
delete(project).with_context(|| format!("failed to delete session"))?;
push_to_remote(repo, user, project)
.with_context(|| format!("failed to push gb commit {} to remote", commit_oid))?;

View File

@ -239,8 +239,9 @@ fn write_beginning_meta_files<R: tauri::Runtime>(
.unwrap()
.as_secs();
session.meta.last_ts = now_ts;
sessions::update_session(project, &session)
.map_err(|e| format!("Error while updating current session: {}", e.to_string()))?;
session
.update(project)
.with_context(|| "failed to update session")?;
events::session(&window, &project, &session);
Ok(session)
}

View File

@ -96,7 +96,8 @@ impl GitWatcher {
{
None => Ok(None),
Some(mut session) => {
sessions::flush_session(&repo, user, project, &mut session)
session
.flush(&repo, user, project)
.with_context(|| "Error while flushing session")?;
Ok(Some(session))
}