feat(ui): localize commit AI and git error messages to English
Translate commit AI prompts, model labels, and git/keychain errors to English so the app and generated messages are consistent. Also add a discard confirmation dialog and update the UI text/styles to match the new flow. - src-tauri/crates/commit_ai/src/cloud.rs - Translate HTTP and API error messages to English. - Keep request timeout and token sizing behavior unchanged. - src-tauri/crates/commit_ai/src/lib.rs - Translate model labels, prompt text, and validation errors. - Keep diff truncation and message sanitization logic intact. - src-tauri/src/git.rs - Translate git, credential, merge, and history errors. - Update AI provider validation messages to English. - src/lib/components/* - Update AI settings, commit panel, credential, and loading UI text. - Add discard confirmation dialog for destructive actions. - src/App.svelte, src/app.css - Adjust app layout and styling for the new dialog and text changes.
This commit is contained in:
+102
-102
@@ -146,7 +146,7 @@ enum CheckoutPlan {
|
||||
|
||||
const FULL_FILE_DIFF_CONTEXT: &str = "--unified=1000000";
|
||||
const EMPTY_TREE_HASH: &str = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
||||
const SEARCH_CANCELLED_MESSAGE: &str = "Suche wurde abgebrochen.";
|
||||
const SEARCH_CANCELLED_MESSAGE: &str = "Search was cancelled.";
|
||||
static CANCELLABLE_GIT_OUTPUT_COUNTER: AtomicU64 = AtomicU64::new(0);
|
||||
|
||||
fn git_command() -> Command {
|
||||
@@ -165,7 +165,7 @@ impl SearchCancellationState {
|
||||
fn cancel(&self, search_id: &str) -> Result<(), String> {
|
||||
self.cancelled
|
||||
.lock()
|
||||
.map_err(|_| "Such-Abbruchstatus ist nicht erreichbar.".to_string())?
|
||||
.map_err(|_| "Search cancellation status is unavailable.".to_string())?
|
||||
.insert(search_id.to_string());
|
||||
Ok(())
|
||||
}
|
||||
@@ -173,7 +173,7 @@ impl SearchCancellationState {
|
||||
fn clear(&self, search_id: &str) -> Result<(), String> {
|
||||
self.cancelled
|
||||
.lock()
|
||||
.map_err(|_| "Such-Abbruchstatus ist nicht erreichbar.".to_string())?
|
||||
.map_err(|_| "Search cancellation status is unavailable.".to_string())?
|
||||
.remove(search_id);
|
||||
Ok(())
|
||||
}
|
||||
@@ -182,7 +182,7 @@ impl SearchCancellationState {
|
||||
Ok(self
|
||||
.cancelled
|
||||
.lock()
|
||||
.map_err(|_| "Such-Abbruchstatus ist nicht erreichbar.".to_string())?
|
||||
.map_err(|_| "Search cancellation status is unavailable.".to_string())?
|
||||
.contains(search_id))
|
||||
}
|
||||
}
|
||||
@@ -221,10 +221,10 @@ pub fn open_repository_file(path: String, file: String) -> Result<(), String> {
|
||||
let file_path = resolve_repo_child_path(&repo, &file)?;
|
||||
|
||||
if !file_path.exists() {
|
||||
return Err(format!("Datei '{file}' existiert im Working Tree nicht."));
|
||||
return Err(format!("File '{file}' does not exist in the working tree."));
|
||||
}
|
||||
if !file_path.is_file() {
|
||||
return Err(format!("'{file}' ist keine Datei."));
|
||||
return Err(format!("'{file}' is not a file."));
|
||||
}
|
||||
|
||||
reveal_path_in_file_manager(&file_path)
|
||||
@@ -262,7 +262,7 @@ pub async fn open_repository_bundle(
|
||||
})
|
||||
})
|
||||
.await
|
||||
.map_err(|err| format!("Repository konnte nicht geladen werden: {err}"))?
|
||||
.map_err(|err| format!("Could not load repository: {err}"))?
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -321,7 +321,7 @@ pub fn checkout_branch(path: String, branch: String) -> Result<GitStatus, String
|
||||
let repo = resolve_repo(&path)?;
|
||||
let branch = branch.trim().to_string();
|
||||
if branch.is_empty() {
|
||||
return Err("Branch-Name darf nicht leer sein.".to_string());
|
||||
return Err("Branch name must not be empty.".to_string());
|
||||
}
|
||||
|
||||
match checkout_plan(&repo, &branch)? {
|
||||
@@ -392,7 +392,7 @@ pub fn delete_branch(path: String, branch: String) -> Result<GitStatus, String>
|
||||
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());
|
||||
return Err("The current branch cannot be deleted.".to_string());
|
||||
}
|
||||
|
||||
run_git(&repo, ["branch", "-d", "--", branch.as_str()])?;
|
||||
@@ -560,21 +560,21 @@ pub async fn commit_ai_generate(
|
||||
match provider.as_str() {
|
||||
"local" => engine.generate_commit_message(&diff, notes).await,
|
||||
"openai" => {
|
||||
let api_key = api_key.ok_or_else(|| "OpenAI-API-Key fehlt.".to_string())?;
|
||||
let api_key = api_key.ok_or_else(|| "OpenAI API key is missing.".to_string())?;
|
||||
let model = model.unwrap_or_else(|| "gpt-4o-mini".to_string());
|
||||
commit_ai::generate_openai(&api_key, &model, &diff, notes).await
|
||||
}
|
||||
"anthropic" => {
|
||||
let api_key = api_key.ok_or_else(|| "Anthropic-API-Key fehlt.".to_string())?;
|
||||
let api_key = api_key.ok_or_else(|| "Anthropic API key is missing.".to_string())?;
|
||||
let model = model.unwrap_or_else(|| "claude-3-5-haiku-latest".to_string());
|
||||
commit_ai::generate_anthropic(&api_key, &model, &diff, notes).await
|
||||
}
|
||||
"custom" => {
|
||||
let base_url = base_url.ok_or_else(|| "Endpoint-URL fehlt.".to_string())?;
|
||||
let model = model.ok_or_else(|| "Modellname fehlt.".to_string())?;
|
||||
let base_url = base_url.ok_or_else(|| "Endpoint URL is missing.".to_string())?;
|
||||
let model = model.ok_or_else(|| "Model name is missing.".to_string())?;
|
||||
commit_ai::generate_custom(&base_url, api_key.as_deref(), &model, &diff, notes).await
|
||||
}
|
||||
other => Err(format!("Unbekannter KI-Provider: {other}")),
|
||||
other => Err(format!("Unknown AI provider: {other}")),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -588,7 +588,7 @@ pub fn apply_file_patch(
|
||||
let repo = resolve_repo(&path)?;
|
||||
validate_files(std::slice::from_ref(&file))?;
|
||||
if patch.trim().is_empty() {
|
||||
return Err("Kein Patch ausgewaehlt.".to_string());
|
||||
return Err("No patch selected.".to_string());
|
||||
}
|
||||
|
||||
let patch_path = write_temp_patch(&patch)?;
|
||||
@@ -603,7 +603,7 @@ pub fn apply_file_patch(
|
||||
.and_then(|_| check_apply_patch(&repo, &patch_path, &["--reverse"]))
|
||||
.and_then(|_| run_apply_patch(&repo, &patch_path, &["--cached", "--reverse"]))
|
||||
.and_then(|_| run_apply_patch(&repo, &patch_path, &["--reverse"])),
|
||||
_ => Err("Ungueltige Patch-Aktion.".to_string()),
|
||||
_ => Err("Invalid patch action.".to_string()),
|
||||
};
|
||||
|
||||
let _ = std::fs::remove_file(&patch_path);
|
||||
@@ -615,13 +615,13 @@ pub fn apply_file_patch(
|
||||
pub fn commit(path: String, message: String) -> Result<GitStatus, String> {
|
||||
let repo = resolve_repo(&path)?;
|
||||
if message.trim().is_empty() {
|
||||
return Err("Commit-Message darf nicht leer sein.".to_string());
|
||||
return Err("Commit message must not be empty.".to_string());
|
||||
}
|
||||
|
||||
let current_status = status_for_repo(&repo)?;
|
||||
if has_unresolved_conflicts(¤t_status) {
|
||||
return Err(
|
||||
"Merge-Konflikte muessen geloest werden, bevor du committen kannst.".to_string(),
|
||||
"Merge conflicts must be resolved before you can commit.".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -647,7 +647,7 @@ pub fn pull(
|
||||
.args(pull_args)
|
||||
.output()
|
||||
.map_err(|err| {
|
||||
format!("Git konnte nicht gestartet werden. Ist Git installiert? {err}")
|
||||
format!("Could not start Git. Is Git installed? {err}")
|
||||
})?,
|
||||
};
|
||||
|
||||
@@ -664,7 +664,7 @@ pub fn pull(
|
||||
if is_auth_error(&details) {
|
||||
return Err(format!("AUTH_FAILED:{details}"));
|
||||
}
|
||||
Err(format!("Git-Befehl fehlgeschlagen: {details}"))
|
||||
Err(format!("Git command failed: {details}"))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -701,10 +701,10 @@ pub struct StoredCredential {
|
||||
fn cred_entry(key: &str) -> Result<keyring::Entry, String> {
|
||||
let key = key.trim();
|
||||
if key.is_empty() {
|
||||
return Err("Kein Schlüssel für die Zugangsdaten angegeben.".to_string());
|
||||
return Err("No key provided for the credentials.".to_string());
|
||||
}
|
||||
keyring::Entry::new(CRED_SERVICE, key)
|
||||
.map_err(|err| format!("Schlüsselbund nicht verfügbar: {err}"))
|
||||
.map_err(|err| format!("Keychain unavailable: {err}"))
|
||||
}
|
||||
|
||||
/// Returns the remote URL used for auth key derivation (upstream remote of the
|
||||
@@ -770,7 +770,7 @@ fn current_branch_name(repo: &Path) -> Result<String, String> {
|
||||
let branch = run_git(repo, ["rev-parse", "--abbrev-ref", "HEAD"])?;
|
||||
let branch = String::from_utf8_lossy(&branch).trim().to_string();
|
||||
if branch.is_empty() || branch == "HEAD" {
|
||||
return Err("Aktueller Branch konnte nicht ermittelt werden.".to_string());
|
||||
return Err("Could not determine current branch.".to_string());
|
||||
}
|
||||
Ok(branch)
|
||||
}
|
||||
@@ -791,7 +791,7 @@ fn initial_push_remote_name(repo: &Path) -> Result<String, String> {
|
||||
}
|
||||
|
||||
first_remote_name(repo).ok_or_else(|| {
|
||||
"Dieser Branch hat keinen Upstream und es ist kein Remote konfiguriert.".to_string()
|
||||
"This branch has no upstream and no remote is configured.".to_string()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -816,11 +816,11 @@ pub fn cred_load(key: String) -> Result<Option<StoredCredential>, String> {
|
||||
match entry.get_password() {
|
||||
Ok(json) => {
|
||||
let cred = serde_json::from_str::<StoredCredential>(&json)
|
||||
.map_err(|err| format!("Gespeicherte Zugangsdaten unlesbar: {err}"))?;
|
||||
.map_err(|err| format!("Stored credentials unreadable: {err}"))?;
|
||||
Ok(Some(cred))
|
||||
}
|
||||
Err(keyring::Error::NoEntry) => Ok(None),
|
||||
Err(err) => Err(format!("Schlüsselbund-Zugriff fehlgeschlagen: {err}")),
|
||||
Err(err) => Err(format!("Keychain access failed: {err}")),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -839,10 +839,10 @@ pub fn cred_save(
|
||||
expires_at,
|
||||
};
|
||||
let json = serde_json::to_string(&cred)
|
||||
.map_err(|err| format!("Zugangsdaten konnten nicht serialisiert werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not serialize credentials: {err}"))?;
|
||||
entry
|
||||
.set_password(&json)
|
||||
.map_err(|err| format!("Speichern im Schlüsselbund fehlgeschlagen: {err}"))
|
||||
.map_err(|err| format!("Saving to keychain failed: {err}"))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -850,7 +850,7 @@ pub fn cred_delete(key: String) -> Result<(), String> {
|
||||
let entry = cred_entry(&key)?;
|
||||
match entry.delete_credential() {
|
||||
Ok(()) | Err(keyring::Error::NoEntry) => Ok(()),
|
||||
Err(err) => Err(format!("Löschen im Schlüsselbund fehlgeschlagen: {err}")),
|
||||
Err(err) => Err(format!("Deleting from keychain failed: {err}")),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -859,7 +859,7 @@ pub fn merge_branch(path: String, branch: String) -> Result<GitStatus, String> {
|
||||
let repo = resolve_repo(&path)?;
|
||||
let branch = branch.trim();
|
||||
if branch.is_empty() {
|
||||
return Err("Branch-Name darf nicht leer sein.".to_string());
|
||||
return Err("Branch name must not be empty.".to_string());
|
||||
}
|
||||
|
||||
let output = git_command()
|
||||
@@ -867,7 +867,7 @@ pub fn merge_branch(path: String, branch: String) -> Result<GitStatus, String> {
|
||||
.arg(&repo)
|
||||
.args(["merge", "--no-edit", branch])
|
||||
.output()
|
||||
.map_err(|err| format!("Git konnte nicht gestartet werden. Ist Git installiert? {err}"))?;
|
||||
.map_err(|err| format!("Could not start Git. Is Git installed? {err}"))?;
|
||||
|
||||
if output.status.success() {
|
||||
return status_for_repo(&repo);
|
||||
@@ -888,10 +888,10 @@ pub fn merge_branch(path: String, branch: String) -> Result<GitStatus, String> {
|
||||
} else if !stdout.trim().is_empty() {
|
||||
stdout.trim()
|
||||
} else {
|
||||
"unbekannter Fehler"
|
||||
"unknown error"
|
||||
};
|
||||
|
||||
Err(format!("Merge fehlgeschlagen: {details}"))
|
||||
Err(format!("Merge failed: {details}"))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -962,7 +962,7 @@ pub async fn list_file_history(
|
||||
result
|
||||
})
|
||||
.await
|
||||
.map_err(|err| format!("Dateihistorie konnte nicht geladen werden: {err}"))?
|
||||
.map_err(|err| format!("Could not load file history: {err}"))?
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -1003,7 +1003,7 @@ fn list_file_history_core(
|
||||
args.push(OsString::from("--follow"));
|
||||
}
|
||||
args.extend([OsString::from("--"), OsString::from(file)]);
|
||||
let output = run_git_cancellable(repo, args, cancellation, "Git-Dateihistorie fehlgeschlagen")?;
|
||||
let output = run_git_cancellable(repo, args, cancellation, "Git file history failed")?;
|
||||
check_search_cancelled(cancellation)?;
|
||||
|
||||
parse_commit_log(repo, &output)
|
||||
@@ -1025,7 +1025,7 @@ pub async fn search_code_introductions(
|
||||
let query = normalize_newlines(&query);
|
||||
let query = query.trim_matches('\n').to_string();
|
||||
if query.trim().is_empty() {
|
||||
return Err("Suchtext darf nicht leer sein.".to_string());
|
||||
return Err("Search text must not be empty.".to_string());
|
||||
}
|
||||
|
||||
if verify_commit(&repo, "HEAD").is_err() {
|
||||
@@ -1058,7 +1058,7 @@ pub async fn search_code_introductions(
|
||||
result
|
||||
})
|
||||
.await
|
||||
.map_err(|err| format!("Such-Task konnte nicht abgeschlossen werden: {err}"))?
|
||||
.map_err(|err| format!("Could not complete search task: {err}"))?
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -1451,7 +1451,7 @@ pub fn read_conflict(path: String, file: String) -> Result<ConflictFile, String>
|
||||
validate_files(std::slice::from_ref(&file))?;
|
||||
|
||||
let bytes = std::fs::read(repo.join(&file))
|
||||
.map_err(|err| format!("Konfliktdatei konnte nicht gelesen werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not read conflict file: {err}"))?;
|
||||
let binary = is_binary_bytes(&bytes);
|
||||
|
||||
// For binary files we cannot offer a text merge, so we only report the side
|
||||
@@ -1493,7 +1493,7 @@ pub fn resolve_conflict_side(
|
||||
let flag = match side.as_str() {
|
||||
"ours" => "--ours",
|
||||
"theirs" => "--theirs",
|
||||
_ => return Err("Ungueltige Seite. Erlaubt sind 'ours' oder 'theirs'.".to_string()),
|
||||
_ => return Err("Invalid side. Allowed values are 'ours' or 'theirs'.".to_string()),
|
||||
};
|
||||
|
||||
run_git_with_paths(&repo, &["checkout", flag], std::slice::from_ref(&file))?;
|
||||
@@ -1531,10 +1531,10 @@ pub fn resolve_conflict(path: String, file: String, content: String) -> Result<G
|
||||
let target = repo.join(&file);
|
||||
if let Some(parent) = target.parent() {
|
||||
std::fs::create_dir_all(parent)
|
||||
.map_err(|err| format!("Verzeichnis konnte nicht erstellt werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not create directory: {err}"))?;
|
||||
}
|
||||
std::fs::write(&target, content)
|
||||
.map_err(|err| format!("Konfliktdatei konnte nicht geschrieben werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not write conflict file: {err}"))?;
|
||||
|
||||
run_git_with_paths(&repo, &["add"], std::slice::from_ref(&file))?;
|
||||
status_for_repo(&repo)
|
||||
@@ -1562,19 +1562,19 @@ fn short_hash(hash: &str) -> String {
|
||||
|
||||
fn resolve_repo(path: &str) -> Result<PathBuf, String> {
|
||||
if path.trim().is_empty() {
|
||||
return Err("Repository-Pfad darf nicht leer sein.".to_string());
|
||||
return Err("Repository path must not be empty.".to_string());
|
||||
}
|
||||
|
||||
let input = PathBuf::from(path);
|
||||
let output = run_git_at(
|
||||
&input,
|
||||
["rev-parse", "--show-toplevel"],
|
||||
"Kein Git-Repository oder nicht erreichbar",
|
||||
"Not a Git repository or unreachable",
|
||||
)?;
|
||||
let top_level = String::from_utf8_lossy(&output).trim().to_string();
|
||||
|
||||
if top_level.is_empty() {
|
||||
return Err("Git konnte keinen Repository-Wurzelpfad ermitteln.".to_string());
|
||||
return Err("Git could not determine the repository root path.".to_string());
|
||||
}
|
||||
|
||||
Ok(PathBuf::from(top_level))
|
||||
@@ -1588,7 +1588,7 @@ fn open_path_in_file_manager(path: &Path) -> Result<(), String> {
|
||||
command.creation_flags(CREATE_NO_WINDOW);
|
||||
command
|
||||
.spawn()
|
||||
.map_err(|err| format!("Explorer konnte nicht gestartet werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not launch Explorer: {err}"))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1597,7 +1597,7 @@ fn open_path_in_file_manager(path: &Path) -> Result<(), String> {
|
||||
Command::new("open")
|
||||
.arg(path)
|
||||
.spawn()
|
||||
.map_err(|err| format!("Finder konnte nicht gestartet werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not launch Finder: {err}"))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1606,7 +1606,7 @@ fn open_path_in_file_manager(path: &Path) -> Result<(), String> {
|
||||
Command::new("xdg-open")
|
||||
.arg(path)
|
||||
.spawn()
|
||||
.map_err(|err| format!("Dateimanager konnte nicht gestartet werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not launch file manager: {err}"))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1622,19 +1622,19 @@ fn resolve_repo_child_path(repo: &Path, child: &str) -> Result<PathBuf, String>
|
||||
)
|
||||
})
|
||||
{
|
||||
return Err("Dateipfad muss innerhalb des Repositorys liegen.".to_string());
|
||||
return Err("File path must stay within the repository.".to_string());
|
||||
}
|
||||
|
||||
let candidate = repo.join(child_path);
|
||||
let repo = repo
|
||||
.canonicalize()
|
||||
.map_err(|err| format!("Repository-Pfad konnte nicht aufgeloest werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not resolve repository path: {err}"))?;
|
||||
let candidate = candidate
|
||||
.canonicalize()
|
||||
.map_err(|err| format!("Dateipfad konnte nicht aufgeloest werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not resolve file path: {err}"))?;
|
||||
|
||||
if !candidate.starts_with(&repo) {
|
||||
return Err("Dateipfad liegt ausserhalb des Repositorys.".to_string());
|
||||
return Err("File path lies outside the repository.".to_string());
|
||||
}
|
||||
|
||||
Ok(candidate)
|
||||
@@ -1648,7 +1648,7 @@ fn reveal_path_in_file_manager(path: &Path) -> Result<(), String> {
|
||||
command.creation_flags(CREATE_NO_WINDOW);
|
||||
command
|
||||
.spawn()
|
||||
.map_err(|err| format!("Explorer konnte nicht gestartet werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not launch Explorer: {err}"))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1658,7 +1658,7 @@ fn reveal_path_in_file_manager(path: &Path) -> Result<(), String> {
|
||||
.arg("-R")
|
||||
.arg(path)
|
||||
.spawn()
|
||||
.map_err(|err| format!("Finder konnte nicht gestartet werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not launch Finder: {err}"))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1669,23 +1669,23 @@ fn reveal_path_in_file_manager(path: &Path) -> Result<(), String> {
|
||||
Command::new("xdg-open")
|
||||
.arg(target)
|
||||
.spawn()
|
||||
.map_err(|err| format!("Dateimanager konnte nicht gestartet werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not launch file manager: {err}"))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn verify_commit(repo: &Path, commit: &str) -> Result<String, String> {
|
||||
let commit = commit.trim();
|
||||
if commit.is_empty() {
|
||||
return Err("Commit darf nicht leer sein.".to_string());
|
||||
return Err("Commit must not be empty.".to_string());
|
||||
}
|
||||
|
||||
let rev = format!("{commit}^{{commit}}");
|
||||
let output = run_git(repo, ["rev-parse", "--verify", "--quiet", rev.as_str()])
|
||||
.map_err(|err| format!("Commit konnte nicht gefunden werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not find commit: {err}"))?;
|
||||
let hash = String::from_utf8_lossy(&output).trim().to_string();
|
||||
|
||||
if hash.is_empty() {
|
||||
return Err("Commit konnte nicht gefunden werden.".to_string());
|
||||
return Err("Commit could not be found.".to_string());
|
||||
}
|
||||
|
||||
Ok(hash)
|
||||
@@ -1940,7 +1940,7 @@ fn search_candidate_commits(
|
||||
repo,
|
||||
["rev-list", "--all", "--reverse"],
|
||||
cancellation,
|
||||
"Git-Suche fehlgeschlagen",
|
||||
"Git search failed",
|
||||
)?
|
||||
} else {
|
||||
let mut args = vec![
|
||||
@@ -1957,7 +1957,7 @@ fn search_candidate_commits(
|
||||
args.push(OsString::from("-i"));
|
||||
}
|
||||
args.push(OsString::from(format!("-S{query}")));
|
||||
run_git_cancellable(repo, args, cancellation, "Git-Suche fehlgeschlagen")?
|
||||
run_git_cancellable(repo, args, cancellation, "Git search failed")?
|
||||
};
|
||||
|
||||
Ok(String::from_utf8_lossy(&output)
|
||||
@@ -2001,7 +2001,7 @@ fn read_text_blob(repo: &Path, commit: &str, file: &str) -> Result<Option<String
|
||||
.arg(repo)
|
||||
.args(["show", spec.as_str()])
|
||||
.output()
|
||||
.map_err(|err| format!("Git konnte nicht gestartet werden. Ist Git installiert? {err}"))?;
|
||||
.map_err(|err| format!("Could not start Git. Is Git installed? {err}"))?;
|
||||
|
||||
if !output.status.success() {
|
||||
return Ok(None);
|
||||
@@ -2064,7 +2064,7 @@ fn first_added_match_line(
|
||||
&["diff", "--no-textconv", "--unified=0", parent, commit],
|
||||
&[file.to_string()],
|
||||
cancellation,
|
||||
"Git-Diff fuer Suchtreffer fehlgeschlagen",
|
||||
"Git diff for search result failed",
|
||||
)?;
|
||||
let patch = String::from_utf8_lossy(&output);
|
||||
let line_query = first_query_line(query);
|
||||
@@ -2169,7 +2169,7 @@ fn commit_search_metadata(repo: &Path, commit: &str) -> Result<GitSearchCommitMe
|
||||
let text = String::from_utf8_lossy(&output);
|
||||
let fields: Vec<&str> = text.trim_end().splitn(6, '\x1f').collect();
|
||||
if fields.len() != 6 {
|
||||
return Err(format!("Unerwarteter Git-Commit-Eintrag: {text}"));
|
||||
return Err(format!("Unexpected Git commit entry: {text}"));
|
||||
}
|
||||
|
||||
Ok(GitSearchCommitMetadata {
|
||||
@@ -2204,7 +2204,7 @@ fn parse_commit_log_inline(output: &[u8]) -> Result<Vec<GitCommit>, String> {
|
||||
let parts: Vec<&[u8]> = record.splitn(9, |byte| *byte == FIELD_SEPARATOR).collect();
|
||||
if parts.len() < 8 {
|
||||
return Err(format!(
|
||||
"Unerwarteter Git-Log-Eintrag: {}",
|
||||
"Unexpected Git log entry: {}",
|
||||
String::from_utf8_lossy(record)
|
||||
));
|
||||
}
|
||||
@@ -2261,7 +2261,7 @@ fn parse_commit_log(repo: &Path, output: &[u8]) -> Result<Vec<GitCommit>, String
|
||||
|
||||
let fields: Vec<&str> = record.splitn(8, FIELD_SEPARATOR).collect();
|
||||
if fields.len() != 8 {
|
||||
return Err(format!("Unerwarteter Git-Log-Eintrag: {record}"));
|
||||
return Err(format!("Unexpected Git log entry: {record}"));
|
||||
}
|
||||
|
||||
let refs = fields[5]
|
||||
@@ -2310,7 +2310,7 @@ fn parse_commit_log_metadata(output: &[u8]) -> Result<Vec<GitCommit>, String> {
|
||||
|
||||
let fields: Vec<&str> = record.splitn(8, FIELD_SEPARATOR).collect();
|
||||
if fields.len() != 8 {
|
||||
return Err(format!("Unerwarteter Git-Log-Eintrag: {record}"));
|
||||
return Err(format!("Unexpected Git log entry: {record}"));
|
||||
}
|
||||
|
||||
let refs = fields[5]
|
||||
@@ -2374,7 +2374,7 @@ fn parse_commit_files(output: &[u8]) -> Result<Vec<GitCommitFile>, String> {
|
||||
let status = map_name_status(&status_text);
|
||||
|
||||
if index >= entries.len() {
|
||||
return Err(format!("Git-Diff-Eintrag ohne Pfad: {status_text}"));
|
||||
return Err(format!("Git diff entry without path: {status_text}"));
|
||||
}
|
||||
|
||||
if matches!(status, FileStatusKind::Renamed) {
|
||||
@@ -2517,7 +2517,7 @@ fn local_branch_name_for_remote(remote_branch: &str) -> Option<&str> {
|
||||
fn validate_new_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());
|
||||
return Err("Branch name must not be empty.".to_string());
|
||||
}
|
||||
|
||||
let output = git_command()
|
||||
@@ -2525,11 +2525,11 @@ fn validate_new_branch_name(repo: &Path, branch: &str) -> Result<String, String>
|
||||
.arg(repo)
|
||||
.args(["check-ref-format", "--branch", branch])
|
||||
.output()
|
||||
.map_err(|err| format!("Git konnte nicht gestartet werden. Ist Git installiert? {err}"))?;
|
||||
.map_err(|err| format!("Could not start Git. Is Git installed? {err}"))?;
|
||||
|
||||
if !output.status.success() {
|
||||
let details = command_output_details(&output);
|
||||
return Err(format!("Ungueltiger Branch-Name: {details}"));
|
||||
return Err(format!("Invalid branch name: {details}"));
|
||||
}
|
||||
|
||||
let normalized = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
||||
@@ -2540,7 +2540,7 @@ fn validate_new_branch_name(repo: &Path, branch: &str) -> Result<String, String>
|
||||
};
|
||||
|
||||
if ref_exists(repo, &format!("refs/heads/{normalized}"))? {
|
||||
return Err(format!("Branch '{normalized}' existiert bereits."));
|
||||
return Err(format!("Branch '{normalized}' already exists."));
|
||||
}
|
||||
|
||||
Ok(normalized)
|
||||
@@ -2549,13 +2549,13 @@ fn validate_new_branch_name(repo: &Path, branch: &str) -> Result<String, String>
|
||||
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());
|
||||
return Err("Branch name must not be empty.".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."
|
||||
"Local branch '{normalized}' was not found."
|
||||
));
|
||||
}
|
||||
|
||||
@@ -2566,11 +2566,11 @@ 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}"))?;
|
||||
.map_err(|err| format!("Could not start Git. Is Git installed? {err}"))?;
|
||||
|
||||
if !output.status.success() {
|
||||
let details = command_output_details(&output);
|
||||
return Err(format!("Ungueltiger Branch-Name: {details}"));
|
||||
return Err(format!("Invalid branch name: {details}"));
|
||||
}
|
||||
|
||||
let normalized = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
||||
@@ -2587,7 +2587,7 @@ fn ref_exists(repo: &Path, ref_name: &str) -> Result<bool, String> {
|
||||
.arg(repo)
|
||||
.args(["show-ref", "--verify", "--quiet", ref_name])
|
||||
.output()
|
||||
.map_err(|err| format!("Git konnte nicht gestartet werden. Ist Git installiert? {err}"))?;
|
||||
.map_err(|err| format!("Could not start Git. Is Git installed? {err}"))?;
|
||||
|
||||
match output.status.code() {
|
||||
Some(0) => Ok(true),
|
||||
@@ -2595,11 +2595,11 @@ fn ref_exists(repo: &Path, ref_name: &str) -> Result<bool, String> {
|
||||
_ => {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
let details = if stderr.trim().is_empty() {
|
||||
"unbekannter Fehler".to_string()
|
||||
"unknown error".to_string()
|
||||
} else {
|
||||
stderr.trim().to_string()
|
||||
};
|
||||
Err(format!("Git-Ref konnte nicht geprueft werden: {details}"))
|
||||
Err(format!("Could not verify Git ref: {details}"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2755,7 +2755,7 @@ fn find_status<'a>(statuses: &'a [GitFileStatus], file: &str) -> Option<&'a GitF
|
||||
|
||||
fn validate_files(files: &[String]) -> Result<(), String> {
|
||||
if files.iter().any(|file| file.is_empty()) {
|
||||
return Err("Dateiliste enthaelt einen leeren Pfad.".to_string());
|
||||
return Err("File list contains an empty path.".to_string());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -2768,7 +2768,7 @@ fn write_temp_patch(patch: &str) -> Result<PathBuf, String> {
|
||||
counter
|
||||
));
|
||||
std::fs::write(&path, patch.as_bytes())
|
||||
.map_err(|err| format!("Patch-Datei konnte nicht geschrieben werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not write patch file: {err}"))?;
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
@@ -2805,9 +2805,9 @@ fn write_askpass_script() -> Result<std::path::PathBuf, String> {
|
||||
let path = std::env::temp_dir().join("gitlite_askpass.sh");
|
||||
let script = "#!/bin/sh\ncase \"$1\" in\n *[Uu]sername*) printf '%s\\n' \"$GIT_CRED_USER\" ;;\n *) printf '%s\\n' \"$GIT_CRED_PASS\" ;;\nesac\n";
|
||||
std::fs::write(&path, script)
|
||||
.map_err(|e| format!("Konnte Authentifizierungsskript nicht schreiben: {e}"))?;
|
||||
.map_err(|e| format!("Could not write authentication script: {e}"))?;
|
||||
std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o700))
|
||||
.map_err(|e| format!("Konnte Skriptrechte nicht setzen: {e}"))?;
|
||||
.map_err(|e| format!("Could not set script permissions: {e}"))?;
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
@@ -2816,7 +2816,7 @@ fn write_askpass_script() -> Result<std::path::PathBuf, String> {
|
||||
let path = std::env::temp_dir().join("gitlite_askpass.bat");
|
||||
let script = "@echo off\necho %1 | findstr /I \"sername\" >nul 2>&1\nif %errorlevel% == 0 (echo %GIT_CRED_USER%) else (echo %GIT_CRED_PASS%)\n";
|
||||
std::fs::write(&path, script)
|
||||
.map_err(|e| format!("Konnte Authentifizierungsskript nicht schreiben: {e}"))?;
|
||||
.map_err(|e| format!("Could not write authentication script: {e}"))?;
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
@@ -2840,7 +2840,7 @@ where
|
||||
if is_auth_error(&details) {
|
||||
return Err(format!("AUTH_FAILED:{details}"));
|
||||
}
|
||||
Err(format!("Git-Befehl fehlgeschlagen: {details}"))
|
||||
Err(format!("Git command failed: {details}"))
|
||||
}
|
||||
|
||||
fn run_git_authenticated_output<I, S>(
|
||||
@@ -2864,7 +2864,7 @@ where
|
||||
.env("GIT_CRED_USER", username)
|
||||
.env("GIT_CRED_PASS", password)
|
||||
.output()
|
||||
.map_err(|err| format!("Git konnte nicht gestartet werden: {err}"));
|
||||
.map_err(|err| format!("Could not start Git: {err}"));
|
||||
|
||||
let _ = std::fs::remove_file(&askpass);
|
||||
result
|
||||
@@ -2878,7 +2878,7 @@ fn command_output_details(output: &Output) -> String {
|
||||
} else if !stdout.trim().is_empty() {
|
||||
stdout.trim().to_string()
|
||||
} else {
|
||||
"Unbekannter Fehler".to_string()
|
||||
"Unknown error".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2932,7 +2932,7 @@ where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
run_git_at(repo, args, "Git-Befehl fehlgeschlagen")
|
||||
run_git_at(repo, args, "Git command failed")
|
||||
}
|
||||
|
||||
fn run_git_cancellable<I, S>(
|
||||
@@ -2960,9 +2960,9 @@ where
|
||||
counter
|
||||
));
|
||||
let stdout_file = std::fs::File::create(&stdout_path)
|
||||
.map_err(|err| format!("Git-Ausgabedatei konnte nicht erstellt werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not create Git output file: {err}"))?;
|
||||
let stderr_file = std::fs::File::create(&stderr_path)
|
||||
.map_err(|err| format!("Git-Fehlerdatei konnte nicht erstellt werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not create Git error file: {err}"))?;
|
||||
|
||||
let mut child = git_command()
|
||||
.arg("-C")
|
||||
@@ -2974,7 +2974,7 @@ where
|
||||
.map_err(|err| {
|
||||
let _ = std::fs::remove_file(&stdout_path);
|
||||
let _ = std::fs::remove_file(&stderr_path);
|
||||
format!("Git konnte nicht gestartet werden. Ist Git installiert? {err}")
|
||||
format!("Could not start Git. Is Git installed? {err}")
|
||||
})?;
|
||||
|
||||
let status = loop {
|
||||
@@ -2988,7 +2988,7 @@ where
|
||||
|
||||
if let Some(status) = child
|
||||
.try_wait()
|
||||
.map_err(|err| format!("Git-Prozess konnte nicht geprueft werden: {err}"))?
|
||||
.map_err(|err| format!("Could not check Git process: {err}"))?
|
||||
{
|
||||
break status;
|
||||
}
|
||||
@@ -2997,9 +2997,9 @@ where
|
||||
};
|
||||
|
||||
let stdout = std::fs::read(&stdout_path)
|
||||
.map_err(|err| format!("Git-Ausgabe konnte nicht gelesen werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not read Git output: {err}"))?;
|
||||
let stderr = std::fs::read(&stderr_path)
|
||||
.map_err(|err| format!("Git-Fehlerausgabe konnte nicht gelesen werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not read Git error output: {err}"))?;
|
||||
let _ = std::fs::remove_file(&stdout_path);
|
||||
let _ = std::fs::remove_file(&stderr_path);
|
||||
|
||||
@@ -3014,7 +3014,7 @@ where
|
||||
} else if !stdout_text.trim().is_empty() {
|
||||
stdout_text.trim()
|
||||
} else {
|
||||
"unbekannter Fehler"
|
||||
"unknown error"
|
||||
};
|
||||
|
||||
Err(format!("{context}: {details}"))
|
||||
@@ -3030,7 +3030,7 @@ where
|
||||
.arg(path)
|
||||
.args(args)
|
||||
.output()
|
||||
.map_err(|err| format!("Git konnte nicht gestartet werden. Ist Git installiert? {err}"))?;
|
||||
.map_err(|err| format!("Could not start Git. Is Git installed? {err}"))?;
|
||||
|
||||
if output.status.success() {
|
||||
return Ok(output.stdout);
|
||||
@@ -3043,7 +3043,7 @@ where
|
||||
} else if !stdout.trim().is_empty() {
|
||||
stdout.trim()
|
||||
} else {
|
||||
"unbekannter Fehler"
|
||||
"unknown error"
|
||||
};
|
||||
|
||||
Err(format!("{context}: {details}"))
|
||||
@@ -3064,17 +3064,17 @@ where
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.map_err(|err| format!("Git konnte nicht gestartet werden. Ist Git installiert? {err}"))?;
|
||||
.map_err(|err| format!("Could not start Git. Is Git installed? {err}"))?;
|
||||
|
||||
if let Some(mut stdin) = child.stdin.take() {
|
||||
stdin
|
||||
.write_all(stdin_data)
|
||||
.map_err(|err| format!("Eingabe konnte nicht an Git gesendet werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not send input to Git: {err}"))?;
|
||||
}
|
||||
|
||||
let output = child
|
||||
.wait_with_output()
|
||||
.map_err(|err| format!("Git-Ausgabe konnte nicht gelesen werden: {err}"))?;
|
||||
.map_err(|err| format!("Could not read Git output: {err}"))?;
|
||||
|
||||
if output.status.success() {
|
||||
return Ok(output.stdout);
|
||||
@@ -3087,10 +3087,10 @@ where
|
||||
} else if !stdout.trim().is_empty() {
|
||||
stdout.trim()
|
||||
} else {
|
||||
"unbekannter Fehler"
|
||||
"unknown error"
|
||||
};
|
||||
|
||||
Err(format!("Git-Befehl fehlgeschlagen: {details}"))
|
||||
Err(format!("Git command failed: {details}"))
|
||||
}
|
||||
|
||||
fn parse_status_output(output: &[u8]) -> Result<(BranchInfo, Vec<GitFileStatus>), String> {
|
||||
@@ -3978,7 +3978,7 @@ mod tests {
|
||||
)
|
||||
.unwrap_err();
|
||||
|
||||
assert!(err.contains("Merge-Konflikte"));
|
||||
assert!(err.contains("Merge conflicts"));
|
||||
let status = status_for_repo(&repo.path).unwrap();
|
||||
assert!(has_unresolved_conflicts(&status));
|
||||
}
|
||||
@@ -4134,7 +4134,7 @@ mod tests {
|
||||
None,
|
||||
)
|
||||
.unwrap_err();
|
||||
assert!(err.contains("existiert bereits"));
|
||||
assert!(err.contains("already exists"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user