branch handling

This commit is contained in:
bkellam 2025-11-19 18:35:03 -08:00
parent 898c9097db
commit 696d06beeb
7 changed files with 33 additions and 20 deletions

View file

@ -233,7 +233,7 @@ export const PathHeader = ({
}}
>
<span className="mr-0.5">@</span>
{`${branchDisplayName}`}
{`${branchDisplayName.replace(/^refs\/(heads|tags)\//, '')}`}
</p>
)}
<span>·</span>

View file

@ -12,6 +12,7 @@ import {
import { Separator } from "@/components/ui/separator";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { RepositoryInfo, SearchResultFile, SearchStats } from "@/features/search/types";
import useCaptureEvent from "@/hooks/useCaptureEvent";
import { useDomain } from "@/hooks/useDomain";
import { useNonEmptyQueryParam } from "@/hooks/useNonEmptyQueryParam";
import { useSearchHistory } from "@/hooks/useSearchHistory";
@ -32,7 +33,6 @@ import { CodePreviewPanel } from "./codePreviewPanel";
import { FilterPanel } from "./filterPanel";
import { useFilteredMatches } from "./filterPanel/useFilterMatches";
import { SearchResultsPanel, SearchResultsPanelHandle } from "./searchResultsPanel";
import useCaptureEvent from "@/hooks/useCaptureEvent";
interface SearchResultsPageProps {
searchQuery: string;
@ -156,6 +156,13 @@ export const SearchResultsPage = ({
router.push(url);
}, [maxMatchCount, router, searchQuery, domain]);
// Look for any files that are not on the default branch.
const isBranchFilteringEnabled = useMemo(() => {
return files.some((file) => {
return file.branches?.some((branch) => branch !== 'HEAD') ?? false;
});
}, [files]);
return (
<div className="flex flex-col h-screen overflow-clip">
{/* TopBar */}
@ -189,8 +196,7 @@ export const SearchResultsPage = ({
isStreaming={isStreaming}
searchStats={stats}
isMoreResultsButtonVisible={!isExhaustive}
// @todo: handle branch filtering
isBranchFilteringEnabled={false}
isBranchFilteringEnabled={isBranchFilteringEnabled}
/>
)}
</div>

View file

@ -75,7 +75,7 @@ export const FileMatchContainer = ({
}
return `${branches[0]}${branches.length > 1 ? ` +${branches.length - 1}` : ''}`;
}, [isBranchFilteringEnabled, branches]);
}, [branches, isBranchFilteringEnabled]);
const repo = useMemo(() => {
return repoInfo[file.repositoryId];

View file

@ -88,7 +88,7 @@ export const SearchResultsPanel = forwardRef<SearchResultsPanelHandle, SearchRes
const resetScroll = useCallback(() => {
virtualizer.scrollToIndex(0);
}, [fileMatches.length, virtualizer]);
}, [virtualizer]);
// Expose the resetScroll function to parent components
useImperativeHandle(ref, () => ({
@ -121,7 +121,7 @@ export const SearchResultsPanel = forwardRef<SearchResultsPanelHandle, SearchRes
align: 'start'
});
}
}, [showAllMatchesMap, virtualizer]);
}, [showAllMatchesActions, showAllMatchesMap, virtualizer]);
return (

View file

@ -33,7 +33,6 @@ const isCacheValid = (entry: CacheEntry): boolean => {
};
export const useStreamedSearch = ({ query, matches, contextLines, whole, isRegexEnabled, isCaseSensitivityEnabled }: SearchRequest) => {
const [state, setState] = useState<{
isStreaming: boolean,
isExhaustive: boolean,

View file

@ -61,7 +61,6 @@ export const transformLezerTreeToZoektGrpcQuery = async ({
isRegexEnabled: boolean;
onExpandSearchContext: (contextName: string) => Promise<string[]>;
}): Promise<ZoektGrpcQuery> => {
const transformNode = async (node: SyntaxNode): Promise<ZoektGrpcQuery> => {
switch (node.type.id) {
case Program: {
@ -336,12 +335,8 @@ const getChildren = (node: SyntaxNode): SyntaxNode[] => {
const children: SyntaxNode[] = [];
let child = node.firstChild;
while (child) {
// Skip certain node types that are just structural
if (!["(", ")", "or"].includes(child.type.name)) {
children.push(child);
}
children.push(child);
child = child.nextSibling;
}
return children;
}

View file

@ -18,6 +18,7 @@ import path from 'path';
import { parseQueryIntoLezerTree, transformLezerTreeToZoektGrpcQuery } from './query';
import { RepositoryInfo, SearchRequest, SearchResponse, SearchResultFile, SearchStats, SourceRange, StreamedSearchResponse } from "./types";
import { FlushReason as ZoektFlushReason } from "@/proto/zoekt/webserver/v1/FlushReason";
import { RevisionExpr } from "@sourcebot/query-language";
const logger = createLogger("searchApi");
@ -454,18 +455,30 @@ const createZoektSearchRequest = async ({
},
});
// Find if there are any `rev:` filters in the query.
let containsRevExpression = false;
tree.iterate({
enter: (node) => {
if (node.type.id === RevisionExpr) {
containsRevExpression = true;
// false to stop the iteration.
return false;
}
}
});
const zoektSearchRequest: ZoektGrpcSearchRequest = {
query: {
and: {
children: [
zoektQuery,
// @todo: handle branch filtering.
{
// If the query does not contain a `rev:` filter, we default to searching `HEAD`.
...(!containsRevExpression ? [{
branch: {
pattern: 'HEAD',
exact: true,
}
}
}] : []),
]
}
},