-
-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathProjectManager.js
More file actions
137 lines (115 loc) · 4.05 KB
/
ProjectManager.js
File metadata and controls
137 lines (115 loc) · 4.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* global atom */
'use strict';
const fs = require('fs');
const mkdirp = require('mkdirp');
module.exports =
class ProjectManager
{
/**
* @param {Object} proxy
*/
constructor(proxy, config) {
this.proxy = proxy;
this.config = config;
this.activeProject = null;
}
/**
* Sets up the specified project for usage with the Serenata server.
*
* @param {String} mainFolder
*/
setUpProject(mainFolder) {
// const process = require('process');
//
// // Great, URI's are supposed to be file:// + host (optional) + path, which on UNIX systems becomes something
// // like file:///my/folder if the host is omitted. Microsoft decided to do it differently and does
// // file:///c:/my/path instead of file://C:/my/path, so add an extra slash and lower case the drive letter.
// if (process.platform === 'win32') {
// mainFolder = '/' + mainFolder.substr(0, 1).toLowerCase() + mainFolder.substr(1);
// }
const path = require('path');
const crypto = require('crypto');
const md5 = crypto.createHash('md5');
const configFileFolderPath = mainFolder + '/.serenata';
const configFilePath = configFileFolderPath + '/config.json';
// NOTE: I wanted to place the index inside the .serenata folder, but it turns out that is a very bad idea.
// Pulsar will start firing massive amounts of change requests, due to it watching the database file, every time
// it is modified. We can disable this for our package, but not for other packages, which will still receive
// these events en masse uselessly, which not only prevents any other responses from being handled in the
// meantime, it also spikes CPU usage.
const indexDatabaseUri = 'file://' + path.join(
this.config.get('storagePath'),
'index-' + md5.update(mainFolder).digest('hex') + '.sqlite'
);
if (fs.existsSync(configFilePath)) {
throw new Error(
'The currently active project was already initialized. To prevent existing settings from being ' +
'lost, the request has been aborted.'
);
}
const template =
`{
"uris": [
"file://${mainFolder.replace(/\\/g, '\\\\')}"
],
"indexDatabaseUri": "${indexDatabaseUri.replace(/\\/g, '\\\\')}",
"phpVersion": 7.3,
"excludedPathExpressions": [],
"fileExtensions": [
"php"
]
}`;
mkdirp.sync(configFileFolderPath);
fs.writeFileSync(configFilePath, template);
}
/**
* @param {String} projectFolder
*
* @return {Boolean}
*/
shouldStartForProject(projectFolder) {
return fs.existsSync(this.getConfigFilePath(projectFolder));
}
/**
* @param {String} projectFolder
*/
tryLoad(projectFolder) {
if (!this.shouldStartForProject(projectFolder)) {
return;
}
this.load(projectFolder);
}
/**
* @param {String} projectFolder
*/
load(projectFolder) {
const path = this.getConfigFilePath(projectFolder);
try {
this.activeProject = JSON.parse(fs.readFileSync(path));
} catch (e) {
const message =
'Loading project configuration in **' + path + '** failed. It likely contains syntax errors. \n \n' +
'The error message returned was:\n \n' +
'```' + e + '```';
atom.notifications.addError('Serenata - Loading Project Failed', {
description: message,
dismissable: true
});
throw new Error('Loading project at "' + path + '" failed due to it not being valid JSON');
}
}
/**
* @param {String} projectFolder
*
* @return {String}
*/
getConfigFilePath(projectFolder) {
return projectFolder + '/.serenata/config.json';
}
/**
* @return {Object|null}
*/
getCurrentProjectSettings() {
return this.activeProject;
}
};