Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #2836 adds sorting by repositories #2991

Merged
merged 2 commits into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- Improves the experience of the _Search Commits_ quick pick menu
- Adds a stateful authors picker to make it much easier to search for commits by specific authors
- Adds a file and folder picker to make it much easier to search for commits containing specific files or in specific folders
- Adds ability to sort repositories in the views and quick pick menus — closes [#2836](https://github.com/gitkraken/vscode-gitlens/issues/2836) thanks to [PR #2991](https://github.com/gitkraken/vscode-gitlens/pull/2991)
- Adds a `gitlens.sortRepositoriesBy` setting to specify how repositories are sorted in quick pick menus and viewsby Aidos Kanapyanov ([@aidoskanapyanov](https://github.com/aidoskanapyanov))
- Adds a _[Show|Hide] Merge Commits_ toggle to the Commits\_ view — closes [#1399](https://github.com/gitkraken/vscode-gitlens/issues/1399) thanks to [PR #1540](https://github.com/gitkraken/vscode-gitlens/pull/1540) by Shashank Shastri ([@Shashank-Shastri](https://github.com/Shashank-Shastri))
- Adds a _Filter Commits by Author..._ commands to the _Commits_ view and comparisons context menus to filter commits in the _Commits_ view by specific authors
- Adds an _Open Comparison on Remote_ command to comparisons in views
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ A big thanks to the people that have contributed to this project 🙏❤️:
- jogo- ([@jogo-](https://github.com/jogo-)) — [contributions](https://github.com/gitkraken/vscode-gitlens/commits?author=jogo-)
- Nils K ([@septatrix](https://github.com/septatrix)) — [contributions](https://github.com/gitkraken/vscode-gitlens/commits?author=septatrix)
- Chris Kaczor ([@ckaczor](https://github.com/ckaczor)) — [contributions](https://github.com/gitkraken/vscode-gitlens/commits?author=ckaczor)
- Aidos Kanapyanov ([@aidoskanapyanov](https://github.com/aidoskanapyanov)) — [contributions](https://github.com/gitkraken/vscode-gitlens/commits?author=aidoskanapyanov)
- Allan Karlson ([@bees4ever](https://github.com/bees4ever)) — [contributions](https://github.com/gitkraken/vscode-gitlens/commits?author=bees4ever)
- Nafiur Rahman Khadem ([@ShafinKhadem](https://github.com/ShafinKhadem)) — [contributions](https://github.com/gitkraken/vscode-gitlens/commits?author=ShafinKhadem)
- Mathew King ([@MathewKing](https://github.com/MathewKing)) — [contributions](https://github.com/gitkraken/vscode-gitlens/commits?author=MathewKing)
Expand Down
156 changes: 92 additions & 64 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1292,25 +1292,6 @@
"scope": "window",
"order": 30
},
"gitlens.sortBranchesBy": {
"type": "string",
"default": "date:desc",
"enum": [
"date:desc",
"date:asc",
"name:asc",
"name:desc"
],
"enumDescriptions": [
"Sorts branches by the most recent commit date in descending order",
"Sorts branches by the most recent commit date in ascending order",
"Sorts branches by name in ascending order",
"Sorts branches by name in descending order"
],
"markdownDescription": "Specifies how branches are sorted in quick pick menus and views",
"scope": "window",
"order": 40
},
"gitlens.views.branches.files.layout": {
"type": "string",
"default": "auto",
Expand Down Expand Up @@ -1556,25 +1537,6 @@
"scope": "window",
"order": 10
},
"gitlens.sortTagsBy": {
"type": "string",
"default": "date:desc",
"enum": [
"date:desc",
"date:asc",
"name:asc",
"name:desc"
],
"enumDescriptions": [
"Sorts tags by date in descending order",
"Sorts tags by date in ascending order",
"Sorts tags by name in ascending order",
"Sorts tags by name in descending order"
],
"markdownDescription": "Specifies how tags are sorted in quick pick menus and views",
"scope": "window",
"order": 20
},
"gitlens.views.tags.files.layout": {
"type": "string",
"default": "auto",
Expand Down Expand Up @@ -1811,29 +1773,6 @@
"scope": "window",
"order": 31
},
"gitlens.sortContributorsBy": {
"type": "string",
"default": "count:desc",
"enum": [
"count:desc",
"count:asc",
"date:desc",
"date:asc",
"name:asc",
"name:desc"
],
"enumDescriptions": [
"Sorts contributors by commit count in descending order",
"Sorts contributors by commit count in ascending order",
"Sorts contributors by the most recent commit date in descending order",
"Sorts contributors by the most recent commit date in ascending order",
"Sorts contributors by name in ascending order",
"Sorts contributors by name in descending order"
],
"markdownDescription": "Specifies how contributors are sorted in quick pick menus and views",
"scope": "window",
"order": 40
},
"gitlens.views.contributors.files.layout": {
"type": "string",
"default": "auto",
Expand Down Expand Up @@ -3303,10 +3242,99 @@
}
}
},
{
"id": "sorting",
"title": "Sorting",
"order": 121,
"properties": {
"gitlens.sortRepositoriesBy": {
"type": "string",
"default": "discovered",
"enum": [
"discovered",
"lastFetched:desc",
"lastFetched:asc",
"name:asc",
"name:desc"
],
"enumDescriptions": [
"Sorts repositories by discovery or workspace order",
"Sorts repositories by last fetched date in descending order",
"Sorts repositories by last fetched date in ascending order",
"Sorts repositories by name in ascending order",
"Sorts repositories by name in descending order"
],
"markdownDescription": "Specifies how repositories are sorted in quick pick menus and views",
"scope": "window",
"order": 10
},
"gitlens.sortBranchesBy": {
"type": "string",
"default": "date:desc",
"enum": [
"date:desc",
"date:asc",
"name:asc",
"name:desc"
],
"enumDescriptions": [
"Sorts branches by the most recent commit date in descending order",
"Sorts branches by the most recent commit date in ascending order",
"Sorts branches by name in ascending order",
"Sorts branches by name in descending order"
],
"markdownDescription": "Specifies how branches are sorted in quick pick menus and views",
"scope": "window",
"order": 20
},
"gitlens.sortTagsBy": {
"type": "string",
"default": "date:desc",
"enum": [
"date:desc",
"date:asc",
"name:asc",
"name:desc"
],
"enumDescriptions": [
"Sorts tags by date in descending order",
"Sorts tags by date in ascending order",
"Sorts tags by name in ascending order",
"Sorts tags by name in descending order"
],
"markdownDescription": "Specifies how tags are sorted in quick pick menus and views",
"scope": "window",
"order": 30
},
"gitlens.sortContributorsBy": {
"type": "string",
"default": "count:desc",
"enum": [
"count:desc",
"count:asc",
"date:desc",
"date:asc",
"name:asc",
"name:desc"
],
"enumDescriptions": [
"Sorts contributors by commit count in descending order",
"Sorts contributors by commit count in ascending order",
"Sorts contributors by the most recent commit date in descending order",
"Sorts contributors by the most recent commit date in ascending order",
"Sorts contributors by name in ascending order",
"Sorts contributors by name in descending order"
],
"markdownDescription": "Specifies how contributors are sorted in quick pick menus and views",
"scope": "window",
"order": 40
}
}
},
{
"id": "menus-toolbars",
"title": "Menus & Toolbars",
"order": 121,
"order": 122,
"properties": {
"gitlens.menus": {
"anyOf": [
Expand Down Expand Up @@ -3681,7 +3709,7 @@
{
"id": "keyboard",
"title": "Keyboard Shortcuts",
"order": 122,
"order": 123,
"properties": {
"gitlens.keymap": {
"type": "string",
Expand All @@ -3705,7 +3733,7 @@
{
"id": "modes",
"title": "Modes",
"order": 123,
"order": 124,
"properties": {
"gitlens.mode.statusBar.enabled": {
"type": "boolean",
Expand Down
2 changes: 2 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ export interface Config {
readonly sortBranchesBy: BranchSorting;
readonly sortContributorsBy: ContributorSorting;
readonly sortTagsBy: TagSorting;
readonly sortRepositoriesBy: RepositoriesSorting;
readonly statusBar: {
readonly alignment: 'left' | 'right';
readonly command: StatusBarCommand;
Expand Down Expand Up @@ -247,6 +248,7 @@ export const enum CodeLensCommand {

export type CodeLensScopes = 'document' | 'containers' | 'blocks';
export type ContributorSorting = 'count:desc' | 'count:asc' | 'date:desc' | 'date:asc' | 'name:asc' | 'name:desc';
export type RepositoriesSorting = 'discovered' | 'lastFetched:desc' | 'lastFetched:asc' | 'name:asc' | 'name:desc';
export type CustomRemoteType =
| 'AzureDevOps'
| 'Bitbucket'
Expand Down
70 changes: 52 additions & 18 deletions src/git/models/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Disposable, EventEmitter, ProgressLocation, RelativePattern, window, wo
import { md5 } from '@env/crypto';
import { ForcePushMode } from '../../@types/vscode.git.enums';
import type { CreatePullRequestActionContext } from '../../api/gitlens';
import type { RepositoriesSorting } from '../../config';
import type { CoreGitConfiguration } from '../../constants';
import { Schemes } from '../../constants';
import type { Container } from '../../container';
Expand All @@ -21,6 +22,7 @@ import { getLoggableName, Logger } from '../../system/logger';
import { getLogScope } from '../../system/logger.scope';
import { updateRecordValue } from '../../system/object';
import { basename, normalizePath } from '../../system/path';
import { sortCompare } from '../../system/string';
import type { GitDir, GitProviderDescriptor, GitRepositoryCaches } from '../gitProvider';
import type { RichRemoteProvider } from '../remotes/richRemoteProvider';
import type { GitSearch, SearchQuery } from '../search';
Expand All @@ -40,6 +42,10 @@ import type { GitStatus } from './status';
import type { GitTag, TagSortOptions } from './tag';
import type { GitWorktree } from './worktree';

export interface RepositoriesSortOptions {
orderBy?: RepositoriesSorting;
}

const emptyArray = Object.freeze([]) as unknown as any[];

const millisecondsPerMinute = 60 * 1000;
Expand All @@ -66,9 +72,7 @@ export const enum RepositoryChange {
Remotes = 5,
Worktrees = 6,
Config = 7,
/*
* Union of Cherry, Merge, and Rebase
*/
/** Union of Cherry, Merge, and Rebase */
Status = 8,
CherryPick = 9,
Merge = 10,
Expand All @@ -84,7 +88,6 @@ export const enum RepositoryChange {

export const enum RepositoryChangeComparisonMode {
Any,
All,
Exclusive,
}

Expand Down Expand Up @@ -175,8 +178,32 @@ export class Repository implements Disposable {
: 0;
}

static sort(repositories: Repository[]) {
return repositories.sort((a, b) => (a.starred ? -1 : 1) - (b.starred ? -1 : 1) || a.index - b.index);
static sort(repositories: Repository[], options?: RepositoriesSortOptions) {
options = { orderBy: configuration.get('sortRepositoriesBy'), ...options };

switch (options.orderBy) {
case 'name:asc':
return repositories.sort(
(a, b) => (a.starred ? -1 : 1) - (b.starred ? -1 : 1) || sortCompare(a.name, b.name),
);
case 'name:desc':
return repositories.sort(
(a, b) => (a.starred ? -1 : 1) - (b.starred ? -1 : 1) || sortCompare(b.name, a.name),
);
case 'lastFetched:asc':
return repositories.sort(
(a, b) =>
(a.starred ? -1 : 1) - (b.starred ? -1 : 1) || (a._lastFetched ?? 0) - (b._lastFetched ?? 0),
);
case 'lastFetched:desc':
return repositories.sort(
(a, b) =>
(a.starred ? -1 : 1) - (b.starred ? -1 : 1) || (b._lastFetched ?? 0) - (a._lastFetched ?? 0),
);
case 'discovered':
default:
return repositories;
}
}

private _onDidChange = new EventEmitter<RepositoryChangeEvent>();
Expand Down Expand Up @@ -269,6 +296,9 @@ export class Repository implements Disposable {
);

this.onConfigurationChanged();
if (this._orderByLastFetched) {
void this.getLastFetched();
}
}

private setupRepoWatchers() {
Expand Down Expand Up @@ -356,12 +386,21 @@ export class Repository implements Disposable {
return this._updatedAt;
}

private _orderByLastFetched = false;
get orderByLastFetched(): boolean {
return this._orderByLastFetched;
}

private _updatedAt: number = 0;
get updatedAt(): number {
return this._updatedAt;
}

private onConfigurationChanged(e?: ConfigurationChangeEvent) {
if (configuration.changed(e, 'sortRepositoriesBy')) {
this._orderByLastFetched = configuration.get('sortRepositoriesBy')?.startsWith('lastFetched:') ?? false;
}

if (e != null && configuration.changed(e, 'remotes', this.folder?.uri)) {
this.resetCaches('remotes');
this.fireChange(RepositoryChange.Remotes);
Expand Down Expand Up @@ -389,6 +428,9 @@ export class Repository implements Disposable {
}

this._lastFetched = undefined;
if (this._orderByLastFetched) {
void this.getLastFetched();
}

const match =
uri != null
Expand Down Expand Up @@ -652,18 +694,10 @@ export class Repository implements Disposable {
private _lastFetched: number | undefined;
@gate()
async getLastFetched(): Promise<number> {
if (this._lastFetched == null) {
if (!(await this.hasRemotes())) return 0;
}

try {
const lastFetched = await this.container.git.getLastFetchedTimestamp(this.uri);
// If we don't get a number, assume the fetch failed, and don't update the timestamp
if (lastFetched != null) {
this._lastFetched = lastFetched;
}
} catch {
this._lastFetched = undefined;
const lastFetched = await this.container.git.getLastFetchedTimestamp(this.uri);
// If we don't get a number, assume the fetch failed, and don't update the timestamp
if (lastFetched != null) {
this._lastFetched = lastFetched;
}

return this._lastFetched ?? 0;
Expand Down
3 changes: 2 additions & 1 deletion src/views/branchesView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,8 @@ export class BranchesView extends ViewBase<'branches', BranchesViewNode, Branche
!configuration.changed(e, 'defaultDateStyle') &&
!configuration.changed(e, 'defaultGravatarsStyle') &&
!configuration.changed(e, 'defaultTimeFormat') &&
!configuration.changed(e, 'sortBranchesBy')
!configuration.changed(e, 'sortBranchesBy') &&
!configuration.changed(e, 'sortRepositoriesBy')
) {
return false;
}
Expand Down
3 changes: 2 additions & 1 deletion src/views/commitsView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,8 @@ export class CommitsView extends ViewBase<'commits', CommitsViewNode, CommitsVie
!configuration.changed(e, 'defaultDateStyle') &&
!configuration.changed(e, 'defaultGravatarsStyle') &&
!configuration.changed(e, 'defaultTimeFormat') &&
!configuration.changed(e, 'plusFeatures.enabled')
!configuration.changed(e, 'plusFeatures.enabled') &&
!configuration.changed(e, 'sortRepositoriesBy')
) {
return false;
}
Expand Down
Loading