Skip to content

Commit bae2093

Browse files
committed
New installer.
- Converted to Promises. - Providing support for Windows. - Normalize paths correctly based on platform.
1 parent 4d7d4ff commit bae2093

File tree

4 files changed

+204
-32
lines changed

4 files changed

+204
-32
lines changed

binding.gyp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
],
4747

4848
'libraries': [
49-
'-L<!(pwd)/vendor/libgit2/build',
49+
'-Lvendor\\libgit2\\build',
5050
'-lgit2'
5151
],
5252

install.js

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,21 @@
1-
var async = require('async'),
2-
child_process = require('child_process'),
3-
spawn = child_process.spawn,
4-
path = require('path'),
5-
request = require('request'),
6-
zlib = require('zlib'),
7-
fs = require('fs-extra'),
8-
tar = require('tar'),
9-
exec = require('child_process').exec;
1+
// Core Node.js modules.
2+
var fs = require('fs');
3+
var path = require('path');
4+
var zlib = require('zlib');
105

11-
function passthru() {
12-
var args = Array.prototype.slice.call(arguments);
13-
var cb = args.splice(-1)[0];
14-
var cmd = args.splice(0, 1)[0];
15-
var opts = {};
16-
if(typeof(args.slice(-1)[0]) === 'object') {
17-
opts = args.splice(-1)[0];
18-
}
19-
var child = spawn(cmd, args, opts);
6+
// Third-party modules.
7+
var Q = require('q');
8+
var request = require('request');
9+
var tar = require('tar');
10+
var which = require('which');
2011

21-
child.stdout.pipe(process.stdout);
22-
child.stderr.pipe(process.stderr);
23-
child.on('exit', cb);
24-
}
12+
// Build options.
13+
var options = {
14+
// Normalize the libgit2 build directory.
15+
libgit2build: path.join(__dirname, 'vendor/libgit2/build')
16+
};
2517

2618
function shpassthru() {
27-
var cmd =
2819
passthru.apply(null, ['/bin/sh', '-c'].concat(Array.prototype.slice.call(arguments)));
2920
}
3021

@@ -34,7 +25,7 @@ function envpassthru() {
3425

3526
var updateSubmodules = function(mainCallback) {
3627
console.log('[nodegit] Downloading libgit2 dependency.');
37-
async.series([
28+
async.series([26
3829
function(callback) {
3930
envpassthru('git', 'submodule', 'init', callback);
4031
}, function(callback) {
@@ -62,10 +53,7 @@ var checkoutDependencies = function(mainCallback) {
6253
});
6354
};
6455

65-
var libgit2BuildDirectory = path.join(__dirname, 'vendor/libgit2/build');
66-
67-
// The python executable to use when building libgit2
68-
var pythonExecutable = 'python';
56+
Q.ninvoke(which, "python2").
6957

7058
async.series([
7159
function checkPython2Exists(callback) {

package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"name": "nodegit",
33
"description": "Node.js libgit2 asynchronous native bindings",
44
"version": "0.1.1",
5+
"libgit2": "e953c1606d0d7aea680c9b19db0b955b34ae63c2",
56
"homepage": "https://github.com/tbranyen/nodegit",
67
"keywords": [
78
"libgit2",
@@ -30,10 +31,12 @@
3031
"node": ">= 0.8"
3132
},
3233
"dependencies": {
33-
"async": ">= 0.1.21",
34-
"request": "2.9.x",
34+
"request": "~2.25.0",
35+
"node-gyp": "~0.10.9",
36+
"tar": "~0.1.18",
37+
"which": "~1.0.5",
38+
"q": "~0.9.6",
3539
"node-gyp": "~0.8.2",
36-
"tar": "0.1.17",
3740
"fs-extra": "0.6.0",
3841
"nan": "0.8.0"
3942
},

test-installer.js

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
// Core Node.js modules.
2+
var fs = require('fs');
3+
var path = require('path');
4+
var zlib = require('zlib');
5+
var exec = require('child_process').exec;
6+
7+
// Third-party modules.
8+
var Q = require('q');
9+
var request = require('request');
10+
var tar = require('tar');
11+
var which = require('which');
12+
var rimraf = require('rimraf');
13+
14+
// This will take in an object and find any matching keys in the environment
15+
// to use as overrides.
16+
//
17+
// ENV variables:
18+
//
19+
// PKG: Location of `package.json` sans `.json`.
20+
// LIBGIT2: Location of libgit2 source.
21+
// BUILD: Location of nodegit build directory.
22+
function envOverride(obj) {
23+
// Look through all keys.
24+
return Object.keys(obj).reduce(function(obj, key) {
25+
var normalize = key.toUpperCase();
26+
27+
// Check for process environment existence.
28+
if (normalize in process.env) {
29+
obj[key] = process.env[normalize];
30+
}
31+
32+
return obj;
33+
}, obj);
34+
}
35+
36+
// Convert to the correct system path.
37+
function systemPath(parts) {
38+
return parts.join(path.sep);
39+
}
40+
41+
// Will be used near the end to configure `node-gyp`.
42+
var python, cmake;
43+
44+
// Common reusable paths that can be overwritten by environment variables.
45+
var paths = envOverride({
46+
pkg: __dirname + '/package',
47+
libgit2: __dirname + '/vendor/libgit2/',
48+
build: __dirname + '/vendor/libgit2/build/',
49+
});
50+
51+
// Load the package.json.
52+
var pkg = require(paths.pkg);
53+
54+
// Ensure all dependencies are available.
55+
var dependencies = Q.allSettled([
56+
// This will prioritize `python2` over `python`, because we always want to
57+
// work with Python 2.* if it's available.
58+
Q.nfcall(which, 'python2'),
59+
Q.nfcall(which, 'python'),
60+
61+
// Check for any version of CMake.
62+
Q.nfcall(which, 'cmake'),
63+
])
64+
65+
// Determine if all the dependency requirements are met.
66+
.then(function(results) {
67+
console.info('[nodegit] Determining dependencies.');
68+
69+
// Assign to reusable variables.
70+
python = results[0].value || results[1].value;
71+
cmake = results[2].value;
72+
73+
// Missing Python.
74+
if (!python) {
75+
throw new Error('Python is required to build libgit2.');
76+
}
77+
78+
// Missing CMake.
79+
if (!cmake) {
80+
throw new Error('CMake is required to build libgit2.');
81+
}
82+
83+
// Now lets check the Python version to ensure it's < 3.
84+
return Q.nfcall(exec, python + ' --version').then(function(version) {
85+
if (version[1].indexOf('Python 3') === 0) {
86+
throw new Error('Incorrect version of Python, gyp requires < 3.');
87+
}
88+
});
89+
})
90+
91+
// Display a warning message about missing dependencies.
92+
.fail(function(message) {
93+
console.info('[nodegit] Failed to build nodegit.');
94+
console.info(message);
95+
96+
throw new Error(message);
97+
})
98+
99+
// Successfully found all dependencies. First step is to clean the vendor
100+
// directory.
101+
.then(function() {
102+
console.info('[nodegit] Removing vendor/libgit2.');
103+
104+
return Q.ninvoke(rimraf, null, paths.libgit2);
105+
})
106+
107+
// Now fetch the libgit2 source from GitHub.
108+
.then(function() {
109+
console.info('[nodegit] Fetching vendor/libgit2.');
110+
111+
var url = 'https://github.com/libgit2/libgit2/tarball/'+ pkg.libgit2;
112+
113+
var extract = tar.Extract({
114+
path: paths.libgit2,
115+
strip: true
116+
});
117+
118+
// First extract from Zlib and then extract from Tar.
119+
var expand = request.get(url).pipe(zlib.createUnzip()).pipe(extract);
120+
121+
return Q.ninvoke(expand, 'on', 'end');
122+
})
123+
124+
// Fetch completed successfully.
125+
.then(function() {
126+
console.info('[nodegit] Creating vendor/libgit2/build.');
127+
128+
return Q.ninvoke(fs, 'mkdir', paths.build);
129+
})
130+
131+
// Configure libgit2.
132+
.then(function() {
133+
console.info('[nodegit] Configuring libgit2.');
134+
135+
return Q.nfcall(exec, 'cmake -DTHREADSAFE=1 -DBUILD_CLAR=0 ..', {
136+
cwd: paths.build
137+
});
138+
}).fail(function(err) {
139+
console.error(err);
140+
})
141+
142+
// Build libgit2.
143+
.then(function() {
144+
console.info('[nodegit] Building libgit2.');
145+
146+
return Q.nfcall(exec, 'cmake --build .', {
147+
cwd: paths.build
148+
});
149+
})
150+
151+
.then(function() {
152+
console.info('[nodegit] Configuring native node module.');
153+
154+
return Q.nfcall(exec, systemPath([
155+
'.', 'node_modules', '.bin', 'node-gyp configure --python ' + python
156+
]), {
157+
cwd: '.'
158+
});
159+
})
160+
161+
.then(function() {
162+
console.info('[nodegit] Building native node module.');
163+
164+
return Q.nfcall(exec, systemPath([
165+
'.', 'node_modules', '.bin', 'node-gyp build ' + python
166+
]), {
167+
cwd: '.'
168+
});
169+
})
170+
171+
// Display a warning message about failing to build native node module.
172+
.fail(function(message) {
173+
console.info('[nodegit] Failed to build nodegit.');
174+
console.info(message);
175+
176+
throw new Error(message);
177+
})
178+
179+
.then(function() {
180+
console.info('[nodegit] Completed installation successfully.');
181+
});

0 commit comments

Comments
 (0)