This repository was archived by the owner on Dec 15, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 407
Expand file tree
/
Copy pathgit-prompt-server.js
More file actions
113 lines (95 loc) · 3.11 KB
/
Copy pathgit-prompt-server.js
File metadata and controls
113 lines (95 loc) · 3.11 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
import net from 'net';
import path from 'path';
import treeKill from 'tree-kill';
import {Emitter} from 'event-kit';
import {getPackageRoot, deleteFileOrFolder, getTempDir, copyFile} from './helpers';
function getAtomHelperPath() {
if (process.platform === 'darwin') {
return path.resolve(process.resourcesPath, '..', 'Frameworks',
'Atom Helper.app', 'Contents', 'MacOS', 'Atom Helper');
} else {
return process.execPath;
}
}
export default class GitPromptServer {
constructor() {
this.emitter = new Emitter();
}
async start(promptForInput) {
// TODO: [mkt] Windows?? yes.
this.promptForInput = promptForInput;
const windows = process.platform === 'win32';
this.tmpFolderPath = await getTempDir('github-');
const credentialHelper = {};
const askPass = {};
const sshWrapper = {};
const sourceFiles = {
'git-credential-atom.js': outfile => (credentialHelper.script = outfile),
'git-credential-atom.sh': outfile => (credentialHelper.launcher = outfile),
'git-askpass-atom.js': outfile => (askPass.script = outfile),
'git-askpass-atom.sh': outfile => (askPass.launcher = outfile),
'linux-ssh-wrapper.sh': outfile => (sshWrapper.script = outfile),
};
await Promise.all(
Object.keys(sourceFiles).map(filename => copyFile(
path.resolve(getPackageRoot(), 'bin', filename),
path.join(this.tmpFolderPath, filename),
).then(sourceFiles[filename])),
);
const socketPath = path.join(this.tmpFolderPath, 'helper.sock');
const namedPipePath = path.join(
'\\\\?\\pipe\\', 'gh-' + require('crypto').randomBytes(8).toString('hex'),
'helper.sock',
);
this.server = await this.startListening(windows ? namedPipePath : socketPath);
return {
socket: windows ? namedPipePath : socketPath,
electron: getAtomHelperPath(),
credentialHelper,
askPass,
sshWrapper,
};
}
startListening(socketPath) {
return new Promise(resolve => {
const server = net.createServer(connection => {
connection.setEncoding('utf8');
const parts = [];
connection.on('data', data => {
const nullIndex = data.indexOf('\u0000');
if (nullIndex === -1) {
parts.push(data);
} else {
parts.push(data.substring(0, nullIndex));
this.handleData(connection, parts.join(''));
}
});
});
server.listen(socketPath, () => resolve(server));
});
}
handleData(connection, data) {
let query;
try {
query = JSON.parse(data);
} catch (e) {
this.emitter.emit('did-cancel');
}
Promise.resolve(this.promptForInput(query))
.then(answer => connection.end(JSON.stringify(answer), 'utf-8'))
.catch(() => {
this.emitter.emit('did-cancel');
if (query.pid) {
treeKill(query.pid);
}
});
}
onDidCancel(cb) {
return this.emitter.on('did-cancel', cb);
}
async terminate() {
await new Promise(resolve => this.server.close(resolve));
await deleteFileOrFolder(this.tmpFolderPath);
this.emitter.dispose();
}
}