Merge branch 'main' into dev

This commit is contained in:
Mohamed Boudra
2026-04-10 20:59:14 +07:00
23 changed files with 947 additions and 275 deletions
@@ -1,6 +1,7 @@
import { describe, it, expect, beforeEach, afterEach } from "vitest";
import { execSync } from "child_process";
import {
existsSync,
mkdtempSync,
rmSync,
writeFileSync,
@@ -30,6 +31,7 @@ import {
MergeConflictError,
MergeFromBaseConflictError,
NotGitRepoError,
pullCurrentBranch,
pushCurrentBranch,
resolveRepositoryDefaultBranch,
parseWorktreeList,
@@ -558,6 +560,85 @@ const x = 1;
expect(() => execSync("git rev-parse -q --verify MERGE_HEAD", { cwd: repoDir })).toThrow();
});
it("pulls the current branch from origin", async () => {
const remoteDir = join(tempDir, "remote.git");
execSync(`git init --bare -b main ${remoteDir}`);
execSync(`git remote add origin ${remoteDir}`, { cwd: repoDir });
execSync("git push -u origin main", { cwd: repoDir });
const otherClone = join(tempDir, "other-clone");
execSync(`git clone ${remoteDir} ${otherClone}`);
execSync("git config user.email 'test@test.com'", { cwd: otherClone });
execSync("git config user.name 'Test'", { cwd: otherClone });
writeFileSync(join(otherClone, "pulled.txt"), "remote\n");
execSync("git add pulled.txt", { cwd: otherClone });
execSync("git -c commit.gpgsign=false commit -m 'remote pull commit'", { cwd: otherClone });
const remoteCommit = execSync("git rev-parse HEAD", { cwd: otherClone }).toString().trim();
execSync("git push", { cwd: otherClone });
await pullCurrentBranch(repoDir);
execSync(`git merge-base --is-ancestor ${remoteCommit} HEAD`, { cwd: repoDir });
expect(readFileSync(join(repoDir, "pulled.txt"), "utf8")).toBe("remote\n");
});
it("aborts pull on merge conflicts and leaves no merge in progress", async () => {
const remoteDir = join(tempDir, "remote.git");
execSync(`git init --bare -b main ${remoteDir}`);
execSync(`git remote add origin ${remoteDir}`, { cwd: repoDir });
execSync("git push -u origin main", { cwd: repoDir });
writeFileSync(join(repoDir, "conflict.txt"), "local\n");
execSync("git add conflict.txt", { cwd: repoDir });
execSync("git -c commit.gpgsign=false commit -m 'local conflict commit'", { cwd: repoDir });
const otherClone = join(tempDir, "other-clone");
execSync(`git clone ${remoteDir} ${otherClone}`);
execSync("git config user.email 'test@test.com'", { cwd: otherClone });
execSync("git config user.name 'Test'", { cwd: otherClone });
writeFileSync(join(otherClone, "conflict.txt"), "remote\n");
execSync("git add conflict.txt", { cwd: otherClone });
execSync("git -c commit.gpgsign=false commit -m 'remote conflict commit'", { cwd: otherClone });
execSync("git push", { cwd: otherClone });
await expect(pullCurrentBranch(repoDir)).rejects.toBeInstanceOf(Error);
const porcelain = execSync("git status --porcelain", { cwd: repoDir }).toString().trim();
expect(porcelain).toBe("");
expect(() => execSync("git rev-parse -q --verify MERGE_HEAD", { cwd: repoDir })).toThrow();
});
it("aborts pull on rebase conflicts and leaves no rebase in progress", async () => {
const remoteDir = join(tempDir, "remote.git");
execSync(`git init --bare -b main ${remoteDir}`);
execSync(`git remote add origin ${remoteDir}`, { cwd: repoDir });
execSync("git push -u origin main", { cwd: repoDir });
execSync("git config pull.rebase true", { cwd: repoDir });
writeFileSync(join(repoDir, "conflict.txt"), "local\n");
execSync("git add conflict.txt", { cwd: repoDir });
execSync("git -c commit.gpgsign=false commit -m 'local rebase conflict commit'", { cwd: repoDir });
const otherClone = join(tempDir, "other-clone");
execSync(`git clone ${remoteDir} ${otherClone}`);
execSync("git config user.email 'test@test.com'", { cwd: otherClone });
execSync("git config user.name 'Test'", { cwd: otherClone });
writeFileSync(join(otherClone, "conflict.txt"), "remote\n");
execSync("git add conflict.txt", { cwd: otherClone });
execSync("git -c commit.gpgsign=false commit -m 'remote rebase conflict commit'", {
cwd: otherClone,
});
execSync("git push", { cwd: otherClone });
await expect(pullCurrentBranch(repoDir)).rejects.toBeInstanceOf(Error);
const gitDir = execSync("git rev-parse --absolute-git-dir", { cwd: repoDir }).toString().trim();
const porcelain = execSync("git status --porcelain", { cwd: repoDir }).toString().trim();
expect(porcelain).toBe("");
expect(existsSync(join(gitDir, "rebase-merge"))).toBe(false);
expect(existsSync(join(gitDir, "rebase-apply"))).toBe(false);
});
it("pushes the current branch to origin", async () => {
const remoteDir = join(tempDir, "remote.git");
execSync(`git init --bare -b main ${remoteDir}`);