Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add Checkout to Commit #234

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open

Add Checkout to Commit #234

wants to merge 4 commits into from

Conversation

hateofhades
Copy link
Contributor

@hateofhades hateofhades commented Dec 26, 2024

Pull Request Overview

This pull request closes #27

Author

Signed-off-by: Andrei Serban - andrei.serban@brewingbytes.com

Summary by CodeRabbit

  • New Features
    • Added functionality to checkout branches and commits directly within the Tauri application.
    • Introduced a method to checkout all files associated with a specific commit, enhancing version control capabilities.
    • Implemented a context menu for right-click interactions on commit list items, allowing users to perform checkout actions easily.
    • Updated the application title to "BranchWise" and added a script to manage the context menu behavior.
    • Added a new ContextMenu component for enhanced user interactions.

Copy link

coderabbitai bot commented Dec 26, 2024

Warning

Rate limit exceeded

@hateofhades has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 15 minutes and 31 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 9071fa7 and 468eeba.

📒 Files selected for processing (7)
  • index.html (1 hunks)
  • src-tauri/src/main.rs (2 hunks)
  • src/App.vue (3 hunks)
  • src/components/Dialogs/ContextMenu.vue (1 hunks)
  • src/components/Project/Commit/CommitListItem.vue (3 hunks)
  • src/stores/dialogs.ts (3 hunks)
  • src/types/tauri.ts (1 hunks)

Walkthrough

The pull request introduces new checkout methods to both the GitCommit and GitBranch structs in the Git-related module. These methods facilitate checking out all files associated with a specific commit or branch, respectively. The implementation retrieves the relevant files from the commit's tree, writes them to the filesystem, and updates the HEAD reference accordingly. Additionally, two new public functions, checkout_branch and checkout_commit, are added to the project folder file, allowing users to perform these operations through Tauri commands. A new ContextMenu component is also introduced for user interactions.

Changes

File Change Summary
src-tauri/src/git/git_commit.rs Added checkout method to GitCommit struct
- Imports added for file and Git-related operations
- Method writes commit files to filesystem
- Updates HEAD reference
src-tauri/src/git/git_branch.rs Added checkout method to GitBranch struct
- Imports added for file handling and error management
- Method creates GitCommit and writes branch name to HEAD file
src-tauri/src/git/project_folder.rs Added checkout_branch and checkout_commit functions
- Both functions are Tauri commands
- Imports added for GitBranch and error handling
index.html Changed document title to "BranchWise"
- Added script to prevent default context menu on right-click
src/App.vue Added ContextMenu component
- Adjusted component registration for DialogComponent
src/components/Dialogs/ContextMenu.vue Introduced ContextMenu component with checkout functionality
src/components/Project/Commit/CommitListItem.vue Added showContextMenu method for right-click context menu
- Updated import for dialog store
src/stores/dialogs.ts Updated IDialogState interface to include contextMenu property
- Added actions for showing and closing context menu
src/types/tauri.ts Added CheckoutBranch and CheckoutCommit commands to TauriCommands enum
src-tauri/src/main.rs Added checkout_branch and checkout_commit functions to invoke handler

Possibly related PRs

  • Add ability to checkout trees #233: The checkout method in the GitCommit struct is related to the get_children_blobs method in the GitTree struct, as both involve retrieving and managing Git objects, enhancing the overall functionality of Git operations within the project.

Poem

🐰 A Rabbit's Git Checkout Delight

Commits dance, files take their flight,
Hopping through trees with all their might,
HEAD points true, filesystem bright,
Git magic unfolds, pure rabbit delight!

🌿✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src-tauri/src/git/git_commit.rs (1)

161-163: Documentation: Improve method documentation.

The current documentation is minimal. Consider adding:

  • Parameter description
  • Return value description
  • Error cases
  • Example usage
-    /**
-     * Checkout all the files in a commit
-     */
+    /// Checks out all files from the commit's tree to the project directory and updates HEAD.
+    ///
+    /// # Arguments
+    /// * `project` - The Git project to checkout files into
+    ///
+    /// # Returns
+    /// * `Ok(())` - If checkout was successful
+    /// * `Err(GitObjectError)` - If any file operation fails or paths are invalid
+    ///
+    /// # Examples
+    /// ```
+    /// let commit = GitCommit::from_hash(project, "abc123")?;
+    /// commit.checkout(project)?;
+    /// ```
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4bdf048 and fa10513.

📒 Files selected for processing (1)
  • src-tauri/src/git/git_commit.rs (2 hunks)
🔇 Additional comments (1)
src-tauri/src/git/git_commit.rs (1)

3-16: LGTM: Imports are well-organized and necessary.

The new imports are properly grouped and provide the required functionality for file operations and Git-related types.

Comment on lines 164 to 188
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(())
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Critical: Add error handling and security measures to checkout implementation.

The current implementation has several critical issues that need to be addressed:

  1. File operations silently ignore errors using let _
  2. Missing directory creation for nested files
  3. No cleanup mechanism on partial failure
  4. Potential path traversal vulnerability

Here's a suggested implementation with proper error handling and security measures:

 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());
-        }
-    });
+    // Track created files for cleanup on failure
+    let mut created_files = Vec::new();
+    
+    // Result to track any failures during file operations
+    let result: Result<(), GitObjectError> = files.iter().try_for_each(|file| {
+        let path = PathBuf::from(project.get_directory()).join(&file.0);
+        
+        // Validate path is within project directory
+        if !path.starts_with(project.get_directory()) {
+            return Err(GitObjectError::InvalidPath);
+        }
+        
+        // Create parent directories
+        if let Some(parent) = path.parent() {
+            fs::create_dir_all(parent).map_err(|_| GitObjectError::FileSystemError)?;
+        }
+        
+        // Create and write file
+        let mut file_in_fs = OpenOptions::new()
+            .write(true)
+            .create(true)
+            .truncate(true)
+            .open(&path)
+            .map_err(|_| GitObjectError::FileSystemError)?;
+            
+        file_in_fs.write_all(file.1.data())
+            .map_err(|_| GitObjectError::FileSystemError)?;
+            
+        created_files.push(path);
+        Ok(())
+    });
+    
+    // If any operation failed, cleanup created files
+    if result.is_err() {
+        for path in created_files {
+            let _ = fs::remove_file(path);
+        }
+        return result;
+    }

     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(())
 }

Committable suggestion skipped: line range outside the PR's diff.


💡 Codebase verification

File safety checks needed in checkout implementation

Based on the codebase analysis, the current implementation lacks important safety checks before overwriting files. The error handling is focused on git-specific errors (GitObjectError, CommitError) but doesn't handle file system conflicts. Specifically:

  • No existence check before creating/overwriting files
  • No error propagation for file write failures (using let _ to ignore results)
  • No backup mechanism for existing files

Key locations that need attention:

  • git_commit.rs:164-188: Add file existence checks before OpenOptions::new()
  • git_commit.rs:169: Propagate file write errors instead of ignoring them with let _
  • Consider adding a new error variant in GitObjectError for file system conflicts
🔗 Analysis chain

Verify: Check for potential file conflicts.

The current implementation might overwrite existing files without warning. Consider:

  1. Adding a dry-run mode
  2. Detecting and handling conflicts
  3. Providing a way to backup existing files

Let's verify if there are any similar implementations in the codebase:


Let me try a different search strategy to verify this concern.


Let me try one final search to check for any file existence checks or error handling patterns.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for similar checkout or file writing implementations
ast-grep --pattern 'fn $name($$$) {
  $$$
  OpenOptions::new().$$$
  $$$
}'

# Search for conflict handling patterns
rg -A 5 'backup|conflict|overwrite'

Length of output: 115


Script:

#!/bin/bash
# Search for file operations in git-related files
fd -e rs git_ --exec rg -A 5 'OpenOptions::new\(\)'

# Search for any existing conflict handling
fd -e rs git_ --exec rg -A 5 'conflict|exists|backup'

# Look for other checkout implementations
ast-grep --pattern 'fn checkout($$$) {
  $$$
}'

Length of output: 908


Script:

#!/bin/bash
# Check for file existence verifications
fd -e rs git_ --exec rg -B 5 -A 5 'Path::new|PathBuf::from.*exists'

# Look for error handling related to files
fd -e rs git_ --exec rg -B 2 -A 2 'GitObjectError::|GitError::'

# Check the error types definition
rg -B 2 -A 2 'enum (GitObjectError|GitError|CommitError)'

Length of output: 7415

Copy link

codecov bot commented Dec 26, 2024

Codecov Report

Attention: Patch coverage is 0% with 51 lines in your changes missing coverage. Please review.

@@            Coverage Diff             @@
##             main     #234      +/-   ##
==========================================
- Coverage   93.58%   92.13%   -1.45%     
==========================================
  Files          17       17              
  Lines        3243     3294      +51     
==========================================
  Hits         3035     3035              
- Misses        208      259      +51     
Components Coverage Δ
rust 92.13% <0.00%> (-1.45%) ⬇️

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
src-tauri/src/git/git_branch.rs (2)

24-25: Consider capturing the commit in a local variable for clarity.
Currently, the commit is constructed and immediately checked out. For debugging or logging, extracting it into a local variable might improve readability and error tracing.


31-36: Improve error contexts.
When writing to the HEAD file fails, the mapping returns broad errors without context about the write failure. Consider including the underlying I/O error detail for better diagnostics.

src-tauri/src/git/project_folder.rs (1)

94-101: Consolidate error handling for commit checkout.
The error is mapped to GitError::InvalidHistory when the checkout fails. While this is valid, you may want to differentiate between a missing commit vs. a file-writing failure for clarity.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ac25be4 and 6d93136.

📒 Files selected for processing (2)
  • src-tauri/src/git/git_branch.rs (2 hunks)
  • src-tauri/src/git/project_folder.rs (2 hunks)
🔇 Additional comments (4)
src-tauri/src/git/git_branch.rs (3)

1-1: Imports look good.
The addition of OpenOptions, Write, and PathBuf for file handling is appropriate and consistent with the new functionality.


5-5: Error handling import is correct.
Using CommitError and GitObjectError aligns well with the existing error management flow.


27-30: Potential concurrent HEAD updates.
Writing to the HEAD file without any locking could cause data races if parallel checkout operations are invoked. If concurrency is a concern, consider implementing file locking or other synchronization mechanisms.

src-tauri/src/git/project_folder.rs (1)

87-93: Validate branch existence before checkout.
The code maps any checkout failure to GitError::NoLocalBranches. Consider verifying that the supplied branch is indeed local or exists, and returning a more descriptive error if not found.

@github-actions github-actions bot added the UI label Dec 26, 2024
@hateofhades hateofhades force-pushed the feat/checkout-commits branch from fe2e13a to aa6af38 Compare December 26, 2024 20:33
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.

Actionable comments posted: 1

🧹 Nitpick comments (6)
src/components/Dialogs/ContextMenu.vue (2)

2-9: Ensure consistent user workflow for the "Checkout" option.

Currently, the menu item is labeled "Checkout" but does not clarify whether it's checking out a branch or a specific commit. Consider dynamically labeling this item (e.g., "Checkout Commit" or "Checkout Branch") based on the user’s selection, or use a sub-menu for clarity.

🧰 Tools
🪛 GitHub Check: Lint And Build

[warning] 2-2:
Expected indentation of 2 spaces but found 4 spaces


[warning] 2-2:
':target' should be on a new line


[warning] 2-2:
'v-on:update:model-value' should be on a new line


[warning] 2-2:
Expected '@' instead of 'v-on:'


[warning] 3-3:
Expected indentation of 4 spaces but found 6 spaces


[warning] 4-4:
Expected indentation of 6 spaces but found 8 spaces


[warning] 4-4:
Expected no line breaks before closing bracket, but 1 line break found


[warning] 5-5:
Expected indentation of 6 spaces but found 8 spaces


[warning] 6-6:
Expected indentation of 8 spaces but found 10 spaces


13-18: Adhere to consistent quote style.

The static analysis hints indicate that double quotes should be used instead of single quotes to match project linting rules. Applying this adjustment helps maintain a uniform code style.

-import { useDialogStore } from '@/stores/dialogs';
-import { useProjectStore } from '@/stores/project';
-import { TauriCommands } from '@/types/tauri';
-import { invoke } from '@tauri-apps/api/core';
-import { mapState } from 'pinia';
-import { defineComponent } from 'vue';
+import { useDialogStore } from "@/stores/dialogs";
+import { useProjectStore } from "@/stores/project";
+import { TauriCommands } from "@/types/tauri";
+import { invoke } from "@tauri-apps/api/core";
+import { mapState } from "pinia";
+import { defineComponent } from "vue";
🧰 Tools
🪛 eslint

[error] 13-13: Strings must use doublequote.

(quotes)


[error] 14-14: Strings must use doublequote.

(quotes)


[error] 15-15: Strings must use doublequote.

(quotes)


[error] 16-16: Strings must use doublequote.

(quotes)


[error] 17-17: Strings must use doublequote.

(quotes)


[error] 18-18: Strings must use doublequote.

(quotes)

🪛 GitHub Check: Lint And Build

[failure] 13-13:
Strings must use doublequote


[failure] 14-14:
Strings must use doublequote


[failure] 15-15:
Strings must use doublequote


[failure] 16-16:
Strings must use doublequote


[failure] 17-17:
Strings must use doublequote


[failure] 18-18:
Strings must use doublequote

src/App.vue (1)

16-16: Ensure proper indentation style.

A tab character is used on this line while the rest of the template uses spaces. Standardizing indentation style is recommended to improve readability and maintain consistency.

🧰 Tools
🪛 GitHub Check: Lint And Build

[warning] 16-16:
Expected " " character, but found "\t" character

src/stores/dialogs.ts (1)

76-85: Allow for flexible extension of showContextMenu.

This method is currently tailored for commits only (requiring hash). In the future, you may want to reuse context menus for other objects, such as branches. Consider adding optional parameters or different payload structures to scale easily.

src/components/Project/Commit/CommitListItem.vue (2)

8-8: Use caution with custom context menus.
Overriding the default context menu can impact accessibility and user expectations. Ensure you provide a suitable alternative for typical right-click functionality, such as standard browser actions for copying links or saving images.


98-101: Address indentation and maintain consistent code style.
Static analysis flags indentation issues. Adhering to your chosen style guide improves readability and maintainability. Consider adjusting the indentation to match the rest of the codebase.

Below is an example of how you might fix it:

 setCommit() {
   useProjectStore().setCommit(this.commit.hash);
-    },
-    showContextMenu(event: MouseEvent) {
-      useDialogStore().showContextMenu(getHash(this.commit), event.clientX, event.clientY);
-    }
+},
+showContextMenu(event: MouseEvent) {
+  useDialogStore().showContextMenu(getHash(this.commit), event.clientX, event.clientY);
+}
🧰 Tools
🪛 eslint

[error] 99-99: Expected indentation of 2 tabs but found 4 spaces.

(indent)


[error] 100-100: Expected indentation of 3 tabs but found 6 spaces.

(indent)


[error] 101-101: Expected indentation of 2 tabs but found 4 spaces.

(indent)

🛑 Comments failed to post (1)
src/stores/dialogs.ts (1)

42-42: ⚠️ Potential issue

Prevent type errors by including commitHash in initial state.

Static analysis indicates the commitHash property is missing in the initial contextMenu state. Provide a default empty string to satisfy the required type.

 contextMenu: {
   isOpen: false,
+  commitHash: "",
   position: {
     x: 0,
     y: 0,
   },
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

			contextMenu: {
				isOpen: false,
				commitHash: "",
				position: {
					x: 0,
					y: 0,
				},
🧰 Tools
🪛 GitHub Check: Lint

[failure] 42-42:
Property 'commitHash' is missing in type '{ isOpen: false; position: { x: number; y: number; }; }' but required in type '{ isOpen: boolean; commitHash: string; position: { x: number; y: number; }; }'.

🪛 GitHub Check: Coverage

[failure] 42-42:
Property 'commitHash' is missing in type '{ isOpen: false; position: { x: number; y: number; }; }' but required in type '{ isOpen: boolean; commitHash: string; position: { x: number; y: number; }; }'.

@hateofhades hateofhades force-pushed the feat/checkout-commits branch from aa6af38 to 9071fa7 Compare December 26, 2024 20:35
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (7)
src/App.vue (2)

16-16: Fix indentation inconsistency

The ContextMenu component uses tabs while the rest of the file uses spaces.

-	<ContextMenu />
+  <ContextMenu />
🧰 Tools
🪛 GitHub Check: Lint And Build

[warning] 16-16:
Expected " " character, but found "\t" character


40-41: Maintain consistent component registration order

Components should be registered in the same order as they appear in the template.

-		DialogComponent,
-		ContextMenu
+		ContextMenu,
+		DialogComponent
src/stores/dialogs.ts (3)

17-24: Add validation for position coordinates

The contextMenu position coordinates should be validated to ensure they're within viewport bounds.

 contextMenu: {
   isOpen: boolean;
   commitHash: string;
   position: {
     x: number;
     y: number;
   };
+  // Add methods to validate coordinates
+  validatePosition(): void;
 }

77-86: Add position validation in showContextMenu action

The showContextMenu action should ensure the menu appears within viewport bounds.

 showContextMenu(hash: string, x: number, y: number) {
+    // Ensure menu stays within viewport
+    const viewportWidth = window.innerWidth;
+    const viewportHeight = window.innerHeight;
+    const menuWidth = 200; // Approximate menu width
+    const menuHeight = 48; // Approximate menu height
+
+    const validX = Math.min(x, viewportWidth - menuWidth);
+    const validY = Math.min(y, viewportHeight - menuHeight);
+
     this.contextMenu = {
         position: {
-            x,
-            y
+            x: validX,
+            y: validY
         },
         commitHash: hash,
         isOpen: true
     };
 }

87-89: Consider resetting contextMenu state on close

The closeContextMenu action only sets isOpen to false, leaving stale data in other fields.

 closeContextMenu() {
-    this.contextMenu.isOpen = false;
+    this.contextMenu = {
+        isOpen: false,
+        commitHash: "",
+        position: {
+            x: 0,
+            y: 0
+        }
+    };
 }
src/components/Project/Commit/CommitListItem.vue (2)

8-8: Consider preventing default context menu behavior

The right-click handler might conflict with the browser's default context menu. Consider preventing the default behavior for a better user experience.

-    @click.right="showContextMenu"
+    @click.right.prevent="showContextMenu"

Line range hint 1-124: Consider accessibility improvements

The context menu implementation should be accessible via keyboard and work with screen readers. Consider:

  1. Adding keyboard shortcut (e.g., Shift+F10) as an alternative to right-click
  2. Using ARIA attributes to improve screen reader support

Example implementation:

 <v-row
   no-gutters
   align="center"
   style="height: 10vh;"
   :class="commitClass"
   @click="setCommit"
   @click.right.prevent="showContextMenu"
+  @keydown.shift.f10.prevent="showContextMenu"
+  role="listitem"
+  aria-label="Commit by ${getAuthorName}"
+  tabindex="0"
 >
🧰 Tools
🪛 eslint

[error] 99-99: Expected indentation of 2 tabs but found 4 spaces.

(indent)


[error] 100-100: Expected indentation of 3 tabs but found 6 spaces.

(indent)


[error] 101-101: Expected indentation of 2 tabs but found 4 spaces.

(indent)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fe2e13a and 9071fa7.

📒 Files selected for processing (7)
  • index.html (1 hunks)
  • src-tauri/src/main.rs (2 hunks)
  • src/App.vue (2 hunks)
  • src/components/Dialogs/ContextMenu.vue (1 hunks)
  • src/components/Project/Commit/CommitListItem.vue (3 hunks)
  • src/stores/dialogs.ts (3 hunks)
  • src/types/tauri.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/types/tauri.ts
  • index.html
🧰 Additional context used
🪛 eslint
src/components/Project/Commit/CommitListItem.vue

[error] 99-99: Expected indentation of 2 tabs but found 4 spaces.

(indent)


[error] 100-100: Expected indentation of 3 tabs but found 6 spaces.

(indent)


[error] 101-101: Expected indentation of 2 tabs but found 4 spaces.

(indent)

src/components/Dialogs/ContextMenu.vue

[error] 13-13: Strings must use doublequote.

(quotes)


[error] 14-14: Strings must use doublequote.

(quotes)


[error] 15-15: Strings must use doublequote.

(quotes)


[error] 16-16: Strings must use doublequote.

(quotes)


[error] 17-17: Strings must use doublequote.

(quotes)


[error] 18-18: Strings must use doublequote.

(quotes)


[error] 21-21: Expected indentation of 1 tab but found 4 spaces.

(indent)


[error] 22-22: Expected indentation of 1 tab but found 4 spaces.

(indent)


[error] 33-33: Expected indentation of 2 tabs but found 8 spaces.

(indent)


[error] 34-34: Expected indentation of 3 tabs but found 12 spaces.

(indent)


[error] 35-35: Expected indentation of 2 tabs but found 8 spaces.

(indent)


[error] 36-36: Expected indentation of 2 tabs but found 8 spaces.

(indent)


[error] 37-37: Expected indentation of 3 tabs but found 12 spaces.

(indent)


[error] 38-38: Expected indentation of 2 tabs but found 8 spaces.

(indent)


[error] 41-41: Expected indentation of 1 tab but found 4 spaces.

(indent)


[error] 42-42: Expected indentation of 2 tabs but found 8 spaces.

(indent)


[error] 43-43: Expected indentation of 3 tabs but found 12 spaces.

(indent)


[error] 44-44: Expected indentation of 2 tabs but found 8 spaces.

(indent)


[error] 45-45: Expected indentation of 2 tabs but found 8 spaces.

(indent)


[error] 46-46: Expected indentation of 3 tabs but found 12 spaces.

(indent)


[error] 47-47: Expected indentation of 4 tabs but found 16 spaces.

(indent)


[error] 48-48: Expected indentation of 4 tabs but found 16 spaces.

(indent)


[error] 49-49: Expected indentation of 3 tabs but found 12 spaces.

(indent)


[error] 50-50: Expected indentation of 2 tabs but found 8 spaces.

(indent)


[error] 51-51: Expected indentation of 1 tab but found 4 spaces.

(indent)

🪛 GitHub Check: Lint And Build
src/App.vue

[warning] 16-16:
Expected " " character, but found "\t" character

src/components/Dialogs/ContextMenu.vue

[warning] 2-2:
Expected indentation of 2 spaces but found 4 spaces


[warning] 2-2:
':target' should be on a new line


[warning] 2-2:
'v-on:update:model-value' should be on a new line


[warning] 2-2:
Expected '@' instead of 'v-on:'


[warning] 3-3:
Expected indentation of 4 spaces but found 6 spaces


[warning] 4-4:
Expected indentation of 6 spaces but found 8 spaces


[warning] 4-4:
Expected no line breaks before closing bracket, but 1 line break found


[warning] 5-5:
Expected indentation of 6 spaces but found 8 spaces


[warning] 6-6:
Expected indentation of 8 spaces but found 10 spaces


[failure] 13-13:
Strings must use doublequote


[failure] 14-14:
Strings must use doublequote


[failure] 15-15:
Strings must use doublequote


[failure] 16-16:
Strings must use doublequote


[failure] 17-17:
Strings must use doublequote


[failure] 18-18:
Strings must use doublequote


[failure] 21-21:
Expected indentation of 1 tab but found 4 spaces


[failure] 22-22:
Expected indentation of 1 tab but found 4 spaces


[failure] 33-33:
Expected indentation of 2 tabs but found 8 spaces


[failure] 34-34:
Expected indentation of 3 tabs but found 12 spaces

🔇 Additional comments (3)
src-tauri/src/main.rs (2)

14-14: Import statements look consistent and well-structured.

The added checkout_branch and checkout_commit imports are properly grouped with related functions from git::project_folder. Make sure they're tested and documented before finalizing.


92-93: Add verification tests for new commands.

The newly added commands checkout_branch and checkout_commit expand the Tauri application interface. However, be sure to thoroughly test them with different Git repositories, including edge cases (empty commits or branch names, conflicting local changes, etc.).

src/stores/dialogs.ts (1)

46-49: Verify checkout command implementation

Let's verify the implementation of the checkout command in the Rust backend.

Comment on lines 2 to 9
<v-menu :model-value="isShowing" :target="[posX, posY]" v-on:update:model-value="closeMenu">
<v-list>
<v-list-item
>
<v-list-item-title @click="checkout">Checkout</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve menu accessibility and user experience

The context menu implementation needs improvements for better accessibility and user experience:

  1. Missing keyboard navigation support
  2. No loading state during checkout
  3. No feedback after checkout operation
 <v-menu :model-value="isShowing" :target="[posX, posY]" v-on:update:model-value="closeMenu">
   <v-list>
     <v-list-item
+      @keydown.enter="checkout"
+      :loading="isLoading"
     >
       <v-list-item-title @click="checkout">Checkout</v-list-item-title>
     </v-list-item>
   </v-list>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<v-menu :model-value="isShowing" :target="[posX, posY]" v-on:update:model-value="closeMenu">
<v-list>
<v-list-item
>
<v-list-item-title @click="checkout">Checkout</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
<v-menu :model-value="isShowing" :target="[posX, posY]" v-on:update:model-value="closeMenu">
<v-list>
<v-list-item
@keydown.enter="checkout"
:loading="isLoading"
>
<v-list-item-title @click="checkout">Checkout</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
🧰 Tools
🪛 GitHub Check: Lint And Build

[warning] 2-2:
Expected indentation of 2 spaces but found 4 spaces


[warning] 2-2:
':target' should be on a new line


[warning] 2-2:
'v-on:update:model-value' should be on a new line


[warning] 2-2:
Expected '@' instead of 'v-on:'


[warning] 3-3:
Expected indentation of 4 spaces but found 6 spaces


[warning] 4-4:
Expected indentation of 6 spaces but found 8 spaces


[warning] 4-4:
Expected no line breaks before closing bracket, but 1 line break found


[warning] 5-5:
Expected indentation of 6 spaces but found 8 spaces


[warning] 6-6:
Expected indentation of 8 spaces but found 10 spaces

Comment on lines 45 to 50
checkout() {
invoke(TauriCommands.CheckoutCommit, {
project: useProjectStore().getSelectedProject,
hash: useDialogStore().contextMenu.commitHash
});
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add error handling for checkout operation

The checkout operation lacks error handling and user feedback.

 checkout() {
+    this.isLoading = true;
     invoke(TauriCommands.CheckoutCommit, {
         project: useProjectStore().getSelectedProject,
         hash: useDialogStore().contextMenu.commitHash
-    });
+    })
+    .then(() => {
+        useDialogStore().openSnackbar({
+            text: "Successfully checked out commit",
+            color: "success"
+        });
+    })
+    .catch((error) => {
+        useDialogStore().showError(error);
+    })
+    .finally(() => {
+        this.isLoading = false;
+        this.closeMenu();
+    });
 }

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 eslint

[error] 45-45: Expected indentation of 2 tabs but found 8 spaces.

(indent)


[error] 46-46: Expected indentation of 3 tabs but found 12 spaces.

(indent)


[error] 47-47: Expected indentation of 4 tabs but found 16 spaces.

(indent)


[error] 48-48: Expected indentation of 4 tabs but found 16 spaces.

(indent)


[error] 49-49: Expected indentation of 3 tabs but found 12 spaces.

(indent)


[error] 50-50: Expected indentation of 2 tabs but found 8 spaces.

(indent)

Comment on lines 99 to 101
showContextMenu(event: MouseEvent) {
useDialogStore().showContextMenu(getHash(this.commit), event.clientX, event.clientY);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Fix indentation to match project style

The indentation should use tabs instead of spaces to maintain consistency with the project style.

-    showContextMenu(event: MouseEvent) {
-      useDialogStore().showContextMenu(getHash(this.commit), event.clientX, event.clientY);
-    }
+		showContextMenu(event: MouseEvent) {
+			useDialogStore().showContextMenu(getHash(this.commit), event.clientX, event.clientY);
+		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
showContextMenu(event: MouseEvent) {
useDialogStore().showContextMenu(getHash(this.commit), event.clientX, event.clientY);
}
showContextMenu(event: MouseEvent) {
useDialogStore().showContextMenu(getHash(this.commit), event.clientX, event.clientY);
}
🧰 Tools
🪛 eslint

[error] 99-99: Expected indentation of 2 tabs but found 4 spaces.

(indent)


[error] 100-100: Expected indentation of 3 tabs but found 6 spaces.

(indent)


[error] 101-101: Expected indentation of 2 tabs but found 4 spaces.

(indent)


💡 Codebase verification

Context menu coordinates need validation to prevent out-of-bounds display

The dialog store's showContextMenu method directly assigns the raw x and y coordinates without any validation or adjustment for viewport bounds. This could lead to the context menu being partially or fully rendered outside the visible area when clicked near screen edges.

  • src/stores/dialogs.ts: Add viewport bounds checking in the showContextMenu method to ensure the menu stays within visible area:
    showContextMenu(hash: string, x: number, y: number) {
      // Need to add validation/adjustment of x, y coordinates
      this.contextMenu = {
        position: { x, y },
        commitHash: hash,
        isOpen: true
      };
    }
🔗 Analysis chain

Verify coordinate handling in dialog store

Ensure that the dialog store properly handles and sanitizes the coordinates to prevent the context menu from appearing outside viewport bounds.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for coordinate validation in dialog store
ast-grep --pattern 'showContextMenu($_) {
  $$$
  clientX $$$
  $$$
  clientY $$$
  $$$
}'

# Check for viewport bounds handling
rg -A 5 'clientX|clientY|viewport|bounds' src/stores/dialogs.ts

Length of output: 158


Script:

#!/bin/bash
# Let's first locate the dialog store file and check its content
fd -e ts "dialog" src/stores/

# Then search for showContextMenu method implementation
rg -l "showContextMenu" src/stores/

# Once we find the file, let's examine its content
ast-grep --pattern 'showContextMenu($$$) {
  $$$
}'

# Also search for any coordinate-related validation
rg -A 5 "position|coordinate|client[XY]|bounds|viewport" src/stores/

Length of output: 819


Script:

#!/bin/bash
# Let's examine the complete implementation of dialogs.ts to understand the context menu handling
cat src/stores/dialogs.ts

# Also check if there are any utility functions that might handle coordinate validation
rg -A 5 "function.*position|function.*coordinate|function.*bounds" src/

Length of output: 2010

🧰 Tools
🪛 eslint

[error] 99-99: Expected indentation of 2 tabs but found 4 spaces.

(indent)


[error] 100-100: Expected indentation of 3 tabs but found 6 spaces.

(indent)


[error] 101-101: Expected indentation of 2 tabs but found 4 spaces.

(indent)

@hateofhades hateofhades force-pushed the feat/checkout-commits branch from 9071fa7 to 468eeba Compare December 26, 2024 20:46
# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Be able to checkout any commit
1 participant