mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-02-13 22:27:47 +01:00
Compare commits
2 Commits
main
...
fix/git-pu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f27d500a2c | ||
|
|
d84fec8c7c |
@@ -44,43 +44,65 @@ pub async fn git_pull(dir: &Path) -> Result<PullResult> {
|
||||
(branch_name, remote_name, remote_url)
|
||||
};
|
||||
|
||||
let out = new_binary_command(dir)
|
||||
// Step 1: fetch the specific branch
|
||||
// NOTE: We use fetch + merge instead of `git pull` to avoid conflicts with
|
||||
// global git config (e.g. pull.ff=only) and the background fetch --all.
|
||||
let fetch_out = new_binary_command(dir)
|
||||
.await?
|
||||
.args(["pull", &remote_name, &branch_name])
|
||||
.args(["fetch", &remote_name, &branch_name])
|
||||
.env("GIT_TERMINAL_PROMPT", "0")
|
||||
.output()
|
||||
.await
|
||||
.map_err(|e| GenericError(format!("failed to run git pull: {e}")))?;
|
||||
.map_err(|e| GenericError(format!("failed to run git fetch: {e}")))?;
|
||||
|
||||
let stdout = String::from_utf8_lossy(&out.stdout);
|
||||
let stderr = String::from_utf8_lossy(&out.stderr);
|
||||
let combined = stdout + stderr;
|
||||
let fetch_stdout = String::from_utf8_lossy(&fetch_out.stdout);
|
||||
let fetch_stderr = String::from_utf8_lossy(&fetch_out.stderr);
|
||||
let fetch_combined = format!("{fetch_stdout}{fetch_stderr}");
|
||||
|
||||
info!("Pulled status={} {combined}", out.status);
|
||||
info!("Fetched status={} {fetch_combined}", fetch_out.status);
|
||||
|
||||
if combined.to_lowercase().contains("could not read") {
|
||||
if fetch_combined.to_lowercase().contains("could not read") {
|
||||
return Ok(PullResult::NeedsCredentials { url: remote_url.to_string(), error: None });
|
||||
}
|
||||
|
||||
if combined.to_lowercase().contains("unable to access") {
|
||||
if fetch_combined.to_lowercase().contains("unable to access") {
|
||||
return Ok(PullResult::NeedsCredentials {
|
||||
url: remote_url.to_string(),
|
||||
error: Some(combined.to_string()),
|
||||
error: Some(fetch_combined.to_string()),
|
||||
});
|
||||
}
|
||||
|
||||
if !out.status.success() {
|
||||
let combined_lower = combined.to_lowercase();
|
||||
if combined_lower.contains("cannot fast-forward")
|
||||
|| combined_lower.contains("not possible to fast-forward")
|
||||
|| combined_lower.contains("diverged")
|
||||
if !fetch_out.status.success() {
|
||||
return Err(GenericError(format!("Failed to fetch: {fetch_combined}")));
|
||||
}
|
||||
|
||||
// Step 2: merge the fetched branch
|
||||
let ref_name = format!("{}/{}", remote_name, branch_name);
|
||||
let merge_out = new_binary_command(dir)
|
||||
.await?
|
||||
.args(["merge", "--ff-only", &ref_name])
|
||||
.output()
|
||||
.await
|
||||
.map_err(|e| GenericError(format!("failed to run git merge: {e}")))?;
|
||||
|
||||
let merge_stdout = String::from_utf8_lossy(&merge_out.stdout);
|
||||
let merge_stderr = String::from_utf8_lossy(&merge_out.stderr);
|
||||
let merge_combined = format!("{merge_stdout}{merge_stderr}");
|
||||
|
||||
info!("Merged status={} {merge_combined}", merge_out.status);
|
||||
|
||||
if !merge_out.status.success() {
|
||||
let merge_lower = merge_combined.to_lowercase();
|
||||
if merge_lower.contains("cannot fast-forward")
|
||||
|| merge_lower.contains("not possible to fast-forward")
|
||||
|| merge_lower.contains("diverged")
|
||||
{
|
||||
return Ok(PullResult::Diverged { remote: remote_name, branch: branch_name });
|
||||
}
|
||||
return Err(GenericError(format!("Failed to pull {combined}")));
|
||||
return Err(GenericError(format!("Failed to merge: {merge_combined}")));
|
||||
}
|
||||
|
||||
if combined.to_lowercase().contains("up to date") {
|
||||
if merge_combined.to_lowercase().contains("up to date") {
|
||||
return Ok(PullResult::UpToDate);
|
||||
}
|
||||
|
||||
|
||||
@@ -176,7 +176,11 @@ export function GitCommitDialog({ syncDir, onDone, workspace }: Props) {
|
||||
}
|
||||
|
||||
if (!hasAnythingToAdd) {
|
||||
return <EmptyStateText>No changes since last commit</EmptyStateText>;
|
||||
return (
|
||||
<div className="h-full px-6 pb-4">
|
||||
<EmptyStateText>No changes since last commit</EmptyStateText>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -230,14 +234,14 @@ export function GitCommitDialog({ syncDir, onDone, workspace }: Props) {
|
||||
hideLabel
|
||||
/>
|
||||
{commitError && <Banner color="danger">{commitError}</Banner>}
|
||||
<HStack alignItems="center">
|
||||
<HStack alignItems="center" space={2}>
|
||||
<InlineCode>{status.data?.headRefShorthand}</InlineCode>
|
||||
<HStack space={2} className="ml-auto">
|
||||
<Button
|
||||
color="secondary"
|
||||
size="sm"
|
||||
onClick={handleCreateCommit}
|
||||
disabled={!hasAddedAnything}
|
||||
disabled={!hasAddedAnything || message.trim().length === 0}
|
||||
isLoading={isPushing}
|
||||
>
|
||||
Commit
|
||||
@@ -245,7 +249,7 @@ export function GitCommitDialog({ syncDir, onDone, workspace }: Props) {
|
||||
<Button
|
||||
color="primary"
|
||||
size="sm"
|
||||
disabled={!hasAddedAnything}
|
||||
disabled={!hasAddedAnything || message.trim().length === 0}
|
||||
onClick={handleCreateCommitAndPush}
|
||||
isLoading={isPushing}
|
||||
>
|
||||
|
||||
@@ -173,7 +173,6 @@ function SyncDropdownWithSyncDir({ syncDir }: { syncDir: string }) {
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: 'Push',
|
||||
hidden: !hasRemotes,
|
||||
leftSlot: <Icon icon="arrow_up_from_line" />,
|
||||
waitForOnSelect: true,
|
||||
async onSelect() {
|
||||
@@ -192,7 +191,6 @@ function SyncDropdownWithSyncDir({ syncDir }: { syncDir: string }) {
|
||||
},
|
||||
{
|
||||
label: 'Pull',
|
||||
hidden: !hasRemotes,
|
||||
leftSlot: <Icon icon="arrow_down_to_line" />,
|
||||
waitForOnSelect: true,
|
||||
async onSelect() {
|
||||
|
||||
@@ -2,13 +2,13 @@ import type { GitCallbacks } from '@yaakapp-internal/git';
|
||||
import { sync } from '../../init/sync';
|
||||
import { promptCredentials } from './credentials';
|
||||
import { promptDivergedStrategy } from './diverged';
|
||||
import { promptUncommittedChangesStrategy } from './uncommitted';
|
||||
import { addGitRemote } from './showAddRemoteDialog';
|
||||
import { promptUncommittedChangesStrategy } from './uncommitted';
|
||||
|
||||
export function gitCallbacks(dir: string): GitCallbacks {
|
||||
return {
|
||||
addRemote: async () => {
|
||||
return addGitRemote(dir);
|
||||
return addGitRemote(dir, 'origin');
|
||||
},
|
||||
promptCredentials: async ({ url, error }) => {
|
||||
const creds = await promptCredentials({ url, error });
|
||||
|
||||
@@ -3,12 +3,12 @@ import { gitMutations } from '@yaakapp-internal/git';
|
||||
import { showPromptForm } from '../../lib/prompt-form';
|
||||
import { gitCallbacks } from './callbacks';
|
||||
|
||||
export async function addGitRemote(dir: string): Promise<GitRemote> {
|
||||
export async function addGitRemote(dir: string, defaultName?: string): Promise<GitRemote> {
|
||||
const r = await showPromptForm({
|
||||
id: 'add-remote',
|
||||
title: 'Add Remote',
|
||||
inputs: [
|
||||
{ type: 'text', label: 'Name', name: 'name' },
|
||||
{ type: 'text', label: 'Name', name: 'name', defaultValue: defaultName },
|
||||
{ type: 'text', label: 'URL', name: 'url' },
|
||||
],
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user