Skip to content

Commit 6b2eafc

Browse files
committed
feat(cli): Create initial commit
0 parents  commit 6b2eafc

File tree

10 files changed

+368
-0
lines changed

10 files changed

+368
-0
lines changed

.cz.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"path": "node_modules/cz-conventional-changelog/"
3+
}

.gitignore

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Logs
2+
logs
3+
*.log
4+
5+
# Runtime data
6+
pids
7+
*.pid
8+
*.seed
9+
10+
# Directory for instrumented libs generated by jscoverage/JSCover
11+
lib-cov
12+
13+
# Coverage directory used by tools like istanbul
14+
coverage
15+
16+
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17+
.grunt
18+
19+
# node-waf configuration
20+
.lock-wscript
21+
22+
# Compiled binary addons (http://nodejs.org/api/addons.html)
23+
build/Release
24+
25+
# Dependency directory
26+
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
27+
node_modules

bin/git-cz

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env node
2+
3+
var app = require('../src/app.js');
4+
app.bootstrap();
5+
6+
// PRIORITY HIGH
7+
// TODO: Tests
8+
// TODO: Examples
9+
10+
// PRIORITY MEDIUM
11+
// TODO: 3. Allow users to use their original messages using
12+
// some kind of template {{m1}} {{m2}} so that they
13+
// aren't lost.

bin/git-cz-debug

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env node
2+
3+
var app = require('../src/app.js');
4+
app.bootstrap({
5+
debug: true
6+
});

bin/git-cz-debug.cmd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@node "%~dpn0" %*

bin/git-cz.cmd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@node "%~dpn0" %*

package.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "commitizen",
3+
"version": "1.0.0",
4+
"description": "Git commit, but play nice with conventions.",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"bin": {
10+
"git-cz": "./bin/git-cz",
11+
"git-cz-debug": "./bin/git-cc-debug",
12+
"commitizen": "./bin/git-cz",
13+
"commitizen-debug": "./bin/git-cc-debug"
14+
},
15+
"author": "Jim Cummins <[email protected]>",
16+
"license": "MIT",
17+
"dependencies": {
18+
"chalk": "^1.0.0",
19+
"cz-conventional-changelog": "^1.0.0",
20+
"dedent": "^0.4.0",
21+
"glob": "^5.0.5",
22+
"gulp": "^3.8.11",
23+
"gulp-git": "^1.1.1",
24+
"inquirer": "^0.8.2",
25+
"minimist": "^1.1.1",
26+
"strip-json-comments": "^1.0.2",
27+
"systemjs": "^0.16.7"
28+
}
29+
}

src/app.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
var process = require('process');
2+
var configLoader = require('./configLoader.js');
3+
var cz = require('./cz.js');
4+
5+
exports.bootstrap = function(environment) {
6+
7+
// Pass through any additional arguments that would normally
8+
// go to git.
9+
var gitArgs = process.argv.slice(2, process.argv.length);
10+
11+
// Get the config from the filesystem
12+
var config = configLoader.load();
13+
14+
// Initialize the commit process
15+
cz.init(gitArgs, environment, config);
16+
17+
}

src/configLoader.js

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
2+
/**
3+
* Command line config helpers
4+
* Shamelessly ripped from with slight modifications:
5+
* https://github.com/jscs-dev/node-jscs/blob/master/lib/cli-config.js
6+
*/
7+
8+
var fs = require('fs');
9+
var path = require('path');
10+
11+
var stripJSONComments = require('strip-json-comments');
12+
var supportsColor = require('chalk').supportsColor;
13+
var glob = require('glob');
14+
15+
// Configuration sources in priority order.
16+
var configs = ['package.json', '.czrc', '.cz.json'];
17+
18+
// Before, "findup-sync" package was used,
19+
// but it does not provide filter callback
20+
function findup(patterns, options, fn) {
21+
/* jshint -W083 */
22+
23+
var lastpath;
24+
var file;
25+
26+
options = Object.create(options);
27+
options.maxDepth = 1;
28+
options.cwd = path.resolve(options.cwd);
29+
30+
do {
31+
file = patterns.filter(function(pattern) {
32+
var configPath = glob.sync(pattern, options)[0];
33+
34+
if (configPath) {
35+
return fn(path.join(options.cwd, configPath));
36+
}
37+
})[0];
38+
39+
if (file) {
40+
return path.join(options.cwd, file);
41+
}
42+
43+
lastpath = options.cwd;
44+
options.cwd = path.resolve(options.cwd, '..');
45+
} while (options.cwd !== lastpath);
46+
}
47+
48+
/**
49+
* Get content of the configuration file
50+
* @param {String} config - partial path to configuration file
51+
* @param {String} directory - directory path which will be joined with config argument
52+
* @return {Object}
53+
*/
54+
exports.getContent = function(config, directory) {
55+
if (!config) {
56+
return;
57+
}
58+
59+
var configPath = path.resolve(directory, config);
60+
var ext;
61+
var content;
62+
63+
config = path.basename(config);
64+
65+
if (fs.existsSync(configPath)) {
66+
ext = path.extname(configPath);
67+
68+
if (ext === '.js' || ext === '.json') {
69+
content = require(configPath);
70+
} else {
71+
content = JSON.parse(
72+
stripJSONComments(
73+
fs.readFileSync(configPath, 'utf8')
74+
)
75+
);
76+
}
77+
78+
// Adding property via Object.defineProperty makes it
79+
// non-enumerable and avoids warning for unsupported rules
80+
Object.defineProperty(content, 'configPath', {
81+
value: configPath
82+
});
83+
}
84+
85+
return content && config === 'package.json' ? content.czConfig : content;
86+
};
87+
88+
/**
89+
* Get content of the configuration file
90+
* @param {String} config - partial path to configuration file
91+
* @param {String} [cwd = process.cwd()] - directory path which will be joined with config argument
92+
* @return {Object|undefined}
93+
*/
94+
exports.load = function(config, cwd) {
95+
var content;
96+
var directory = cwd || process.cwd();
97+
98+
// If config option is given, attempt to load it
99+
if (config) {
100+
return this.getContent(config, directory);
101+
}
102+
103+
content = this.getContent(
104+
findup(configs, { nocase: true, cwd: directory }, function(configPath) {
105+
if (path.basename(configPath) === 'package.json') {
106+
return !!this.getContent(configPath);
107+
}
108+
109+
return true;
110+
}.bind(this))
111+
);
112+
113+
if (content) {
114+
return content;
115+
}
116+
117+
// Try to load standard configs from home dir
118+
var directoryArr = [process.env.USERPROFILE, process.env.HOMEPATH, process.env.HOME];
119+
for (var i = 0, dirLen = directoryArr.length; i < dirLen; i++) {
120+
if (!directoryArr[i]) {
121+
continue;
122+
}
123+
124+
for (var j = 0, len = configs.length; j < len; j++) {
125+
content = this.getContent(configs[j], directoryArr[i]);
126+
127+
if (content) {
128+
return content;
129+
}
130+
}
131+
}
132+
};

src/cz.js

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
var System = require('systemjs');
2+
var fs = require('fs');
3+
var dedent = require('dedent');
4+
var inquirer = require('inquirer');
5+
var gulp = require('gulp');
6+
var git = require('gulp-git');
7+
var process = require('process');
8+
var minimist = require('minimist');
9+
10+
exports.init = function(rawGitArgs, environment, config) {
11+
if(typeof environment === 'undefined') {
12+
environment = {};
13+
}
14+
15+
if(typeof config !== 'undefined') {
16+
withConfig(rawGitArgs, environment, config);
17+
} else {
18+
withoutConfig(rawGitArgs, environment);
19+
}
20+
}
21+
22+
function withConfig(rawGitArgs, environment, config) {
23+
24+
System.baseURL = config.path;
25+
26+
// TODO Store the stripped out m's for use later
27+
strippedGitArgs = stripGitArgsMessages(rawGitArgs);
28+
29+
// Load the config
30+
fs.open(config.path, 'r', function() {
31+
32+
// Load the module based on the config
33+
System.import('index').then(function(m) {
34+
35+
// Call the prompter method on the module, get the template
36+
m.prompter(inquirer, function(template) {
37+
38+
// TODO, apply the stored m's to the template
39+
40+
// Get a gulp stream based off the config
41+
gulp.src(config.path)
42+
43+
// Format then commit
44+
.pipe(git.commit(dedent(template), {args: strippedGitArgs, disableAppendPaths: true}))
45+
46+
// Handle commit success
47+
.on('end', function() {
48+
console.log('✓ Commit succeeded.');
49+
})
50+
51+
// Handle commit failure
52+
.on('error', function (error) {
53+
console.error('✗ Commit failed. Did you forget to \'git add\' your files?');
54+
});
55+
});
56+
});
57+
});
58+
}
59+
60+
// We don't have a config, so either we use raw args to try to commit
61+
// or if debug is enabled then we do a strict check for a config file.
62+
function withoutConfig(rawGitArgs, environment) {
63+
if(environment.debug === true) {
64+
console.error('COMMITIZEN DEBUG: No git-cz friendly config was detected. I looked for .czrc, .cz.json, or czConfig in package.json.');
65+
} else {
66+
// Get a gulp stream based off the config
67+
gulp.src(process.cwd())
68+
69+
// Format then commit
70+
.pipe(git.commit(undefined, {args: rawGitArgs, disableMessageRequirement: true}))
71+
72+
// Handle commit success
73+
.on('end', function() {
74+
console.log('✓ Commit succeeded.');
75+
})
76+
77+
// Handle commit failure
78+
.on('error', function (error) {
79+
console.error('✗ Commit failed. Did you forget to \'git add\' your files or add a commit message?');
80+
});
81+
}
82+
}
83+
84+
// Aww shit it is ugly
85+
function stripGitArgsMessages(rawGitArgs) {
86+
87+
var args = minimist(rawGitArgs, {
88+
alias: {
89+
m: 'message'
90+
}
91+
});
92+
93+
// Loop through all keys
94+
var output = ' ';
95+
96+
for (arg in args) {
97+
98+
if (!args.hasOwnProperty(arg)) {
99+
//The current property is not a direct property
100+
continue;
101+
}
102+
103+
var key = arg;
104+
var value = args[arg];
105+
106+
/**
107+
* Ugly, but this is recompiles an argument string without
108+
* any messages passed in.
109+
*/
110+
if (key === '_' && value.length > 0) {
111+
// Anything in the _ array of strings is a one off file
112+
output += value.join(' ') + ' ';
113+
} else if (key === 'message') {
114+
/**
115+
* We strip out message because we're already handling this
116+
* in minimist's aliases.
117+
*/
118+
continue;
119+
} else if (typeof value === String) {
120+
output += '-' + key + ' ' + value + ' ';
121+
} else if (typeof value === Array) {
122+
output += '-' + key + ' ' + value.join(' -' + key) + ' ';
123+
} else if (value === true || value === false) {
124+
output += '-' + key + ' ';
125+
} else {
126+
/**
127+
* Based on the current minimist object structure, we should
128+
* never get here, but we'll protect against breaking changes.
129+
*/
130+
continue;
131+
}
132+
}
133+
134+
if(output.trim().length < 1) {
135+
return '';
136+
} else {
137+
return output;
138+
}
139+
}

0 commit comments

Comments
 (0)