Skip to content

Commit 49c908b

Browse files
committed
Fixed pulling and merging
1 parent 8a4282f commit 49c908b

3 files changed

Lines changed: 55 additions & 6 deletions

File tree

Backend/src/tauri_commands/remotes.rs

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,22 @@ fn looks_like_ssh_auth_failure(msg: &str) -> bool {
9292
|| m.contains("authentication failed")
9393
}
9494

95+
/// Heuristically detects fast-forward-only divergence failures.
96+
///
97+
/// # Parameters
98+
/// - `msg`: Error text.
99+
///
100+
/// # Returns
101+
/// - `true` when text resembles a diverged ff-only pull.
102+
/// - `false` otherwise.
103+
fn looks_like_ff_only_divergence(msg: &str) -> bool {
104+
let m = msg.to_lowercase();
105+
m.contains("not possible to fast-forward")
106+
|| m.contains("can't be fast-forwarded")
107+
|| m.contains("cannot be fast-forwarded")
108+
|| (m.contains("fast-forward") && m.contains("diverg"))
109+
}
110+
95111
/// Returns remote URL for a named remote.
96112
///
97113
/// # Parameters
@@ -428,10 +444,10 @@ pub async fn vcs_pull<R: Runtime>(
428444
});
429445
}
430446

431-
info!("Fast-forward pulling '{current}' from {remote}/{upstream_branch}");
447+
info!("Pulling '{current}' from {remote}/{upstream_branch}");
432448
match repo.inner().pull_ff_only(remote, upstream_branch, on) {
433449
Ok(()) => {
434-
info!("Pull (ff-only) completed successfully for branch '{current}'");
450+
info!("Pull completed successfully for branch '{current}'");
435451
Ok(PullResult {
436452
pulled: true,
437453
branch: current,
@@ -450,9 +466,20 @@ pub async fn vcs_pull<R: Runtime>(
450466
}
451467
Err(e) => {
452468
let msg = e.to_string();
469+
if looks_like_ff_only_divergence(&msg) {
470+
info!("Pull skipped for branch '{current}': {msg}");
471+
return Ok(PullResult {
472+
pulled: false,
473+
branch: current.clone(),
474+
reason: Some(format!(
475+
"Branch '{current}' diverged from {remote}/{upstream_branch}; fast-forward pull skipped"
476+
)),
477+
});
478+
}
479+
453480
let url = remote_url_for(repo.inner(), remote).unwrap_or_default();
454481
emit_ssh_prompt(&app, remote, &url, &msg);
455-
error!("Pull (ff-only) failed for branch '{current}': {msg}");
482+
error!("Pull failed for branch '{current}': {msg}");
456483
Err(msg)
457484
}
458485
}
@@ -605,6 +632,27 @@ pub async fn vcs_undo_since_push<R: Runtime>(
605632
.await
606633
}
607634

635+
#[cfg(test)]
636+
mod tests {
637+
use super::looks_like_ff_only_divergence;
638+
639+
#[test]
640+
fn detects_fast_forward_only_divergence() {
641+
assert!(looks_like_ff_only_divergence(
642+
"fatal: Not possible to fast-forward, aborting."
643+
));
644+
assert!(looks_like_ff_only_divergence(
645+
"hint: Diverging branches can't be fast-forwarded, you need to either:"
646+
));
647+
}
648+
649+
#[test]
650+
fn ignores_unrelated_pull_failures() {
651+
assert!(!looks_like_ff_only_divergence("permission denied (publickey)"));
652+
assert!(!looks_like_ff_only_divergence("could not resolve hostname origin"));
653+
}
654+
}
655+
608656
#[tauri::command]
609657
/// Soft-resets HEAD to a selected commit, constrained to ahead-of-upstream history.
610658
///

Frontend/src/scripts/main.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,9 @@ async function boot() {
300300
} else {
301301
notify((res?.reason ?? 'No upstream configured for this branch; pull skipped') as string);
302302
}
303-
} catch {
304-
notify('Pull failed');
303+
} catch (e) {
304+
const msg = String(e || '').trim();
305+
notify(msg ? `Pull failed: ${msg}` : 'Pull failed');
305306
} finally {
306307
ctl.clearBusy();
307308
}

docs/Features.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ OpenVCS is plugin-first and VCS-agnostic. Features, themes, UI changes, and VCS
8282
<tr><td>Set remote URL</td><td align="center">✅</td><td>Remote configuration</td></tr>
8383
<tr><td>Fetch single remote</td><td align="center">✅</td><td>Targeted fetch</td></tr>
8484
<tr><td>Fetch all remotes</td><td align="center">✅</td><td>Full remote update</td></tr>
85-
<tr><td>Pull fast-forward only</td><td align="center">✅</td><td>Conservative pull behaviour</td></tr>
85+
<tr><td>Pull</td><td align="center">✅</td><td>Merges remote changes like GitHub Desktop</td></tr>
8686
<tr><td>Push</td><td align="center">✅</td><td>Push local changes; branches already present on origin are treated as pushable, and first publish establishes upstream tracking</td></tr>
8787
</table>
8888

0 commit comments

Comments
 (0)