Browse Source

Adds "Incoming Activity" node to repos view - #735

Replaces "recent incoming changes" node
main
Eric Amodio 5 years ago
parent
commit
ae5c728270
14 changed files with 341 additions and 111 deletions
  1. +13
    -0
      CHANGELOG.md
  2. +11
    -0
      README.md
  3. +4
    -0
      images/dark/icon-merge.svg
  4. +4
    -0
      images/light/icon-merge.svg
  5. +7
    -1
      src/git/git.ts
  6. +11
    -3
      src/git/gitService.ts
  7. +60
    -6
      src/git/models/reflog.ts
  8. +83
    -23
      src/git/parsers/reflogParser.ts
  9. +4
    -3
      src/views/nodes.ts
  10. +0
    -61
      src/views/nodes/recentIncomingChangesNode.ts
  11. +66
    -0
      src/views/nodes/reflogNode.ts
  12. +67
    -0
      src/views/nodes/reflogRecordNode.ts
  13. +9
    -13
      src/views/nodes/repositoryNode.ts
  14. +2
    -1
      src/views/nodes/viewNode.ts

+ 13
- 0
CHANGELOG.md View File

@ -6,6 +6,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
## [Unreleased] ## [Unreleased]
## Added
- Adds a new experimental _Incoming Activity_ node to each repository in the _Repositories_ view (enabled via `"gitlens.insiders": true`) — closes [#735](https://github.com/eamodio/vscode-gitlens/issues/735)
- **Incoming Activity** — lists the recent incoming activity (merges and pulls) to your local repository
- Provides the activity command, branch (if available), and date
- A context menu provides access to the _Refresh_ command
- Each activity expands to list the commits added by the command
- An inline toolbar provides quick access to the _Compare with HEAD_ (`alt-click` for _Compare with Working Tree_), _Copy Commit ID to Clipboard_ (`alt-click` for _Copy Commit Message to Clipboard_), and _Open Commit on Remote_ (if available) commands
- A context menu provides access to more common revision (commit) commands
- Each revision (commit) expands to list its set of changed files, complete with status indicators for adds, changes, renames, and deletes
- An inline toolbar provides quick access to the _Open File_, _Copy Commit ID to Clipboard_ (`alt-click` for _Copy Commit Message to Clipboard_), and _Open File on Remote_ (if available) commands
- A context menu provides access to more common file revision commands
## Fixed ## Fixed
- Fixes issues with the _Show More Actions_ button on the _Details_ hover not working with renamed files - Fixes issues with the _Show More Actions_ button on the _Details_ hover not working with renamed files

+ 11
- 0
README.md View File

@ -316,6 +316,17 @@ The repositories view provides the following features,
- An inline toolbar provides quick access to the _Open File_, _Copy Commit ID to Clipboard_ (`alt-click` for _Copy Commit Message to Clipboard_), and _Open File on Remote_ (if available) commands - An inline toolbar provides quick access to the _Open File_, _Copy Commit ID to Clipboard_ (`alt-click` for _Copy Commit Message to Clipboard_), and _Open File on Remote_ (if available) commands
- A context menu provides access to more common file revision commands - A context menu provides access to more common file revision commands
- **Incoming Activity** — lists the recent incoming activity (merges and pulls) to your local repository (experimental, enabled via `"gitlens.insiders": true`)
- Provides the activity command, branch (if available), and date
- A context menu provides access to the _Refresh_ command
- Each activity expands to list the commits added by the command
- An inline toolbar provides quick access to the _Compare with HEAD_ (`alt-click` for _Compare with Working Tree_), _Copy Commit ID to Clipboard_ (`alt-click` for _Copy Commit Message to Clipboard_), and _Open Commit on Remote_ (if available) commands
- A context menu provides access to more common revision (commit) commands
- Each revision (commit) expands to list its set of changed files, complete with status indicators for adds, changes, renames, and deletes
- An inline toolbar provides quick access to the _Open File_, _Copy Commit ID to Clipboard_ (`alt-click` for _Copy Commit Message to Clipboard_), and _Open File on Remote_ (if available) commands
- A context menu provides access to more common file revision commands
- **Remotes** — lists the remotes in the repository - **Remotes** — lists the remotes in the repository
- Provides the name of each remote, an indicator of the direction of the remote (fetch, push, both), remote service (if applicable), and repository path - Provides the name of each remote, an indicator of the direction of the remote (fetch, push, both), remote service (if applicable), and repository path

+ 4
- 0
images/dark/icon-merge.svg View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 22">
<path fill="#C5C5C5" d="M12 10.005c-.73 0-1.38.41-1.73 1.02v-.02c-1.05-.02-2.27-.36-3.13-1.02-.75-.58-1.5-1.61-1.89-2.44 1.199-.958.911-2.854-.518-3.413A2.002 2.002 0 0 0 2 6.005a2 2 0 0 0 1 1.72v6.56c-.59.35-1 .99-1 1.72 0 1.11.89 2 2 2 1.534.004 2.497-1.654 1.734-2.985A1.99 1.99 0 0 0 5 14.285v-3.61c.67.7 1.44 1.27 2.3 1.69.86.42 2.03.63 2.97.64v-.02c.36.61 1 1.02 1.73 1.02 1.11 0 2-.89 2-2 0-1.11-.89-2-2-2zm-6.8 6c0 .66-.55 1.2-1.2 1.2-.65 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2zM4 7.205c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm8 6c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"/>
</svg>

+ 4
- 0
images/light/icon-merge.svg View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 22">
<path fill="#424242" d="M12 10.005c-.73 0-1.38.41-1.73 1.02v-.02c-1.05-.02-2.27-.36-3.13-1.02-.75-.58-1.5-1.61-1.89-2.44 1.199-.958.911-2.854-.518-3.413A2.002 2.002 0 0 0 2 6.005a2 2 0 0 0 1 1.72v6.56c-.59.35-1 .99-1 1.72 0 1.11.89 2 2 2 1.534.004 2.497-1.654 1.734-2.985A1.99 1.99 0 0 0 5 14.285v-3.61c.67.7 1.44 1.27 2.3 1.69.86.42 2.03.63 2.97.64v-.02c.36.61 1 1.02 1.73 1.02 1.11 0 2-.89 2-2 0-1.11-.89-2-2-2zm-6.8 6c0 .66-.55 1.2-1.2 1.2-.65 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2zM4 7.205c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm8 6c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"/>
</svg>

+ 7
- 1
src/git/git.ts View File

@ -806,8 +806,14 @@ export class Git {
return git<string>({ cwd: repoPath }, ...params, ref1, ref2); return git<string>({ cwd: repoPath }, ...params, ref1, ref2);
} }
static reflog(repoPath: string, { branch, since }: { branch?: string; since?: string } = {}): Promise<string> {
static reflog(
repoPath: string,
{ all, branch, since }: { all?: boolean; branch?: string; since?: string } = {}
): Promise<string> {
const params = ['log', '-g', `--format=${GitReflogParser.defaultFormat}`, '--date=unix']; const params = ['log', '-g', `--format=${GitReflogParser.defaultFormat}`, '--date=unix'];
if (all) {
params.push('--all');
}
if (branch) { if (branch) {
params.push(branch); params.push(branch);
} }

+ 11
- 3
src/git/gitService.ts View File

@ -95,6 +95,7 @@ export enum GitRepoSearchBy {
} }
const emptyPromise: Promise<GitBlame | GitDiff | GitLog | undefined> = Promise.resolve(undefined); const emptyPromise: Promise<GitBlame | GitDiff | GitLog | undefined> = Promise.resolve(undefined);
const reflogCommands = ['merge', 'pull'];
export class GitService implements Disposable { export class GitService implements Disposable {
private _onDidChangeRepositories = new EventEmitter<void>(); private _onDidChangeRepositories = new EventEmitter<void>();
@ -1955,9 +1956,9 @@ export class GitService implements Disposable {
} }
@log() @log()
async getRecentIncomingChanges(
async getIncomingActivity(
repoPath: string, repoPath: string,
options: { branch?: string; since?: string } = {}
{ maxCount, ...options }: { all?: boolean; branch?: string; maxCount?: number; since?: string } = {}
): Promise<GitReflog | undefined> { ): Promise<GitReflog | undefined> {
const cc = Logger.getCorrelationContext(); const cc = Logger.getCorrelationContext();
@ -1965,7 +1966,14 @@ export class GitService implements Disposable {
const data = await Git.reflog(repoPath, options); const data = await Git.reflog(repoPath, options);
if (data === undefined) return undefined; if (data === undefined) return undefined;
return GitReflogParser.parseRecentIncomingChanges(data, repoPath);
const reflog = GitReflogParser.parse(
data,
repoPath,
reflogCommands,
maxCount == null ? Container.config.advanced.maxListItems || 0 : maxCount
);
return reflog;
} }
catch (ex) { catch (ex) {
Logger.error(ex, cc); Logger.error(ex, cc);

+ 60
- 6
src/git/models/reflog.ts View File

@ -1,19 +1,31 @@
'use strict'; 'use strict';
import { Dates, memoize } from '../../system'; import { Dates, memoize } from '../../system';
import { CommitFormatting } from '../git';
import { CommitFormatting, Git } from '../git';
import { DateStyle } from '../../config'; import { DateStyle } from '../../config';
export class GitReflog {
previousRef: string | undefined;
export interface GitReflog {
readonly repoPath: string;
readonly records: GitReflogRecord[];
readonly count: number;
readonly maxCount: number | undefined;
readonly truncated: boolean;
}
export class GitReflogRecord {
private _previousSha: string | undefined;
constructor( constructor(
public readonly repoPath: string, public readonly repoPath: string,
public readonly ref: string,
public readonly sha: string,
private _selector: string,
public readonly date: Date, public readonly date: Date,
public readonly command: string
public readonly command: string,
public readonly commandArgs: string | undefined,
public readonly details: string | undefined
) {} ) {}
@memoize<GitReflog['formatDate']>(format => (format == null ? 'MMMM Do, YYYY h:mma' : format))
@memoize<GitReflogRecord['formatDate']>(format => (format == null ? 'MMMM Do, YYYY h:mma' : format))
formatDate(format?: string | null) { formatDate(format?: string | null) {
if (format == null) { if (format == null) {
format = 'MMMM Do, YYYY h:mma'; format = 'MMMM Do, YYYY h:mma';
@ -33,6 +45,48 @@ export class GitReflog {
} }
@memoize() @memoize()
get HEAD() {
if (this._selector == null || this._selector.length === 0) return '';
if (this._selector.startsWith('refs/heads')) {
return this._selector.substr(11);
}
if (this._selector.startsWith('refs/remotes')) {
return this._selector.substr(13);
}
return this._selector;
}
get previousSha() {
return this._previousSha;
}
@memoize()
get previousShortSha() {
return Git.shortenSha(this._previousSha);
}
get selector() {
return this._selector;
}
@memoize()
get shortSha() {
return Git.shortenSha(this.sha);
}
update(previousSha?: string, selector?: string) {
if (previousSha !== undefined) {
this._previousSha = previousSha;
}
if (selector !== undefined) {
this._selector = selector;
}
}
@memoize()
private get dateFormatter(): Dates.DateFormatter { private get dateFormatter(): Dates.DateFormatter {
return Dates.getFormatter(this.date); return Dates.getFormatter(this.date);
} }

+ 83
- 23
src/git/parsers/reflogParser.ts View File

@ -1,9 +1,10 @@
'use strict'; 'use strict';
import { debug } from '../../system'; import { debug } from '../../system';
import { GitReflog } from '../models/reflog';
import { GitReflog, GitReflogRecord } from '../models/reflog';
const incomingCommands = ['merge', 'pull'];
const reflogRegex = /^<r>(.+)<d>(?:.+?)@{(.+)}<s>(\w*).*$/gm;
const reflogRegex = /^<r>(.+)<d>(.+?)@{(.+)}<s>(\w*)(.*?)(?::(.*))?$/gm;
// const reflogRegex = /^<r>(.+)<d>(.+?)@{(.+)}<s>(\w*)(.*?)(?::(.*))?<n>(.*)$/gm;
const reflogHEADRegex = /.*?\/?HEAD$/;
// Using %x00 codes because some shells seem to try to expand things if not // Using %x00 codes because some shells seem to try to expand things if not
const lb = '%x3c'; // `%x${'<'.charCodeAt(0).toString(16)}`; const lb = '%x3c'; // `%x${'<'.charCodeAt(0).toString(16)}`;
@ -14,49 +15,108 @@ export class GitReflogParser {
`${lb}r${rb}%H`, // ref `${lb}r${rb}%H`, // ref
`${lb}d${rb}%gD`, // reflog selector (with UNIX timestamp) `${lb}d${rb}%gD`, // reflog selector (with UNIX timestamp)
`${lb}s${rb}%gs` // reflog subject `${lb}s${rb}%gs` // reflog subject
// `${lb}n${rb}%D` // ref names
].join(''); ].join('');
@debug({ args: false }) @debug({ args: false })
static parseRecentIncomingChanges(data: string, repoPath: string): GitReflog | undefined {
static parse(data: string, repoPath: string, commands: string[], maxCount: number): GitReflog | undefined {
if (!data) return undefined; if (!data) return undefined;
let reflog: GitReflog | undefined;
const records: GitReflogRecord[] = [];
let match: RegExpExecArray | null;
let sha;
let selector;
let date; let date;
let ref;
let command; let command;
let commandArgs;
let details;
let head;
let headDate;
let headSha;
let count = 0;
let recordDate;
let record: GitReflogRecord | undefined;
let truncated = false;
let match: RegExpExecArray | null;
do { do {
match = reflogRegex.exec(data); match = reflogRegex.exec(data);
if (match == null) break; if (match == null) break;
[, ref, date, command] = match;
[, sha, selector, date, command, commandArgs, details] = match;
if (record !== undefined) {
// If the next record has the same sha as the previous, use it if it is not pointing to just HEAD and the previous is
if (
sha === record.sha &&
(date !== recordDate || !reflogHEADRegex.test(record.selector) || reflogHEADRegex.test(selector))
) {
continue;
}
if (sha !== record.sha) {
if (
head != null &&
headDate === recordDate &&
headSha == record.sha &&
reflogHEADRegex.test(record.selector)
) {
record.update(sha, head);
}
else {
record.update(sha);
}
records.push(record);
record = undefined;
recordDate = undefined;
count++;
if (maxCount !== 0 && count >= maxCount) {
truncated = true;
break;
}
}
}
// If we don't have a reflog, or are still at the same ref with a proper command, save it
if (
(reflog === undefined || (reflog !== undefined && ref === reflog.ref)) &&
incomingCommands.includes(command)
) {
reflog = new GitReflog(
if (command === 'HEAD') {
head = selector;
headDate = date;
headSha = sha;
continue;
}
if (commands.includes(command)) {
record = new GitReflogRecord(
repoPath, repoPath,
// Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869 // Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869
` ${ref}`.substr(1),
new Date((date! as any) * 1000),
` ${sha}`.substr(1),
// Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869
` ${selector}`.substr(1),
new Date(Number(date) * 1000),
// Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869 // Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869
` ${command}`.substr(1)
` ${command}`.substr(1),
// Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869
commandArgs == null || commandArgs.length === 0 ? undefined : commandArgs.substr(1),
// Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869
details == null || details.length === 0 ? undefined : details.substr(1)
); );
}
else if (reflog !== undefined && ref !== reflog.ref) {
reflog.previousRef = ref;
break;
recordDate = date;
} }
} while (match != null); } while (match != null);
// Ensure the regex state is reset // Ensure the regex state is reset
reflogRegex.lastIndex = 0; reflogRegex.lastIndex = 0;
return reflog;
return {
repoPath: repoPath,
records: records,
count: count,
maxCount: maxCount,
truncated: truncated
};
} }
} }

+ 4
- 3
src/views/nodes.ts View File

@ -6,6 +6,8 @@ export * from './nodes/branchNode';
export * from './nodes/branchTrackingStatusNode'; export * from './nodes/branchTrackingStatusNode';
export * from './nodes/commitFileNode'; export * from './nodes/commitFileNode';
export * from './nodes/commitNode'; export * from './nodes/commitNode';
export * from './nodes/compareNode';
export * from './nodes/compareResultsNode';
export * from './nodes/contributorNode'; export * from './nodes/contributorNode';
export * from './nodes/contributorsNode'; export * from './nodes/contributorsNode';
export * from './nodes/fileHistoryNode'; export * from './nodes/fileHistoryNode';
@ -13,13 +15,12 @@ export * from './nodes/fileHistoryTrackerNode';
export * from './nodes/folderNode'; export * from './nodes/folderNode';
export * from './nodes/lineHistoryNode'; export * from './nodes/lineHistoryNode';
export * from './nodes/lineHistoryTrackerNode'; export * from './nodes/lineHistoryTrackerNode';
export * from './nodes/recentIncomingChangesNode';
export * from './nodes/reflogNode';
export * from './nodes/reflogRecordNode';
export * from './nodes/remoteNode'; export * from './nodes/remoteNode';
export * from './nodes/remotesNode'; export * from './nodes/remotesNode';
export * from './nodes/repositoriesNode'; export * from './nodes/repositoriesNode';
export * from './nodes/repositoryNode'; export * from './nodes/repositoryNode';
export * from './nodes/compareResultsNode';
export * from './nodes/compareNode';
export * from './nodes/resultsCommitsNode'; export * from './nodes/resultsCommitsNode';
export * from './nodes/resultsFileNode'; export * from './nodes/resultsFileNode';
export * from './nodes/resultsFilesNode'; export * from './nodes/resultsFilesNode';

+ 0
- 61
src/views/nodes/recentIncomingChangesNode.ts View File

@ -1,61 +0,0 @@
'use strict';
import { TreeItem, TreeItemCollapsibleState } from 'vscode';
import { GlyphChars } from '../../constants';
import { Container } from '../../container';
import { GitReflog, GitUri } from '../../git/gitService';
import { Iterables } from '../../system';
import { ViewWithFiles } from '../viewBase';
import { CommitNode } from './commitNode';
import { MessageNode, ShowMoreNode } from './common';
import { insertDateMarkers } from './helpers';
import { PageableViewNode, ResourceType, ViewNode } from './viewNode';
export class RecentIncomingChangesNode extends ViewNode<ViewWithFiles> implements PageableViewNode {
readonly supportsPaging: boolean = true;
maxCount: number | undefined;
constructor(view: ViewWithFiles, parent: ViewNode, public readonly reflog: GitReflog) {
super(GitUri.fromRepoPath(reflog.repoPath), view, parent);
}
get id(): string {
return `${this._instanceId}:gitlens:repository(${this.uri.repoPath}):recent-incoming-changes`;
}
async getChildren(): Promise<ViewNode[]> {
const range = `${this.reflog.previousRef}..${this.reflog.ref}`;
const log = await Container.git.getLog(this.uri.repoPath!, {
maxCount: this.maxCount !== undefined ? this.maxCount : this.view.config.defaultItemLimit,
ref: range
});
if (log === undefined) return [new MessageNode(this.view, this, 'No changes')];
const children = [
...insertDateMarkers(Iterables.map(log.commits.values(), c => new CommitNode(this.view, this, c)), this, 1)
];
if (log.truncated) {
children.push(new ShowMoreNode(this.view, this, 'Commits', children[children.length - 1]));
}
return children;
}
getTreeItem(): TreeItem {
const item = new TreeItem('Recent incoming changes', TreeItemCollapsibleState.Collapsed);
item.id = this.id;
item.description = `via ${this.reflog.command} ${GlyphChars.Space}${GlyphChars.Dot}${GlyphChars.Space} ${
this.reflog.formattedDate
}`;
item.contextValue = ResourceType.RecentIncomingChanges;
item.tooltip = `Recent incoming changes via ${this.reflog.command}\n${this.reflog.formatDate()}`;
// const iconSuffix = ahead ? 'upload' : 'download';
// item.iconPath = {
// dark: Container.context.asAbsolutePath(`images/dark/icon-${iconSuffix}.svg`),
// light: Container.context.asAbsolutePath(`images/light/icon-${iconSuffix}.svg`)
// };
return item;
}
}

+ 66
- 0
src/views/nodes/reflogNode.ts View File

@ -0,0 +1,66 @@
'use strict';
import { TreeItem, TreeItemCollapsibleState } from 'vscode';
import { Container } from '../../container';
import { GitUri, Repository } from '../../git/gitService';
import { PageableViewNode, ResourceType, ViewNode } from './viewNode';
import { RepositoriesView } from '../repositoriesView';
import { ReflogRecordNode } from './reflogRecordNode';
import { debug, gate } from '../../system';
import { MessageNode, ShowMoreNode } from './common';
export class ReflogNode extends ViewNode<RepositoriesView> implements PageableViewNode {
readonly supportsPaging: boolean = true;
maxCount: number | undefined;
private _children: ViewNode[] | undefined;
constructor(uri: GitUri, view: RepositoriesView, parent: ViewNode, public readonly repo: Repository) {
super(uri, view, parent);
}
get id(): string {
return `${this._instanceId}:gitlens:repository(${this.repo.path}):reflog`;
}
async getChildren(): Promise<ViewNode[]> {
if (this._children === undefined) {
const children = [];
const reflog = await Container.git.getIncomingActivity(this.repo.path, {
all: true,
maxCount: this.maxCount !== undefined ? this.maxCount : this.view.config.defaultItemLimit
});
if (reflog === undefined || reflog.records.length === 0) {
return [new MessageNode(this.view, this, 'No activity could be found.')];
}
children.push(...reflog.records.map(r => new ReflogRecordNode(this.view, this, r)));
if (reflog.truncated) {
children.push(new ShowMoreNode(this.view, this, 'Activity', children[children.length - 1]));
}
this._children = children;
}
return this._children;
}
getTreeItem(): TreeItem {
const item = new TreeItem('Incoming Activity', TreeItemCollapsibleState.Collapsed);
item.id = this.id;
item.contextValue = ResourceType.Reflog;
item.description = 'experimental';
item.iconPath = {
dark: Container.context.asAbsolutePath('images/dark/icon-merge.svg'),
light: Container.context.asAbsolutePath('images/light/icon-merge.svg')
};
return item;
}
@gate()
@debug()
refresh() {
this._children = undefined;
}
}

+ 67
- 0
src/views/nodes/reflogRecordNode.ts View File

@ -0,0 +1,67 @@
'use strict';
import { TreeItem, TreeItemCollapsibleState } from 'vscode';
import { GlyphChars } from '../../constants';
import { Container } from '../../container';
import { GitReflogRecord, GitUri } from '../../git/gitService';
import { Iterables } from '../../system';
import { ViewWithFiles } from '../viewBase';
import { CommitNode } from './commitNode';
import { MessageNode, ShowMoreNode } from './common';
import { PageableViewNode, ResourceType, ViewNode } from './viewNode';
export class ReflogRecordNode extends ViewNode<ViewWithFiles> implements PageableViewNode {
readonly supportsPaging: boolean = true;
maxCount: number | undefined;
constructor(view: ViewWithFiles, parent: ViewNode, public readonly record: GitReflogRecord) {
super(GitUri.fromRepoPath(record.repoPath), view, parent);
}
get id(): string {
return `${this._instanceId}:gitlens:repository(${this.uri.repoPath}):reflog-record(${this.record.sha}|${
this.record.selector
}|${this.record.command}|${this.record.commandArgs || ''}|${this.record.date.getTime()})`;
}
async getChildren(): Promise<ViewNode[]> {
const range = `${this.record.previousSha}..${this.record.sha}`;
const log = await Container.git.getLog(this.uri.repoPath!, {
maxCount: this.maxCount !== undefined ? this.maxCount : this.view.config.defaultItemLimit,
ref: range
});
if (log === undefined) return [new MessageNode(this.view, this, 'No commits')];
const children: (CommitNode | ShowMoreNode)[] = [
...Iterables.map(log.commits.values(), c => new CommitNode(this.view, this, c))
];
if (log.truncated) {
children.push(new ShowMoreNode(this.view, this, 'Commits', children[children.length - 1]));
}
return children;
}
getTreeItem(): TreeItem {
const item = new TreeItem(
`${this.record.command}${this.record.commandArgs ? ` ${this.record.commandArgs}` : ''}`,
TreeItemCollapsibleState.Collapsed
);
item.id = this.id;
item.description = `${
this.record.HEAD.length === 0
? ''
: `${this.record.HEAD} ${GlyphChars.Space}${GlyphChars.Dot}${GlyphChars.Space} `
}${this.record.formattedDate}`;
item.contextValue = ResourceType.ReflogRecord;
item.tooltip = `${this.record.HEAD.length === 0 ? '' : `${this.record.HEAD}\n`}${this.record.command}${
this.record.commandArgs ? ` ${this.record.commandArgs}` : ''
}${
this.record.details ? ` (${this.record.details})` : ''
}\n${this.record.formatDateFromNow()} (${this.record.formatDate()})\n${this.record.previousShortSha} ${
GlyphChars.Space
}${GlyphChars.ArrowRight}${GlyphChars.Space} ${this.record.shortSha}`;
return item;
}
}

+ 9
- 13
src/views/nodes/repositoryNode.ts View File

@ -18,7 +18,7 @@ import { BranchNode } from './branchNode';
import { BranchTrackingStatusNode } from './branchTrackingStatusNode'; import { BranchTrackingStatusNode } from './branchTrackingStatusNode';
import { MessageNode } from './common'; import { MessageNode } from './common';
import { ContributorsNode } from './contributorsNode'; import { ContributorsNode } from './contributorsNode';
import { RecentIncomingChangesNode } from './recentIncomingChangesNode';
import { ReflogNode } from './reflogNode';
import { RemotesNode } from './remotesNode'; import { RemotesNode } from './remotesNode';
import { StashesNode } from './stashesNode'; import { StashesNode } from './stashesNode';
import { StatusFilesNode } from './statusFilesNode'; import { StatusFilesNode } from './statusFilesNode';
@ -47,17 +47,6 @@ export class RepositoryNode extends SubscribeableViewNode {
const children = []; const children = [];
const status = await this._status; const status = await this._status;
if (Container.config.insiders) {
const reflog = await Container.git.getRecentIncomingChanges(this.uri.repoPath!, {
// branch: status !== undefined ? status.branch : undefined,
since: '1 month ago'
});
if (reflog !== undefined) {
children.push(new RecentIncomingChangesNode(this.view, this, reflog));
}
}
if (status !== undefined) { if (status !== undefined) {
const branch = new GitBranch( const branch = new GitBranch(
status.repoPath, status.repoPath,
@ -92,7 +81,14 @@ export class RepositoryNode extends SubscribeableViewNode {
children.push( children.push(
new BranchesNode(this.uri, this.view, this, this.repo), new BranchesNode(this.uri, this.view, this, this.repo),
new ContributorsNode(this.uri, this.view, this, this.repo),
new ContributorsNode(this.uri, this.view, this, this.repo)
);
if (Container.config.insiders) {
children.push(new ReflogNode(this.uri, this.view, this, this.repo));
}
children.push(
new RemotesNode(this.uri, this.view, this, this.repo), new RemotesNode(this.uri, this.view, this, this.repo),
new StashesNode(this.uri, this.view, this, this.repo), new StashesNode(this.uri, this.view, this, this.repo),
new TagsNode(this.uri, this.view, this, this.repo) new TagsNode(this.uri, this.view, this, this.repo)

+ 2
- 1
src/views/nodes/viewNode.ts View File

@ -27,7 +27,8 @@ export enum ResourceType {
LineHistory = 'gitlens:history:line', LineHistory = 'gitlens:history:line',
Message = 'gitlens:message', Message = 'gitlens:message',
Pager = 'gitlens:pager', Pager = 'gitlens:pager',
RecentIncomingChanges = 'gitlens:recent-incoming-changes',
Reflog = 'gitlens:reflog',
ReflogRecord = 'gitlens:reflog-record',
Remote = 'gitlens:remote', Remote = 'gitlens:remote',
Remotes = 'gitlens:remotes', Remotes = 'gitlens:remotes',
Repositories = 'gitlens:repositories', Repositories = 'gitlens:repositories',

Loading…
Cancel
Save