adds support for `include`

master
jonschlinkert 7 years ago
parent ae8a931c62
commit 4a32467144

@ -9,6 +9,7 @@
var fs = require('fs'); var fs = require('fs');
var path = require('path'); var path = require('path');
var expand = require('expand-tilde');
var exists = require('fs-exists-sync'); var exists = require('fs-exists-sync');
var extend = require('extend-shallow'); var extend = require('extend-shallow');
var configPath = require('git-config-path'); var configPath = require('git-config-path');
@ -33,23 +34,36 @@ var ini = require('ini');
function parse(options, cb) { function parse(options, cb) {
if (typeof options === 'function') { if (typeof options === 'function') {
cb = options; cb = options;
options = {}; options = null;
} }
if (typeof cb !== 'function') { if (typeof cb !== 'function') {
throw new TypeError('parse-git-config async expects a callback function.'); throw new TypeError('expected callback to be a function');
} }
options = options || {}; var filepath = parse.resolveConfigPath(options);
var filepath = parse.resolve(options); if (filepath === null) {
cb();
return;
}
fs.stat(filepath, function(err, stat) { fs.stat(filepath, function(err, stat) {
if (err) return cb(err); if (err) {
cb(err);
return;
}
fs.readFile(filepath, 'utf8', function(err, str) { fs.readFile(filepath, 'utf8', function(err, str) {
if (err) return cb(err); if (err) {
var parsed = ini.parse(str); cb(err);
cb(null, parsed); return;
}
if (options && options.include === true) {
str = injectInclude(str, path.resolve(path.dirname(filepath)));
}
cb(null, ini.parse(str));
}); });
}); });
} }
@ -69,12 +83,17 @@ function parse(options, cb) {
*/ */
parse.sync = function parseSync(options) { parse.sync = function parseSync(options) {
options = options || {}; var filepath = parse.resolveConfigPath(options);
var filepath = parse.resolve(options);
if (filepath && exists(filepath)) { if (filepath && exists(filepath)) {
var str = fs.readFileSync(filepath, 'utf8'); var input = fs.readFileSync(filepath, 'utf8');
return ini.parse(str);
if (options && options.include === true) {
var cwd = path.resolve(path.dirname(filepath));
var str = injectInclude(input, cwd);
return ini.parse(str);
}
return ini.parse(input);
} }
return {}; return {};
}; };
@ -83,15 +102,23 @@ parse.sync = function parseSync(options) {
* Resolve the git config path * Resolve the git config path
*/ */
parse.resolve = function resolve(options) { parse.resolveConfigPath = function(options) {
if (typeof options === 'string') { if (typeof options === 'string') {
options = { type: options }; options = { type: options };
} }
var opts = extend({cwd: process.cwd()}, options); var opts = extend({cwd: process.cwd()}, options);
var fp = opts.path || configPath(opts.type); var fp = opts.path ? expand(opts.path) : configPath(opts.type);
return fp ? path.resolve(opts.cwd, fp) : null; return fp ? path.resolve(opts.cwd, fp) : null;
}; };
/**
* Deprecated: use `.resolveConfigPath` instead
*/
parse.resolve = function(options) {
return parse.resolveConfigPath(options);
};
/** /**
* Returns an object with only the properties that had ini-style keys * Returns an object with only the properties that had ini-style keys
* converted to objects (example below). * converted to objects (example below).
@ -118,6 +145,38 @@ parse.keys = function parseKeys(config) {
return res; return res;
}; };
function injectInclude(input, cwd) {
var pathRegex = /^\s*path\s*=\s*/;
var lines = input.split('\n');
var len = lines.length;
var filepath = '';
var res = [];
for (var i = 0; i < len; i++) {
var line = lines[i];
var n = i;
if (line.indexOf('[include]') === 0) {
while (n < len && !pathRegex.test(filepath)) {
filepath = lines[++n];
}
if (!filepath) {
return input;
}
filepath = filepath.replace(pathRegex, '');
var fp = path.resolve(cwd, expand(filepath));
res.push(fs.readFileSync(fp));
} else {
res.push(line);
}
}
return res.join('\n');
}
/** /**
* Expose `parse` * Expose `parse`
*/ */

@ -25,15 +25,16 @@
"test": "mocha" "test": "mocha"
}, },
"dependencies": { "dependencies": {
"extend-shallow": "^2.0.1", "expand-tilde": "^2.0.2",
"extend-shallow": "^3.0.2",
"fs-exists-sync": "^0.1.0", "fs-exists-sync": "^0.1.0",
"git-config-path": "^1.0.1", "git-config-path": "^1.0.1",
"ini": "^1.3.4" "ini": "^1.3.5"
}, },
"devDependencies": { "devDependencies": {
"gulp-format-md": "^0.1.11", "gulp-format-md": "^1.0.0",
"homedir-polyfill": "^1.0.1", "mocha": "^3.5.3",
"mocha": "^3.2.0" "homedir-polyfill": "^1.0.1"
}, },
"keywords": [ "keywords": [
"config", "config",

@ -0,0 +1,122 @@
module.exports = {
user: {
email: 'email',
name: 'name',
signingkey: 'https://help.github.com/articles/generating-a-new-gpg-key/'
},
github: {
user: 'name',
token: 'https://github.com/settings/tokens'
},
commit: {
gpgsign: true
},
tag: {
gpgsign: true,
path: '_gitconfig.local',
sort: 'version:refname'
},
core: {
legacyheaders: false,
quotepath: false,
trustctime: false,
precomposeunicode: false,
pager: 'cat',
logAllRefUpdates: true,
excludesfile: '~/.gitignore'
},
repack: {
usedeltabaseoffset: true
},
merge: {
log: true,
conflictstyle: 'diff3'
},
apply: {
whitespace: 'fix'
},
help: {
autocorrect: '1'
},
rerere: {
enabled: true
},
color: {
diff: 'auto',
status: 'auto',
branch: 'auto',
interactive: 'auto',
ui: 'always'
},
'color "diff"': {
meta: 'yellow bold',
frag: 'magenta',
plain: 'white bold',
old: 'red bold',
new: 'green bold',
commit: 'yellow bold',
func: 'green dim',
whitespace: 'red reverse'
},
'color "status"': {
added: 'yellow',
changed: 'green',
untracked: 'cyan'
},
'color "branch"': {
current: 'yellow reverse',
local: 'yellow',
remote: 'green'
},
diff: {
renames: 'copies',
algorithm: 'patience',
compactionHeuristic: true,
wsErrorHighlight: 'all'
},
'diff "bin"': {
textconv: 'hexdump -v -C'
},
credential: {
helper: 'store'
},
status: {
relativePaths: true,
showUntrackedFiles: 'no'
},
pull: {
rebase: true
},
push: {
default: 'current',
followTags: true
},
alias: {
a: 'commit --amend',
c: 'commit -am',
d: '!git diff --exit-code && git diff --cached',
dif: 'diff',
git: '!exec git',
p: 'push -u',
r: 'reset --soft HEAD~1',
s: 'status',
sc: 'clone --depth=1',
l: 'log --graph --pretty=format:\'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset\' --abbrev-commit -n 15'
},
'remote "origin"': {
fetch: '+refs/tags/*:refs/tags/*'
},
branch: {
autosetupmerge: 'always',
autosetuprebase: 'always'
},
http: {
sslverify: false
},
submodule: {
fetchJobs: '0'
},
fetch: {
prune: true
}
};

@ -0,0 +1,86 @@
[include]
path = _gitconfig.local
[core]
legacyheaders = false
quotepath = false
trustctime = false
precomposeunicode = false
pager = cat
logAllRefUpdates = true
excludesfile = ~/.gitignore
[repack]
usedeltabaseoffset = true
[merge]
log = true
conflictstyle = diff3
[apply]
whitespace = fix
[help]
autocorrect = 1
[rerere]
enabled = true
[color]
diff = auto
status = auto
branch = auto
interactive = auto
ui = always
[color "diff"]
meta = yellow bold
frag = magenta
plain = white bold
old = red bold
new = green bold
commit = yellow bold
func = green dim
whitespace = red reverse
[color "status"]
added = yellow
changed = green
untracked = cyan
[color "branch"]
current = yellow reverse
local = yellow
remote = green
[diff]
renames = copies
algorithm = patience
compactionHeuristic = true
wsErrorHighlight = all
[diff "bin"]
textconv = hexdump -v -C
[credential]
helper = store
[status]
relativePaths = true
showUntrackedFiles = no
[pull]
rebase = true
[push]
default = current
followTags = true
[alias]
a = commit --amend
c = commit -am
d = !git diff --exit-code && git diff --cached
dif = diff
git = !exec git
p = push -u
r = reset --soft HEAD~1
s = status
sc = clone --depth=1
l = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit -n 15
[remote "origin"]
fetch = +refs/pr/*/head:refs/remotes/origin/pr/*
fetch = +refs/tags/*:refs/tags/*
[branch]
autosetupmerge = always
autosetuprebase = always
[http]
sslverify = false
[submodule]
fetchJobs = 0
[fetch]
prune = true
[tag]
sort = version:refname

@ -0,0 +1,11 @@
[user]
email = email
name = name
signingkey = https://help.github.com/articles/generating-a-new-gpg-key/
[github]
user = name
token = https://github.com/settings/tokens
[commit]
gpgsign = true
[tag]
gpgsign = true

@ -1,7 +1,7 @@
/*! /*!
* parse-git-config <https://github.com/jonschlinkert/parse-git-config> * parse-git-config <https://github.com/jonschlinkert/parse-git-config>
* *
* Copyright (c) 2015 Jon Schlinkert. * Copyright (c) 2015-2018 Jon Schlinkert.
* Licensed under the MIT license. * Licensed under the MIT license.
*/ */
@ -9,11 +9,16 @@
require('mocha'); require('mocha');
var isTravis = process.env.TRAVIS || process.env.CLI; var isTravis = process.env.TRAVIS || process.env.CLI;
var fs = require('fs');
var os = require('os'); var os = require('os');
var assert = require('assert'); var assert = require('assert');
var path = require('path'); var path = require('path');
var homedir = require('homedir-polyfill'); var homedir = require('homedir-polyfill');
var parse = require('./'); var parse = require('..');
function read(filepath) {
return fs.readFileSync(path.join(__dirname, filepath), 'utf8');
}
describe('sync:', function() { describe('sync:', function() {
it('should return an object', function() { it('should return an object', function() {
@ -22,14 +27,10 @@ describe('sync:', function() {
}); });
describe('async:', function() { describe('async:', function() {
it('should throw a callback is not passed:', function(cb) { it('should throw a callback is not passed:', function() {
try { assert.throws(function() {
parse(); parse();
cb(new Error('expected an error')); }, /expected/);
} catch (err) {
assert.equal(err.message, 'parse-git-config async expects a callback function.');
cb();
}
}); });
it('should parse .git/config', function(cb) { it('should parse .git/config', function(cb) {
@ -40,8 +41,18 @@ describe('async:', function() {
}); });
}); });
it('should include other config sources', function() {
var fp = path.join(__dirname, 'fixtures/_gitconfig');
parse({ path: fp, include: true }, function(err, config) {
assert(!err);
assert.deepEqual(config, require('./expected/_gitconfig.js'));
cb();
});
});
it('should throw an error when .git/config does not exist:', function(cb) { it('should throw an error when .git/config does not exist:', function(cb) {
parse({path: 'foo'}, function(err, config) { parse({ path: 'foo' }, function(err, config) {
assert(err instanceof Error); assert(err instanceof Error);
assert(/ENOENT.*parse-git-config/.test(err.message)); assert(/ENOENT.*parse-git-config/.test(err.message));
cb(); cb();
@ -56,11 +67,17 @@ describe('resolve:', function() {
it('should allow override path', function() { it('should allow override path', function() {
var fp = path.resolve(homedir(), '.gitconfig'); var fp = path.resolve(homedir(), '.gitconfig');
assert.equal(parse.resolve({path: fp}), fp); assert.equal(parse.resolve({ path: fp }), fp);
});
it('should include other config sources', function() {
var fp = path.join(__dirname, 'fixtures/_gitconfig');
var actual = parse.sync({ path: fp, include: true });
assert.deepEqual(actual, require('./expected/_gitconfig.js'));
}); });
it('should resolve relative path to cwd', function() { it('should resolve relative path to cwd', function() {
assert.equal(parse.resolve({path: '.config'}), path.resolve(process.cwd(), '.config')); assert.equal(parse.resolve({ path: '.config' }), path.resolve(process.cwd(), '.config'));
}); });
it('should resolve relative path to the global git config when `global` is passed', function() { it('should resolve relative path to the global git config when `global` is passed', function() {
@ -69,7 +86,7 @@ describe('resolve:', function() {
}); });
it('should allow override of cwd', function() { it('should allow override of cwd', function() {
var actual = parse.resolve({path: '.config', cwd: '/opt/config'}); var actual = parse.resolve({ path: '.config', cwd: '/opt/config' });
assert.equal(actual, path.resolve('/opt/config/.config')); assert.equal(actual, path.resolve('/opt/config/.config'));
}); });
}); });
Loading…
Cancel
Save