Adding Git ref association
This commit is contained in:
Родитель
b1f28f76c1
Коммит
21375e00fe
|
@ -1,3 +1,7 @@
|
|||
## v0.0.8 (03/14/2020)
|
||||
|
||||
- Added the ability to associate a tour with a specific Git tag and/or commit, in order to enable it to be resilient to code changes
|
||||
|
||||
## v0.0.7 (03/14/2020)
|
||||
|
||||
- Added the `Edit Tour` command to tour nodes in the `CodeTour` tree, in order to allow editing existing tours
|
||||
|
|
17
package.json
17
package.json
|
@ -43,6 +43,10 @@
|
|||
"command": "codetour.changeTourDescription",
|
||||
"title": "Change Description"
|
||||
},
|
||||
{
|
||||
"command": "codetour.changeTourRef",
|
||||
"title": "Change Git Ref"
|
||||
},
|
||||
{
|
||||
"command": "codetour.changeTourTitle",
|
||||
"title": "Change Title"
|
||||
|
@ -68,7 +72,7 @@
|
|||
"command": "codetour.endTour",
|
||||
"title": "End Tour",
|
||||
"category": "Code Tour",
|
||||
"icon": "$(close)"
|
||||
"icon": "$(debug-stop)"
|
||||
},
|
||||
{
|
||||
"command": "codetour.moveTourStepBack",
|
||||
|
@ -121,7 +125,7 @@
|
|||
"command": "codetour.startTour",
|
||||
"title": "Start Tour",
|
||||
"category": "CodeTour",
|
||||
"icon": "$(play)"
|
||||
"icon": "$(debug-start)"
|
||||
}
|
||||
],
|
||||
"menus": {
|
||||
|
@ -146,6 +150,10 @@
|
|||
"command": "codetour.addTourStep",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "codetour.changeTourRef",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "codetour.changeTourTitle",
|
||||
"when": "false"
|
||||
|
@ -299,6 +307,11 @@
|
|||
"when": "viewItem =~ /^codetour.tour(.recording)?(.active)?$/",
|
||||
"group": "change@2"
|
||||
},
|
||||
{
|
||||
"command": "codetour.changeTourRef",
|
||||
"when": "viewItem =~ /^codetour.tour(.recording)?(.active)?$/ && gitOpenRepositoryCount != 0",
|
||||
"group": "change@3"
|
||||
},
|
||||
{
|
||||
"command": "codetour.editTour",
|
||||
"when": "viewItem =~ /^codetour.tour(.active)?$/",
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
import { discoverTours } from "./store/provider";
|
||||
import { CodeTourNode, CodeTourStepNode } from "./tree/nodes";
|
||||
import { runInAction } from "mobx";
|
||||
import { api, RefType } from "./git";
|
||||
|
||||
interface CodeTourQuickPickItem extends vscode.QuickPickItem {
|
||||
tour: CodeTour;
|
||||
|
@ -288,6 +289,23 @@ export function registerCommands() {
|
|||
(node: CodeTourNode) => updateTourProperty(node.tour, "title")
|
||||
);
|
||||
|
||||
vscode.commands.registerCommand(
|
||||
`${EXTENSION_NAME}.changeTourRef`,
|
||||
async (node: CodeTourNode) => {
|
||||
const uri = vscode.Uri.parse(node.tour.id!);
|
||||
const ref = await promptForTourRef(uri);
|
||||
if (ref) {
|
||||
if (ref === "HEAD") {
|
||||
delete node.tour.ref;
|
||||
} else {
|
||||
node.tour.ref = ref;
|
||||
}
|
||||
}
|
||||
|
||||
saveTourIfNeccessary(node.tour);
|
||||
}
|
||||
);
|
||||
|
||||
vscode.commands.registerCommand(
|
||||
`${EXTENSION_NAME}.deleteTour`,
|
||||
async (node: CodeTourNode) => {
|
||||
|
@ -352,6 +370,58 @@ export function registerCommands() {
|
|||
}
|
||||
);
|
||||
|
||||
interface GitRefQuickPickItem extends vscode.QuickPickItem {
|
||||
ref?: string;
|
||||
}
|
||||
|
||||
async function promptForTourRef(
|
||||
uri: vscode.Uri
|
||||
): Promise<string | undefined> {
|
||||
const repository = api.getRepository(uri);
|
||||
if (!repository) {
|
||||
return;
|
||||
}
|
||||
let items: GitRefQuickPickItem[] = [
|
||||
{
|
||||
label: "$(circle-slash) None",
|
||||
description: "Allow the tour to apply to all versions of the repo",
|
||||
ref: "HEAD",
|
||||
alwaysShow: true
|
||||
},
|
||||
{
|
||||
label: "$(git-commit) Current commit",
|
||||
description: "Keep the tour stable as the repo changes over time",
|
||||
ref: repository.state.HEAD ? repository.state.HEAD.commit! : "",
|
||||
alwaysShow: true
|
||||
}
|
||||
];
|
||||
|
||||
const tags = repository.state.refs
|
||||
.filter(ref => ref.type === RefType.Tag)
|
||||
.map(ref => ref.name!)
|
||||
.sort()
|
||||
.map(ref => ({
|
||||
label: `$(tag) ${ref}`,
|
||||
description: "Lock the tour to this tag",
|
||||
ref
|
||||
}));
|
||||
|
||||
if (tags) {
|
||||
items.push(...tags);
|
||||
}
|
||||
|
||||
const response = await vscode.window.showQuickPick<GitRefQuickPickItem>(
|
||||
items,
|
||||
{
|
||||
placeHolder: "Select the Git ref to associate the tour with:"
|
||||
}
|
||||
);
|
||||
|
||||
if (response) {
|
||||
return response.ref;
|
||||
}
|
||||
}
|
||||
|
||||
vscode.commands.registerCommand(`${EXTENSION_NAME}.saveTour`, async () => {
|
||||
const file = store
|
||||
.activeTour!.tour.title.toLocaleLowerCase()
|
||||
|
@ -360,10 +430,17 @@ export function registerCommands() {
|
|||
|
||||
const tour = store.activeTour!.tour;
|
||||
delete tour.id;
|
||||
const tourContent = JSON.stringify(tour, null, 2);
|
||||
|
||||
const workspaceRoot = vscode.workspace.workspaceFolders![0].uri.toString();
|
||||
const uri = vscode.Uri.parse(`${workspaceRoot}/.vscode/tours/${file}.json`);
|
||||
|
||||
const ref = await promptForTourRef(uri);
|
||||
if (ref && ref !== "HEAD") {
|
||||
tour.ref = ref;
|
||||
}
|
||||
|
||||
const tourContent = JSON.stringify(tour, null, 2);
|
||||
|
||||
vscode.workspace.fs.writeFile(uri, new Buffer(tourContent));
|
||||
|
||||
vscode.commands.executeCommand("setContext", "codetour:recording", false);
|
||||
|
|
|
@ -5,6 +5,7 @@ import { registerStatusBar } from "./status";
|
|||
import { store } from "./store";
|
||||
import { discoverTours } from "./store/provider";
|
||||
import { registerTreeProvider } from "./tree";
|
||||
import { initializeGitApi } from "./git";
|
||||
|
||||
async function promptForTour(
|
||||
workspaceRoot: string,
|
||||
|
@ -35,5 +36,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||
registerStatusBar();
|
||||
|
||||
promptForTour(workspaceRoot, context.globalState);
|
||||
|
||||
initializeGitApi();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import * as vscode from "vscode";
|
||||
|
||||
export const enum RefType {
|
||||
Head,
|
||||
RemoteHead,
|
||||
Tag
|
||||
}
|
||||
|
||||
export interface Ref {
|
||||
readonly type: RefType;
|
||||
readonly name?: string;
|
||||
readonly commit?: string;
|
||||
readonly remote?: string;
|
||||
}
|
||||
|
||||
export interface RepositoryState {
|
||||
readonly HEAD: Ref | undefined;
|
||||
readonly refs: Ref[];
|
||||
}
|
||||
|
||||
export interface Repository {
|
||||
readonly state: RepositoryState;
|
||||
}
|
||||
|
||||
interface GitAPI {
|
||||
toGitUri(uri: vscode.Uri, ref: string): vscode.Uri;
|
||||
getRepository(uri: vscode.Uri): Repository | null;
|
||||
}
|
||||
|
||||
export let api: GitAPI;
|
||||
export async function initializeGitApi() {
|
||||
const extension = vscode.extensions.getExtension("vscode.git");
|
||||
if (!extension) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!extension.isActive) {
|
||||
await extension.activate();
|
||||
}
|
||||
|
||||
api = extension.exports.getAPI(1);
|
||||
}
|
|
@ -18,6 +18,7 @@ import {
|
|||
import { CodeTour, store } from ".";
|
||||
import { EXTENSION_NAME } from "../constants";
|
||||
import { reaction } from "mobx";
|
||||
import { api } from "../git";
|
||||
|
||||
const IN_TOUR_KEY = `${EXTENSION_NAME}:inTour`;
|
||||
|
||||
|
@ -82,10 +83,23 @@ async function renderCurrentStep() {
|
|||
const workspaceRoot = workspace.workspaceFolders
|
||||
? workspace.workspaceFolders[0].uri.toString()
|
||||
: "";
|
||||
const uri = step.uri
|
||||
let uri = step.uri
|
||||
? Uri.parse(step.uri)
|
||||
: Uri.parse(`${workspaceRoot}/${step.file}`);
|
||||
|
||||
if (currentTour.ref && currentTour.ref !== "HEAD") {
|
||||
const repo = api.getRepository(uri);
|
||||
|
||||
if (
|
||||
repo &&
|
||||
repo.state.HEAD &&
|
||||
repo.state.HEAD.name !== currentTour.ref &&
|
||||
repo.state.HEAD.commit !== currentTour.ref
|
||||
) {
|
||||
uri = await api.toGitUri(uri, currentTour.ref);
|
||||
}
|
||||
}
|
||||
|
||||
store.activeTour!.thread = controller.createCommentThread(uri, range, []);
|
||||
store.activeTour!.thread.comments = [
|
||||
new CodeTourComment(step.description, label, store.activeTour!.thread!)
|
||||
|
|
Загрузка…
Ссылка в новой задаче