Skip to content
Merged
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
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
# **v1.4.0 under development**

## What's New

* @edgardmessias Added support to configure non-standard layout. To configure, edit the options:
* "svn.layout.trunk" : Relative path for 'trunk' in SVN URL, 'null' to disable. (Ex.: 'trunk', 'main')
* "svn.layout.branches" : Relative path for 'branches' in SVN URL, 'null' to disable. (Ex.: 'branches', 'versions')
* "svn.layout.tags" : Relative path for 'tags' in SVN URL, 'null' to disable. (Ex.: 'tags', 'stamps')

## Bug Fixes

* @edgardmessias Fixed config option form svn path

# **v1.3.2**

## Bug Fixes
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,8 @@ Files\TortoiseSVN\bin` is available in PATH.
[Issues](https://github.com/JohnstonCode/svn-scm/issues)
* Feel free to submit
[pull requests](https://github.com/JohnstonCode/svn-scm/pulls)

## Contributors

* @JohnstonCode
* @edgardmessias
27 changes: 21 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,28 @@
"type": "boolean",
"description": "Whether svn is enabled",
"default": true
},
"svn.path": {
"type": ["string", "null"],
"description": "Path to the svn executable",
"default": null,
"isExecutable": true
},
"svn.layout.trunk": {
"type": ["string", "null"],
"description": "Relative path for 'trunk' in SVN URL, 'null' to disable. (Ex.: 'trunk', 'main')",
"default": "trunk"
},
"svn.layout.branches": {
"type": ["string", "null"],
"description": "Relative path for 'branches' in SVN URL, 'null' to disable. (Ex.: 'branches', 'versions')",
"default": "branches"
},
"svn.layout.tags": {
"type": ["string", "null"],
"description": "Relative path for 'tags' in SVN URL, 'null' to disable. (Ex.: 'tags', 'stamps')",
"default": "tags"
}
},
"svn.path": {
"type": ["string", "null"],
"description": "Path to the svn executable",
"default": null,
"isExecutable": true
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class SwitchBranchItem implements QuickPickItem {
this.tree = parts[0];
this.name = parts[1];
} else {
this.tree = "trunk";
this.tree = parts[0];
this.name = parts[0];
}
}
Expand Down
79 changes: 55 additions & 24 deletions src/svnRepository.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { workspace } from "vscode";
import { Svn, CpOptions } from "./svn";

export class Repository {
Expand Down Expand Up @@ -62,16 +63,22 @@ export class Repository {
}

async getRepoUrl() {
const config = workspace.getConfiguration("svn");
const trunkLayout = config.get<string>("layout.trunk");
const branchesLayout = config.get<string>("layout.branches");
const tagsLayout = config.get<string>("layout.tags");

const trees = [trunkLayout, branchesLayout, tagsLayout].filter(x => x != null);
const regex = new RegExp("<url>(.*?)\/(" + trees.join("|") + ").*?<\/url>");

const info = await this.svn.info(this.root);

if (info.exitCode !== 0) {
throw new Error(info.stderr);
}

let repoUrl = info.stdout.match(/<root>(.*?)<\/root>/)[1];
const match = info.stdout.match(
/<url>(.*?)\/(trunk|branches|tags).*?<\/url>/
);
const match = info.stdout.match(regex);

if (match && match[1]) {
repoUrl = match[1];
Expand All @@ -81,30 +88,45 @@ export class Repository {
}

async getBranches() {
const config = workspace.getConfiguration("svn");
const trunkLayout = config.get<string>("layout.trunk");
const branchesLayout = config.get<string>("layout.branches");
const tagsLayout = config.get<string>("layout.tags");

const repoUrl = await this.getRepoUrl();

let branches: string[] = [];

let promises = [];

promises.push(
new Promise<string[]>(async resolve => {
let trunkExists = await this.svn.exec("", [
"ls",
repoUrl + "/trunk",
"--depth",
"empty"
]);

if (trunkExists.exitCode === 0) {
resolve(["trunk"]);
return;
}
resolve([]);
})
);

const trees = ["branches", "tags"];
if (trunkLayout) {
promises.push(
new Promise<string[]>(async resolve => {
let trunkExists = await this.svn.exec("", [
"ls",
repoUrl + "/" + trunkLayout,
"--depth",
"empty"
]);

if (trunkExists.exitCode === 0) {
resolve([trunkLayout]);
return;
}
resolve([]);
})
);
}

let trees: string[] = [];

if (branchesLayout) {
trees.push(branchesLayout);
}

if (tagsLayout) {
trees.push(tagsLayout);
}

for (let index in trees) {
promises.push(
Expand Down Expand Up @@ -139,11 +161,20 @@ export class Repository {
}

async branch(name: string) {
const config = workspace.getConfiguration("svn");
const branchesLayout = config.get<string>("layout.branches");

if (!branchesLayout) {
return false;
}

const repoUrl = await this.getRepoUrl();
const newBranch = repoUrl + "/branches/" + name;
const rootUrl = repoUrl + "/trunk";
const newBranch = repoUrl + "/" + branchesLayout + "/" + name;
const resultBranch = await this.svn.info(this.root);
const currentBranch = resultBranch.stdout
.match(/<url>(.*?)<\/url>/)[1];

const result = await this.svn.copy(rootUrl, newBranch, name);
const result = await this.svn.copy(currentBranch, newBranch, name);

if (result.exitCode !== 0) {
throw new Error(result.stderr);
Expand Down