Skip to content

Commit 8c5901f

Browse files
committed
BUG multi-file push in browser
1 parent 21d047c commit 8c5901f

File tree

3 files changed

+53
-27
lines changed

3 files changed

+53
-27
lines changed

src/App.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,7 +1413,12 @@ const App = () => {
14131413
showToast('Successfully pushed changes!', 'success');
14141414
await updateGitStatus();
14151415
} catch (error) {
1416-
showToast(`Failed to push changes: ${(error as Error).message}`, 'error');
1416+
const msg = (error as Error).message;
1417+
if (msg.includes('not a simple fast-forward') || msg.includes('Push rejected')) {
1418+
showToast('Push rejected: Remote has changes you don\'t have. Please Pull first.', 'error');
1419+
} else {
1420+
showToast(`Failed to push changes: ${msg}`, 'error');
1421+
}
14171422
console.error('Push error:', error);
14181423
}
14191424
});
@@ -1424,7 +1429,12 @@ const App = () => {
14241429
showToast('Successfully pushed changes!', 'success');
14251430
await updateGitStatus();
14261431
} catch (error) {
1427-
showToast(`Failed to push changes: ${(error as Error).message}`, 'error');
1432+
const msg = (error as Error).message;
1433+
if (msg.includes('not a simple fast-forward') || msg.includes('Push rejected')) {
1434+
showToast('Push rejected: Remote has changes you don\'t have. Please Pull first.', 'error');
1435+
} else {
1436+
showToast(`Failed to push changes: ${msg}`, 'error');
1437+
}
14281438
console.error('Push error:', error);
14291439
}
14301440
}

src/gitManager.ts

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -399,8 +399,13 @@ export class GitManager {
399399
await writable.close();
400400
console.log(' ✓ Synced:', fileName);
401401
}
402-
} catch (e) {
403-
console.error(' Error syncing file:', relativePath, e);
402+
} catch (e: any) {
403+
if (e.name === 'NoModificationAllowedError') {
404+
// This is expected for some git objects/pack files that are read-only
405+
console.warn(` Read-only file detected (skipping): ${relativePath}`);
406+
} else {
407+
console.error(' Error syncing file:', relativePath, e);
408+
}
404409
}
405410
}
406411

@@ -495,6 +500,7 @@ export class GitManager {
495500
name: 'EasyEdit User',
496501
497502
},
503+
corsProxy: 'https://cors.isomorphic-git.org', // Add CORS proxy
498504
};
499505

500506
if (this.credentials) {
@@ -553,7 +559,31 @@ export class GitManager {
553559
}
554560

555561
console.log('Calling git.push()...');
556-
await git.push(pushOptions);
562+
const pushResult = await git.push(pushOptions);
563+
console.log('Push result:', pushResult);
564+
565+
if (pushResult.ok === false) {
566+
throw new Error(`Push failed: ${pushResult.error || 'Unknown error'}`);
567+
}
568+
569+
// Check individual refs for errors
570+
if (pushResult.refs) {
571+
for (const [ref, result] of Object.entries(pushResult.refs)) {
572+
if (!result.ok) {
573+
throw new Error(`Failed to push ref ${ref}: ${result.error}`);
574+
}
575+
}
576+
}
577+
578+
// Sync the .git directory back to disk to update local status
579+
if (this.dirHandle) {
580+
console.log('Syncing .git directory back to disk...');
581+
const gitPath = `${this.repoDir}/.git`;
582+
// Sync .git content (repoName='.git' forces strict sync into .git folder)
583+
await this.syncToFileSystem(gitPath, this.dirHandle, '.git');
584+
console.log('.git directory synced back to disk');
585+
}
586+
557587
console.log('=== Git Push Completed Successfully ===');
558588
} catch (error: any) {
559589
console.error('=== Git Push Failed ===');
@@ -591,6 +621,7 @@ export class GitManager {
591621
http,
592622
dir: this.repoDir,
593623
remote: 'origin',
624+
corsProxy: 'https://cors.isomorphic-git.org', // Add CORS proxy
594625
};
595626

596627
if (this.credentials) {
@@ -600,6 +631,7 @@ export class GitManager {
600631
});
601632
}
602633

634+
// Fetch does not return a result with ok/error, it throws on failure
603635
await git.fetch(fetchOptions);
604636
} catch (error) {
605637
throw new Error(`Failed to fetch from remote: ${(error as Error).message}`);
@@ -704,11 +736,17 @@ export class GitManager {
704736
});
705737

706738
if (status === 'modified') {
739+
result.staged.push(filepath);
740+
} else if (status === '*modified') {
707741
result.modified.push(filepath);
708742
} else if (status === 'added') {
709743
result.staged.push(filepath);
710744
} else if (status === '*added') {
711745
result.untracked.push(filepath);
746+
} else if (status === 'deleted') {
747+
result.staged.push(filepath);
748+
} else if (status === '*deleted') {
749+
result.modified.push(filepath);
712750
}
713751
}
714752

src/insertSave.ts

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -226,28 +226,6 @@ export const detectGitRepo = async (fileHandle: any): Promise<string | null> =>
226226
return null;
227227
} else {
228228
console.log('[GitDetection] getParent() not available - use "Git → Open Repository" for full Git features');
229-
230-
// Fallback: Prompt user to select repository if they want Git features
231-
const shouldPrompt = await new Promise<boolean>((resolve) => {
232-
// Create a simple confirmation dialog
233-
const result = confirm(
234-
'Git features are not available when opening individual files.\n\n' +
235-
'Would you like to open the entire repository instead to enable Git operations (save, stage, commit, push)?'
236-
);
237-
resolve(result);
238-
});
239-
240-
if (shouldPrompt) {
241-
// Trigger repository selection
242-
const repoResult = await selectGitRepository();
243-
if (repoResult && repoResult.isGitRepo) {
244-
// Store the directory handle globally for later use
245-
(window as any).selectedDirHandle = repoResult.dirHandle;
246-
console.log('[GitDetection] Repository selected for Git features:', repoResult.path);
247-
return repoResult.path;
248-
}
249-
}
250-
251229
return null;
252230
}
253231
} catch (error) {

0 commit comments

Comments
 (0)