This commit is contained in:
Jonathan Carter 2020-03-14 15:36:25 -07:00
Родитель b1f28f76c1
Коммит 21375e00fe
6 изменённых файлов: 157 добавлений и 4 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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();
}
}

42
src/git.ts Normal file
Просмотреть файл

@ -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!)