Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions apps/desktop/src/lib/trpc/routers/projects/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
} from "main/lib/project-icons";
import { getWorkspaceRuntimeRegistry } from "main/lib/workspace-runtime";
import { PROJECT_COLOR_VALUES } from "shared/constants/project-colors";
import simpleGit, { type SimpleGitProgressEvent } from "simple-git";
import type { SimpleGitProgressEvent } from "simple-git";
import { z } from "zod";
import { publicProcedure, router } from "../..";
import { resolveDefaultEditor } from "../external";
Expand All @@ -45,11 +45,11 @@ import {
refreshDefaultBranch,
sanitizeAuthorPrefix,
} from "../workspaces/utils/git";
import { getSimpleGitWithShellPath } from "../workspaces/utils/git-client";
import {
execWithShellEnv,
getProcessEnvWithShellPath,
} from "../workspaces/utils/shell-env";
createSimpleGitWithShellPath,
getSimpleGitWithShellPath,
} from "../workspaces/utils/git-client";
import { execWithShellEnv } from "../workspaces/utils/shell-env";
import { getDefaultProjectColor } from "./utils/colors";
import { discoverAndSaveProjectIcon } from "./utils/favicon-discovery";
import { fetchGitHubOwner, getGitHubAvatarUrl } from "./utils/github";
Expand Down Expand Up @@ -1493,7 +1493,7 @@ export const createProjectsRouter = (getWindow: () => BrowserWindow | null) => {
`Preparing clone into ${basename(clonePath)}`,
);
try {
const gitWithProgress = simpleGit({
const gitWithProgress = await createSimpleGitWithShellPath({
abort: abortController.signal,
progress: (event: SimpleGitProgressEvent) => {
emitCloneEvent({
Expand All @@ -1507,7 +1507,6 @@ export const createProjectsRouter = (getWindow: () => BrowserWindow | null) => {
});
},
});
gitWithProgress.env(await getProcessEnvWithShellPath());
emitCloneLog(
cloneId,
`Cloning ${redactGitCredentials(input.url)}`,
Expand Down
60 changes: 56 additions & 4 deletions apps/desktop/src/lib/trpc/routers/workspaces/utils/git-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,67 @@ import {
type ExecFileOptionsWithStringEncoding,
execFile,
} from "node:child_process";
import simpleGit, { type SimpleGit } from "simple-git";
import {
buildSimpleGitUnsafeOptions,
type SimpleGitUnsafeOptions,
} from "@superset/shared/simple-git-unsafe";
import simpleGit, {
type SimpleGit,
type SimpleGitProgressEvent,
} from "simple-git";
import { getProcessEnvWithShellPath } from "./shell-env";

interface CreateSimpleGitWithShellPathOptions {
abort?: AbortSignal;
baseEnv?: NodeJS.ProcessEnv;
progress?: (event: SimpleGitProgressEvent) => void;
repoPath?: string;
}

function createSimpleGitWithEnv(
env: Record<string, string>,
options: Omit<CreateSimpleGitWithShellPathOptions, "baseEnv"> = {},
): SimpleGit {
const unsafe = buildSimpleGitUnsafeOptions(env);
const gitOptions: {
abort?: AbortSignal;
baseDir?: string;
progress?: (event: SimpleGitProgressEvent) => void;
unsafe?: SimpleGitUnsafeOptions;
} = {};

if (options.abort) {
gitOptions.abort = options.abort;
}
if (options.progress) {
gitOptions.progress = options.progress;
}
if (options.repoPath) {
gitOptions.baseDir = options.repoPath;
}
if (unsafe) {
gitOptions.unsafe = unsafe;
}

const git =
Object.keys(gitOptions).length > 0
? simpleGit(gitOptions as never)
: simpleGit();
git.env(env);
return git;
}

export async function createSimpleGitWithShellPath(
options: CreateSimpleGitWithShellPathOptions = {},
): Promise<SimpleGit> {
const env = await getProcessEnvWithShellPath(options.baseEnv ?? process.env);
return createSimpleGitWithEnv(env, options);
}

export async function getSimpleGitWithShellPath(
repoPath?: string,
): Promise<SimpleGit> {
const git = repoPath ? simpleGit(repoPath) : simpleGit();
git.env(await getProcessEnvWithShellPath());
return git;
return createSimpleGitWithShellPath({ repoPath });
}

export async function execGitWithShellPath(
Expand Down
16 changes: 11 additions & 5 deletions packages/host-service/src/runtime/git/git.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import simpleGit from "simple-git";

import { createSimpleGitWithEnv } from "./simple-git";
import type { GitCredentialProvider, GitFactory } from "./types";
import { getRemoteUrl } from "./utils";

export function createGitFactory(provider: GitCredentialProvider): GitFactory {
return async (repoPath: string) => {
const initialCredentials = await provider.getCredentials(null);
const git = simpleGit(repoPath).env(initialCredentials.env);
const git = createSimpleGitWithEnv({
baseDir: repoPath,
env: initialCredentials.env,
});
const remoteUrl = await getRemoteUrl(git);
const credentials = await provider.getCredentials(remoteUrl);

return git.env({
const env = {
...initialCredentials.env,
...credentials.env,
GIT_OPTIONAL_LOCKS: "0",
};

return createSimpleGitWithEnv({
baseDir: repoPath,
env,
});
};
}
48 changes: 48 additions & 0 deletions packages/host-service/src/runtime/git/simple-git.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {
buildSimpleGitUnsafeOptions,
type SimpleGitUnsafeOptions,
} from "@superset/shared/simple-git-unsafe";
import simpleGit, { type SimpleGit } from "simple-git";

interface CreateSimpleGitWithEnvOptions {
baseDir?: string;
env?: NodeJS.ProcessEnv | Record<string, string>;
}

function copyStringEnv(
baseEnv: NodeJS.ProcessEnv | Record<string, string> = process.env,
): Record<string, string> {
const env: Record<string, string> = {};

for (const [key, value] of Object.entries(baseEnv)) {
if (typeof value === "string") {
env[key] = value;
}
}

return env;
}

export function createSimpleGitWithEnv(
options: CreateSimpleGitWithEnvOptions = {},
): SimpleGit {
const env = copyStringEnv(options.env ?? process.env);
const unsafe = buildSimpleGitUnsafeOptions(env);
const gitOptions: {
baseDir?: string;
unsafe?: SimpleGitUnsafeOptions;
} = {};

if (options.baseDir) {
gitOptions.baseDir = options.baseDir;
}
if (unsafe) {
gitOptions.unsafe = unsafe;
}

const git =
Object.keys(gitOptions).length > 0
? simpleGit(gitOptions as never)
: simpleGit();
return git.env(env);
}
14 changes: 9 additions & 5 deletions packages/host-service/src/trpc/router/project/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { existsSync, rmSync, statSync } from "node:fs";
import { basename, join, resolve } from "node:path";
import { TRPCError } from "@trpc/server";
import { eq } from "drizzle-orm";
import simpleGit from "simple-git";
import { z } from "zod";
import { projects, workspaces } from "../../../db/schema";
import { createSimpleGitWithEnv } from "../../../runtime/git/simple-git";
import { parseGitHubRemote } from "../../../runtime/pull-requests/utils/parse-github-remote";
import { protectedProcedure, router } from "../../index";
import {
Expand Down Expand Up @@ -162,7 +162,7 @@ async function importExistingRepo(
});
}

const git = simpleGit(localPath);
const git = createSimpleGitWithEnv({ baseDir: localPath });

let gitRoot: string;
try {
Expand All @@ -174,7 +174,9 @@ async function importExistingRepo(
});
}

const remotes = await getGitHubRemotes(simpleGit(gitRoot));
const remotes = await getGitHubRemotes(
createSimpleGitWithEnv({ baseDir: gitRoot }),
);
const matchingRemote = findMatchingRemote(remotes, expectedSlug);

if (!matchingRemote) {
Expand Down Expand Up @@ -230,7 +232,7 @@ async function cloneRepo(
}

try {
await simpleGit().clone(repoCloneUrl, targetPath);
await createSimpleGitWithEnv().clone(repoCloneUrl, targetPath);
} catch (err) {
if (existsSync(targetPath)) {
rmSync(targetPath, { recursive: true, force: true });
Expand All @@ -241,7 +243,9 @@ async function cloneRepo(
});
}

const remotes = await getGitHubRemotes(simpleGit(targetPath));
const remotes = await getGitHubRemotes(
createSimpleGitWithEnv({ baseDir: targetPath }),
);
const matchingRemote = findMatchingRemote(remotes, expectedSlug);

if (!matchingRemote) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { dirname, join, resolve, sep } from "node:path";
import { getDeviceName, getHashedDeviceId } from "@superset/shared/device-info";
import { TRPCError } from "@trpc/server";
import { and, eq } from "drizzle-orm";
import simpleGit from "simple-git";
import { z } from "zod";
import { projects, workspaces } from "../../../db/schema";
import {
Expand All @@ -13,6 +12,7 @@ import {
resolveDefaultBranchName,
resolveRef,
} from "../../../runtime/git/refs";
import { createSimpleGitWithEnv } from "../../../runtime/git/simple-git";
import { createTerminalSessionInternal } from "../../../terminal/terminal";
import type { HostServiceContext } from "../../../types";
import { protectedProcedure, router } from "../../index";
Expand Down Expand Up @@ -732,7 +732,10 @@ export const workspaceCreationRouter = router({

if (!existsSync(repoPath)) {
mkdirSync(dirname(repoPath), { recursive: true });
await simpleGit().clone(cloudProject.repoCloneUrl, repoPath);
await createSimpleGitWithEnv().clone(
cloudProject.repoCloneUrl,
repoPath,
);
}

localProject = ctx.db
Expand Down Expand Up @@ -1073,7 +1076,10 @@ export const workspaceCreationRouter = router({
const repoPath = join(homeDir, ".superset", "repos", input.projectId);
if (!existsSync(repoPath)) {
mkdirSync(dirname(repoPath), { recursive: true });
await simpleGit().clone(cloudProject.repoCloneUrl, repoPath);
await createSimpleGitWithEnv().clone(
cloudProject.repoCloneUrl,
repoPath,
);
}
localProject = ctx.db
.insert(projects)
Expand Down
7 changes: 5 additions & 2 deletions packages/host-service/src/trpc/router/workspace/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { dirname, join } from "node:path";
import { getDeviceName, getHashedDeviceId } from "@superset/shared/device-info";
import { TRPCError } from "@trpc/server";
import { eq } from "drizzle-orm";
import simpleGit from "simple-git";
import { z } from "zod";
import { projects, workspaces } from "../../../db/schema";
import { createSimpleGitWithEnv } from "../../../runtime/git/simple-git";
import { protectedProcedure, router } from "../../index";

export const workspaceRouter = router({
Expand Down Expand Up @@ -64,7 +64,10 @@ export const workspaceRouter = router({

if (!existsSync(repoPath)) {
mkdirSync(dirname(repoPath), { recursive: true });
await simpleGit().clone(cloudProject.repoCloneUrl, repoPath);
await createSimpleGitWithEnv().clone(
cloudProject.repoCloneUrl,
repoPath,
);
}

const inserted = ctx.db
Expand Down
4 changes: 4 additions & 0 deletions packages/shared/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@
"./shell-ready-scanner": {
"types": "./src/shell-ready-scanner.ts",
"default": "./src/shell-ready-scanner.ts"
},
"./simple-git-unsafe": {
"types": "./src/simple-git-unsafe.ts",
"default": "./src/simple-git-unsafe.ts"
}
},
"scripts": {
Expand Down
Loading
Loading