@ -1,85 +1,101 @@ | |||
'use strict'; | |||
import { commands, TextEditor, Uri, window } from 'vscode'; | |||
import { ActiveEditorTracker } from '../activeEditorTracker'; | |||
import { ActiveEditorCommand, Commands, getCommandUri } from './common'; | |||
import { TextEditorComparer, UriComparer } from '../comparers'; | |||
import { BuiltInCommands } from '../constants'; | |||
import { GitService } from '../gitService'; | |||
import { Logger } from '../logger'; | |||
import { Messages } from '../messages'; | |||
export interface CloseUnchangedFilesCommandArgs { | |||
uris?: Uri[]; | |||
} | |||
export class CloseUnchangedFilesCommand extends ActiveEditorCommand { | |||
constructor(private git: GitService) { | |||
super(Commands.CloseUnchangedFiles); | |||
} | |||
async execute(editor: TextEditor, uri?: Uri, args: CloseUnchangedFilesCommandArgs = {}) { | |||
uri = getCommandUri(uri, editor); | |||
try { | |||
if (args.uris === undefined) { | |||
const repoPath = await this.git.getRepoPathFromUri(uri); | |||
if (!repoPath) return Messages.showNoRepositoryWarningMessage(`Unable to close unchanged files`); | |||
const status = await this.git.getStatusForRepo(repoPath); | |||
if (status === undefined) return window.showWarningMessage(`Unable to close unchanged files`); | |||
args.uris = status.files.map(_ => _.Uri); | |||
} | |||
if (args.uris.length === 0) return commands.executeCommand(BuiltInCommands.CloseAllEditors); | |||
const editorTracker = new ActiveEditorTracker(); | |||
let count = 0; | |||
let previous = undefined; | |||
let editor = window.activeTextEditor; | |||
while (true) { | |||
if (editor !== undefined) { | |||
if (TextEditorComparer.equals(previous, editor, { useId: true, usePosition: true })) { | |||
break; | |||
} | |||
if (editor.document !== undefined && | |||
(editor.document.isDirty || args.uris.some(_ => UriComparer.equals(_, editor!.document && editor!.document.uri)))) { | |||
'use strict'; | |||
import { commands, TextEditor, Uri, window } from 'vscode'; | |||
import { ActiveEditorTracker } from '../activeEditorTracker'; | |||
import { ActiveEditorCommand, CommandContext, Commands, getCommandUri } from './common'; | |||
import { TextEditorComparer, UriComparer } from '../comparers'; | |||
import { BuiltInCommands } from '../constants'; | |||
import { GitService } from '../gitService'; | |||
import { Logger } from '../logger'; | |||
import { Messages } from '../messages'; | |||
export interface CloseUnchangedFilesCommandArgs { | |||
uris?: Uri[]; | |||
} | |||
export class CloseUnchangedFilesCommand extends ActiveEditorCommand { | |||
constructor(private git: GitService) { | |||
super(Commands.CloseUnchangedFiles); | |||
} | |||
async run(context: CommandContext, args: CloseUnchangedFilesCommandArgs = {}): Promise<any> { | |||
// Since we can change the args and they could be cached -- make a copy | |||
switch (context.type) { | |||
case 'uri': | |||
return this.execute(context.editor, context.uri, { ...args }); | |||
case 'scm-states': | |||
return undefined; | |||
case 'scm-groups': | |||
// const group = context.scmResourceGroups[0]; | |||
// args.uris = group.resourceStates.map(_ => _.resourceUri); | |||
return this.execute(undefined, undefined, { ...args }); | |||
default: | |||
return this.execute(context.editor, undefined, { ...args }); | |||
} | |||
} | |||
async execute(editor: TextEditor | undefined, uri?: Uri, args: CloseUnchangedFilesCommandArgs = {}) { | |||
uri = getCommandUri(uri, editor); | |||
try { | |||
if (args.uris === undefined) { | |||
const repoPath = await this.git.getRepoPathFromUri(uri); | |||
if (!repoPath) return Messages.showNoRepositoryWarningMessage(`Unable to close unchanged files`); | |||
const status = await this.git.getStatusForRepo(repoPath); | |||
if (status === undefined) return window.showWarningMessage(`Unable to close unchanged files`); | |||
args.uris = status.files.map(_ => _.Uri); | |||
} | |||
if (args.uris.length === 0) return commands.executeCommand(BuiltInCommands.CloseAllEditors); | |||
const editorTracker = new ActiveEditorTracker(); | |||
let count = 0; | |||
let previous = undefined; | |||
let editor = window.activeTextEditor; | |||
while (true) { | |||
if (editor !== undefined) { | |||
if (TextEditorComparer.equals(previous, editor, { useId: true, usePosition: true })) { | |||
break; | |||
} | |||
if (editor.document !== undefined && | |||
(editor.document.isDirty || args.uris.some(_ => UriComparer.equals(_, editor!.document && editor!.document.uri)))) { | |||
const lastPrevious = previous; | |||
previous = editor; | |||
editor = await editorTracker.awaitNext(500); | |||
previous = editor; | |||
editor = await editorTracker.awaitNext(500); | |||
if (TextEditorComparer.equals(lastPrevious, editor, { useId: true, usePosition: true })) { | |||
break; | |||
} | |||
continue; | |||
} | |||
} | |||
previous = editor; | |||
editor = await editorTracker.awaitClose(500); | |||
if (previous === undefined && editor === undefined) { | |||
count++; | |||
// This is such a shitty hack, but I can't figure out any other reliable way to know that we've cycled through all the editors :( | |||
if (count >= 4) { | |||
break; | |||
} | |||
} | |||
else { | |||
count = 0; | |||
} | |||
} | |||
editorTracker.dispose(); | |||
return undefined; | |||
} | |||
catch (ex) { | |||
Logger.error(ex, 'CloseUnchangedFilesCommand'); | |||
return window.showErrorMessage(`Unable to close unchanged files. See output channel for more details`); | |||
} | |||
} | |||
continue; | |||
} | |||
} | |||
previous = editor; | |||
editor = await editorTracker.awaitClose(500); | |||
if (previous === undefined && editor === undefined) { | |||
count++; | |||
// This is such a shitty hack, but I can't figure out any other reliable way to know that we've cycled through all the editors :( | |||
if (count >= 4) { | |||
break; | |||
} | |||
} | |||
else { | |||
count = 0; | |||
} | |||
} | |||
editorTracker.dispose(); | |||
return undefined; | |||
} | |||
catch (ex) { | |||
Logger.error(ex, 'CloseUnchangedFilesCommand'); | |||
return window.showErrorMessage(`Unable to close unchanged files. See output channel for more details`); | |||
} | |||
} | |||
} |
@ -1,63 +1,78 @@ | |||
'use strict'; | |||
import { commands, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode'; | |||
import { ActiveEditorCommand, Commands, getCommandUri } from './common'; | |||
import { BuiltInCommands, GlyphChars } from '../constants'; | |||
import { GitService, GitUri } from '../gitService'; | |||
import { Logger } from '../logger'; | |||
import { Messages } from '../messages'; | |||
import { BranchesQuickPick, CommandQuickPickItem } from '../quickPicks'; | |||
import * as path from 'path'; | |||
export interface DiffWithBranchCommandArgs { | |||
line?: number; | |||
showOptions?: TextDocumentShowOptions; | |||
goBackCommand?: CommandQuickPickItem; | |||
} | |||
export class DiffWithBranchCommand extends ActiveEditorCommand { | |||
constructor(private git: GitService) { | |||
super(Commands.DiffWithBranch); | |||
} | |||
async execute(editor: TextEditor, uri?: Uri, args: DiffWithBranchCommandArgs = {}): Promise<any> { | |||
uri = getCommandUri(uri, editor); | |||
if (uri === undefined) return undefined; | |||
'use strict'; | |||
import { commands, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode'; | |||
import { ActiveEditorCommand, CommandContext, Commands, getCommandUri } from './common'; | |||
import { BuiltInCommands, GlyphChars } from '../constants'; | |||
import { GitService, GitUri } from '../gitService'; | |||
import { Logger } from '../logger'; | |||
import { Messages } from '../messages'; | |||
import { BranchesQuickPick, CommandQuickPickItem } from '../quickPicks'; | |||
import * as path from 'path'; | |||
export interface DiffWithBranchCommandArgs { | |||
line?: number; | |||
showOptions?: TextDocumentShowOptions; | |||
goBackCommand?: CommandQuickPickItem; | |||
} | |||
export class DiffWithBranchCommand extends ActiveEditorCommand { | |||
constructor(private git: GitService) { | |||
super(Commands.DiffWithBranch); | |||
} | |||
async run(context: CommandContext, args: DiffWithBranchCommandArgs = {}): Promise<any> { | |||
// Since we can change the args and they could be cached -- make a copy | |||
switch (context.type) { | |||
case 'uri': | |||
return this.execute(context.editor, context.uri, { ...args }); | |||
case 'scm-states': | |||
const resource = context.scmResourceStates[0]; | |||
return this.execute(undefined, resource.resourceUri, { ...args }); | |||
case 'scm-groups': | |||
return undefined; | |||
default: | |||
return this.execute(context.editor, undefined, { ...args }); | |||
} | |||
} | |||
async execute(editor: TextEditor | undefined, uri?: Uri, args: DiffWithBranchCommandArgs = {}): Promise<any> { | |||
uri = getCommandUri(uri, editor); | |||
if (uri === undefined) return undefined; | |||
if (args.line === undefined) { | |||
args.line = editor === undefined ? 0 : editor.selection.active.line; | |||
} | |||
const gitUri = await GitUri.fromUri(uri, this.git); | |||
if (!gitUri.repoPath) return Messages.showNoRepositoryWarningMessage(`Unable to open branch compare`); | |||
const branches = await this.git.getBranches(gitUri.repoPath); | |||
const pick = await BranchesQuickPick.show(branches, `Compare ${path.basename(gitUri.fsPath)} to ${GlyphChars.Ellipsis}`, args.goBackCommand); | |||
if (pick === undefined) return undefined; | |||
if (pick instanceof CommandQuickPickItem) return pick.execute(); | |||
const branch = pick.branch.name; | |||
if (branch === undefined) return undefined; | |||
try { | |||
const compare = await this.git.getVersionedFile(gitUri.repoPath, gitUri.fsPath, branch); | |||
await commands.executeCommand(BuiltInCommands.Diff, | |||
Uri.file(compare), | |||
gitUri.fileUri(), | |||
`${path.basename(gitUri.fsPath)} (${branch}) ${GlyphChars.ArrowLeftRight} ${path.basename(gitUri.fsPath)}`, | |||
args.showOptions); | |||
if (args.line === undefined || args.line === 0) return undefined; | |||
// TODO: Figure out how to focus the left pane | |||
return await commands.executeCommand(BuiltInCommands.RevealLine, { lineNumber: args.line, at: 'center' }); | |||
} | |||
catch (ex) { | |||
Logger.error(ex, 'DiffWithBranchCommand', 'getVersionedFile'); | |||
return window.showErrorMessage(`Unable to open branch compare. See output channel for more details`); | |||
} | |||
} | |||
const gitUri = await GitUri.fromUri(uri, this.git); | |||
if (!gitUri.repoPath) return Messages.showNoRepositoryWarningMessage(`Unable to open branch compare`); | |||
const branches = await this.git.getBranches(gitUri.repoPath); | |||
const pick = await BranchesQuickPick.show(branches, `Compare ${path.basename(gitUri.fsPath)} to ${GlyphChars.Ellipsis}`, args.goBackCommand); | |||
if (pick === undefined) return undefined; | |||
if (pick instanceof CommandQuickPickItem) return pick.execute(); | |||
const branch = pick.branch.name; | |||
if (branch === undefined) return undefined; | |||
try { | |||
const compare = await this.git.getVersionedFile(gitUri.repoPath, gitUri.fsPath, branch); | |||
await commands.executeCommand(BuiltInCommands.Diff, | |||
Uri.file(compare), | |||
gitUri.fileUri(), | |||
`${path.basename(gitUri.fsPath)} (${branch}) ${GlyphChars.ArrowLeftRight} ${path.basename(gitUri.fsPath)}`, | |||
args.showOptions); | |||
if (args.line === undefined || args.line === 0) return undefined; | |||
// TODO: Figure out how to focus the left pane | |||
return await commands.executeCommand(BuiltInCommands.RevealLine, { lineNumber: args.line, at: 'center' }); | |||
} | |||
catch (ex) { | |||
Logger.error(ex, 'DiffWithBranchCommand', 'getVersionedFile'); | |||
return window.showErrorMessage(`Unable to open branch compare. See output channel for more details`); | |||
} | |||
} | |||
} |