fix(git): exit nested-repo states once resolution succeeds

NestedRepoResolutionStates had no success exit: on a non-repo root
rootIsGitRepo stays false forever, so once repositories were found the
pull-request and walkthrough tabs kept showing 'Checking repository'
even after the selected repository probed as a repository. GitView never
hit this because its call site sits inside its own isGitRepo === false
branch. The component now takes the operating directory's probe and
returns null when it resolves true.

DiffView also still keyed its not-a-repository gate and every diff
fetch off the raw project root, so opening a change from a nested
repository showed 'This directory is not a Git repository'. It now
resolves the nested repository for git data and diff operations while
session-scoped lookups (session messages, review-flow directory) stay
on the root.
This commit is contained in:
jaygupta17
2026-08-25 19:55:00 +05:30
parent cda273d69f
commit e26b55e067
6 changed files with 23 additions and 5 deletions
@@ -487,6 +487,7 @@ export const MobileChangesSurface: React.FC<MobileChangesSurfaceProps> = ({ onCl
return renderListState(
<NestedRepoResolutionStates
rootIsGitRepo={rootIsGitRepo}
resolvedIsGitRepo={isGitRepo}
nestedRepos={nestedRepos}
onRetryDiscovery={() => {
if (rootDirectory) void ensureNestedRepos(rootDirectory, { force: true });
@@ -2,6 +2,7 @@ import React from 'react';
import { useUIStore } from '@/stores/useUIStore';
import { useEffectiveDirectory } from '@/hooks/useEffectiveDirectory';
import { useNestedGitDirectory } from '@/hooks/useNestedGitDirectory';
import { useGitStore, useGitStatus, useIsGitRepo, useGitLoadingStatus } from '@/stores/useGitStore';
import { useGitBaseBranchStore, gitBaseBranchEntryKey } from '@/stores/useGitBaseBranchStore';
import { coerceDiffScope, branchRangeKey, isBranchScopeAvailable, isBranchScopeDefinitelyUnavailable, useRangeKeyedCache, useBoundedDirectoryRetry } from './branchDiffScope';
@@ -997,7 +998,11 @@ export const DiffView: React.FC<DiffViewProps> = ({
}) => {
const { t } = useI18n();
const { git, files } = useRuntimeAPIs();
const effectiveDirectory = useEffectiveDirectory();
const rootDirectory = useEffectiveDirectory();
// Diffs belong to the repository being diffed: when the root is not
// itself a repository, operate on the resolved nested repository instead.
const { gitDirectory: nestedGitDirectory } = useNestedGitDirectory(rootDirectory ?? null);
const effectiveDirectory = nestedGitDirectory ?? rootDirectory;
const openContextSurface = useUIStore((state) => state.openContextSurface);
const requestWalkthroughSource = useWalkthroughStore((state) => state.requestSource);
const { screenWidth, isMobile } = useDeviceInfo();
@@ -1038,7 +1043,7 @@ export const DiffView: React.FC<DiffViewProps> = ({
const setDiffWrapLines = useUIStore((state) => state.setDiffWrapLines);
const openContextFileAtLine = useUIStore((state) => state.openContextFileAtLine);
const currentSessionId = useSessionUIStore((state) => state.currentSessionId);
const sessionMessages = useSessionMessages(currentSessionId ?? '', effectiveDirectory ?? undefined);
const sessionMessages = useSessionMessages(currentSessionId ?? '', rootDirectory ?? undefined);
const diffWrapLines = diffWrapLinesStore;
const forcedStaged = activeDiffScope === 'staged' ? true : activeDiffScope === 'working' ? false : null;
const activeDiffStaged = forcedStaged ?? displayFileStaged;
@@ -1645,7 +1650,7 @@ export const DiffView: React.FC<DiffViewProps> = ({
const handleStartReviewFlow = React.useCallback(async (execution: ReviewFlowExecution) => {
if (!currentSessionId) return;
const directory = useSessionUIStore.getState().getDirectoryForSession(currentSessionId) || effectiveDirectory || '';
const directory = useSessionUIStore.getState().getDirectoryForSession(currentSessionId) || rootDirectory || '';
if (!directory) {
toast.error(t('diffView.reviewDialog.toast.noSessionDirectory'));
return;
@@ -2343,6 +2343,7 @@ export const GitView: React.FC<GitViewProps> = ({ isActive }) => {
return (
<NestedRepoResolutionStates
rootIsGitRepo={rootIsGitRepo}
resolvedIsGitRepo={isGitRepo}
nestedRepos={nestedRepos}
onRetryDiscovery={() => {
if (currentDirectory) {
@@ -265,6 +265,7 @@ export const PullRequestView: React.FC = () => {
return (
<NestedRepoResolutionStates
rootIsGitRepo={rootIsGitRepo}
resolvedIsGitRepo={isGitRepo}
nestedRepos={nestedRepos}
onRetryDiscovery={() => {
void ensureNestedRepos(currentDirectory, { force: true });
@@ -8,6 +8,12 @@ import type { NestedRepoDiscovery } from '@/stores/useGitStore';
type NestedRepoResolutionStatesProps = {
/** Probe of the project root: `false` means nested resolution applies. */
rootIsGitRepo: boolean | null;
/**
* Probe of the directory the consumer operates on (root or selected nested
* repository). `true` means resolution succeeded and the consumer should
* render its own content.
*/
resolvedIsGitRepo: boolean | null;
/** Discovery outcome for the root (`undefined` = not run yet). */
nestedRepos: NestedRepoDiscovery | undefined;
onRetryDiscovery: () => void;
@@ -17,8 +23,9 @@ type NestedRepoResolutionStatesProps = {
/**
* Shared empty/loading states for git surfaces while nested-repository
* resolution is pending, failed, or impossible. Renders null once
* repositories are resolved so the consumer can proceed into its own content.
* resolution is pending, failed, or impossible. Renders null once resolution
* has finished — either the root is a repository or the operating directory
* probed as one — so the consumer can proceed into its own content.
*
* A runtime without the discovery route (VS Code) reports "unsupported": the
* honest state there is the plain not-a-repository empty state, without a
@@ -26,6 +33,7 @@ type NestedRepoResolutionStatesProps = {
*/
export const NestedRepoResolutionStates: React.FC<NestedRepoResolutionStatesProps> = ({
rootIsGitRepo,
resolvedIsGitRepo,
nestedRepos,
onRetryDiscovery,
emptyStateFooter,
@@ -33,6 +41,7 @@ export const NestedRepoResolutionStates: React.FC<NestedRepoResolutionStatesProp
const { t } = useI18n();
if (rootIsGitRepo !== false) return null;
if (resolvedIsGitRepo === true) return null;
if (nestedRepos === undefined || nestedRepos === null) {
return (
@@ -498,6 +498,7 @@ export const WalkthroughView = ({ directory: rootDirectory }: WalkthroughViewPro
return (
<NestedRepoResolutionStates
rootIsGitRepo={rootIsGitRepo}
resolvedIsGitRepo={isGitRepo}
nestedRepos={nestedRepos}
onRetryDiscovery={() => {
if (rootDirectory) void ensureNestedRepos(rootDirectory, { force: true });