Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Cargo.lock
.vscode
.zed
.trae
*.code-workspace

# Mac
.DS_Store
Expand Down
1 change: 1 addition & 0 deletions aria/contents/docs/libra/command/commit/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ If the `--allow-empty` option is not given, the commit will be aborted if the in
Check if the commit message is conventional format, if not, the commit will be aborted.
- `-h`, `--help` Print help
- `-s`,`--signoff` Add sign-off-by trailer by the committer at the end of the commit message.
- `--disable-pre` Ignore the pre-commit hook.

<Note type="note" title="Note">
The commit message should align with Git’s behavior as closely as possible, excpet the `--conventional` option, which is not supported in Git. Refs https://git-scm.com/docs/git-commit for more information.
Expand Down
45 changes: 45 additions & 0 deletions libra/src/command/commit.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::process::Stdio;
use std::str::FromStr;
use std::{collections::HashSet, path::PathBuf};

Expand All @@ -15,6 +16,7 @@ use mercury::internal::index::Index;
use mercury::internal::object::commit::Commit;
use mercury::internal::object::tree::{Tree, TreeItem, TreeItemMode};
use mercury::internal::object::ObjectTrait;
use std::process::Command;

use super::save_object;

Expand All @@ -38,6 +40,9 @@ pub struct CommitArgs {
/// add signed-off-by line at the end of the commit message
#[arg(short = 's', long)]
pub signoff: bool,

Copilot AI Jul 27, 2025

Copy link

Choose a reason for hiding this comment

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

The disable_pre argument is missing documentation. Add a doc comment to explain its purpose, similar to other arguments in the struct.

Suggested change
/// disable pre-commit hooks or checks

Copilot uses AI. Check for mistakes.
#[arg(long)]
pub disable_pre: bool,
}

pub async fn execute(args: CommitArgs) {
Expand All @@ -49,6 +54,46 @@ pub async fn execute(args: CommitArgs) {
panic!("fatal: no changes added to commit, use --allow-empty to override");
}

// run pre commit hook

Copilot AI Jul 27, 2025

Copy link

Choose a reason for hiding this comment

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

The comment has a grammatical error. It should be "run pre-commit hook" (with hyphen) to match the terminology used elsewhere in the codebase.

Suggested change
// run pre commit hook
// run pre-commit hook

Copilot uses AI. Check for mistakes.
if !args.disable_pre {
let hooks_dir = path::hooks();

#[cfg(not(target_os = "windows"))]
let hook_path = hooks_dir.join("pre-commit.sh");

#[cfg(target_os = "windows")]
let hook_path = hooks_dir.join("pre-commit.ps1");
if hook_path.exists() {
let hook_display = hook_path.display();
#[cfg(not(target_os = "windows"))]
let output = Command::new("sh")
.arg(&hook_path)
.current_dir(util::working_dir())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.output()
.unwrap_or_else(|e| panic!("Failed to execute hook {hook_display}: {e}"));

#[cfg(target_os = "windows")]
let output = Command::new("powershell")
.arg("-File")
.arg(&hook_path)
.current_dir(util::working_dir())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.output()
.unwrap_or_else(|e| panic!("Failed to execute hook {hook_display}: {e}"));

if !output.status.success() {
panic!(
"Hook {} failed with exit code {}",
hook_display,
output.status.code().unwrap_or(-1)
);
}
}
}

//Prepare commit message
let commit_message = if args.signoff {
// get user
Expand Down
21 changes: 20 additions & 1 deletion libra/src/command/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ pub async fn init(args: InitArgs) -> io::Result<()> {
}

// Create .libra & sub-dirs
let dirs = ["objects/pack", "objects/info", "info"];
let dirs = ["objects/pack", "objects/info", "info", "hooks"];
for dir in dirs {
fs::create_dir_all(root_dir.join(dir))?;
}
Expand All @@ -143,6 +143,25 @@ pub async fn init(args: InitArgs) -> io::Result<()> {
root_dir.join("description"),
include_str!("../../template/description"),
)?;
// Create .libra/hooks/pre-commit.sh
fs::write(
root_dir.join("hooks").join("pre-commit.sh"),
include_str!("../../template/pre-commit.sh"),
)?;

// Set Permission
#[cfg(not(target_os = "windows"))]
{
use std::os::unix::fs::PermissionsExt;
let perms = fs::Permissions::from_mode(0o755);
fs::set_permissions(root_dir.join("hooks").join("pre-commit.sh"), perms)?;
}

// Create .libra/hooks/pre-commit.ps1
fs::write(
root_dir.join("hooks").join("pre-commit.ps1"),
include_str!("../../template/pre-commit.ps1"),
)?;

// Create database: .libra/libra.db
let conn;
Expand Down
4 changes: 4 additions & 0 deletions libra/src/utils/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ pub fn database() -> PathBuf {
util::storage_path().join(util::DATABASE)
}

pub fn hooks() -> PathBuf {
util::storage_path().join("hooks")
}

pub fn attributes() -> PathBuf {
util::working_dir().join(util::ATTRIBUTES)
}
12 changes: 12 additions & 0 deletions libra/template/pre-commit.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

#!/bin/sh

Copilot AI Jul 27, 2025

Copy link

Choose a reason for hiding this comment

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

The shebang line #!/bin/sh is incorrect for a PowerShell script. PowerShell scripts should not have a shebang line, or if needed for cross-platform compatibility, should use a PowerShell-specific shebang like #!/usr/bin/env pwsh.

Suggested change
#!/bin/sh
#!/usr/bin/env pwsh

Copilot uses AI. Check for mistakes.


# Pre-commit hook example
# Exit with 0 to allow commit, non-zero to reject

# Example
# Write-Host "Running pre-commit hook"


exit 0
11 changes: 11 additions & 0 deletions libra/template/pre-commit.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/sh


# Pre-commit hook example
# Exit with 0 to allow commit, non-zero to reject

# Example
# echo "Running pre-commit hook"


exit 0
4 changes: 4 additions & 0 deletions libra/tests/command/branch_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ async fn test_branch() {
conventional: false,
amend: false,
signoff: false,
disable_pre:true,
};
commit::execute(commit_args).await;
let first_commit_id = Branch::find_branch("master", None).await.unwrap().commit;
Expand All @@ -27,6 +28,7 @@ async fn test_branch() {
conventional: false,
amend: false,
signoff: false,
disable_pre:true,
};
commit::execute(commit_args).await;
let second_commit_id = Branch::find_branch("master", None).await.unwrap().commit;
Expand Down Expand Up @@ -112,6 +114,7 @@ async fn test_create_branch_from_remote() {
conventional: false,
amend: false,
signoff: false,
disable_pre:true,
};
commit::execute(args).await;
let hash = Head::current_commit().await.unwrap();
Expand Down Expand Up @@ -150,6 +153,7 @@ async fn test_invalid_branch_name() {
conventional: false,
amend: false,
signoff: false,
disable_pre:true,
};
commit::execute(args).await;

Expand Down
1 change: 1 addition & 0 deletions libra/tests/command/checkout_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ async fn test_checkout_module_functions() {
conventional: false,
amend: false,
signoff: false,
disable_pre:true,
};
commit::execute(commit_args).await;

Expand Down
5 changes: 5 additions & 0 deletions libra/tests/command/commit_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ async fn test_execute_commit_with_empty_index_fail() {
conventional: false,
amend: false,
signoff: false,
disable_pre:true,
};
commit::execute(args).await;
}
Expand All @@ -41,6 +42,7 @@ async fn test_execute_commit() {
conventional: false,
amend: false,
signoff: false,
disable_pre:true,
};
commit::execute(args).await;

Expand All @@ -66,6 +68,7 @@ async fn test_execute_commit() {
conventional: false,
amend: true,
signoff: false,
disable_pre:true,
};
commit::execute(args).await;

Expand Down Expand Up @@ -107,6 +110,7 @@ async fn test_execute_commit() {
conventional: false,
amend: false,
signoff: false,
disable_pre:true,
};
commit::execute(args).await;

Expand Down Expand Up @@ -135,6 +139,7 @@ async fn test_execute_commit() {
conventional: false,
amend: true,
signoff: false,
disable_pre:true,
};
commit::execute(args).await;

Expand Down
4 changes: 4 additions & 0 deletions libra/tests/command/reset_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ async fn setup_standard_repo(temp_path: &std::path::Path) -> (SHA1, SHA1, SHA1,
conventional: false,
amend: false,
signoff: false,
disable_pre:true,
})
.await;
let commit1 = Head::current_commit().await.unwrap();
Expand Down Expand Up @@ -54,6 +55,7 @@ async fn setup_standard_repo(temp_path: &std::path::Path) -> (SHA1, SHA1, SHA1,
conventional: false,
amend: false,
signoff: false,
disable_pre:true,
})
.await;
let commit2 = Head::current_commit().await.unwrap();
Expand Down Expand Up @@ -84,6 +86,7 @@ async fn setup_standard_repo(temp_path: &std::path::Path) -> (SHA1, SHA1, SHA1,
conventional: false,
amend: false,
signoff: false,
disable_pre:true,
})
.await;
let commit3 = Head::current_commit().await.unwrap();
Expand Down Expand Up @@ -114,6 +117,7 @@ async fn setup_standard_repo(temp_path: &std::path::Path) -> (SHA1, SHA1, SHA1,
conventional: false,
amend: false,
signoff: false,
disable_pre:true,
})
.await;
let commit4 = Head::current_commit().await.unwrap();
Expand Down
4 changes: 4 additions & 0 deletions libra/tests/command/switch_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ async fn test_switch_function() {
conventional: false,
amend: false,
signoff: false,
disable_pre:true,
};
commit::execute(args).await;
}
Expand Down Expand Up @@ -84,6 +85,7 @@ async fn test_switch_function() {
conventional: false,
amend: false,
signoff: false,
disable_pre:true,
};
commit::execute(args).await;

Expand Down Expand Up @@ -160,6 +162,7 @@ async fn test_detach_head_basic() {
conventional: false,
amend: false,
signoff: false,
disable_pre:true,
};
commit::execute(args).await;
}
Expand Down Expand Up @@ -199,6 +202,7 @@ async fn test_detach_head_basic() {
conventional: false,
amend: false,
signoff: false,
disable_pre:true,
};
commit::execute(args).await;
}
Expand Down
Loading