Skip to content

Commit ac02641

Browse files
committed
Aligns git vs github search query parsing
1 parent f12d66d commit ac02641

File tree

6 files changed

+131
-121
lines changed

6 files changed

+131
-121
lines changed

src/env/node/git/sub-providers/commits.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ import {
4141
} from '../../../../git/parsers/logParser';
4242
import { parseGitRefLog, parseGitRefLogDefaultFormat } from '../../../../git/parsers/reflogParser';
4343
import type { SearchQueryFilters } from '../../../../git/search';
44-
import { parseSearchQueryCommand } from '../../../../git/search';
44+
import { parseSearchQueryGitCommand } from '../../../../git/search';
4545
import { processNaturalLanguageToSearchQuery } from '../../../../git/search.naturalLanguage';
4646
import { createUncommittedChangesCommit } from '../../../../git/utils/-webview/commit.utils';
4747
import { isRevisionRange, isSha, isUncommitted, isUncommittedStaged } from '../../../../git/utils/revision.utils';
@@ -1047,7 +1047,7 @@ export class CommitsGitSubProvider implements GitCommitsSubProvider {
10471047
'--use-mailmap',
10481048
];
10491049

1050-
const { args: searchArgs, files, shas, filters } = parseSearchQueryCommand(search, currentUser);
1050+
const { args: searchArgs, files, shas, filters } = parseSearchQueryGitCommand(search, currentUser);
10511051

10521052
let stashes: Map<string, GitStashCommit> | undefined;
10531053
let stdin: string | undefined;

src/env/node/git/sub-providers/graph.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import {
2929
getShaLogParser,
3030
} from '../../../../git/parsers/logParser';
3131
import type { GitGraphSearch, GitGraphSearchResultData, GitGraphSearchResults } from '../../../../git/search';
32-
import { getSearchQueryComparisonKey, parseSearchQueryCommand } from '../../../../git/search';
32+
import { getSearchQueryComparisonKey, parseSearchQueryGitCommand } from '../../../../git/search';
3333
import { isBranchStarred } from '../../../../git/utils/-webview/branch.utils';
3434
import { getRemoteIconUri } from '../../../../git/utils/-webview/icons';
3535
import { groupWorktreesByBranch } from '../../../../git/utils/-webview/worktree.utils';
@@ -643,7 +643,7 @@ export class GraphGitSubProvider implements GitGraphSubProvider {
643643
? await this.provider.config.getCurrentUser(repoPath)
644644
: undefined;
645645

646-
const { args: searchArgs, files, shas, filters } = parseSearchQueryCommand(search, currentUser);
646+
const { args: searchArgs, files, shas, filters } = parseSearchQueryGitCommand(search, currentUser);
647647

648648
const tipsOnly = filters.type === 'tip';
649649
const parser = getShaAndDatesLogParser(tipsOnly);

src/git/search.ts

Lines changed: 111 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@ import type { GitUser } from './models/user';
77
import { isSha, shortenRevision } from './utils/revision.utils';
88

99
export interface GitGraphSearchResultData {
10-
date: number;
11-
i: number;
10+
readonly date: number;
11+
readonly i: number;
1212
}
1313
export type GitGraphSearchResults = Map<string, GitGraphSearchResultData>;
1414

1515
export interface GitGraphSearch {
16-
repoPath: string;
17-
query: SearchQuery;
18-
comparisonKey: string;
19-
results: GitGraphSearchResults;
16+
readonly repoPath: string;
17+
readonly query: SearchQuery;
18+
readonly comparisonKey: string;
19+
readonly results: GitGraphSearchResults;
2020

2121
readonly paging?: {
2222
readonly limit: number | undefined;
@@ -203,7 +203,7 @@ export interface SearchQueryFilters {
203203
refs: boolean;
204204
}
205205

206-
export interface SearchQueryCommand {
206+
export interface SearchQueryGitCommand {
207207
/** Git log args */
208208
args: string[];
209209
/** Pathspecs to search, if any */
@@ -212,19 +212,19 @@ export interface SearchQueryCommand {
212212
shas?: Set<string> | undefined;
213213

214214
filters: SearchQueryFilters;
215+
operations: Map<SearchOperatorsLongForm, Set<string>>;
215216
}
216217

217-
export function parseSearchQueryCommand(search: SearchQuery, currentUser: GitUser | undefined): SearchQueryCommand {
218+
export function parseSearchQueryGitCommand(
219+
search: SearchQuery,
220+
currentUser: GitUser | undefined,
221+
): SearchQueryGitCommand {
218222
const { operations } = parseSearchQuery(search);
219223

220224
const searchArgs = new Set<string>();
221225
const files: string[] = [];
222226
let shas;
223-
const filters: SearchQueryFilters = {
224-
files: false,
225-
type: undefined,
226-
refs: false,
227-
};
227+
const filters: SearchQueryFilters = { files: false, type: undefined, refs: false };
228228

229229
let op;
230230
let values = operations.get('commit:');
@@ -404,5 +404,103 @@ export function parseSearchQueryCommand(search: SearchQuery, currentUser: GitUse
404404
files: files,
405405
shas: shas,
406406
filters: filters,
407+
operations: operations,
407408
};
408409
}
410+
411+
export interface SearchQueryGitHubCommand {
412+
/** Query args */
413+
args: string[];
414+
415+
filters: SearchQueryFilters;
416+
operations: Map<SearchOperatorsLongForm, Set<string>>;
417+
}
418+
419+
export function parseSearchQueryGitHubCommand(
420+
search: SearchQuery,
421+
currentUser: GitUser | undefined,
422+
): SearchQueryGitHubCommand {
423+
const { operations } = parseSearchQuery(search);
424+
425+
const queryArgs = [];
426+
const filters: SearchQueryFilters = { files: false, type: undefined, refs: false };
427+
428+
for (const [op, values] of operations.entries()) {
429+
switch (op) {
430+
case 'message:':
431+
for (let value of values) {
432+
if (!value) continue;
433+
434+
if (value.startsWith('"') && value.endsWith('"')) {
435+
value = value.slice(1, -1);
436+
if (!value) continue;
437+
}
438+
439+
if (search.matchWholeWord && search.matchRegex) {
440+
value = `\\b${value}\\b`;
441+
}
442+
443+
queryArgs.push(value.replace(/ /g, '+'));
444+
}
445+
break;
446+
447+
case 'author:': {
448+
for (let value of values) {
449+
if (!value) continue;
450+
451+
if (value.startsWith('"') && value.endsWith('"')) {
452+
value = value.slice(1, -1);
453+
if (!value) continue;
454+
}
455+
456+
if (value === '@me') {
457+
if (!currentUser?.name) continue;
458+
459+
value = `@${currentUser.username}`;
460+
}
461+
462+
value = value.replace(/ /g, '+');
463+
if (value.startsWith('@')) {
464+
value = value.slice(1);
465+
queryArgs.push(`author:${value.slice(1)}`);
466+
} else if (value.includes('@')) {
467+
queryArgs.push(`author-email:${value}`);
468+
} else {
469+
queryArgs.push(`author-name:${value}`);
470+
}
471+
}
472+
473+
break;
474+
}
475+
476+
case 'type:':
477+
case 'file:':
478+
case 'change:':
479+
case 'ref:':
480+
// Not supported in GitHub search
481+
break;
482+
483+
case 'after:':
484+
case 'before:': {
485+
const flag = op === 'after:' ? 'author-date:>' : 'author-date:<';
486+
487+
for (let value of values) {
488+
if (!value) continue;
489+
490+
if (value.startsWith('"') && value.endsWith('"')) {
491+
value = value.slice(1, -1);
492+
if (!value) continue;
493+
}
494+
495+
// if value is YYYY-MM-DD then include it, otherwise we can't use it
496+
if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
497+
queryArgs.push(`${flag}${value}`);
498+
}
499+
}
500+
break;
501+
}
502+
}
503+
}
504+
505+
return { args: queryArgs, filters: filters, operations: operations };
506+
}

src/plus/integrations/providers/github/sub-providers/commits.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { CancellationToken, Uri } from 'vscode';
33
import type { SearchQuery } from '../../../../../constants.search';
44
import type { Source } from '../../../../../constants.telemetry';
55
import type { Container } from '../../../../../container';
6+
import { CancellationError } from '../../../../../errors';
67
import type { GitCache } from '../../../../../git/cache';
78
import type {
89
GitCommitsSubProvider,
@@ -22,7 +23,7 @@ import type { GitLog } from '../../../../../git/models/log';
2223
import type { GitRevisionRange } from '../../../../../git/models/revision';
2324
import { deletedOrMissing } from '../../../../../git/models/revision';
2425
import type { GitUser } from '../../../../../git/models/user';
25-
import { parseSearchQuery } from '../../../../../git/search';
26+
import { parseSearchQueryGitHubCommand } from '../../../../../git/search';
2627
import { processNaturalLanguageToSearchQuery } from '../../../../../git/search.naturalLanguage';
2728
import { createUncommittedChangesCommit } from '../../../../../git/utils/-webview/commit.utils';
2829
import { createRevisionRange, isUncommitted } from '../../../../../git/utils/revision.utils';
@@ -36,7 +37,6 @@ import { GitDocumentState } from '../../../../../trackers/trackedDocument';
3637
import type { GitHubGitProviderInternal } from '../githubGitProvider';
3738
import { stripOrigin } from '../githubGitProvider';
3839
import { fromCommitFileStatus } from '../models';
39-
import { getQueryArgsFromSearchQuery } from '../utils/-webview/search.utils';
4040

4141
const emptyPromise: Promise<GitBlame | ParsedGitDiffHunks | GitLog | undefined> = Promise.resolve(undefined);
4242

@@ -902,7 +902,7 @@ export class CommitsGitSubProvider implements GitCommitsSubProvider {
902902
search: SearchQuery,
903903
source: Source,
904904
options?: GitSearchCommitsOptions,
905-
_cancellation?: CancellationToken,
905+
cancellation?: CancellationToken,
906906
): Promise<SearchCommitsResult> {
907907
if (repoPath == null) return { search: search, log: undefined };
908908

@@ -916,7 +916,12 @@ export class CommitsGitSubProvider implements GitCommitsSubProvider {
916916
search = await processNaturalLanguageToSearchQuery(this.container, search, source);
917917
}
918918

919-
const { operations } = parseSearchQuery(search);
919+
const currentUser = search.query.includes('@me')
920+
? await this.provider.config.getCurrentUser(repoPath)
921+
: undefined;
922+
if (cancellation?.isCancellationRequested) throw new CancellationError();
923+
924+
const { args: queryArgs, operations } = parseSearchQueryGitHubCommand(search, currentUser);
920925

921926
const values = operations.get('commit:');
922927
if (values?.size) {
@@ -936,7 +941,6 @@ export class CommitsGitSubProvider implements GitCommitsSubProvider {
936941
};
937942
}
938943

939-
const queryArgs = await getQueryArgsFromSearchQuery(this.provider, search, operations, repoPath);
940944
if (!queryArgs.length) return { search: search, log: undefined };
941945

942946
const limit = this.provider.getPagingLimit(options?.limit);

src/plus/integrations/providers/github/sub-providers/graph.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import type { GitRemote } from '../../../../../git/models/remote';
2121
import type { GitUser } from '../../../../../git/models/user';
2222
import type { GitWorktree } from '../../../../../git/models/worktree';
2323
import type { GitGraphSearch, GitGraphSearchResultData, GitGraphSearchResults } from '../../../../../git/search';
24-
import { getSearchQueryComparisonKey, parseSearchQuery } from '../../../../../git/search';
24+
import { getSearchQueryComparisonKey, parseSearchQueryGitHubCommand } from '../../../../../git/search';
2525
import { isBranchStarred } from '../../../../../git/utils/-webview/branch.utils';
2626
import { getRemoteIconUri } from '../../../../../git/utils/-webview/icons';
2727
import { getBranchId, getBranchNameWithoutRemote } from '../../../../../git/utils/branch.utils';
@@ -41,7 +41,6 @@ import type {
4141
GraphTagContextValue,
4242
} from '../../../../../webviews/plus/graph/protocol';
4343
import type { GitHubGitProviderInternal } from '../githubGitProvider';
44-
import { getQueryArgsFromSearchQuery } from '../utils/-webview/search.utils';
4544

4645
const doubleQuoteRegex = /"/g;
4746

@@ -514,8 +513,12 @@ export class GraphGitSubProvider implements GitGraphSubProvider {
514513
const comparisonKey = getSearchQueryComparisonKey(search);
515514

516515
try {
516+
const currentUser = search.query.includes('@me')
517+
? await this.provider.config.getCurrentUser(repoPath)
518+
: undefined;
519+
517520
const results: GitGraphSearchResults = new Map<string, GitGraphSearchResultData>();
518-
const { operations } = parseSearchQuery(search);
521+
const { args: queryArgs, operations } = parseSearchQueryGitHubCommand(search, currentUser);
519522

520523
const values = operations.get('commit:');
521524
if (values != null) {
@@ -542,8 +545,7 @@ export class GraphGitSubProvider implements GitGraphSubProvider {
542545
};
543546
}
544547

545-
const queryArgs = await getQueryArgsFromSearchQuery(this.provider, search, operations, repoPath);
546-
if (queryArgs.length === 0) {
548+
if (!queryArgs.length) {
547549
return {
548550
repoPath: repoPath,
549551
query: search,

src/plus/integrations/providers/github/utils/-webview/search.utils.ts

Lines changed: 0 additions & 94 deletions
This file was deleted.

0 commit comments

Comments
 (0)