Procházet zdrojové kódy

Removes statics for better tree shaking

main
Eric Amodio před 2 roky
rodič
revize
12771dbceb
32 změnil soubory, kde provedl 357 přidání a 360 odebrání
  1. +5
    -6
      src/annotations/annotationProvider.ts
  2. +5
    -5
      src/annotations/fileAnnotationController.ts
  3. +82
    -83
      src/commands/base.ts
  4. +2
    -2
      src/commands/git/pull.ts
  5. +10
    -6
      src/commands/git/push.ts
  6. +3
    -3
      src/commands/openFileOnRemote.ts
  7. +2
    -2
      src/commands/openWorkingFile.ts
  8. +10
    -10
      src/commands/quickCommand.steps.ts
  9. +7
    -7
      src/env/node/git/localGitProvider.ts
  10. +7
    -7
      src/extension.ts
  11. +2
    -2
      src/git/fsProvider.ts
  12. +8
    -11
      src/git/gitUri.ts
  13. +77
    -85
      src/git/models/branch.ts
  14. +2
    -2
      src/git/models/reference.ts
  15. +7
    -5
      src/git/models/repository.ts
  16. +51
    -45
      src/git/models/status.ts
  17. +24
    -24
      src/git/models/tag.ts
  18. +4
    -4
      src/plus/github/githubGitProvider.ts
  19. +5
    -5
      src/quickpicks/remoteProviderPicker.ts
  20. +2
    -2
      src/system/utils.ts
  21. +3
    -2
      src/trackers/documentTracker.ts
  22. +5
    -5
      src/views/nodes/branchTrackingStatusNode.ts
  23. +4
    -4
      src/views/nodes/common.ts
  24. +2
    -2
      src/views/nodes/comparePickerNode.ts
  25. +5
    -5
      src/views/nodes/fileHistoryTrackerNode.ts
  26. +5
    -5
      src/views/nodes/lineHistoryTrackerNode.ts
  27. +2
    -2
      src/views/nodes/repositoriesNode.ts
  28. +2
    -6
      src/views/nodes/searchResultsNode.ts
  29. +7
    -6
      src/views/nodes/viewNode.ts
  30. +2
    -2
      src/views/remotesView.ts
  31. +2
    -2
      src/views/repositoriesView.ts
  32. +3
    -3
      src/views/searchAndCompareView.ts

+ 5
- 6
src/annotations/annotationProvider.ts Zobrazit soubor

@ -24,14 +24,13 @@ export interface AnnotationContext {
}
export type TextEditorCorrelationKey = string;
export function getEditorCorrelationKey(editor: TextEditor | undefined): TextEditorCorrelationKey {
return `${editor?.document.uri.toString()}|${editor?.viewColumn}`;
}
export abstract class AnnotationProviderBase<TContext extends AnnotationContext = AnnotationContext>
implements Disposable
{
static getCorrelationKey(editor: TextEditor | undefined): TextEditorCorrelationKey {
return `${editor?.document.uri.toString()}|${editor?.viewColumn}`;
}
annotationContext: TContext | undefined;
correlationKey: TextEditorCorrelationKey;
document: TextDocument;
@ -47,7 +46,7 @@ export abstract class AnnotationProviderBase
public editor: TextEditor,
protected readonly trackedDocument: TrackedDocument<GitDocumentState>,
) {
this.correlationKey = AnnotationProviderBase.getCorrelationKey(this.editor);
this.correlationKey = getEditorCorrelationKey(this.editor);
this.document = this.editor.document;
this.disposable = Disposable.from(
@ -121,7 +120,7 @@ export abstract class AnnotationProviderBase
}
this.editor = editor;
this.correlationKey = AnnotationProviderBase.getCorrelationKey(editor);
this.correlationKey = getEditorCorrelationKey(editor);
this.document = editor.document;
if (this.decorations?.length) {

+ 5
- 5
src/annotations/fileAnnotationController.ts Zobrazit soubor

@ -42,8 +42,8 @@ import type {
DocumentDirtyStateChangeEvent,
GitDocumentState,
} from '../trackers/gitDocumentTracker';
import type { AnnotationContext, TextEditorCorrelationKey } from './annotationProvider';
import { AnnotationProviderBase, AnnotationStatus } from './annotationProvider';
import type { AnnotationContext, AnnotationProviderBase, TextEditorCorrelationKey } from './annotationProvider';
import { AnnotationStatus, getEditorCorrelationKey } from './annotationProvider';
import { GutterBlameAnnotationProvider } from './gutterBlameAnnotationProvider';
import type { ChangesAnnotationContext } from './gutterChangesAnnotationProvider';
import { GutterChangesAnnotationProvider } from './gutterChangesAnnotationProvider';
@ -259,7 +259,7 @@ export class FileAnnotationController implements Disposable {
return this.clearAll();
}
return this.clearCore(AnnotationProviderBase.getCorrelationKey(editor), reason);
return this.clearCore(getEditorCorrelationKey(editor), reason);
}
async clearAll() {
@ -281,7 +281,7 @@ export class FileAnnotationController implements Disposable {
getProvider(editor: TextEditor | undefined): AnnotationProviderBase | undefined {
if (editor == null || editor.document == null) return undefined;
return this._annotationProviders.get(AnnotationProviderBase.getCorrelationKey(editor));
return this._annotationProviders.get(getEditorCorrelationKey(editor));
}
async show(editor: TextEditor | undefined, type: FileAnnotationType, context?: AnnotationContext): Promise<boolean>;
@ -415,7 +415,7 @@ export class FileAnnotationController implements Disposable {
this._annotationProviders.delete(key);
provider.dispose();
if (this._annotationProviders.size === 0 || key === AnnotationProviderBase.getCorrelationKey(this._editor)) {
if (this._annotationProviders.size === 0 || key === getEditorCorrelationKey(this._editor)) {
await setContext(ContextKeys.AnnotationStatus, undefined);
await this.detachKeyboardHook();
}

+ 82
- 83
src/commands/base.ts Zobrazit soubor

@ -9,7 +9,8 @@ import type {
import { commands, Disposable, Uri, window } from 'vscode';
import type { ActionContext } from '../api/gitlens';
import type { Commands } from '../constants';
import { GitBranch } from '../git/models/branch';
import type { GitBranch } from '../git/models/branch';
import { isBranch } from '../git/models/branch';
import type { GitStashCommit } from '../git/models/commit';
import { GitCommit } from '../git/models/commit';
import { GitContributor } from '../git/models/contributor';
@ -17,7 +18,8 @@ import type { GitFile } from '../git/models/file';
import type { GitReference } from '../git/models/reference';
import { GitRemote } from '../git/models/remote';
import { Repository } from '../git/models/repository';
import { GitTag } from '../git/models/tag';
import type { GitTag } from '../git/models/tag';
import { isTag } from '../git/models/tag';
import { sequentialize } from '../system/function';
import { ViewNode, ViewRefNode } from '../views/nodes/viewNode';
@ -89,7 +91,7 @@ export function isCommandContextViewNodeHasBranch(
): context is CommandViewNodeContext & { node: ViewNode & { branch: GitBranch } } {
if (context.type !== 'viewItem') return false;
return GitBranch.is((context.node as ViewNode & { branch: GitBranch }).branch);
return isBranch((context.node as ViewNode & { branch: GitBranch }).branch);
}
export function isCommandContextViewNodeHasCommit<T extends GitCommit | GitStashCommit>(
@ -175,7 +177,7 @@ export function isCommandContextViewNodeHasTag(
): context is CommandViewNodeContext & { node: ViewNode & { tag: GitTag } } {
if (context.type !== 'viewItem') return false;
return GitTag.is((context.node as ViewNode & { tag: GitTag }).tag);
return isTag((context.node as ViewNode & { tag: GitTag }).tag);
}
export type CommandContext =
@ -264,7 +266,7 @@ export abstract class Command implements Disposable {
abstract execute(...args: any[]): any;
protected _execute(command: string, ...args: any[]): Promise<unknown> {
const [context, rest] = Command.parseContext(command, { ...this.contextParsingOptions }, ...args);
const [context, rest] = parseCommandContext(command, { ...this.contextParsingOptions }, ...args);
// If there an array of contexts, then we want to execute the command for each
if (Array.isArray(context)) {
@ -277,110 +279,107 @@ export abstract class Command implements Disposable {
return this.preExecute(context, ...rest);
}
}
private static parseContext(
command: string,
options: CommandContextParsingOptions,
...args: any[]
): [CommandContext | CommandContext[], any[]] {
let editor: TextEditor | undefined = undefined;
function parseCommandContext(
command: string,
options: CommandContextParsingOptions,
...args: any[]
): [CommandContext | CommandContext[], any[]] {
let editor: TextEditor | undefined = undefined;
let firstArg = args[0];
let firstArg = args[0];
if (options.expectsEditor) {
if (firstArg == null || (firstArg.id != null && firstArg.document?.uri != null)) {
editor = firstArg;
args = args.slice(1);
firstArg = args[0];
}
if (options.expectsEditor) {
if (firstArg == null || (firstArg.id != null && firstArg.document?.uri != null)) {
editor = firstArg;
args = args.slice(1);
firstArg = args[0];
}
if (args.length > 0 && (firstArg == null || firstArg instanceof Uri)) {
const [uri, ...rest] = args as [Uri, any];
if (uri != null) {
// If the uri matches the active editor (or we are in a left-hand side of a diff), then pass the active editor
if (
editor == null &&
(uri.toString() === window.activeTextEditor?.document.uri.toString() ||
command.endsWith('InDiffLeft'))
) {
editor = window.activeTextEditor;
}
const uris = rest[0];
if (uris != null && Array.isArray(uris) && uris.length !== 0 && uris[0] instanceof Uri) {
return [
{ command: command, type: 'uris', editor: editor, uri: uri, uris: uris },
rest.slice(1),
];
}
return [{ command: command, type: 'uri', editor: editor, uri: uri }, rest];
if (args.length > 0 && (firstArg == null || firstArg instanceof Uri)) {
const [uri, ...rest] = args as [Uri, any];
if (uri != null) {
// If the uri matches the active editor (or we are in a left-hand side of a diff), then pass the active editor
if (
editor == null &&
(uri.toString() === window.activeTextEditor?.document.uri.toString() ||
command.endsWith('InDiffLeft'))
) {
editor = window.activeTextEditor;
}
args = args.slice(1);
} else if (editor == null) {
// If we are expecting an editor and we have no uri, then pass the active editor
editor = window.activeTextEditor;
const uris = rest[0];
if (uris != null && Array.isArray(uris) && uris.length !== 0 && uris[0] instanceof Uri) {
return [{ command: command, type: 'uris', editor: editor, uri: uri, uris: uris }, rest.slice(1)];
}
return [{ command: command, type: 'uri', editor: editor, uri: uri }, rest];
}
args = args.slice(1);
} else if (editor == null) {
// If we are expecting an editor and we have no uri, then pass the active editor
editor = window.activeTextEditor;
}
}
if (firstArg instanceof ViewNode) {
let [node, ...rest] = args as [ViewNode, unknown];
if (firstArg instanceof ViewNode) {
let [node, ...rest] = args as [ViewNode, unknown];
// If there is a node followed by an array of nodes, then we want to execute the command for each
firstArg = rest[0];
if (Array.isArray(firstArg) && firstArg[0] instanceof ViewNode) {
let nodes;
[nodes, ...rest] = rest as unknown as [ViewNode[], unknown];
// If there is a node followed by an array of nodes, then we want to execute the command for each
firstArg = rest[0];
if (Array.isArray(firstArg) && firstArg[0] instanceof ViewNode) {
let nodes;
[nodes, ...rest] = rest as unknown as [ViewNode[], unknown];
const contexts: CommandContext[] = [];
for (const n of nodes) {
if (n?.constructor === node.constructor) {
contexts.push({ command: command, type: 'viewItem', node: n, uri: n.uri });
}
const contexts: CommandContext[] = [];
for (const n of nodes) {
if (n?.constructor === node.constructor) {
contexts.push({ command: command, type: 'viewItem', node: n, uri: n.uri });
}
return [contexts, rest];
}
return [{ command: command, type: 'viewItem', node: nodespan>, uri: node.uri }, rest];
return [contexts, rest];
}
if (isScmResourceState(firstArg)) {
const states = [];
let count = 0;
for (const arg of args) {
if (!isScmResourceState(arg)) break;
return [{ command: command, type: 'viewItem', node: node, uri: node.uri }, rest];
}
count++;
states.push(arg);
}
if (isScmResourceState(firstArg)) {
const states = [];
let count = 0;
for (const arg of args) {
if (!isScmResourceState(arg)) break;
return [
{ command: command, type: 'scm-states', scmResourceStates: states, uri: states[0].resourceUri },
args.slice(count),
];
count++;
states.push(arg);
}
if (isScmResourceGroup(firstArg)) {
const groups = [];
let count = 0;
for (const arg of args) {
if (!isScmResourceGroup(arg)) break;
return [
{ command: command, type: 'scm-states', scmResourceStates: states, uri: states[0].resourceUri },
args.slice(count),
];
}
count++;
groups.push(arg);
}
if (isScmResourceGroup(firstArg)) {
const groups = [];
let count = 0;
for (const arg of args) {
if (!isScmResourceGroup(arg)) break;
return [{ command: command, type: 'scm-groups', scmResourceGroups: groups }, args.slice(count)];
count++;
groups.push(arg);
}
if (isGitTimelineItem(firstArg)) {
const [item, uri, ...rest] = args as [GitTimelineItem, Uri, any];
return [{ command: command, type: 'timeline-item:git', item: item, uri: uri }, rest];
}
return [{ command: command, type: 'scm-groups', scmResourceGroups: groups }, args.slice(count)];
}
return [{ command: command, type: 'unknown', editor: editor, uri: editor?.document.uri }, args];
if (isGitTimelineItem(firstArg)) {
const [item, uri, ...rest] = args as [GitTimelineItem, Uri, any];
return [{ command: command, type: 'timeline-item:git', item: item, uri: uri }, rest];
}
return [{ command: command, type: 'unknown', editor: editor, uri: editor?.document.uri }, args];
}
export abstract class ActiveEditorCommand extends Command {

+ 2
- 2
src/commands/git/pull.ts Zobrazit soubor

@ -1,6 +1,6 @@
import { GlyphChars } from '../../constants';
import type { Container } from '../../container';
import { GitBranch } from '../../git/models/branch';
import { isBranch } from '../../git/models/branch';
import type { GitBranchReference } from '../../git/models/reference';
import { GitReference } from '../../git/models/reference';
import type { Repository } from '../../git/models/repository';
@ -69,7 +69,7 @@ export class PullGitCommand extends QuickCommand {
async execute(state: PullStepState) {
if (GitReference.isBranch(state.reference)) {
// Only resort to a branch fetch if the branch isn't the current one
if (!GitBranch.is(state.reference) || !state.reference.current) {
if (!isBranch(state.reference) || !state.reference.current) {
const currentBranch = await state.repos[0].getBranch();
if (currentBranch?.name !== state.reference.name) {
return state.repos[0].fetch({ branch: state.reference, pull: true });

+ 10
- 6
src/commands/git/push.ts Zobrazit soubor

@ -1,7 +1,7 @@
import { configuration } from '../../configuration';
import { CoreGitConfiguration, GlyphChars } from '../../constants';
import type { Container } from '../../container';
import { GitBranch } from '../../git/models/branch';
import { getRemoteNameFromBranchName } from '../../git/models/branch';
import type { GitBranchReference } from '../../git/models/reference';
import { GitReference } from '../../git/models/reference';
import type { Repository } from '../../git/models/repository';
@ -329,7 +329,9 @@ export class PushGitCommand extends QuickCommand {
[],
DirectiveQuickPickItem.create(Directive.Cancel, true, {
label: `Cancel ${this.title}`,
detail: `Cannot push; No commits ahead of ${GitBranch.getRemote(status.upstream)}`,
detail: `Cannot push; No commits ahead of ${getRemoteNameFromBranchName(
status.upstream,
)}`,
}),
);
}
@ -349,10 +351,10 @@ export class PushGitCommand extends QuickCommand {
label: false,
})}`
: ''
}${status?.upstream ? ` to ${GitBranch.getRemote(status.upstream)}` : ''}`;
}${status?.upstream ? ` to ${getRemoteNameFromBranchName(status.upstream)}` : ''}`;
} else {
pushDetails = `${status?.state.ahead ? ` ${pluralize('commit', status.state.ahead)}` : ''}${
status?.upstream ? ` to ${GitBranch.getRemote(status.upstream)}` : ''
status?.upstream ? ` to ${getRemoteNameFromBranchName(status.upstream)}` : ''
}`;
}
@ -373,7 +375,9 @@ export class PushGitCommand extends QuickCommand {
detail: `Will force push${useForceWithLease ? ' (with lease)' : ''} ${pushDetails}${
status != null && status.state.behind > 0
? `, overwriting ${pluralize('commit', status.state.behind)}${
status?.upstream ? ` on ${GitBranch.getRemote(status.upstream)}` : ''
status?.upstream
? ` on ${getRemoteNameFromBranchName(status.upstream)}`
: ''
}`
: ''
}`,
@ -383,7 +387,7 @@ export class PushGitCommand extends QuickCommand {
? DirectiveQuickPickItem.create(Directive.Cancel, true, {
label: `Cancel ${this.title}`,
detail: `Cannot push; ${GitReference.toString(branch)} is behind${
status?.upstream ? ` ${GitBranch.getRemote(status.upstream)}` : ''
status?.upstream ? ` ${getRemoteNameFromBranchName(status.upstream)}` : ''
} by ${pluralize('commit', status.state.behind)}`,
})
: undefined,

+ 3
- 3
src/commands/openFileOnRemote.ts Zobrazit soubor

@ -5,7 +5,7 @@ import { BranchSorting, TagSorting } from '../configuration';
import { Commands, GlyphChars } from '../constants';
import type { Container } from '../container';
import { GitUri } from '../git/gitUri';
import { GitBranch } from '../git/models/branch';
import { getBranchNameWithoutRemote, getRemoteNameFromBranchName } from '../git/models/branch';
import { GitRevision } from '../git/models/reference';
import { RemoteResourceType } from '../git/remotes/provider';
import { Logger } from '../logger';
@ -169,9 +169,9 @@ export class OpenFileOnRemoteCommand extends ActiveEditorCommand {
if (pick.refType === 'branch') {
if (pick.remote) {
args.branchOrTag = GitBranch.getNameWithoutRemote(pick.name);
args.branchOrTag = getBranchNameWithoutRemote(pick.name);
const remoteName = GitBranch.getRemote(pick.name);
const remoteName = getRemoteNameFromBranchName(pick.name);
const remote = remotes.find(r => r.name === remoteName);
if (remote != null) {
remotes = [remote];

+ 2
- 2
src/commands/openWorkingFile.ts Zobrazit soubor

@ -3,7 +3,7 @@ import { Range, window } from 'vscode';
import type { FileAnnotationType } from '../configuration';
import { Commands } from '../constants';
import type { Container } from '../container';
import { GitUri } from '../git/gitUri';
import { GitUri, isGitUri } from '../git/gitUri';
import { Logger } from '../logger';
import { showGenericErrorMessage } from '../messages';
import { command } from '../system/command';
@ -38,7 +38,7 @@ export class OpenWorkingFileCommand extends ActiveEditorCommand {
}
args.uri = await GitUri.fromUri(uri);
if (GitUri.is(args.uri) && args.uri.sha) {
if (isGitUri(args.uri) && args.uri.sha) {
const workingUri = await this.container.git.getWorkingUri(args.uri.repoPath!, args.uri);
if (workingUri === undefined) {
void window.showWarningMessage(

+ 10
- 10
src/commands/quickCommand.steps.ts Zobrazit soubor

@ -4,8 +4,8 @@ import { Commands, GlyphChars, quickPickTitleMaxChars } from '../constants';
import { Container } from '../container';
import type { PlusFeatures } from '../features';
import type { PagedResult } from '../git/gitProvider';
import type { BranchSortOptions } from '../git/models/branch';
import { GitBranch } from '../git/models/branch';
import type { BranchSortOptions, GitBranch } from '../git/models/branch';
import { sortBranches } from '../git/models/branch';
import type { GitStashCommit } from '../git/models/commit';
import { GitCommit } from '../git/models/commit';
import type { GitContributor } from '../git/models/contributor';
@ -16,8 +16,8 @@ import { GitRemote } from '../git/models/remote';
import { Repository } from '../git/models/repository';
import type { GitStash } from '../git/models/stash';
import type { GitStatus } from '../git/models/status';
import type { TagSortOptions } from '../git/models/tag';
import { GitTag } from '../git/models/tag';
import type { GitTag, TagSortOptions } from '../git/models/tag';
import { sortTags } from '../git/models/tag';
import type { GitWorktree } from '../git/models/worktree';
import { RemoteResourceType } from '../git/remotes/provider';
import { SearchPattern } from '../git/search';
@ -247,13 +247,13 @@ export async function getBranchesAndOrTags(
: undefined;
if (include.includes('branches') && branchesByRepo != null) {
branches = GitBranch.sort(
branches = sortBranches(
intersection(...branchesByRepo, (b1: GitBranch, b2: GitBranch) => b1.name === b2.name),
);
}
if (include.includes('tags') && tagsByRepo != null) {
tags = GitTag.sort(intersection(...tagsByRepo, (t1: GitTag, t2: GitTag) => t1.name === t2.name));
tags = sortTags(intersection(...tagsByRepo, (t1: GitTag, t2: GitTag) => t1.name === t2.name));
}
}
@ -1609,7 +1609,7 @@ export async function* showCommitOrStashStep<
onDidPressKey: async (quickpick, key) => {
if (quickpick.activeItems.length === 0) return;
(await quickpick.activeItems[0].onDidPressKey(key));
await quickpick.activeItems[0].onDidPressKey(key);
},
});
const selection: StepSelection<typeof step> = yield step;
@ -1896,7 +1896,7 @@ export function* showCommitOrStashFilesStep<
onDidPressKey: async (quickpick, key) => {
if (quickpick.activeItems.length === 0) return;
(await quickpick.activeItems[0].onDidPressKey(key));
await quickpick.activeItems[0].onDidPressKey(key);
},
});
const selection: StepSelection<typeof step> = yield step;
@ -1968,7 +1968,7 @@ export async function* showCommitOrStashFileStep<
onDidPressKey: async (quickpick, key) => {
if (quickpick.activeItems.length === 0) return;
(await quickpick.activeItems[0].onDidPressKey(key));
await quickpick.activeItems[0].onDidPressKey(key);
},
});
const selection: StepSelection<typeof step> = yield step;
@ -2090,7 +2090,7 @@ export function* showRepositoryStatusStep<
onDidPressKey: async (quickpick, key) => {
if (quickpick.activeItems.length === 0) return;
(await quickpick.activeItems[0].onDidPressKey(key));
await quickpick.activeItems[0].onDidPressKey(key);
},
});
const selection: StepSelection<typeof step> = yield step;

+ 7
- 7
src/env/node/git/localGitProvider.ts Zobrazit soubor

@ -42,7 +42,7 @@ import { GitProviderService } from '../../../git/gitProviderService';
import { encodeGitLensRevisionUriAuthority, GitUri } from '../../../git/gitUri';
import type { GitBlame, GitBlameAuthor, GitBlameLine, GitBlameLines } from '../../../git/models/blame';
import type { BranchSortOptions } from '../../../git/models/branch';
import { GitBranch } from '../../../git/models/branch';
import { GitBranch, isDetachedHead, sortBranches } from '../../../git/models/branch';
import type { GitStashCommit } from '../../../git/models/commit';
import { GitCommit, GitCommitIdentity } from '../../../git/models/commit';
import { GitContributor } from '../../../git/models/contributor';
@ -61,8 +61,8 @@ import { Repository, RepositoryChange, RepositoryChangeComparisonMode } from '..
import type { GitStash } from '../../../git/models/stash';
import type { GitStatusFile } from '../../../git/models/status';
import { GitStatus } from '../../../git/models/status';
import type { TagSortOptions } from '../../../git/models/tag';
import { GitTag } from '../../../git/models/tag';
import type { GitTag, TagSortOptions } from '../../../git/models/tag';
import { sortTags } from '../../../git/models/tag';
import type { GitTreeEntry } from '../../../git/models/tree';
import type { GitUser } from '../../../git/models/user';
import { isUserMatch } from '../../../git/models/user';
@ -1403,7 +1403,7 @@ export class LocalGitProvider implements GitProvider, Disposable {
if (data == null) return undefined;
const [name, upstream] = data[0].split('\n');
if (GitBranch.isDetached(name)) {
if (isDetachedHead(name)) {
const [rebaseStatus, committerDate] = await Promise.all([
this.getRebaseStatus(repoPath),
@ -1454,7 +1454,7 @@ export class LocalGitProvider implements GitProvider, Disposable {
if (data != null) {
const [name, upstream] = data[0].split('\n');
const [rebaseStatus, committerDate] = await Promise.all([
GitBranch.isDetached(name) ? this.getRebaseStatus(repoPath!) : undefined,
isDetachedHead(name) ? this.getRebaseStatus(repoPath!) : undefined,
this.git.log__recent_committerdate(repoPath!, commitOrdering),
]);
@ -1502,7 +1502,7 @@ export class LocalGitProvider implements GitProvider, Disposable {
}
if (options?.sort) {
GitBranch.sort(result.values, typeof options.sort === 'boolean' ? undefined : options.sort);
sortBranches(result.values, typeof options.sort === 'boolean' ? undefined : options.sort);
}
return result;
@ -3447,7 +3447,7 @@ export class LocalGitProvider implements GitProvider, Disposable {
}
if (options?.sort) {
GitTag.sort(result.values, typeof options.sort === 'boolean' ? undefined : options.sort);
sortTags(result.values, typeof options.sort === 'boolean' ? undefined : options.sort);
}
return result;

+ 7
- 7
src/extension.ts Zobrazit soubor

@ -8,8 +8,8 @@ import { configuration, Configuration, OutputLevel } from './configuration';
import { Commands, ContextKeys, CoreCommands } from './constants';
import { Container } from './container';
import { setContext } from './context';
import { GitUri } from './git/gitUri';
import { GitBranch } from './git/models/branch';
import { isGitUri } from './git/gitUri';
import { getBranchNameWithoutRemote } from './git/models/branch';
import { GitCommit } from './git/models/commit';
import { Logger, LogLevel } from './logger';
import { showDebugLoggingWarningMessage, showInsidersErrorMessage, showWhatsNewMessage } from './messages';
@ -20,7 +20,7 @@ import { setDefaultDateLocales } from './system/date';
import { once } from './system/event';
import { Stopwatch } from './system/stopwatch';
import { compare, satisfies } from './system/version';
import { ViewNode } from './views/nodes/viewNode';
import { isViewNode } from './views/nodes/viewNode';
export async function activate(context: ExtensionContext): Promise<GitLensApi | undefined> {
const gitlensVersion = context.extension.packageJSON.version;
@ -28,7 +28,7 @@ export async function activate(context: ExtensionContext): Promise
const outputLevel = configuration.get('outputLevel');
Logger.configure(context, configuration.get('outputLevel'), o => {
if (GitUri.is(o)) {
if (isGitUri(o)) {
return `GitUri(${o.toString(true)}${o.repoPath ? ` repoPath=${o.repoPath}` : ''}${
o.sha ? ` sha=${o.sha}` : ''
})`;
@ -38,7 +38,7 @@ export async function activate(context: ExtensionContext): Promise
return `GitCommit(${o.sha ? ` sha=${o.sha}` : ''}${o.repoPath ? ` repoPath=${o.repoPath}` : ''})`;
}
if (ViewNode.is(o)) return o.toString();
if (isViewNode(o)) return o.toString();
return undefined;
});
@ -194,9 +194,9 @@ function registerBuiltInActionRunners(container: Container): void {
void (await executeCommand<CreatePullRequestOnRemoteCommandArgs>(Commands.CreatePullRequestOnRemote, {
base: undefined,
compare: ctx.branch.isRemote
? GitBranch.getNameWithoutRemote(ctx.branch.name)
? getBranchNameWithoutRemote(ctx.branch.name)
: ctx.branch.upstream
? GitBranch.getNameWithoutRemote(ctx.branch.upstream)
? getBranchNameWithoutRemote(ctx.branch.upstream)
: ctx.branch.name,
remote: ctx.remote?.name ?? '',
repoPath: ctx.repoPath,

+ 2
- 2
src/git/fsProvider.ts Zobrazit soubor

@ -3,7 +3,7 @@ import { Disposable, EventEmitter, FileSystemError, FileType, workspace } from '
import { isLinux } from '@env/platform';
import { Schemes } from '../constants';
import type { Container } from '../container';
import { GitUri } from '../git/gitUri';
import { GitUri, isGitUri } from '../git/gitUri';
import { debug } from '../system/decorators/log';
import { map } from '../system/iterable';
import { normalizePath, relative } from '../system/path';
@ -14,7 +14,7 @@ import type { GitTreeEntry } from './models/tree';
const emptyArray = new Uint8Array(0);
export function fromGitLensFSUri(uri: Uri): { path: string; ref: string; repoPath: string } {
const gitUri = GitUri.is(uri) ? uri : GitUri.fromRevisionUri(uri);
const gitUri = isGitUri(uri) ? uri : GitUri.fromRevisionUri(uri);
return { path: gitUri.relativePath, ref: gitUri.sha!, repoPath: gitUri.repoPath! };
}

+ 8
- 11
src/git/gitUri.ts Zobrazit soubor

@ -39,15 +39,6 @@ interface UriEx {
}
export class GitUri extends (Uri as any as UriEx) {
private static readonly _unknown = new GitUri();
static get unknown() {
return this._unknown;
}
static is(uri: any): uri is GitUri {
return uri instanceof GitUri;
}
readonly repoPath?: string;
readonly sha?: string;
@ -214,7 +205,7 @@ export class GitUri extends (Uri as any as UriEx) {
equals(uri: Uri | undefined) {
if (!UriComparer.equals(this, uri)) return false;
return this.sha === (GitUri.is(uri) ? uri.sha : undefined);
return this.sha === (isGitUri(uri) ? uri.sha : undefined);
}
getFormattedFileName(options?: { suffix?: string; truncateTo?: number }): string {
@ -255,7 +246,7 @@ export class GitUri extends (Uri as any as UriEx) {
exit: uri => `returned ${Logger.toLoggable(uri)}`,
})
static async fromUri(uri: Uri): Promise<GitUri> {
if (GitUri.is(uri)) return uri;
if (isGitUri(uri)) return uri;
if (!Container.instance.git.isTrackable(uri)) return new GitUri(uri);
if (uri.scheme === Schemes.GitLens) return new GitUri(uri);
@ -346,6 +337,12 @@ export class GitUri extends (Uri as any as UriEx) {
}
}
export const unknownGitUri = Object.freeze(new GitUri());
export function isGitUri(uri: any): uri is GitUri {
return uri instanceof GitUri;
}
export function decodeGitLensRevisionUriAuthority<T>(authority: string): T {
return JSON.parse(decodeUtf8Hex(authority)) as T;
}

+ 77
- 85
src/git/models/branch.ts Zobrazit soubor

@ -11,7 +11,7 @@ import type { PullRequest, PullRequestState } from './pullRequest';
import type { GitBranchReference, GitReference } from './reference';
import { GitRevision } from './reference';
import type { GitRemote } from './remote';
import { GitStatus } from './status';
import { getUpstreamStatus } from './status';
const whitespaceRegex = /\s/;
const detachedHEADRegex = /^(?=.*\bHEAD\b)?(?=.*\bdetached\b).*$/;
@ -39,72 +39,6 @@ export interface BranchSortOptions {
}
export class GitBranch implements GitBranchReference {
static is(branch: any): branch is GitBranch {
return branch instanceof GitBranch;
}
static isOfRefType(branch: GitReference | undefined) {
return branch?.refType === 'branch';
}
static sort(branches: GitBranch[], options?: BranchSortOptions) {
options = { current: true, orderBy: configuration.get('sortBranchesBy'), ...options };
switch (options.orderBy) {
case BranchSorting.DateAsc:
return branches.sort(
(a, b) =>
(options!.missingUpstream
? (a.upstream?.missing ? -1 : 1) - (b.upstream?.missing ? -1 : 1)
: 0) ||
(options!.current ? (a.current ? -1 : 1) - (b.current ? -1 : 1) : 0) ||
(a.starred ? -1 : 1) - (b.starred ? -1 : 1) ||
(b.remote ? -1 : 1) - (a.remote ? -1 : 1) ||
(a.date == null ? -1 : a.date.getTime()) - (b.date == null ? -1 : b.date.getTime()),
);
case BranchSorting.NameAsc:
return branches.sort(
(a, b) =>
(options!.missingUpstream
? (a.upstream?.missing ? -1 : 1) - (b.upstream?.missing ? -1 : 1)
: 0) ||
(options!.current ? (a.current ? -1 : 1) - (b.current ? -1 : 1) : 0) ||
(a.starred ? -1 : 1) - (b.starred ? -1 : 1) ||
(a.name === 'main' ? -1 : 1) - (b.name === 'main' ? -1 : 1) ||
(a.name === 'master' ? -1 : 1) - (b.name === 'master' ? -1 : 1) ||
(a.name === 'develop' ? -1 : 1) - (b.name === 'develop' ? -1 : 1) ||
(b.remote ? -1 : 1) - (a.remote ? -1 : 1) ||
sortCompare(a.name, b.name),
);
case BranchSorting.NameDesc:
return branches.sort(
(a, b) =>
(options!.missingUpstream
? (a.upstream?.missing ? -1 : 1) - (b.upstream?.missing ? -1 : 1)
: 0) ||
(options!.current ? (a.current ? -1 : 1) - (b.current ? -1 : 1) : 0) ||
(a.starred ? -1 : 1) - (b.starred ? -1 : 1) ||
(a.name === 'main' ? -1 : 1) - (b.name === 'main' ? -1 : 1) ||
(a.name === 'master' ? -1 : 1) - (b.name === 'master' ? -1 : 1) ||
(a.name === 'develop' ? -1 : 1) - (b.name === 'develop' ? -1 : 1) ||
(b.remote ? -1 : 1) - (a.remote ? -1 : 1) ||
sortCompare(b.name, a.name),
);
case BranchSorting.DateDesc:
default:
return branches.sort(
(a, b) =>
(options!.missingUpstream
? (a.upstream?.missing ? -1 : 1) - (b.upstream?.missing ? -1 : 1)
: 0) ||
(options!.current ? (a.current ? -1 : 1) - (b.current ? -1 : 1) : 0) ||
(a.starred ? -1 : 1) - (b.starred ? -1 : 1) ||
(b.remote ? -1 : 1) - (a.remote ? -1 : 1) ||
(b.date == null ? -1 : b.date.getTime()) - (a.date == null ? -1 : a.date.getTime()),
);
}
}
readonly refType = 'branch';
readonly detached: boolean;
readonly id: string;
@ -126,9 +60,9 @@ export class GitBranch implements GitBranchReference {
) {
this.id = `${repoPath}|${remote ? 'remotes/' : 'heads/'}${name}`;
this.detached = detached || (this.current ? GitBranch.isDetached(name) : false);
this.detached = detached || (this.current ? isDetachedHead(name) : false);
if (this.detached) {
this.name = GitBranch.formatDetached(this.sha!);
this.name = formatDetachedHeadName(this.sha!);
}
this.upstream = upstream?.name == null || upstream.name.length === 0 ? undefined : upstream;
@ -210,8 +144,8 @@ export class GitBranch implements GitBranchReference {
@memoize()
getRemoteName(): string | undefined {
if (this.remote) return GitBranch.getRemote(this.name);
if (this.upstream != null) return GitBranch.getRemote(this.upstream.name);
if (this.remote) return getRemoteNameFromBranchName(this.name);
if (this.upstream != null) return getRemoteNameFromBranchName(this.upstream.name);
return undefined;
}
@ -243,7 +177,7 @@ export class GitBranch implements GitBranchReference {
separator?: string;
suffix?: string;
}): string {
return GitStatus.getUpstreamStatus(this.upstream, this.state, options);
return getUpstreamStatus(this.upstream, this.state, options);
}
get starred() {
@ -258,22 +192,80 @@ export class GitBranch implements GitBranchReference {
unstar() {
return Container.instance.git.getRepository(this.repoPath)?.unstar(this);
}
}
static formatDetached(sha: string): string {
return `(${GitRevision.shorten(sha)}...)`;
}
export function formatDetachedHeadName(sha: string): string {
return `(${GitRevision.shorten(sha)}...)`;
}
static getNameWithoutRemote(name: string): string {
return name.substring(name.indexOf('/') + 1);
}
export function getBranchNameWithoutRemote(name: string): string {
return name.substring(name.indexOf('/') + 1);
}
static getRemote(name: string): string {
return name.substring(0, name.indexOf('/'));
}
export function getRemoteNameFromBranchName(name: string): string {
return name.substring(0, name.indexOf('/'));
}
export function isBranch(branch: any): branch is GitBranch {
return branch instanceof GitBranch;
}
export function isDetachedHead(name: string): boolean {
// If there is whitespace in the name assume this is not a valid branch name
// Deals with detached HEAD states
return whitespaceRegex.test(name) || detachedHEADRegex.test(name);
}
export function isOfBranchRefType(branch: GitReference | undefined) {
return branch?.refType === 'branch';
}
static isDetached(name: string): boolean {
// If there is whitespace in the name assume this is not a valid branch name
// Deals with detached HEAD states
return whitespaceRegex.test(name) || detachedHEADRegex.test(name);
export function sortBranches(branches: GitBranch[], options?: BranchSortOptions) {
options = { current: true, orderBy: configuration.get('sortBranchesBy'), ...options };
switch (options.orderBy) {
case BranchSorting.DateAsc:
return branches.sort(
(a, b) =>
(options!.missingUpstream ? (a.upstream?.missing ? -1 : 1) - (b.upstream?.missing ? -1 : 1) : 0) ||
(options!.current ? (a.current ? -1 : 1) - (b.current ? -1 : 1) : 0) ||
(a.starred ? -1 : 1) - (b.starred ? -1 : 1) ||
(b.remote ? -1 : 1) - (a.remote ? -1 : 1) ||
(a.date == null ? -1 : a.date.getTime()) - (b.date == null ? -1 : b.date.getTime()),
);
case BranchSorting.NameAsc:
return branches.sort(
(a, b) =>
(options!.missingUpstream ? (a.upstream?.missing ? -1 : 1) - (b.upstream?.missing ? -1 : 1) : 0) ||
(options!.current ? (a.current ? -1 : 1) - (b.current ? -1 : 1) : 0) ||
(a.starred ? -1 : 1) - (b.starred ? -1 : 1) ||
(a.name === 'main' ? -1 : 1) - (b.name === 'main' ? -1 : 1) ||
(a.name === 'master' ? -1 : 1) - (b.name === 'master' ? -1 : 1) ||
(a.name === 'develop' ? -1 : 1) - (b.name === 'develop' ? -1 : 1) ||
(b.remote ? -1 : 1) - (a.remote ? -1 : 1) ||
sortCompare(a.name, b.name),
);
case BranchSorting.NameDesc:
return branches.sort(
(a, b) =>
(options!.missingUpstream ? (a.upstream?.missing ? -1 : 1) - (b.upstream?.missing ? -1 : 1) : 0) ||
(options!.current ? (a.current ? -1 : 1) - (b.current ? -1 : 1) : 0) ||
(a.starred ? -1 : 1) - (b.starred ? -1 : 1) ||
(a.name === 'main' ? -1 : 1) - (b.name === 'main' ? -1 : 1) ||
(a.name === 'master' ? -1 : 1) - (b.name === 'master' ? -1 : 1) ||
(a.name === 'develop' ? -1 : 1) - (b.name === 'develop' ? -1 : 1) ||
(b.remote ? -1 : 1) - (a.remote ? -1 : 1) ||
sortCompare(b.name, a.name),
);
case BranchSorting.DateDesc:
default:
return branches.sort(
(a, b) =>
(options!.missingUpstream ? (a.upstream?.missing ? -1 : 1) - (b.upstream?.missing ? -1 : 1) : 0) ||
(options!.current ? (a.current ? -1 : 1) - (b.current ? -1 : 1) : 0) ||
(a.starred ? -1 : 1) - (b.starred ? -1 : 1) ||
(b.remote ? -1 : 1) - (a.remote ? -1 : 1) ||
(b.date == null ? -1 : b.date.getTime()) - (a.date == null ? -1 : a.date.getTime()),
);
}
}

+ 2
- 2
src/git/models/reference.ts Zobrazit soubor

@ -1,6 +1,6 @@
import { configuration } from '../../configuration';
import { GlyphChars } from '../../constants';
import { GitBranch } from './branch';
import { getBranchNameWithoutRemote } from './branch';
const rangeRegex = /^(\S*?)(\.\.\.?)(\S*)\s*$/;
const shaLikeRegex = /(^[0-9a-f]{40}([\^@~:]\S*)?$)|(^[0]{40}(:|-)$)/;
@ -221,7 +221,7 @@ export namespace GitReference {
export function getNameWithoutRemote(ref: GitReference) {
if (ref.refType === 'branch') {
return ref.remote ? GitBranch.getNameWithoutRemote(ref.name) : ref.name;
return ref.remote ? getBranchNameWithoutRemote(ref.name) : ref.name;
}
return ref.name;
}

+ 7
- 5
src/git/models/repository.ts Zobrazit soubor

@ -25,8 +25,8 @@ import type { RemoteProviders } from '../remotes/factory';
import { RemoteProviderFactory } from '../remotes/factory';
import { RichRemoteProvider } from '../remotes/provider';
import type { SearchPattern } from '../search';
import type { BranchSortOptions } from './branch';
import { GitBranch } from './branch';
import type { BranchSortOptions, GitBranch } from './branch';
import { getBranchNameWithoutRemote, getRemoteNameFromBranchName } from './branch';
import type { GitCommit } from './commit';
import type { GitContributor } from './contributor';
import type { GitDiffShortStat } from './diff';
@ -421,14 +421,16 @@ export class Repository implements Disposable {
if (options?.remote) {
const trackingBranches = localBranches.filter(b => b.upstream != null);
if (trackingBranches.length !== 0) {
const branchesByOrigin = groupByMap(trackingBranches, b => GitBranch.getRemote(b.upstream!.name));
const branchesByOrigin = groupByMap(trackingBranches, b =>
getRemoteNameFromBranchName(b.upstream!.name),
);
for (const [remote, branches] of branchesByOrigin.entries()) {
this.runTerminalCommand(
'push',
'-d',
remote,
...branches.map(b => GitBranch.getNameWithoutRemote(b.upstream!.name)),
...branches.map(b => getBranchNameWithoutRemote(b.upstream!.name)),
);
}
}
@ -437,7 +439,7 @@ export class Repository implements Disposable {
const remoteBranches = branches.filter(b => b.remote);
if (remoteBranches.length !== 0) {
const branchesByOrigin = groupByMap(remoteBranches, b => GitBranch.getRemote(b.name));
const branchesByOrigin = groupByMap(remoteBranches, b => getRemoteNameFromBranchName(b.name));
for (const [remote, branches] of branchesByOrigin.entries()) {
this.runTerminalCommand(

+ 51
- 45
src/git/models/status.ts Zobrazit soubor

@ -4,7 +4,7 @@ import { Container } from '../../container';
import { memoize } from '../../system/decorators/memoize';
import { pluralize } from '../../system/string';
import type { GitTrackingState } from './branch';
import { GitBranch } from './branch';
import { formatDetachedHeadName, getRemoteNameFromBranchName, isDetachedHead } from './branch';
import { GitCommit, GitCommitIdentity } from './commit';
import type { GitFileStatus } from './file';
import { GitFile, GitFileChange, GitFileConflictStatus, GitFileIndexStatus, GitFileWorkingTreeStatus } from './file';
@ -38,9 +38,9 @@ export class GitStatus {
public readonly upstream?: string,
public readonly rebasing: boolean = false,
) {
this.detached = GitBranch.isDetached(branch);
this.detached = isDetachedHead(branch);
if (this.detached) {
this.branch = GitBranch.formatDetached(this.sha);
this.branch = formatDetachedHeadName(this.sha);
}
}
@ -245,7 +245,7 @@ export class GitStatus {
const remotes = await Container.instance.git.getRemotesWithProviders(this.repoPath);
if (remotes.length === 0) return undefined;
const remoteName = GitBranch.getRemote(this.upstream);
const remoteName = getRemoteNameFromBranchName(this.upstream);
return remotes.find(r => r.name === remoteName);
}
@ -257,59 +257,65 @@ export class GitStatus {
separator?: string;
suffix?: string;
}): string {
return GitStatus.getUpstreamStatus(
return getUpstreamStatus(
this.upstream ? { name: this.upstream, missing: false } : undefined,
this.state,
options,
);
}
}
static getUpstreamStatus(
upstream: { name: string; missing: boolean } | undefined,
state: { ahead: number; behind: number },
options: {
count?: boolean;
empty?: string;
expand?: boolean;
icons?: boolean;
prefix?: string;
separator?: string;
suffix?: string;
} = {},
): string {
const { count = true, expand = false, icons = false, prefix = '', separator = ' ', suffix = '' } = options;
if (upstream == null || (state.behind === 0 && state.ahead === 0)) return options.empty ?? '';
export function getUpstreamStatus(
upstream: { name: string; missing: boolean } | undefined,
state: { ahead: number; behind: number },
options?: {
count?: boolean;
empty?: string;
expand?: boolean;
icons?: boolean;
prefix?: string;
separator?: string;
suffix?: string;
},
): string {
let count = true;
let expand = false;
let icons = false;
let prefix = '';
let separator = ' ';
let suffix = '';
if (options != null) {
({ count = true, expand = false, icons = false, prefix = '', separator = ' ', suffix = '' } = options);
}
if (upstream == null || (state.behind === 0 && state.ahead === 0)) return options?.empty ?? '';
if (expand) {
let status = '';
if (upstream.missing) {
status = 'missing';
} else {
if (state.behind) {
status += `${pluralize('commit', state.behind, {
infix: icons ? '$(arrow-down) ' : undefined,
})} behind`;
}
if (state.ahead) {
status += `${status.length === 0 ? '' : separator}${pluralize('commit', state.ahead, {
infix: icons ? '$(arrow-up) ' : undefined,
})} ahead`;
if (suffix.startsWith(` ${upstream.name.split('/')[0]}`)) {
status += ' of';
}
if (expand) {
let status = '';
if (upstream.missing) {
status = 'missing';
} else {
if (state.behind) {
status += `${pluralize('commit', state.behind, {
infix: icons ? '$(arrow-down) ' : undefined,
})} behind`;
}
if (state.ahead) {
status += `${status.length === 0 ? '' : separator}${pluralize('commit', state.ahead, {
infix: icons ? '$(arrow-up) ' : undefined,
})} ahead`;
if (suffix.startsWith(` ${upstream.name.split('/')[0]}`)) {
status += ' of';
}
}
return `${prefix}${status}${suffix}`;
}
return `${prefix}${status}${suffix}`;
}
const showCounts = count && !upstream.missing;
const showCounts = count && !upstream.missing;
return `${prefix}${showCounts ? state.behind : ''}${
showCounts || state.behind !== 0 ? GlyphChars.ArrowDown : ''
}${separator}${showCounts ? state.ahead : ''}${
showCounts || state.ahead !== 0 ? GlyphChars.ArrowUp : ''
}${suffix}`;
}
return `${prefix}${showCounts ? state.behind : ''}${
showCounts || state.behind !== 0 ? GlyphChars.ArrowDown : ''
}${separator}${showCounts ? state.ahead : ''}${showCounts || state.ahead !== 0 ? GlyphChars.ArrowUp : ''}${suffix}`;
}
export class GitStatusFile implements GitFile {

+ 24
- 24
src/git/models/tag.ts Zobrazit soubor

@ -11,30 +11,6 @@ export interface TagSortOptions {
}
export class GitTag implements GitTagReference {
static is(tag: any): tag is GitTag {
return tag instanceof GitTag;
}
static isOfRefType(tag: GitReference | undefined) {
return tag?.refType === 'tag';
}
static sort(tags: GitTag[], options?: TagSortOptions) {
options = { orderBy: configuration.get('sortTagsBy'), ...options };
switch (options.orderBy) {
case TagSorting.DateAsc:
return tags.sort((a, b) => (a.date?.getTime() ?? 0) - (b.date?.getTime() ?? 0));
case TagSorting.NameAsc:
return tags.sort((a, b) => sortCompare(a.name, b.name));
case TagSorting.NameDesc:
return tags.sort((a, b) => sortCompare(b.name, a.name));
case TagSorting.DateDesc:
default:
return tags.sort((a, b) => (b.date?.getTime() ?? 0) - (a.date?.getTime() ?? 0));
}
}
readonly refType = 'tag';
constructor(
@ -80,3 +56,27 @@ export class GitTag implements GitTagReference {
return index !== -1 ? this.name.substring(index + 1) : this.name;
}
}
export function isTag(tag: any): tag is GitTag {
return tag instanceof GitTag;
}
export function isOfTagRefType(tag: GitReference | undefined) {
return tag?.refType === 'tag';
}
export function sortTags(tags: GitTag[], options?: TagSortOptions) {
options = { orderBy: configuration.get('sortTagsBy'), ...options };
switch (options.orderBy) {
case TagSorting.DateAsc:
return tags.sort((a, b) => (a.date?.getTime() ?? 0) - (b.date?.getTime() ?? 0));
case TagSorting.NameAsc:
return tags.sort((a, b) => sortCompare(a.name, b.name));
case TagSorting.NameDesc:
return tags.sort((a, b) => sortCompare(b.name, a.name));
case TagSorting.DateDesc:
default:
return tags.sort((a, b) => (b.date?.getTime() ?? 0) - (a.date?.getTime() ?? 0));
}
}

+ 4
- 4
src/plus/github/githubGitProvider.ts Zobrazit soubor

@ -28,7 +28,7 @@ import { GitProviderId, RepositoryVisibility } from '../../git/gitProvider';
import { GitUri } from '../../git/gitUri';
import type { GitBlame, GitBlameAuthor, GitBlameLine, GitBlameLines } from '../../git/models/blame';
import type { BranchSortOptions } from '../../git/models/branch';
import { GitBranch } from '../../git/models/branch';
import { GitBranch, sortBranches } from '../../git/models/branch';
import type { GitCommitLine } from '../../git/models/commit';
import { GitCommit, GitCommitIdentity } from '../../git/models/commit';
import { GitContributor } from '../../git/models/contributor';
@ -47,7 +47,7 @@ import { Repository } from '../../git/models/repository';
import type { GitStash } from '../../git/models/stash';
import type { GitStatus, GitStatusFile } from '../../git/models/status';
import type { TagSortOptions } from '../../git/models/tag';
import { GitTag } from '../../git/models/tag';
import { GitTag, sortTags } from '../../git/models/tag';
import type { GitTreeEntry } from '../../git/models/tree';
import type { GitUser } from '../../git/models/user';
import { isUserMatch } from '../../git/models/user';
@ -814,7 +814,7 @@ export class GitHubGitProvider implements GitProvider, Disposable {
}
if (options?.sort != null) {
GitBranch.sort(result.values, typeof options.sort === 'boolean' ? undefined : options.sort);
sortBranches(result.values, typeof options.sort === 'boolean' ? undefined : options.sort);
}
return result;
@ -2259,7 +2259,7 @@ export class GitHubGitProvider implements GitProvider, Disposable {
}
if (options?.sort != null) {
GitTag.sort(result.values, typeof options.sort === 'boolean' ? undefined : options.sort);
sortTags(result.values, typeof options.sort === 'boolean' ? undefined : options.sort);
}
return result;

+ 5
- 5
src/quickpicks/remoteProviderPicker.ts Zobrazit soubor

@ -3,7 +3,7 @@ import { env, ThemeIcon, Uri, window } from 'vscode';
import type { OpenOnRemoteCommandArgs } from '../commands';
import { Commands, GlyphChars } from '../constants';
import { Container } from '../container';
import { GitBranch } from '../git/models/branch';
import { getBranchNameWithoutRemote, getRemoteNameFromBranchName } from '../git/models/branch';
import { GitRemote } from '../git/models/remote';
import type { RemoteProvider, RemoteResource } from '../git/remotes/provider';
import { getNameFromRemoteResource, RemoteResourceType } from '../git/remotes/provider';
@ -41,12 +41,12 @@ export class CopyOrOpenRemoteCommandQuickPickItem extends CommandQuickPickItem {
override async execute(): Promise<void> {
let resource = this.resource;
if (resource.type === RemoteResourceType.Comparison) {
if (GitBranch.getRemote(resource.base) === this.remote.name) {
resource = { ...resource, base: GitBranch.getNameWithoutRemote(resource.base) };
if (getRemoteNameFromBranchName(resource.base) === this.remote.name) {
resource = { ...resource, base: getBranchNameWithoutRemote(resource.base) };
}
if (GitBranch.getRemote(resource.compare) === this.remote.name) {
resource = { ...resource, compare: GitBranch.getNameWithoutRemote(resource.compare) };
if (getRemoteNameFromBranchName(resource.compare) === this.remote.name) {
resource = { ...resource, compare: getBranchNameWithoutRemote(resource.compare) };
}
} else if (resource.type === RemoteResourceType.CreatePullRequest) {
let branch = resource.base.branch;

+ 2
- 2
src/system/utils.ts Zobrazit soubor

@ -2,7 +2,7 @@ import type { TextDocument, TextDocumentShowOptions, TextEditor, Uri } from 'vsc
import { ViewColumn, window, workspace } from 'vscode';
import { configuration } from '../configuration';
import { CoreCommands, ImageMimetypes, Schemes } from '../constants';
import { GitUri } from '../git/gitUri';
import { isGitUri } from '../git/gitUri';
import { Logger } from '../logger';
import { executeCoreCommand } from './command';
import { extname } from './path';
@ -98,7 +98,7 @@ export async function openEditor(
): Promise<TextEditor | undefined> {
const { rethrow, ...opts } = options;
try {
if (GitUri.is(uri)) {
if (isGitUri(uri)) {
uri = uri.documentUri();
}

+ 3
- 2
src/trackers/documentTracker.ts Zobrazit soubor

@ -15,7 +15,8 @@ import { ContextKeys } from '../constants';
import type { Container } from '../container';
import { setContext } from '../context';
import type { RepositoriesChangeEvent } from '../git/gitProviderService';
import { GitUri } from '../git/gitUri';
import type { GitUri } from '../git/gitUri';
import { isGitUri } from '../git/gitUri';
import type { RepositoryChangeEvent } from '../git/models/repository';
import { RepositoryChange, RepositoryChangeComparisonMode } from '../git/models/repository';
import { debug } from '../system/decorators/log';
@ -235,7 +236,7 @@ export class DocumentTracker implements Disposable {
add(documentOrUri: TextDocument | Uri): Promise<TrackedDocument<T>>;
async add(documentOrUri: TextDocument | Uri): Promise<TrackedDocument<T>> {
let document;
if (GitUri.is(documentOrUri)) {
if (isGitUri(documentOrUri)) {
try {
document = await workspace.openTextDocument(documentOrUri.documentUri());
} catch (ex) {

+ 5
- 5
src/views/nodes/branchTrackingStatusNode.ts Zobrazit soubor

@ -1,8 +1,8 @@
import { MarkdownString, ThemeColor, ThemeIcon, TreeItem, TreeItemCollapsibleState, window } from 'vscode';
import { Colors } from '../../constants';
import { GitUri } from '../../git/gitUri';
import type { GitTrackingState } from '../../git/models/branch';
import { GitBranch } from '../../git/models/branch';
import type { GitBranch, GitTrackingState } from '../../git/models/branch';
import { getRemoteNameFromBranchName } from '../../git/models/branch';
import type { GitLog } from '../../git/models/log';
import { GitRevision } from '../../git/models/reference';
import { GitRemote } from '../../git/models/remote';
@ -170,7 +170,7 @@ export class BranchTrackingStatusNode extends ViewNode impleme
case 'ahead': {
const remote = await this.branch.getRemote();
label = `Changes to push to ${remote?.name ?? GitBranch.getRemote(this.status.upstream!)}${
label = `Changes to push to ${remote?.name ?? getRemoteNameFromBranchName(this.status.upstream!)}${
remote?.provider?.name ? ` on ${remote?.provider.name}` : ''
}`;
description = pluralize('commit', this.status.state.ahead);
@ -191,7 +191,7 @@ export class BranchTrackingStatusNode extends ViewNode impleme
case 'behind': {
const remote = await this.branch.getRemote();
label = `Changes to pull from ${remote?.name ?? GitBranch.getRemote(this.status.upstream!)}${
label = `Changes to pull from ${remote?.name ?? getRemoteNameFromBranchName(this.status.upstream!)}${
remote?.provider?.name ? ` on ${remote.provider.name}` : ''
}`;
description = pluralize('commit', this.status.state.behind);
@ -212,7 +212,7 @@ export class BranchTrackingStatusNode extends ViewNode impleme
case 'same': {
const remote = await this.branch.getRemote();
label = `Up to date with ${remote?.name ?? GitBranch.getRemote(this.status.upstream!)}${
label = `Up to date with ${remote?.name ?? getRemoteNameFromBranchName(this.status.upstream!)}${
remote?.provider?.name ? ` on ${remote.provider.name}` : ''
}`;
description = lastFetched ? `Last fetched ${fromNow(new Date(lastFetched))}` : '';

+ 4
- 4
src/views/nodes/common.ts Zobrazit soubor

@ -2,7 +2,7 @@ import type { Command, ThemeIcon, Uri } from 'vscode';
import { TreeItem, TreeItemCollapsibleState } from 'vscode';
import { configuration } from '../../configuration';
import { GlyphChars } from '../../constants';
import { GitUri } from '../../git/gitUri';
import { unknownGitUri } from '../../git/gitUri';
import type { View } from '../viewBase';
import type { PageableViewNode } from './viewNode';
import { ContextValues, ViewNode } from './viewNode';
@ -24,7 +24,7 @@ export class MessageNode extends ViewNode {
| ThemeIcon,
private readonly _contextValue?: string,
) {
super(GitUri.unknown, view, parent);
super(unknownGitUri, view, parent);
}
getChildren(): ViewNode[] | Promise<ViewNode[]> {
@ -93,7 +93,7 @@ export class UpdateableMessageNode extends ViewNode {
}
| ThemeIcon,
) {
super(GitUri.unknown, view, parent);
super(unknownGitUri, view, parent);
this.id = id;
}
@ -154,7 +154,7 @@ export abstract class PagerNode extends ViewNode {
getCount?: () => Promise<number | undefined>;
}, // protected readonly pageSize: number = configuration.get('views.pageItemLimit'), // protected readonly countFn?: () => Promise<number | undefined>, // protected readonly context?: Record<string, unknown>, // protected readonly beforeLoadCallback?: (mode: 'all' | 'more') => void,
) {
super(GitUri.unknown, view, parent);
super(unknownGitUri, view, parent);
}
async loadAll() {

+ 2
- 2
src/views/nodes/comparePickerNode.ts Zobrazit soubor

@ -1,6 +1,6 @@
import { TreeItem, TreeItemCollapsibleState } from 'vscode';
import { GlyphChars } from '../../constants';
import { GitUri } from '../../git/gitUri';
import { unknownGitUri } from '../../git/gitUri';
import type { NamedRef } from '../../storage';
import type { SearchAndCompareView, SearchAndCompareViewNode } from '../searchAndCompareView';
import { ContextValues, ViewNode } from './viewNode';
@ -16,7 +16,7 @@ export class ComparePickerNode extends ViewNode {
readonly pinned: boolean = false;
constructor(view: SearchAndCompareView, parent: SearchAndCompareViewNode, public readonly selectedRef: RepoRef) {
super(GitUri.unknown, view, parent);
super(unknownGitUri, view, parent);
}
get canDismiss(): boolean {

+ 5
- 5
src/views/nodes/fileHistoryTrackerNode.ts Zobrazit soubor

@ -4,7 +4,7 @@ import { UriComparer } from '../../comparers';
import { ContextKeys } from '../../constants';
import { setContext } from '../../context';
import type { GitCommitish } from '../../git/gitUri';
import { GitUri } from '../../git/gitUri';
import { GitUri, unknownGitUri } from '../../git/gitUri';
import { GitReference, GitRevision } from '../../git/models/reference';
import { Logger } from '../../logger';
import { ReferencePicker } from '../../quickpicks/referencePicker';
@ -24,7 +24,7 @@ export class FileHistoryTrackerNode extends SubscribeableViewNode
protected override splatted = true;
constructor(view: FileHistoryView) {
super(GitUri.unknown, view);
super(unknownGitUri, view);
}
override dispose() {
@ -99,7 +99,7 @@ export class FileHistoryTrackerNode extends SubscribeableViewNode
}
get hasUri(): boolean {
return this._uri != GitUri.unknown;
return this._uri != unknownGitUri;
}
@gate()
@ -140,7 +140,7 @@ export class FileHistoryTrackerNode extends SubscribeableViewNode
if (!this.canSubscribe) return false;
if (reset) {
if (this._uri != null && this._uri !== GitUri.unknown) {
if (this._uri != null && this._uri !== unknownGitUri) {
await this.view.container.tracker.resetCache(this._uri, 'log');
}
@ -256,7 +256,7 @@ export class FileHistoryTrackerNode extends SubscribeableViewNode
}
setUri(uri?: GitUri) {
this._uri = uri ?? GitUri.unknown;
this._uri = uri ?? unknownGitUri;
void setContext(ContextKeys.ViewsFileHistoryCanPin, this.hasUri);
}
}

+ 5
- 5
src/views/nodes/lineHistoryTrackerNode.ts Zobrazit soubor

@ -4,7 +4,7 @@ import { UriComparer } from '../../comparers';
import { ContextKeys } from '../../constants';
import { setContext } from '../../context';
import type { GitCommitish } from '../../git/gitUri';
import { GitUri } from '../../git/gitUri';
import { GitUri, unknownGitUri } from '../../git/gitUri';
import { GitReference, GitRevision } from '../../git/models/reference';
import { Logger } from '../../logger';
import { ReferencePicker } from '../../quickpicks/referencePicker';
@ -26,7 +26,7 @@ export class LineHistoryTrackerNode extends SubscribeableViewNode
protected override splatted = true;
constructor(view: FileHistoryView | LineHistoryView) {
super(GitUri.unknown, view);
super(unknownGitUri, view);
}
override dispose() {
@ -109,7 +109,7 @@ export class LineHistoryTrackerNode extends SubscribeableViewNode
}
get hasUri(): boolean {
return this._uri != GitUri.unknown;
return this._uri != unknownGitUri;
}
@gate()
@ -150,7 +150,7 @@ export class LineHistoryTrackerNode extends SubscribeableViewNode
if (!this.canSubscribe) return false;
if (reset) {
if (this._uri != null && this._uri !== GitUri.unknown) {
if (this._uri != null && this._uri !== unknownGitUri) {
await this.view.container.tracker.resetCache(this._uri, 'log');
}
@ -258,7 +258,7 @@ export class LineHistoryTrackerNode extends SubscribeableViewNode
}
setUri(uri?: GitUri) {
this._uri = uri ?? GitUri.unknown;
this._uri = uri ?? unknownGitUri;
void setContext(ContextKeys.ViewsFileHistoryCanPin, this.hasUri);
}
}

+ 2
- 2
src/views/nodes/repositoriesNode.ts Zobrazit soubor

@ -1,7 +1,7 @@
import type { TextEditor } from 'vscode';
import { Disposable, TreeItem, TreeItemCollapsibleState, window } from 'vscode';
import type { RepositoriesChangeEvent } from '../../git/gitProviderService';
import { GitUri } from '../../git/gitUri';
import { GitUri, unknownGitUri } from '../../git/gitUri';
import { Logger } from '../../logger';
import { gate } from '../../system/decorators/gate';
import { debug } from '../../system/decorators/log';
@ -16,7 +16,7 @@ export class RepositoriesNode extends SubscribeableViewNode {
private _children: (RepositoryNode | MessageNode)[] | undefined;
constructor(view: RepositoriesView) {
super(GitUri.unknown, view);
super(unknownGitUri, view);
}
override dispose() {

+ 2
- 6
src/views/nodes/searchResultsNode.ts Zobrazit soubor

@ -35,10 +35,6 @@ export class SearchResultsNode extends ViewNode implements
return md5(`${repoPath}|${SearchPattern.toKey(search)}`);
}
static override is(node: any): node is SearchResultsNode {
return node instanceof SearchResultsNode;
}
private _instanceId: number;
constructor(
view: SearchAndCompareView,
@ -170,7 +166,7 @@ export class SearchResultsNode extends ViewNode implements
log: Promise<GitLog | undefined> | GitLog | undefined;
}) {
if (search == null) {
(await executeGitCommand({
await executeGitCommand({
command: 'search',
prefillOnly: true,
state: {
@ -178,7 +174,7 @@ export class SearchResultsNode extends ViewNode implements
...this.search,
showResultsInSideBar: this,
},
}));
});
return;
}

+ 7
- 6
src/views/nodes/viewNode.ts Zobrazit soubor

@ -2,7 +2,8 @@ import type { Command, Event, TreeViewVisibilityChangeEvent } from 'vscode';
import { Disposable, MarkdownString, TreeItem, TreeItemCollapsibleState } from 'vscode';
import { GlyphChars } from '../../constants';
import type { RepositoriesChangeEvent } from '../../git/gitProviderService';
import { GitUri } from '../../git/gitUri';
import type { GitUri } from '../../git/gitUri';
import { unknownGitUri } from '../../git/gitUri';
import type { GitFile } from '../../git/models/file';
import type { GitRevisionReference } from '../../git/models/reference';
import { GitReference } from '../../git/models/reference';
@ -85,10 +86,6 @@ export interface ViewNode {
@logName<ViewNode>((c, name) => `${name}${c.id != null ? `(${c.id})` : ''}`)
export abstract class ViewNode<TView extends View = View, State extends object = any> {
static is(node: any): node is ViewNode {
return node instanceof ViewNode;
}
protected splatted = false;
constructor(uri: GitUri, public readonly view: TView, protected readonly parent?: ViewNode) {
@ -163,6 +160,10 @@ export abstract class ViewNode
}
}
export function isViewNode(node: any): node is ViewNode {
return node instanceof ViewNode;
}
type StateKey<T> = keyof T;
type StateValue<T, P extends StateKey<T>> = P extends keyof T ? T[P] : never;
@ -543,7 +544,7 @@ export abstract class RepositoriesSubscribeableNode<
protected children: TChild[] | undefined;
constructor(view: TView) {
super(GitUri.unknown, view);
super(unknownGitUri, view);
}
override async getSplattedChild() {

+ 2
- 2
src/views/remotesView.ts Zobrazit soubor

@ -5,7 +5,7 @@ import { configuration, ViewBranchesLayout, ViewFilesLayout } from '../configura
import { Commands } from '../constants';
import type { Container } from '../container';
import { GitUri } from '../git/gitUri';
import { GitBranch } from '../git/models/branch';
import { getRemoteNameFromBranchName } from '../git/models/branch';
import { GitCommit } from '../git/models/commit';
import type { GitBranchReference, GitRevisionReference } from '../git/models/reference';
import { GitReference } from '../git/models/reference';
@ -209,7 +209,7 @@ export class RemotesView extends ViewBase {
if (n instanceof RemoteNode) {
if (!n.id.startsWith(repoNodeId)) return false;
return n.remote.name === GitBranch.getRemote(branch.name);
return n.remote.name === getRemoteNameFromBranchName(branch.name);
}
return false;

+ 2
- 2
src/views/repositoriesView.ts Zobrazit soubor

@ -5,7 +5,7 @@ import { configuration, ViewBranchesLayout, ViewFilesLayout, ViewShowBranchCompa
import { Commands, ContextKeys } from '../constants';
import type { Container } from '../container';
import { setContext } from '../context';
import { GitBranch } from '../git/models/branch';
import { getRemoteNameFromBranchName } from '../git/models/branch';
import { GitCommit } from '../git/models/commit';
import type { GitContributor } from '../git/models/contributor';
import type {
@ -294,7 +294,7 @@ export class RepositoriesView extends ViewBase
if (n instanceof RemoteNode) {
if (!n.id.startsWith(repoNodeId)) return false;
return branch.remote && n.remote.name === GitBranch.getRemote(branch.name); //branch.getRemoteName();
return branch.remote && n.remote.name === getRemoteNameFromBranchName(branch.name); //branch.getRemoteName();
}
if (

+ 3
- 3
src/views/searchAndCompareView.ts Zobrazit soubor

@ -5,7 +5,7 @@ import { configuration, ViewFilesLayout } from '../configuration';
import { Commands, ContextKeys } from '../constants';
import type { Container } from '../container';
import { setContext } from '../context';
import { GitUri } from '../git/gitUri';
import { unknownGitUri } from '../git/gitUri';
import type { GitLog } from '../git/models/log';
import { GitRevision } from '../git/models/reference';
import type { SearchPattern } from '../git/search';
@ -41,7 +41,7 @@ export class SearchAndCompareViewNode extends ViewNode {
private comparePicker: ComparePickerNode | undefined;
constructor(view: SearchAndCompareView) {
super(GitUri.unknown, view);
super(unknownGitUri, view);
}
private _children: (ComparePickerNode | CompareResultsNode | SearchResultsNode)[] | undefined;
@ -173,7 +173,7 @@ export class SearchAndCompareViewNode extends ViewNode {
}
this.removeComparePicker();
(await this.view.compare(repoPath, selectedRef.ref, ref));
await this.view.compare(repoPath, selectedRef.ref, ref);
}
async selectForCompare(repoPath?: string, ref?: string | NamedRef, options?: { prompt?: boolean }) {

Načítá se…
Zrušit
Uložit