add Repo Managment / Kontext Menu in Braches
This commit is contained in:
@@ -347,6 +347,42 @@ pub fn create_branch(
|
||||
status_for_repo(&repo)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn rename_branch(
|
||||
path: String,
|
||||
old_branch: String,
|
||||
new_branch: String,
|
||||
) -> Result<GitStatus, String> {
|
||||
let repo = resolve_repo(&path)?;
|
||||
let old_branch = validate_existing_local_branch_name(&repo, &old_branch)?;
|
||||
let new_branch = validate_new_branch_name(&repo, &new_branch)?;
|
||||
|
||||
run_git(
|
||||
&repo,
|
||||
[
|
||||
"branch",
|
||||
"-m",
|
||||
"--",
|
||||
old_branch.as_str(),
|
||||
new_branch.as_str(),
|
||||
],
|
||||
)?;
|
||||
status_for_repo(&repo)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn delete_branch(path: String, branch: String) -> Result<GitStatus, String> {
|
||||
let repo = resolve_repo(&path)?;
|
||||
let branch = validate_existing_local_branch_name(&repo, &branch)?;
|
||||
let status = status_for_repo(&repo)?;
|
||||
if status.current_branch.as_deref() == Some(branch.as_str()) {
|
||||
return Err("Der aktuelle Branch kann nicht geloescht werden.".to_string());
|
||||
}
|
||||
|
||||
run_git(&repo, ["branch", "-d", "--", branch.as_str()])?;
|
||||
status_for_repo(&repo)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn stage_files(path: String, files: Vec<String>) -> Result<GitStatus, String> {
|
||||
let repo = resolve_repo(&path)?;
|
||||
@@ -2103,6 +2139,41 @@ fn validate_new_branch_name(repo: &Path, branch: &str) -> Result<String, String>
|
||||
Ok(normalized)
|
||||
}
|
||||
|
||||
fn validate_existing_local_branch_name(repo: &Path, branch: &str) -> Result<String, String> {
|
||||
let branch = branch.trim();
|
||||
if branch.is_empty() {
|
||||
return Err("Branch-Name darf nicht leer sein.".to_string());
|
||||
}
|
||||
|
||||
let normalized = validate_branch_ref_name(branch)?;
|
||||
if !ref_exists(repo, &format!("refs/heads/{normalized}"))? {
|
||||
return Err(format!(
|
||||
"Lokaler Branch '{normalized}' wurde nicht gefunden."
|
||||
));
|
||||
}
|
||||
|
||||
Ok(normalized)
|
||||
}
|
||||
|
||||
fn validate_branch_ref_name(branch: &str) -> Result<String, String> {
|
||||
let output = git_command()
|
||||
.args(["check-ref-format", "--branch", branch])
|
||||
.output()
|
||||
.map_err(|err| format!("Git konnte nicht gestartet werden. Ist Git installiert? {err}"))?;
|
||||
|
||||
if !output.status.success() {
|
||||
let details = command_output_details(&output);
|
||||
return Err(format!("Ungueltiger Branch-Name: {details}"));
|
||||
}
|
||||
|
||||
let normalized = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
||||
Ok(if normalized.is_empty() {
|
||||
branch.to_string()
|
||||
} else {
|
||||
normalized
|
||||
})
|
||||
}
|
||||
|
||||
fn ref_exists(repo: &Path, ref_name: &str) -> Result<bool, String> {
|
||||
let output = git_command()
|
||||
.arg("-C")
|
||||
@@ -3516,6 +3587,51 @@ mod tests {
|
||||
assert!(err.contains("existiert bereits"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rename_branch_renames_existing_local_branch() {
|
||||
let repo = init_temp_repo("rename_branch");
|
||||
commit_initial_file(&repo.path);
|
||||
let current = git_output_test(&repo.path, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
||||
run_git_test(&repo.path, ["branch", "feature/old-panel"]);
|
||||
|
||||
let status = rename_branch(
|
||||
repo.path.to_string_lossy().to_string(),
|
||||
"feature/old-panel".to_string(),
|
||||
"feature/new-panel".to_string(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(status.current_branch.as_deref(), Some(current.as_str()));
|
||||
assert!(
|
||||
!ref_exists(&repo.path, "refs/heads/feature/old-panel").unwrap(),
|
||||
"old branch should be gone"
|
||||
);
|
||||
assert!(
|
||||
ref_exists(&repo.path, "refs/heads/feature/new-panel").unwrap(),
|
||||
"new branch should exist"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn delete_branch_removes_local_branch_but_rejects_current_branch() {
|
||||
let repo = init_temp_repo("delete_branch");
|
||||
commit_initial_file(&repo.path);
|
||||
let current = git_output_test(&repo.path, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
||||
run_git_test(&repo.path, ["branch", "stale"]);
|
||||
|
||||
let status =
|
||||
delete_branch(repo.path.to_string_lossy().to_string(), "stale".to_string()).unwrap();
|
||||
|
||||
assert_eq!(status.current_branch.as_deref(), Some(current.as_str()));
|
||||
assert!(
|
||||
!ref_exists(&repo.path, "refs/heads/stale").unwrap(),
|
||||
"deleted branch should be gone"
|
||||
);
|
||||
|
||||
let err = delete_branch(repo.path.to_string_lossy().to_string(), current).unwrap_err();
|
||||
assert!(err.contains("aktuelle Branch"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn apply_file_patch_stages_and_discards_selected_changes() {
|
||||
let repo = init_temp_repo("apply_file_patch");
|
||||
|
||||
@@ -5,11 +5,12 @@ mod git;
|
||||
use git::{
|
||||
apply_file_patch, cancel_code_search, checkout_branch, commit, compare_commits,
|
||||
compare_file_to_head, compare_file_to_parent, create_branch, cred_delete, cred_load, cred_save,
|
||||
diff_file_against_working_tree, get_file_patch, get_remote_url, get_status, list_branches,
|
||||
list_commits, list_file_history, list_repository_files, merge_branch, open_repo_in_explorer,
|
||||
open_repository, open_repository_bundle, pull, push, read_conflict, resolve_conflict,
|
||||
resolve_conflict_side, restore_file_from_commit, restore_files, restore_to_commit,
|
||||
search_code_introductions, stage_files, unstage_files, SearchCancellationState,
|
||||
delete_branch, diff_file_against_working_tree, get_file_patch, get_remote_url, get_status,
|
||||
list_branches, list_commits, list_file_history, list_repository_files, merge_branch,
|
||||
open_repo_in_explorer, open_repository, open_repository_bundle, pull, push, read_conflict,
|
||||
rename_branch, resolve_conflict, resolve_conflict_side, restore_file_from_commit,
|
||||
restore_files, restore_to_commit, search_code_introductions, stage_files, unstage_files,
|
||||
SearchCancellationState,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
@@ -24,6 +25,8 @@ fn main() {
|
||||
list_branches,
|
||||
checkout_branch,
|
||||
create_branch,
|
||||
rename_branch,
|
||||
delete_branch,
|
||||
stage_files,
|
||||
unstage_files,
|
||||
restore_files,
|
||||
|
||||
Reference in New Issue
Block a user