From fa105138def7d51e9ee96b902258ef119c1e0130 Mon Sep 17 00:00:00 2001 From: Andrei Serban Date: Thu, 26 Dec 2024 16:45:33 +0200 Subject: [PATCH 1/4] add checkout to commit --- src-tauri/src/git/git_commit.rs | 37 +++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src-tauri/src/git/git_commit.rs b/src-tauri/src/git/git_commit.rs index 2c57d16..d6d8b2c 100644 --- a/src-tauri/src/git/git_commit.rs +++ b/src-tauri/src/git/git_commit.rs @@ -1,11 +1,19 @@ use super::{ git_commit_author::{GitCommitAuthor, GitCommitAuthorType}, + git_files::GitFilesRequired, + git_folders::{GitFolders, GIT_FOLDER}, git_project::GitProject, + git_tree::GitTree, object::{GitObject, Header}, }; use crate::errors::git_object_error::{CommitError, GitObjectError}; use core::fmt; use serde::{Deserialize, Serialize}; +use std::{ + fs::{self, OpenOptions}, + io::Write, + path::{Path, PathBuf}, +}; pub enum CommitPrefix { Tree, @@ -149,6 +157,35 @@ impl GitCommit { Ok(history) } + + /** + * Checkout all the files in a commit + */ + pub fn checkout(&self, project: &GitProject) -> Result<(), GitObjectError> { + let files = + GitTree::from_hash(project, &self.get_tree_hash())?.get_object_blobs(project, None); + + let _ = files.iter().for_each(|file| { + let path = PathBuf::from(project.get_directory()).join(&file.0); + let file_in_fs = OpenOptions::new().write(true).create(true).open(path); + + if let Ok(mut file_in_fs) = file_in_fs { + let _ = file_in_fs.write_all(file.1.data()); + } + }); + + let head_path = PathBuf::from(project.get_directory()) + .join(GIT_FOLDER) + .join(GitFilesRequired::HEAD.as_ref()); + OpenOptions::new() + .write(true) + .open(head_path) + .map_err(|_| GitObjectError::InvalidCommitFile(CommitError::InvalidContent))? + .write_all(self.get_hash().as_bytes()) + .map_err(|_| GitObjectError::InvalidHash)?; + + Ok(()) + } } impl GitObject for GitCommit { From ac25be4138b639fc9a6e9374195ac5357728534c Mon Sep 17 00:00:00 2001 From: Andrei Serban Date: Thu, 26 Dec 2024 17:26:24 +0200 Subject: [PATCH 2/4] clippy --- src-tauri/src/git/git_commit.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src-tauri/src/git/git_commit.rs b/src-tauri/src/git/git_commit.rs index d6d8b2c..93bb33f 100644 --- a/src-tauri/src/git/git_commit.rs +++ b/src-tauri/src/git/git_commit.rs @@ -1,7 +1,7 @@ use super::{ git_commit_author::{GitCommitAuthor, GitCommitAuthorType}, git_files::GitFilesRequired, - git_folders::{GitFolders, GIT_FOLDER}, + git_folders::GIT_FOLDER, git_project::GitProject, git_tree::GitTree, object::{GitObject, Header}, @@ -9,11 +9,7 @@ use super::{ use crate::errors::git_object_error::{CommitError, GitObjectError}; use core::fmt; use serde::{Deserialize, Serialize}; -use std::{ - fs::{self, OpenOptions}, - io::Write, - path::{Path, PathBuf}, -}; +use std::{fs::OpenOptions, io::Write, path::PathBuf}; pub enum CommitPrefix { Tree, @@ -163,11 +159,15 @@ impl GitCommit { */ pub fn checkout(&self, project: &GitProject) -> Result<(), GitObjectError> { let files = - GitTree::from_hash(project, &self.get_tree_hash())?.get_object_blobs(project, None); + GitTree::from_hash(project, self.get_tree_hash())?.get_object_blobs(project, None); - let _ = files.iter().for_each(|file| { + files.iter().for_each(|file| { let path = PathBuf::from(project.get_directory()).join(&file.0); - let file_in_fs = OpenOptions::new().write(true).create(true).open(path); + let file_in_fs = OpenOptions::new() + .write(true) + .truncate(true) + .create(true) + .open(path); if let Ok(mut file_in_fs) = file_in_fs { let _ = file_in_fs.write_all(file.1.data()); From 6d931366f631440b087e4661f3bf978c2364df51 Mon Sep 17 00:00:00 2001 From: Andrei Serban Date: Thu, 26 Dec 2024 22:00:25 +0200 Subject: [PATCH 3/4] add commands --- src-tauri/src/git/git_branch.rs | 25 +++++++++++++++++++++++++ src-tauri/src/git/project_folder.rs | 17 +++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src-tauri/src/git/git_branch.rs b/src-tauri/src/git/git_branch.rs index 882ffb9..9409d47 100644 --- a/src-tauri/src/git/git_branch.rs +++ b/src-tauri/src/git/git_branch.rs @@ -1,5 +1,14 @@ +use std::{fs::OpenOptions, io::Write, path::PathBuf}; + use serde::{Deserialize, Serialize}; +use crate::errors::git_object_error::{CommitError, GitObjectError}; + +use super::{ + git_commit::GitCommit, git_files::GitFilesRequired, git_folders::GIT_FOLDER, + git_project::GitProject, object::GitObject, +}; + #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] #[serde(rename_all = "camelCase")] pub struct GitBranch { @@ -11,6 +20,22 @@ impl GitBranch { pub fn new(name: String, commit: String) -> GitBranch { GitBranch { name, commit } } + + pub fn checkout(&self, project: &GitProject) -> Result<(), GitObjectError> { + GitCommit::from_hash(project, &self.commit)?.checkout(project)?; + + let head_path = PathBuf::from(project.get_directory()) + .join(GIT_FOLDER) + .join(GitFilesRequired::HEAD.as_ref()); + OpenOptions::new() + .write(true) + .open(head_path) + .map_err(|_| GitObjectError::InvalidCommitFile(CommitError::InvalidContent))? + .write_all(self.name.as_bytes()) + .map_err(|_| GitObjectError::InvalidHash)?; + + Ok(()) + } } #[cfg(test)] diff --git a/src-tauri/src/git/project_folder.rs b/src-tauri/src/git/project_folder.rs index 30c9c96..fa64cef 100644 --- a/src-tauri/src/git/project_folder.rs +++ b/src-tauri/src/git/project_folder.rs @@ -1,4 +1,5 @@ use super::{ + git_branch::GitBranch, git_commit::{GitCommit, GitCommitWithHash}, git_folders::GitBranchType, git_project::GitProject, @@ -83,6 +84,22 @@ pub fn get_commit_history( .map_err(|_| GitError::InvalidHistory) } +#[tauri::command] +pub fn checkout_branch(project: GitProject, branch: GitBranch) -> Result<(), GitError> { + branch + .checkout(&project) + .map_err(|_| GitError::NoLocalBranches) +} + +#[tauri::command] +pub fn checkout_commit(project: GitProject, hash: &str) -> Result<(), GitError> { + let commit = GitCommit::from_hash(&project, hash).map_err(|_| GitError::InvalidHistory)?; + + commit + .checkout(&project) + .map_err(|_| GitError::InvalidHistory) +} + #[cfg(test)] mod tests { use std::{ From 468eebadd34712571a2af47f49671fcaf562a931 Mon Sep 17 00:00:00 2001 From: Andrei Serban Date: Thu, 26 Dec 2024 22:32:06 +0200 Subject: [PATCH 4/4] Add checkout --- index.html | 5 +- src-tauri/src/main.rs | 4 +- src/App.vue | 13 +++-- src/components/Dialogs/ContextMenu.vue | 58 +++++++++++++++++++ .../Project/Commit/CommitListItem.vue | 21 ++++--- src/stores/dialogs.ts | 31 +++++++++- src/types/tauri.ts | 2 + 7 files changed, 118 insertions(+), 16 deletions(-) create mode 100644 src/components/Dialogs/ContextMenu.vue diff --git a/index.html b/index.html index 99f203f..53c071c 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,10 @@ - Tauri + Vue + Typescript App + BranchWise + diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 7fadae7..da0ee95 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -11,7 +11,7 @@ use database::storage::DATABASE; use errors::git_error::GitErrorProject; use git::project_folder::{ get_commit_history, get_database_projects, open_git_project, remove_database_project, - set_current_project, + set_current_project, checkout_branch, checkout_commit }; use tauri::{AppHandle, Emitter, Manager}; @@ -89,6 +89,8 @@ fn main() { remove_database_project, set_current_project, get_commit_history, + checkout_branch, + checkout_commit ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/src/App.vue b/src/App.vue index 2ac836b..5543613 100644 --- a/src/App.vue +++ b/src/App.vue @@ -13,11 +13,13 @@ {{ snackbar.text }} + diff --git a/src/components/Project/Commit/CommitListItem.vue b/src/components/Project/Commit/CommitListItem.vue index e7464d4..b831217 100644 --- a/src/components/Project/Commit/CommitListItem.vue +++ b/src/components/Project/Commit/CommitListItem.vue @@ -5,6 +5,7 @@ style="height: 10vh;" :class="commitClass" @click="setCommit" + @click.right="showContextMenu" > - + {{ getMessage }} @@ -50,6 +51,7 @@