|
|
@ -1,10 +1,18 @@ |
|
|
|
'use strict'; |
|
|
|
import { commands, Disposable, TerminalLink, TerminalLinkContext, TerminalLinkProvider, window } from 'vscode'; |
|
|
|
import { Commands, ShowQuickBranchHistoryCommandArgs, ShowQuickCommitCommandArgs } from '../commands'; |
|
|
|
import { |
|
|
|
Commands, |
|
|
|
GitCommandsCommandArgs, |
|
|
|
ShowQuickBranchHistoryCommandArgs, |
|
|
|
ShowQuickCommitCommandArgs, |
|
|
|
} from '../commands'; |
|
|
|
import { Container } from '../container'; |
|
|
|
import { GitReference } from '../git/git'; |
|
|
|
|
|
|
|
const commandsRegexShared = /\b(g(?:it)?\b\s*)\b(branch|checkout|cherry-pick|fetch|grep|log|merge|pull|push|rebase|reset|revert|show|stash|status|tag)\b/gi; |
|
|
|
const refRegexShared = /\b((?!\/)(?!\S*\/\/)(?!\S*@\{)(?!@$)(?!\S*\\)[^\000-\037\177 ~^:?*[]+(?<!\.lock)(?<!\/)(?<!\.))\b/gi; |
|
|
|
const rangeRegex = /^[0-9a-f]{7,40}\.\.\.?[0-9a-f]{7,40}$/; |
|
|
|
const shaRegex = /^[0-9a-f]{7,40}$/; |
|
|
|
const refRegex = /\b((?!\S*\/\.)(?!\S*\.\.)(?!\/)(?!\S*\/\/)(?!\S*@\{)(?!@$)(?!\S*\\)[^\000-\037\177 ~^:?*[]+(?<!\.lock)(?<!\/)(?<!\.))\b/gi; |
|
|
|
|
|
|
|
interface GitTerminalLink<T = object> extends TerminalLink { |
|
|
|
command: { |
|
|
@ -35,11 +43,30 @@ export class GitTerminalLinkProvider implements Disposable, TerminalLinkProvider |
|
|
|
const branchesAndTags = await Container.git.getBranchesAndOrTags(repoPath); |
|
|
|
|
|
|
|
// Don't use the shared regex instance directly, because we can be called reentrantly (because of the awaits below)
|
|
|
|
const regex = new RegExp(refRegex, refRegex.flags); |
|
|
|
const refRegex = new RegExp(refRegexShared, refRegexShared.flags); |
|
|
|
const commandsRegex = new RegExp(commandsRegexShared, commandsRegexShared.flags); |
|
|
|
|
|
|
|
let match; |
|
|
|
do { |
|
|
|
match = regex.exec(context.line); |
|
|
|
match = commandsRegex.exec(context.line); |
|
|
|
if (match != null) { |
|
|
|
const [_, git, command] = match; |
|
|
|
|
|
|
|
const link: GitTerminalLink<GitCommandsCommandArgs> = { |
|
|
|
startIndex: match.index + git.length, |
|
|
|
length: command.length, |
|
|
|
tooltip: 'Open in Git Command Palette', |
|
|
|
command: { |
|
|
|
command: Commands.GitCommands, |
|
|
|
args: { |
|
|
|
command: command as GitCommandsCommandArgs['command'], |
|
|
|
}, |
|
|
|
}, |
|
|
|
}; |
|
|
|
links.push(link); |
|
|
|
} |
|
|
|
|
|
|
|
match = refRegex.exec(context.line); |
|
|
|
if (match == null) break; |
|
|
|
|
|
|
|
const [_, ref] = match; |
|
|
@ -82,7 +109,28 @@ export class GitTerminalLinkProvider implements Disposable, TerminalLinkProvider |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (!shaRegex.test(ref)) continue; |
|
|
|
if (!shaRegex.test(ref)) { |
|
|
|
if (rangeRegex.test(ref)) { |
|
|
|
const link: GitTerminalLink<GitCommandsCommandArgs> = { |
|
|
|
startIndex: match.index, |
|
|
|
length: ref.length, |
|
|
|
tooltip: 'Show Commits', |
|
|
|
command: { |
|
|
|
command: Commands.GitCommands, |
|
|
|
args: { |
|
|
|
command: 'log', |
|
|
|
state: { |
|
|
|
repo: repoPath, |
|
|
|
reference: GitReference.create(ref, repoPath, { refType: 'revision' }), |
|
|
|
}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
}; |
|
|
|
links.push(link); |
|
|
|
} |
|
|
|
|
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (await Container.git.validateReference(repoPath, ref)) { |
|
|
|
const link: GitTerminalLink<ShowQuickCommitCommandArgs> = { |
|
|
|