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

Adds support for --update-refs flag when using interactive rebase editor #3705

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
### Added

- Adds support for OpenAI's GPT-4o Mini model for GitLens' experimental AI features
- Adds support for `--update-refs` flag when using interactive rebase editor - closes [#2387](https://github.com/gitkraken/vscode-gitlens/issues/2387) thanks to [PR #3705](https://github.com/gitkraken/vscode-gitlens/pull/3705) by Gavin Bath ([@thezwap](https://github.com/thezwap))

### Changed

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ A big thanks to the people that have contributed to this project 🙏❤️:
- may ([@m4rch3n1ng](https://github.com/m4rch3n1ng)) — [contributions](https://github.com/gitkraken/vscode-gitlens/commits?author=m4rch3n1ng)
- bm-w ([@bm-w](https://github.com/bm-w)) — [contributions](https://github.com/gitkraken/vscode-gitlens/commits?author=bm-w)
- Tyler Johnson ([@TJohnsonSE](https://github.com/TJohnsonSE)) — [contributions](https://github.com/gitkraken/vscode-gitlens/commits?author=TJohnsonSE)
- Gavin Bath ([@thezwap](https://github.com/thezwap)) — [contributions](https://github.com/gitkraken/vscode-gitlens/commits?author=thezwap)

Also special thanks to the people that have provided support, testing, brainstorming, etc:

Expand Down
59 changes: 38 additions & 21 deletions src/webviews/apps/rebase/rebase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
import { App } from '../shared/appBase';
import { DOM } from '../shared/dom';

const rebaseActions = ['pick', 'reword', 'edit', 'squash', 'fixup', 'drop'];
const rebaseActions = ['pick', 'reword', 'edit', 'squash', 'fixup', 'drop', 'update-ref'];
const rebaseActionsMap = new Map<string, RebaseEntryAction>([
['p', 'pick'],
['P', 'pick'],
Expand All @@ -33,6 +33,8 @@ const rebaseActionsMap = new Map<string, RebaseEntryAction>([
['F', 'fixup'],
['d', 'drop'],
['D', 'drop'],
['u', 'update-ref'],
['U', 'update-ref'],
]);

class RebaseEditor extends App<State> {
Expand Down Expand Up @@ -414,6 +416,7 @@ class RebaseEditor extends App<State> {
index: 0,
message: commit.message,
sha: state.onto.sha,
branch: undefined!,
},
state,
++tabIndex,
Expand Down Expand Up @@ -448,6 +451,7 @@ class RebaseEditor extends App<State> {
$entry.classList.add('entry', `entry--${action}`);
$entry.classList.toggle('entry--squash-to', squashToHere);
$entry.dataset.sha = entry.sha;
$entry.dataset.branch = entry.branch;

let $content: HTMLElement = $entry;
if (action === 'base') {
Expand All @@ -467,24 +471,30 @@ class RebaseEditor extends App<State> {
$selectContainer.classList.add('entry-action', 'select-container');
$entry.appendChild($selectContainer);

const $select = document.createElement('select');
$select.dataset.sha = entry.sha;
$select.name = 'action';

const $options = document.createDocumentFragment();
for (const action of rebaseActions) {
const $option = document.createElement('option');
$option.value = action;
$option.text = action;
if (action === 'update-ref') {
const $updateRefAction = document.createElement('span');
$updateRefAction.textContent = 'Update Ref';
$selectContainer.appendChild($updateRefAction);
} else {
const $select = document.createElement('select');
$select.dataset.sha = entry.sha;
$select.name = 'action';

const $options = document.createDocumentFragment();
for (const action of rebaseActions) {
const $option = document.createElement('option');
$option.value = action;
$option.text = action;

if (entry.action === action) {
$option.selected = true;
}

if (entry.action === action) {
$option.selected = true;
$options.appendChild($option);
}

$options.appendChild($option);
$select.appendChild($options);
$selectContainer.appendChild($select);
}
$select.appendChild($options);
$selectContainer.appendChild($select);
}

const commit = entry.commit;
Expand Down Expand Up @@ -537,11 +547,18 @@ class RebaseEditor extends App<State> {
}
}

const $sha = document.createElement('a');
$sha.classList.add('entry-sha', 'icon--commit');
$sha.href = state.commands.commit.replace(this.commitTokenRegex, commit?.sha ?? entry.sha);
$sha.textContent = entry.sha.substr(0, 7);
$content.appendChild($sha);
if (entry.action != 'update-ref') {
const $sha = document.createElement('a');
$sha.classList.add('entry-sha', 'icon--commit');
$sha.href = state.commands.commit.replace(this.commitTokenRegex, commit?.sha ?? entry.sha);
$sha.textContent = entry.sha.substr(0, 7);
$content.appendChild($sha);
} else {
const $branch = document.createElement('span');
$branch.classList.add('entry-sha', 'icon--branch');
$branch.textContent = entry.branch;
$content.appendChild($branch);
}

return [$entry, tabIndex];
}
Expand Down
8 changes: 7 additions & 1 deletion src/webviews/rebase/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ export interface State extends WebviewState<CustomEditorIds> {
export interface RebaseEntry {
readonly action: RebaseEntryAction;
readonly sha: string;
readonly branch: string;
readonly message: string;
readonly index: number;

commit?: Commit;
refUpdate?: RefUpdate;
}

export type RebaseEntryAction = 'pick' | 'reword' | 'edit' | 'squash' | 'fixup' | 'break' | 'drop';
export type RebaseEntryAction = 'pick' | 'reword' | 'edit' | 'squash' | 'fixup' | 'break' | 'drop' | 'update-ref';

export interface Author {
readonly author: string;
Expand All @@ -46,6 +48,10 @@ export interface Commit {
// readonly command: string;
}

export interface RefUpdate {
readonly branch: string;
}

// COMMANDS

export const AbortCommand = new IpcCommand(scope, 'abort');
Expand Down
19 changes: 15 additions & 4 deletions src/webviews/rebase/rebaseEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ const ipcSequencer = getScopedCounter();
const webviewIdGenerator = getScopedCounter();

const rebaseRegex = /^\s?#\s?Rebase\s([0-9a-f]+)(?:..([0-9a-f]+))?\sonto\s([0-9a-f]+)\s.*$/im;
const rebaseCommandsRegex = /^\s?(p|pick|r|reword|e|edit|s|squash|f|fixup|d|drop)\s([0-9a-f]+?)\s(.*)$/gm;
const rebaseCommandsRegex =
/^\s?(p|pick|r|reword|e|edit|s|squash|f|fixup|d|drop|u|update-ref)(?:\s([0-9a-f]+)\s(.*)|\s(refs\/heads\/\S+))$/gm;

const rebaseActionsMap = new Map<string, RebaseEntryAction>([
['p', 'pick'],
Expand All @@ -71,6 +72,8 @@ const rebaseActionsMap = new Map<string, RebaseEntryAction>([
['fixup', 'fixup'],
['d', 'drop'],
['drop', 'drop'],
['u', 'update-ref'],
['update-ref', 'update-ref'],
]);

interface RebaseEditorContext {
Expand Down Expand Up @@ -440,7 +443,13 @@ export class RebaseEditorProvider implements CustomTextEditorProvider, Disposabl
}

edit.delete(context.document.uri, range);
edit.insert(context.document.uri, new Position(newLine, 0), `${action} ${entry.sha} ${entry.message}\n`);
let entryToInsert = '';
if (entry.action === 'update-ref') {
entryToInsert = `${action}${entry.branch}\n`;
} else {
entryToInsert = `${action} ${entry.sha} ${entry.message}\n`;
}
edit.insert(context.document.uri, new Position(newLine, 0), entryToInsert);

await workspace.applyEdit(edit);
}
Expand Down Expand Up @@ -701,18 +710,20 @@ function parseRebaseTodoEntries(contentsOrDocument: string | TextDocument): Reba
let action;
let sha;
let message;
let branch;

do {
match = rebaseCommandsRegex.exec(contents);
if (match == null) break;

[, action, sha, message] = match;
[, action, sha, message, branch] = match;

entries.push({
index: match.index,
action: rebaseActionsMap.get(action) ?? 'pick',
// Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869
sha: ` ${sha}`.substr(1),
sha: sha ? ` ${sha}`.substr(1) : `UpdateRefId${match.index}`,
branch: ` ${branch}`,
// Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869
message: message == null || message.length === 0 ? '' : ` ${message}`.substr(1),
});
Expand Down