Skip to content

Commit 70bc12d

Browse files
committed
Multi-root Workspaces support. svn is broken
1 parent d2f770b commit 70bc12d

File tree

9 files changed

+184
-133
lines changed

9 files changed

+184
-133
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@
4040
"title": "add",
4141
"category": "svn",
4242
"icon": {
43-
"light": "icons/add.svg",
44-
"dark": "icons/add.svg"
43+
"light": "icons/light/add.svg",
44+
"dark": "icons/dark/add.svg"
4545
}
4646
}
4747
],

src/Resource.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
const { Uri, workspace } = require("vscode");
22
const path = require("path");
33

4-
function Resource(relativePath, type) {
4+
function Resource(rootPath, relativePath, type) {
55
this.type = type;
6+
this.rootPath = rootPath;
67

78
return {
89
resourceUri: this.getResourceUri(relativePath),
@@ -20,7 +21,7 @@ Resource.prototype.getCommand = function(relativePath) {
2021
};
2122

2223
Resource.prototype.getResourceUri = function(relativePath) {
23-
const absolutePath = path.join(workspace.rootPath, relativePath);
24+
const absolutePath = path.join(this.rootPath, relativePath);
2425
return Uri.file(absolutePath);
2526
};
2627

src/extension.js

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,18 @@
11
const vscode = require("vscode");
22
const path = require("path");
33
const Svn = require("./svn");
4-
const svnSCM = require("./svnSCM");
54
const svnContentProvider = require("./svnContentProvider");
65
const SvnCommands = require("./commands");
6+
const Model = require("./model");
77

88
function activate(context) {
99
console.log("svn-scm is now active!");
1010

1111
const disposable = [];
12-
const rootPath = vscode.workspace.rootPath;
13-
14-
const watcher = vscode.workspace.createFileSystemWatcher(`${rootPath}/**/*`);
15-
1612
const commands = new SvnCommands();
17-
const sourceControl = new svnSCM();
18-
const contentProvider = new svnContentProvider();
1913
const svn = new Svn();
14+
const model = new Model(svn);
15+
const contentProvider = new svnContentProvider();
2016

2117
context.subscriptions.push(disposable);
2218
}

src/model.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
const { workspace, Uri } = require("vscode");
2+
const fs = require("fs");
3+
const path = require("path");
4+
const Repository = require("./repository");
5+
6+
function Model(svn) {
7+
this.svn = svn;
8+
this.openRepositories = [];
9+
this.scanWorkspaceFolders();
10+
}
11+
12+
Model.prototype.scanWorkspaceFolders = async function() {
13+
for (const folder of workspace.workspaceFolders || []) {
14+
const root = folder.uri.fsPath;
15+
this.tryOpenRepository(root);
16+
}
17+
};
18+
19+
Model.prototype.tryOpenRepository = async function(path) {
20+
if (this.getRepository(path)) {
21+
return;
22+
}
23+
24+
try {
25+
const repositoryRoot = await this.svn.getRepositoryRoot(path);
26+
const repository = new Repository(this.svn.open(repositoryRoot));
27+
28+
// this.open(repository);
29+
} catch (err) {
30+
return;
31+
}
32+
};
33+
34+
Model.prototype.getRepository = function(path) {
35+
const liveRepository = this.getOpenRepository(path);
36+
return liveRepository && liveRepository.repository;
37+
};
38+
39+
Model.prototype.getOpenRepository = function(path) {
40+
if (!path) {
41+
return undefined;
42+
}
43+
44+
path = Uri.file(path);
45+
46+
for (const liveRepository of this.openRepositories) {
47+
const relativePath = path.relative(
48+
liveRepository.repository.root,
49+
path.fsPath
50+
);
51+
52+
if (!/^\.\./.test(relativePath)) {
53+
return liveRepository;
54+
}
55+
56+
return undefined;
57+
}
58+
};
59+
60+
Model.prototype.open = function(repository) {
61+
this.openRepositories.push(repository);
62+
};
63+
64+
module.exports = Model;

src/repository.js

Lines changed: 82 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,90 @@
1-
const Svn = require('./svn');
1+
const { Uri, scm, workspace } = require("vscode");
2+
const Resource = require("./Resource");
23

3-
function repository() {
4-
this.svn = new Svn();
5-
this.filePaths = [];
6-
this.update();
7-
}
4+
function Repository(repository) {
5+
this.repository = repository;
6+
this.watcher = workspace.createFileSystemWatcher("**");
7+
this.sourceControl = scm.createSourceControl(
8+
"svn",
9+
"svn",
10+
Uri.parse(this.repository.root)
11+
);
12+
this.sourceControl.acceptInputCommand = {
13+
command: "svn.commitWithMessage",
14+
title: "commit"
15+
};
16+
this.sourceControl.quickDiffProvider = this;
17+
18+
this.changes = this.sourceControl.createResourceGroup("changes", "Changes");
19+
this.notTracked = this.sourceControl.createResourceGroup(
20+
"unversioned",
21+
"Not Tracked"
22+
);
823

9-
repository.prototype.update = function() {
10-
this.svn.getStatus().then(result => {
11-
result.forEach(item => {
12-
this.filePaths.push(item.$.path);
13-
});
14-
});
24+
this.changes.hideWhenEmpty = true;
25+
this.notTracked.hideWhenEmpty = true;
26+
27+
this.addEventListeners();
28+
this.update();
1529
}
1630

17-
repository.prototype.getRepositoryFilePath = function(relativePath) {
18-
let repositoryFilePath = false;
31+
Repository.prototype.addEventListeners = function() {
32+
this.watcher.onDidChange(() => {
33+
this.update();
34+
});
35+
this.watcher.onDidCreate(() => {
36+
this.update();
37+
});
38+
this.watcher.onDidDelete(() => {
39+
this.update();
40+
});
41+
};
1942

20-
this.filePaths.forEach(filePath => {
21-
const fileName = relativePath.split('/').pop();
43+
Repository.prototype.provideOriginalResource = uri => {
44+
if (uri.scheme !== "file") {
45+
return;
46+
}
2247

23-
let regex = new RegExp(fileName, 'g');
24-
let matches = filePath.match(regex);
48+
return new Uri().with({ scheme: "svn", query: uri.path, path: uri.path });
49+
};
2550

26-
if (matches) {
27-
repositoryFilePath = filePath;
28-
}
29-
});
30-
31-
return repositoryFilePath;
32-
}
51+
Repository.prototype.update = function() {
52+
let changes = [];
53+
let notTracked = [];
54+
55+
this.changes.resourceStates = [];
56+
this.notTracked.resourceStates = [];
57+
58+
this.repository
59+
.getStatus()
60+
.then(result => {
61+
let changes = [];
62+
let notTracked = [];
63+
64+
result.forEach(item => {
65+
switch (item["wc-status"].$.item) {
66+
case "modified":
67+
case "deleted":
68+
case "conflicted":
69+
case "replaced":
70+
case "missing":
71+
case "added":
72+
changes.push(new Resource(this.repository.root, item.$.path, item["wc-status"].$.item));
73+
break;
74+
case "unversioned":
75+
notTracked.push(
76+
new Resource(this.repository.root, item.$.path, item["wc-status"].$.item)
77+
);
78+
break;
79+
}
80+
});
81+
82+
this.changes.resourceStates = changes;
83+
this.notTracked.resourceStates = notTracked;
84+
})
85+
.catch(error => {
86+
console.log(error);
87+
});
88+
};
3389

34-
module.exports = repository;
90+
module.exports = Repository;

src/resourceGroup.js

Whitespace-only changes.

src/svn.js

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,25 @@ const SvnSpawn = require("svn-spawn");
22
const vscode = require("vscode");
33

44
function svn() {
5-
const rootPath = vscode.workspace.rootPath;
6-
75
this.client = new SvnSpawn({
8-
cwd: rootPath,
96
noAuthCache: true
107
});
118
}
129

10+
svn.prototype.getRepositoryRoot = async function(path) {
11+
try {
12+
let result = await this.cmd(["info", path]);
13+
let match = result.match(/(?=Working Copy Root Path:)(.*)/i)[0].replace('Working Copy Root Path:', '').trim();
14+
return match;
15+
} catch (error) {
16+
console.log(error);
17+
}
18+
};
19+
20+
svn.prototype.open = function(repositoryRoot) {
21+
return new Repository(this, repositoryRoot);
22+
}
23+
1324
svn.prototype.cmd = function(args) {
1425
return new Promise((resolve, reject) => {
1526
this.client.cmd(args, (err, data) => (err ? reject(err) : resolve(data)));
@@ -41,3 +52,17 @@ svn.prototype.add = function(filePath) {
4152
};
4253

4354
module.exports = svn;
55+
56+
function Repository(svn, repositoryRoot) {
57+
this.svn = new SvnSpawn({
58+
cwd: repositoryRoot,
59+
noAuthCache: true
60+
});
61+
this.root = repositoryRoot;
62+
}
63+
64+
Repository.prototype.getStatus = function() {
65+
return new Promise((resolve, reject) => {
66+
this.svn.getStatus((err, data) => (err ? reject(err) : resolve(data)));
67+
});
68+
}

src/svnContentProvider.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,10 @@ function svnContentProvider() {
88
}
99

1010
svnContentProvider.prototype.provideTextDocumentContent = function(uri) {
11-
const relativePath = path
12-
.relative(vscode.workspace.rootPath, uri.fsPath)
13-
.replace(/\\/g, "/");
14-
1511
return new Promise((resolve, reject) => {
1612
this.svn
17-
.cmd(["ls", relativePath])
18-
.then(() => this.svn.cmd(["cat", "-r", "HEAD", relativePath]))
13+
.cmd(["ls", uri.fsPath])
14+
.then(() => this.svn.cmd(["cat", "-r", "HEAD", uri.fsPath]))
1915
.then(result => {
2016
resolve(result);
2117
})

src/svnSCM.js

Lines changed: 0 additions & 87 deletions
This file was deleted.

0 commit comments

Comments
 (0)