forked from dflourusso/pre-push
-
Notifications
You must be signed in to change notification settings - Fork 0
/
install.js
130 lines (109 loc) · 3.88 KB
/
install.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
'use strict';
//
// Compatibility with older node.js as path.exists got moved to `fs`.
//
var fs = require('fs')
, path = require('path')
, os = require('os')
, hook = path.join(__dirname, 'hook')
, root = path.resolve(__dirname, '..', '..')
, exists = fs.existsSync || path.existsSync;
//
// Gather the location of the possible hidden .git directory, the hooks
// directory which contains all git hooks and the absolute location of the
// `pre-push` file. The path needs to be absolute in order for the symlinking
// to work correctly.
//
var git = getGitFolderPath(root);
// Function to recursively finding .git folder
function getGitFolderPath(currentPath) {
var git = path.resolve(currentPath, '.git')
if (!exists(git) || !fs.lstatSync(git).isDirectory()) {
console.log('pre-push:');
console.log('pre-push: Not found .git folder in', git);
var newPath = path.resolve(currentPath, '..');
// Stop if we on top folder
if (currentPath === newPath) {
return null;
}
return getGitFolderPath(newPath);
}
console.log('pre-push:');
console.log('pre-push: Found .git folder in', git);
return git;
}
//
// Resolve git directory for submodules
//
if (exists(git) && fs.lstatSync(git).isFile()) {
var gitinfo = fs.readFileSync(git).toString()
, gitdirmatch = /gitdir: (.+)/.exec(gitinfo)
, gitdir = gitdirmatch.length == 2 ? gitdirmatch[1] : null;
if (gitdir !== null) {
git = path.resolve(root, gitdir);
hooks = path.resolve(git, 'hooks');
prepush = path.resolve(hooks, 'pre-push');
}
}
//
// Bail out if we don't have an `.git` directory as the hooks will not get
// triggered. If we do have directory create a hooks folder if it doesn't exist.
//
if (!git) {
console.log('pre-push:');
console.log('pre-push: Not found any .git folder for installing pre-push hook');
return;
}
var hooks = path.resolve(git, 'hooks')
, prepush = path.resolve(hooks, 'pre-push');
if (!exists(hooks)) fs.mkdirSync(hooks);
//
// If there's an existing `pre-push` hook we want to back it up instead of
// overriding it and losing it completely as it might contain something
// important.
//
if (exists(prepush) && !fs.lstatSync(prepush).isSymbolicLink()) {
console.log('pre-push:');
console.log('pre-push: Detected an existing git pre-push hook');
fs.writeFileSync(prepush +'.old', fs.readFileSync(prepush));
console.log('pre-push: Old pre-push hook backuped to pre-push.old');
console.log('pre-push:');
}
//
// We cannot create a symlink over an existing file so make sure it's gone and
// finish the installation process.
//
try { fs.unlinkSync(prepush); }
catch (e) {}
// Create generic prepush hook that launches this modules hook (as well
// as stashing - unstashing the unstaged changes)
// TODO: we could keep launching the old pre-push scripts
var hookRelativeUnixPath = hook.replace(root, '.');
if(os.platform() === 'win32') {
hookRelativeUnixPath = hookRelativeUnixPath.replace(/[\\\/]+/g, '/');
}
var prepushContent = '#!/usr/bin/env bash' + os.EOL
+ hookRelativeUnixPath + os.EOL
+ 'RESULT=$?' + os.EOL
+ '[ $RESULT -ne 0 ] && exit 1' + os.EOL
+ 'exit 0' + os.EOL;
//
// It could be that we do not have rights to this folder which could cause the
// installation of this module to completely fail. We should just output the
// error instead destroying the whole npm install process.
//
try { fs.writeFileSync(prepush, prepushContent); }
catch (e) {
console.error('pre-push:');
console.error('pre-push: Failed to create the hook file in your .git/hooks folder because:');
console.error('pre-push: '+ e.message);
console.error('pre-push: The hook was not installed.');
console.error('pre-push:');
}
try { fs.chmodSync(prepush, '777'); }
catch (e) {
console.error('pre-push:');
console.error('pre-push: chmod 0777 the pre-push file in your .git/hooks folder because:');
console.error('pre-push: '+ e.message);
console.error('pre-push:');
}