Browse Source

Adds create worktree command to GHPR PRs

main
Eric Amodio 1 year ago
parent
commit
5838f6621f
6 changed files with 126 additions and 1 deletions
  1. +1
    -0
      CHANGELOG.md
  2. +14
    -0
      package.json
  3. +1
    -0
      src/commands.ts
  4. +103
    -0
      src/commands/ghpr/createWorktree.ts
  5. +2
    -0
      src/constants.ts
  6. +5
    -1
      src/system/promise.ts

+ 1
- 0
CHANGELOG.md View File

@ -23,6 +23,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- Creates new worktrees from the "main" repo, if already in a worktree
- Shows the _Worktrees_ view after creating a new worktree
- Adds a new _remote_ command to the _Git Command Palette_ to add, prune, and remove remotes
- Adds a _Create Worktree for Pull Request via GitLens..._ context menu command on pull requests in the _GitHub Pull Requests and Issues_ extension's views
### Changed

+ 14
- 0
package.json View File

@ -5460,6 +5460,11 @@
"icon": "$(add)"
},
{
"command": "gitlens.ghpr.views.createWorktree",
"title": "Create Worktree for Pull Request via GitLens...",
"category": "GitLens"
},
{
"command": "gitlens.views.title.createWorktree",
"title": "Create Worktree...",
"category": "GitLens",
@ -7852,6 +7857,10 @@
"when": "false"
},
{
"command": "gitlens.ghpr.views.createWorktree",
"when": "false"
},
{
"command": "gitlens.views.title.createWorktree",
"when": "false"
},
@ -11236,6 +11245,11 @@
"command": "gitlens.views.setShowRelativeDateMarkersOff",
"when": "viewItem == gitlens:date-marker && config.gitlens.views.showRelativeDateMarkers",
"group": "1_gitlens@0"
},
{
"command": "gitlens.ghpr.views.createWorktree",
"when": "view == pr:github && viewItem =~ /pullrequest(:local)?:nonactive|description/",
"group": "pullrequest@2"
}
],
"webview/context": [

+ 1
- 0
src/commands.ts View File

@ -16,6 +16,7 @@ export * from './commands/diffWithRevision';
export * from './commands/diffWithRevisionFrom';
export * from './commands/diffWithWorking';
export * from './commands/externalDiff';
export * from './commands/ghpr/createWorktree';
export * from './commands/gitCommands';
export * from './commands/inviteToLiveShare';
export * from './commands/logging';

+ 103
- 0
src/commands/ghpr/createWorktree.ts View File

@ -0,0 +1,103 @@
import type { Uri } from 'vscode';
import { window } from 'vscode';
import { Commands } from '../../constants';
import type { Container } from '../../container';
import { GitReference } from '../../git/models/reference';
import type { GitRemote } from '../../git/models/remote';
import { Logger } from '../../logger';
import { command } from '../../system/command';
import { waitUntilNextTick } from '../../system/promise';
import { Command } from '../base';
import { GitActions } from '../gitCommands.actions';
interface PullRequestNode {
readonly pullRequestModel: PullRequest;
}
interface PullRequest {
readonly githubRepository: {
readonly rootUri: Uri;
};
readonly head: {
readonly ref: string;
readonly sha: string;
readonly repositoryCloneUrl: {
readonly owner: string;
readonly url: Uri;
};
};
readonly item: {
readonly number: number;
};
}
@command()
export class CreateWorktreeCommand extends Command {
constructor(private readonly container: Container) {
super(Commands.CreateWorktreeForGHPR);
}
async execute(...args: [PullRequestNode | PullRequest, ...unknown[]]) {
const [arg] = args;
let pr;
if ('pullRequestModel' in arg) {
pr = arg.pullRequestModel;
} else {
pr = arg;
}
const {
githubRepository: { rootUri },
head: {
repositoryCloneUrl: { url: remoteUri, owner: remoteOwner },
ref,
},
} = pr;
let repo = this.container.git.getRepository(rootUri);
if (repo == null) {
void window.showWarningMessage(
`Unable to find repository(${rootUri.toString()}) for PR #${pr.item.number}`,
);
return;
}
repo = await repo.getMainRepository();
if (repo == null) {
void window.showWarningMessage(
`Unable to find main repository(${rootUri.toString()}) for PR #${pr.item.number}`,
);
return;
}
const remoteUrl = remoteUri.toString();
let remote: GitRemote | undefined;
[remote] = await repo.getRemotes({ filter: r => r.url === remoteUrl });
if (remote == null) {
await GitActions.Remote.add(repo, remoteOwner, remoteUrl, { fetch: true });
[remote] = await repo.getRemotes({ filter: r => r.url === remoteUrl });
if (remote == null) return;
} else {
await this.container.git.fetch(repo.path, { remote: remote.name });
}
await waitUntilNextTick();
try {
await GitActions.Worktree.create(
repo,
undefined,
GitReference.create(`${remote.name}/${ref}`, repo.path, {
refType: 'branch',
name: `${remote.name}/${ref}`,
remote: true,
}),
);
} catch (ex) {
Logger.error(ex, 'CreateWorktreeCommand', 'Unable to create worktree');
void window.showErrorMessage(`Unable to create worktree for ${ref}`);
}
}
}

+ 2
- 0
src/constants.ts View File

@ -229,6 +229,8 @@ export const enum Commands {
ViewsOpenDirectoryDiff = 'gitlens.views.openDirectoryDiff',
ViewsOpenDirectoryDiffWithWorking = 'gitlens.views.openDirectoryDiffWithWorking',
CreateWorktreeForGHPR = 'gitlens.ghpr.views.createWorktree',
Deprecated_DiffHeadWith = 'gitlens.diffHeadWith',
Deprecated_DiffWorkingWith = 'gitlens.diffWorkingWith',
Deprecated_OpenBranchesInRemote = 'gitlens.openBranchesInRemote',

+ 5
- 1
src/system/promise.ts View File

@ -250,7 +250,11 @@ export async function raceAll(
}
export async function wait(ms: number): Promise<void> {
await new Promise(resolve => setTimeout(resolve, ms));
await new Promise<void>(resolve => setTimeout(resolve, ms));
}
export async function waitUntilNextTick(): Promise<void> {
await new Promise<void>(resolve => queueMicrotask(resolve));
}
export class AggregateError extends Error {

Loading…
Cancel
Save