Skip to content

Commit 1762e4c

Browse files
author
chris
committed
switching branches works and encoding does
1 parent 27b917c commit 1762e4c

File tree

5 files changed

+191
-33
lines changed

5 files changed

+191
-33
lines changed

package.json

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,18 @@
1515
"bugs": {
1616
"url": "https://github.com/JohnstonCode/svn-scm/issues"
1717
},
18-
"categories": ["Other", "SCM Providers"],
19-
"keywords": ["multi-root ready", "scm", "svn"],
20-
"activationEvents": ["*"],
18+
"categories": [
19+
"Other",
20+
"SCM Providers"
21+
],
22+
"keywords": [
23+
"multi-root ready",
24+
"scm",
25+
"svn"
26+
],
27+
"activationEvents": [
28+
"*"
29+
],
2130
"main": "./out/extension",
2231
"scripts": {
2332
"vscode:prepublish": "tsc -p ./",
@@ -26,7 +35,8 @@
2635
"test": "node ./node_modules/vscode/bin/test"
2736
},
2837
"dependencies": {
29-
"iconv-lite": "^0.4.19"
38+
"iconv-lite": "^0.4.19",
39+
"jschardet": "^1.6.0"
3040
},
3141
"devDependencies": {
3242
"typescript": "^2.5.2",

src/commands.ts

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
import { commands, scm, window, Uri, TextDocumentShowOptions } from "vscode";
1+
import {
2+
commands,
3+
scm,
4+
window,
5+
Uri,
6+
TextDocumentShowOptions,
7+
QuickPickItem
8+
} from "vscode";
29
import { inputCommitMessage, changesCommitted } from "./messages";
310
import { Svn } from "./svn";
411
import { Model } from "./model";
@@ -11,6 +18,38 @@ interface CommandOptions {
1118
repository?: boolean;
1219
}
1320

21+
class CreateBranchItem implements QuickPickItem {
22+
constructor(private commands: SvnCommands) {}
23+
24+
get label(): string {
25+
return "$(plus) Create new branch";
26+
}
27+
28+
get description(): string {
29+
return "";
30+
}
31+
32+
async run(repository: Repository): Promise<void> {
33+
await this.commands.branch(repository);
34+
}
35+
}
36+
37+
class SwitchBranchItem implements QuickPickItem {
38+
constructor(protected ref: string) {}
39+
40+
get label(): string {
41+
return this.ref;
42+
}
43+
44+
get description(): string {
45+
return "";
46+
}
47+
48+
async run(repository: Repository): Promise<void> {
49+
await repository.switchBranch(this.ref);
50+
}
51+
}
52+
1453
export class SvnCommands {
1554
private commands: any[] = [];
1655

@@ -47,8 +86,13 @@ export class SvnCommands {
4786
options: {}
4887
},
4988
{
50-
commandId: "svn.checkout",
51-
method: this.checkout,
89+
commandId: "svn.switchBranch",
90+
method: this.switchBranch,
91+
options: { repository: true }
92+
},
93+
{
94+
commandId: "svn.branch",
95+
method: this.branch,
5296
options: { repository: true }
5397
}
5498
];
@@ -239,15 +283,38 @@ export class SvnCommands {
239283
return resource.resourceUri;
240284
}
241285

242-
async checkout(repository: Repository) {
243-
const branches = repository.branches;
286+
async switchBranch(repository: Repository) {
287+
const branches = repository.branches.map(
288+
branch => new SwitchBranchItem(branch)
289+
);
244290
const placeHolder = "Pick a branch to switch to.";
245-
const choice = await window.showQuickPick(branches, { placeHolder });
291+
const createBranch = new CreateBranchItem(this);
292+
const picks = [createBranch, ...branches];
293+
294+
const choice = await window.showQuickPick(picks, { placeHolder });
246295

247296
if (!choice) {
248297
return;
249298
}
250299

251-
console.log(choice);
300+
await choice.run(repository);
301+
}
302+
303+
async branch(repository: Repository): Promise<void> {
304+
const result = await window.showInputBox({
305+
placeholder: "Branch name",
306+
prompt: "Please provide a branch name",
307+
ignoreFocusOut: true
308+
});
309+
310+
if (!result) {
311+
return;
312+
}
313+
314+
const name = result.replace(
315+
/^\.|\/\.|\.\.|~|\^|:|\/$|\.lock$|\.lock\/|\\|\*|\s|^\s*$|\.$/g,
316+
"-"
317+
);
318+
await repository.branch(name);
252319
}
253320
}

src/repository.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ export class Repository {
2222
public changes: SourceControlResourceGroup;
2323
public notTracked: SourceControlResourceGroup;
2424
private disposables: Disposable[] = [];
25-
public branch = "";
26-
public branches: any[];
25+
public currentBranch = "";
26+
public branches: any[] = [];
2727

2828
private _onDidChangeStatus = new EventEmitter<void>();
2929
readonly onDidChangeStatus: Event<void> = this._onDidChangeStatus.event;
@@ -130,7 +130,7 @@ export class Repository {
130130
this.changes.resourceStates = changes;
131131
this.notTracked.resourceStates = notTracked;
132132

133-
this.branch = await this.getCurrentBranch();
133+
this.currentBranch = await this.getCurrentBranch();
134134

135135
try {
136136
this.branches = await this.repository.getBranches();
@@ -152,10 +152,7 @@ export class Repository {
152152
}
153153

154154
show(filePath: string): Promise<string> {
155-
const config = workspace.getConfiguration("files", Uri.file(filePath));
156-
const encoding = config.get<string>("encoding");
157-
158-
return this.repository.show(filePath, { encoding });
155+
return this.repository.show(filePath);
159156
}
160157

161158
addFile(filePath: string) {
@@ -169,4 +166,12 @@ export class Repository {
169166
getCurrentBranch() {
170167
return this.repository.getCurrentBranch();
171168
}
169+
170+
branch(name: string) {
171+
return this.repository.branch(name);
172+
}
173+
174+
switchBranch(name: string) {
175+
return this.repository.switchBranch(name);
176+
}
172177
}

src/statusBar.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ export class SvnStatusBar {
1818
}
1919

2020
get commands() {
21-
const title = `$(git-branch) ${this.repository.branch}`;
21+
const title = `$(git-branch) ${this.repository.currentBranch}`;
2222

2323
return [
2424
{
25-
command: "svn.checkout",
26-
tooltip: "Checkout...",
25+
command: "svn.switchBranch",
26+
tooltip: "switch branch",
2727
title,
2828
arguments: [this.repository]
2929
}

src/svn.ts

Lines changed: 88 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { window } from "vscode";
22
import * as cp from "child_process";
33
import * as iconv from "iconv-lite";
4+
import * as jschardet from "jschardet";
45

56
interface CpOptions {
67
cwd?: string;
@@ -38,8 +39,10 @@ export class Svn {
3839
})
3940
]);
4041

41-
let encoding = options.encoding || "utf8";
42-
encoding = iconv.encodingExists(encoding) ? encoding : "utf8";
42+
const encodingGuess = jschardet.detect(stdout);
43+
const encoding = iconv.encodingExists(encodingGuess.encoding)
44+
? encodingGuess.encoding
45+
: "utf8";
4346

4447
stdout = iconv.decode(stdout, encoding);
4548

@@ -104,6 +107,24 @@ export class Svn {
104107
info(path: string) {
105108
return this.exec(path, ["info", "--xml"]);
106109
}
110+
111+
copy(rootPath: string, branchPath: string, name: string) {
112+
return this.exec("", [
113+
"copy",
114+
rootPath,
115+
branchPath,
116+
"-m",
117+
`Created new branch ${name}`
118+
]);
119+
}
120+
121+
checkout(root: string, branchPath: string) {
122+
return this.exec(root, ["checkout", branchPath]);
123+
}
124+
125+
switchBranch(root: string, path: string) {
126+
return this.exec(root, ["switch", path]);
127+
}
107128
}
108129

109130
export class Repository {
@@ -131,15 +152,22 @@ export class Repository {
131152

132153
async show(path: string, options: CpOptions = {}): Promise<string> {
133154
const result = await this.svn.show(path, options);
155+
156+
if (result.exitCode !== 0) {
157+
throw new Error(result.stderr);
158+
}
159+
134160
return result.stdout;
135161
}
136162

137163
async commitFiles(message: string, files: any[]) {
138-
try {
139-
return await this.svn.commit(message, files);
140-
} catch (error) {
141-
throw new Error("Unable to commit files");
164+
const result = await this.svn.commit(message, files);
165+
166+
if (result.exitCode !== 0) {
167+
throw new Error(result.stderr);
142168
}
169+
170+
return result.stdout;
143171
}
144172

145173
addFile(filePath: string) {
@@ -163,18 +191,16 @@ export class Repository {
163191
async getBranches() {
164192
const info = await this.svn.info(this.root);
165193

166-
if (info.exitCode === 0) {
194+
if (info.exitCode !== 0) {
167195
throw new Error(info.stderr);
168196
}
169197

170-
const repoUrl = info.stdout
171-
.match(/<url>(.*?)<\/url>/)[1]
172-
.replace(/\/[^\/]+$/, "");
198+
const repoUrl = info.stdout.match(/<root>(.*?)<\/root>/)[1];
173199
const branchUrl = repoUrl + "/branches";
174200

175201
const result = await this.svn.list(branchUrl);
176202

177-
if (result.exitCode === 0) {
203+
if (result.exitCode !== 0) {
178204
throw new Error(result.stderr);
179205
}
180206

@@ -183,6 +209,56 @@ export class Repository {
183209
.replace(/\/|\\/g, "")
184210
.split("\n");
185211

186-
return branches;
212+
return ["trunk", ...branches];
213+
}
214+
215+
async branch(name: string) {
216+
const info = await this.svn.info(this.root);
217+
218+
if (info.exitCode !== 0) {
219+
throw new Error(info.stderr);
220+
}
221+
222+
const repoUrl = info.stdout.match(/<root>(.*?)<\/root>/)[1];
223+
const newBranch = repoUrl + "/branches/" + name;
224+
const rootUrl = repoUrl + "/trunk";
225+
226+
const result = await this.svn.copy(rootUrl, newBranch, name);
227+
228+
if (result.exitCode !== 0) {
229+
throw new Error(result.stderr);
230+
}
231+
232+
const switchBranch = await this.svn.switchBranch(this.root, newBranch);
233+
234+
if (switchBranch.exitCode !== 0) {
235+
throw new Error(switchBranch.stderr);
236+
}
237+
238+
return true;
239+
}
240+
241+
async switchBranch(ref: string) {
242+
const info = await this.svn.info(this.root);
243+
244+
if (info.exitCode !== 0) {
245+
throw new Error(info.stderr);
246+
}
247+
248+
const repoUrl = info.stdout.match(/<root>(.*?)<\/root>/)[1];
249+
250+
if (ref === "trunk") {
251+
var branchUrl = repoUrl + "/trunk";
252+
} else {
253+
var branchUrl = repoUrl + "/branches/" + ref;
254+
}
255+
256+
const switchBranch = await this.svn.switchBranch(this.root, branchUrl);
257+
258+
if (switchBranch.exitCode !== 0) {
259+
throw new Error(switchBranch.stderr);
260+
}
261+
262+
return true;
187263
}
188264
}

0 commit comments

Comments
 (0)