mirror of
https://github.com/OpenHands/OpenHands.git
synced 2026-03-22 13:47:19 +08:00
fix(frontend): use correct git path based on sandbox grouping strategy (#13488)
This commit is contained in:
@@ -4,27 +4,96 @@ import { getGitPath } from "#/utils/get-git-path";
|
||||
describe("getGitPath", () => {
|
||||
const conversationId = "abc123";
|
||||
|
||||
it("should return /workspace/project/{conversationId} when no repository is selected", () => {
|
||||
expect(getGitPath(conversationId, null)).toBe(`/workspace/project/${conversationId}`);
|
||||
expect(getGitPath(conversationId, undefined)).toBe(`/workspace/project/${conversationId}`);
|
||||
describe("without sandbox grouping (NO_GROUPING)", () => {
|
||||
it("should return /workspace/project when no repository is selected", () => {
|
||||
expect(getGitPath(conversationId, null, false)).toBe("/workspace/project");
|
||||
expect(getGitPath(conversationId, undefined, false)).toBe(
|
||||
"/workspace/project",
|
||||
);
|
||||
});
|
||||
|
||||
it("should handle standard owner/repo format (GitHub)", () => {
|
||||
expect(getGitPath(conversationId, "OpenHands/OpenHands", false)).toBe(
|
||||
"/workspace/project/OpenHands",
|
||||
);
|
||||
expect(getGitPath(conversationId, "facebook/react", false)).toBe(
|
||||
"/workspace/project/react",
|
||||
);
|
||||
});
|
||||
|
||||
it("should handle nested group paths (GitLab)", () => {
|
||||
expect(
|
||||
getGitPath(conversationId, "modernhealth/frontend-guild/pan", false),
|
||||
).toBe("/workspace/project/pan");
|
||||
expect(getGitPath(conversationId, "group/subgroup/repo", false)).toBe(
|
||||
"/workspace/project/repo",
|
||||
);
|
||||
expect(getGitPath(conversationId, "a/b/c/d/repo", false)).toBe(
|
||||
"/workspace/project/repo",
|
||||
);
|
||||
});
|
||||
|
||||
it("should handle single segment paths", () => {
|
||||
expect(getGitPath(conversationId, "repo", false)).toBe(
|
||||
"/workspace/project/repo",
|
||||
);
|
||||
});
|
||||
|
||||
it("should handle empty string", () => {
|
||||
expect(getGitPath(conversationId, "", false)).toBe("/workspace/project");
|
||||
});
|
||||
});
|
||||
|
||||
it("should handle standard owner/repo format (GitHub)", () => {
|
||||
expect(getGitPath(conversationId, "OpenHands/OpenHands")).toBe(`/workspace/project/${conversationId}/OpenHands`);
|
||||
expect(getGitPath(conversationId, "facebook/react")).toBe(`/workspace/project/${conversationId}/react`);
|
||||
describe("with sandbox grouping enabled", () => {
|
||||
it("should return /workspace/project/{conversationId} when no repository is selected", () => {
|
||||
expect(getGitPath(conversationId, null, true)).toBe(
|
||||
`/workspace/project/${conversationId}`,
|
||||
);
|
||||
expect(getGitPath(conversationId, undefined, true)).toBe(
|
||||
`/workspace/project/${conversationId}`,
|
||||
);
|
||||
});
|
||||
|
||||
it("should handle standard owner/repo format (GitHub)", () => {
|
||||
expect(getGitPath(conversationId, "OpenHands/OpenHands", true)).toBe(
|
||||
`/workspace/project/${conversationId}/OpenHands`,
|
||||
);
|
||||
expect(getGitPath(conversationId, "facebook/react", true)).toBe(
|
||||
`/workspace/project/${conversationId}/react`,
|
||||
);
|
||||
});
|
||||
|
||||
it("should handle nested group paths (GitLab)", () => {
|
||||
expect(
|
||||
getGitPath(conversationId, "modernhealth/frontend-guild/pan", true),
|
||||
).toBe(`/workspace/project/${conversationId}/pan`);
|
||||
expect(getGitPath(conversationId, "group/subgroup/repo", true)).toBe(
|
||||
`/workspace/project/${conversationId}/repo`,
|
||||
);
|
||||
expect(getGitPath(conversationId, "a/b/c/d/repo", true)).toBe(
|
||||
`/workspace/project/${conversationId}/repo`,
|
||||
);
|
||||
});
|
||||
|
||||
it("should handle single segment paths", () => {
|
||||
expect(getGitPath(conversationId, "repo", true)).toBe(
|
||||
`/workspace/project/${conversationId}/repo`,
|
||||
);
|
||||
});
|
||||
|
||||
it("should handle empty string", () => {
|
||||
expect(getGitPath(conversationId, "", true)).toBe(
|
||||
`/workspace/project/${conversationId}`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it("should handle nested group paths (GitLab)", () => {
|
||||
expect(getGitPath(conversationId, "modernhealth/frontend-guild/pan")).toBe(`/workspace/project/${conversationId}/pan`);
|
||||
expect(getGitPath(conversationId, "group/subgroup/repo")).toBe(`/workspace/project/${conversationId}/repo`);
|
||||
expect(getGitPath(conversationId, "a/b/c/d/repo")).toBe(`/workspace/project/${conversationId}/repo`);
|
||||
});
|
||||
|
||||
it("should handle single segment paths", () => {
|
||||
expect(getGitPath(conversationId, "repo")).toBe(`/workspace/project/${conversationId}/repo`);
|
||||
});
|
||||
|
||||
it("should handle empty string", () => {
|
||||
expect(getGitPath(conversationId, "")).toBe(`/workspace/project/${conversationId}`);
|
||||
describe("default behavior (useSandboxGrouping defaults to false)", () => {
|
||||
it("should default to no sandbox grouping", () => {
|
||||
expect(getGitPath(conversationId, null)).toBe("/workspace/project");
|
||||
expect(getGitPath(conversationId, "owner/repo")).toBe(
|
||||
"/workspace/project/repo",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ import V1GitService from "#/api/git-service/v1-git-service.api";
|
||||
import { useConversationId } from "#/hooks/use-conversation-id";
|
||||
import { useActiveConversation } from "#/hooks/query/use-active-conversation";
|
||||
import { useRuntimeIsReady } from "#/hooks/use-runtime-is-ready";
|
||||
import { useSettings } from "#/hooks/query/use-settings";
|
||||
import { getGitPath } from "#/utils/get-git-path";
|
||||
import type { GitChange } from "#/api/open-hands.types";
|
||||
|
||||
@@ -16,6 +17,7 @@ import type { GitChange } from "#/api/open-hands.types";
|
||||
export const useUnifiedGetGitChanges = () => {
|
||||
const { conversationId } = useConversationId();
|
||||
const { data: conversation } = useActiveConversation();
|
||||
const { data: settings } = useSettings();
|
||||
const [orderedChanges, setOrderedChanges] = React.useState<GitChange[]>([]);
|
||||
const previousDataRef = React.useRef<GitChange[] | null>(null);
|
||||
const runtimeIsReady = useRuntimeIsReady();
|
||||
@@ -25,10 +27,15 @@ export const useUnifiedGetGitChanges = () => {
|
||||
const sessionApiKey = conversation?.session_api_key;
|
||||
const selectedRepository = conversation?.selected_repository;
|
||||
|
||||
// Calculate git path based on selected repository
|
||||
// Sandbox grouping is enabled when strategy is not NO_GROUPING
|
||||
const useSandboxGrouping =
|
||||
settings?.sandbox_grouping_strategy !== "NO_GROUPING" &&
|
||||
settings?.sandbox_grouping_strategy !== undefined;
|
||||
|
||||
// Calculate git path based on selected repository and sandbox grouping strategy
|
||||
const gitPath = React.useMemo(
|
||||
() => getGitPath(conversationId, selectedRepository),
|
||||
[selectedRepository],
|
||||
() => getGitPath(conversationId, selectedRepository, useSandboxGrouping),
|
||||
[conversationId, selectedRepository, useSandboxGrouping],
|
||||
);
|
||||
|
||||
const result = useQuery({
|
||||
|
||||
@@ -4,6 +4,7 @@ import GitService from "#/api/git-service/git-service.api";
|
||||
import V1GitService from "#/api/git-service/v1-git-service.api";
|
||||
import { useConversationId } from "#/hooks/use-conversation-id";
|
||||
import { useActiveConversation } from "#/hooks/query/use-active-conversation";
|
||||
import { useSettings } from "#/hooks/query/use-settings";
|
||||
import { getGitPath } from "#/utils/get-git-path";
|
||||
import type { GitChangeStatus } from "#/api/open-hands.types";
|
||||
|
||||
@@ -21,20 +22,36 @@ type UseUnifiedGitDiffConfig = {
|
||||
export const useUnifiedGitDiff = (config: UseUnifiedGitDiffConfig) => {
|
||||
const { conversationId } = useConversationId();
|
||||
const { data: conversation } = useActiveConversation();
|
||||
const { data: settings } = useSettings();
|
||||
|
||||
const isV1Conversation = conversation?.conversation_version === "V1";
|
||||
const conversationUrl = conversation?.url;
|
||||
const sessionApiKey = conversation?.session_api_key;
|
||||
const selectedRepository = conversation?.selected_repository;
|
||||
|
||||
// Sandbox grouping is enabled when strategy is not NO_GROUPING
|
||||
const useSandboxGrouping =
|
||||
settings?.sandbox_grouping_strategy !== "NO_GROUPING" &&
|
||||
settings?.sandbox_grouping_strategy !== undefined;
|
||||
|
||||
// For V1, we need to convert the relative file path to an absolute path
|
||||
// The diff endpoint expects: /workspace/project/RepoName/relative/path
|
||||
const absoluteFilePath = React.useMemo(() => {
|
||||
if (!isV1Conversation) return config.filePath;
|
||||
|
||||
const gitPath = getGitPath(conversationId, selectedRepository);
|
||||
const gitPath = getGitPath(
|
||||
conversationId,
|
||||
selectedRepository,
|
||||
useSandboxGrouping,
|
||||
);
|
||||
return `${gitPath}/${config.filePath}`;
|
||||
}, [isV1Conversation, selectedRepository, config.filePath]);
|
||||
}, [
|
||||
isV1Conversation,
|
||||
conversationId,
|
||||
selectedRepository,
|
||||
useSandboxGrouping,
|
||||
config.filePath,
|
||||
]);
|
||||
|
||||
return useQuery({
|
||||
queryKey: [
|
||||
|
||||
@@ -1,17 +1,29 @@
|
||||
/**
|
||||
* Get the git repository path for a conversation
|
||||
* If a repository is selected, returns /workspace/project/{repo-name}
|
||||
* Otherwise, returns /workspace/project
|
||||
*
|
||||
* When sandbox grouping is enabled (strategy != NO_GROUPING), each conversation
|
||||
* gets its own subdirectory: /workspace/project/{conversationId}[/{repoName}]
|
||||
*
|
||||
* When sandbox grouping is disabled (NO_GROUPING), the path is simply:
|
||||
* /workspace/project[/{repoName}]
|
||||
*
|
||||
* @param conversationId The conversation ID
|
||||
* @param selectedRepository The selected repository (e.g., "OpenHands/OpenHands", "owner/repo", or "group/subgroup/repo")
|
||||
* @param useSandboxGrouping Whether sandbox grouping is enabled (strategy != NO_GROUPING)
|
||||
* @returns The git path to use
|
||||
*/
|
||||
export function getGitPath(
|
||||
conversationId: string,
|
||||
selectedRepository: string | null | undefined,
|
||||
useSandboxGrouping: boolean = false,
|
||||
): string {
|
||||
// Base path depends on sandbox grouping strategy
|
||||
const basePath = useSandboxGrouping
|
||||
? `/workspace/project/${conversationId}`
|
||||
: "/workspace/project";
|
||||
|
||||
if (!selectedRepository) {
|
||||
return `/workspace/project/${conversationId}`;
|
||||
return basePath;
|
||||
}
|
||||
|
||||
// Extract the repository name from the path
|
||||
@@ -19,5 +31,5 @@ export function getGitPath(
|
||||
const parts = selectedRepository.split("/");
|
||||
const repoName = parts[parts.length - 1];
|
||||
|
||||
return `/workspace/project/${conversationId}/${repoName}`;
|
||||
return `${basePath}/${repoName}`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user