This repository has been archived by the owner on Dec 25, 2021. It is now read-only.
forked from lehni/vscode-fix-checksums
-
Notifications
You must be signed in to change notification settings - Fork 1
/
extension.js
167 lines (150 loc) · 4.7 KB
/
extension.js
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
const vscode = require('vscode')
const crypto = require('crypto')
const path = require('path')
const sudo = require('sudo-prompt')
const tmp = require('tmp')
const fs = require('fs')
const appDir = path.dirname(require.main.filename)
const rootDir = path.join(appDir, '..')
const productFile = path.join(rootDir, 'product.json')
const origFile = `${productFile}.orig.${vscode.version}`
exports.activate = function activate(context) {
context.subscriptions.push(
vscode.commands.registerCommand('fixChecksums.apply', apply),
vscode.commands.registerCommand('fixChecksums.restore', restore)
)
cleanupOrigFiles()
}
const messages = {
changed: verb => `Checksums ${verb}. Please restart VSCode to see effect.`,
unchanged: 'No changes to checksums were necessary.',
error: `An error occurred during execution.
Make sure you have write access rights to the VSCode files, see README`
}
function apply() {
const product = require(productFile)
let changed = false
let message = messages.unchanged
for (const [filePath, curChecksum] of Object.entries(product.checksums)) {
const checksum = computeChecksum(path.join(appDir, ...filePath.split('/')))
if (checksum !== curChecksum) {
product.checksums[filePath] = checksum
changed = true
}
}
if (changed) {
const json = JSON.stringify(product, null, '\t')
try {
if (!fs.existsSync(origFile)) {
moveFileAdmin(productFile, origFile).then(
() => writeFileAdmin(productFile, json)
).catch(error => { throw error })
} else {
writeFileAdmin(productFile, json)
}
message = messages.changed('applied')
} catch (err) {
console.error(err)
message = messages.error
}
}
if (changed) reloadWindow(message)
else vscode.window.showInformationMessage(message)
}
function restore() {
let message = messages.unchanged
let reload = false;
try {
if (fs.existsSync(origFile)) {
deleteFileAdmin(productFile).then(
() => moveFileAdmin(origFile, productFile)
).catch(error => { throw error })
message = messages.changed('restored')
reload = true;
}
} catch (err) {
console.error(err)
message = messages.error
}
if (reload) reloadWindow(message)
else vscode.window.showInformationMessage(message)
}
function computeChecksum(file) {
var contents = fs.readFileSync(file)
return crypto
.createHash('md5')
.update(contents)
.digest('base64')
.replace(/=+$/, '')
}
function cleanupOrigFiles() {
// Remove all old backup files that aren't related to the current version
// of VSCode anymore.
const oldOrigFiles = fs.readdirSync(rootDir)
.filter(file => /\.orig\./.test(file))
.filter(file => !file.endsWith(vscode.version))
for (const file of oldOrigFiles) {
deleteFileAdmin(path.join(rootDir, file))
}
}
function writeFileAdmin(filePath, writeString, encoding = 'utf-8', promptName = 'File Writer') {
console.info('Writing file with administrator priveleges.')
return new Promise((resolve, reject) => {
tmp.file((error, tempFilePath) => {
if (error) reject(error)
else fs.writeFile(tempFilePath, writeString, encoding, (error) => {
if (error) reject(error)
else sudo.exec(
(process.platform === 'win32' ? 'copy /y ' : 'cp -f ') +
'"' + tempFilePath + '" "' + filePath + '"',
{ name: promptName },
(error) => {
if (error) reject(error)
else resolve(error)
}
);
});
});
});
}
function deleteFileAdmin(filePath, promptName = 'File Deleter') {
console.info('Deleting file with administrator privileges')
return new Promise((resolve, reject) => {
sudo.exec(
(process.platform === 'win32' ? 'del /f /q ' : 'rm -f ') +
'"' + filePath + '"',
{ name: promptName },
(error) => {
if (error) reject(error)
else resolve(error)
}
);
});
}
function moveFileAdmin(filePath, newPath, promptName = 'File Renamer') {
console.info('Renaming file with administrator privileges')
return new Promise((resolve, reject) => {
sudo.exec(
(process.platform === 'win32' ? 'move /y ' : 'mv -f ') +
'"' + filePath + '" "' + newPath + '"',
{ name: promptName },
(error) => {
if (error) reject(error)
else resolve(error)
}
);
});
}
function reloadWindow(message) {
if (message === undefined) {
console.info('Reloading window.');
vscode.commands.executeCommand('workbench.action.reloadWindow');
} else {
console.info('Requesting to reload window.');
vscode.window.showInformationMessage(message, {
title: 'Reload Window'
}).then(clicked => {
if (clicked) reloadWindow();
});
}
}