diff --git a/.editorconfig b/.editorconfig
index 818e072..449f0da 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,13 +1,14 @@
+# http://editorconfig.org/
root = true
[*]
-indent_style = space
-end_of_line = lf
charset = utf-8
+end_of_line = lf
indent_size = 2
-trim_trailing_whitespace = true
+indent_style = space
insert_final_newline = true
+trim_trailing_whitespace = true
[{**/{actual,fixtures,expected,templates}/**,*.md}]
trim_trailing_whitespace = false
-insert_final_newline = false
\ No newline at end of file
+insert_final_newline = false
diff --git a/.eslintrc.json b/.eslintrc.json
index 948dbdb..61e8895 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -1,9 +1,4 @@
{
- "ecmaFeatures": {
- "modules": true,
- "experimentalObjectRestSpread": true
- },
-
"env": {
"browser": false,
"es6": true,
diff --git a/.gitignore b/.gitignore
index 13bb9ba..f969a2c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,20 +1,30 @@
# always ignore files
*.DS_Store
+.idea
+.vscode
*.sublime-*
# test related, or directories generated by tests
test/actual
actual
coverage
+.nyc*
# npm
node_modules
npm-debug.log
+# yarn
+yarn.lock
+yarn-error.log
+
# misc
_gh_pages
+_draft
+_drafts
bower_components
vendor
temp
tmp
TODO.md
+package-lock.json
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index f28113a..dedfdd4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,7 +5,5 @@ os:
language: node_js
node_js:
- node
- - '6'
- - '5'
- - '0.12'
- - '0.10'
+ - '9'
+ - '8'
diff --git a/.verb.md b/.verb.md
index 9b25dd1..9088a2a 100644
--- a/.verb.md
+++ b/.verb.md
@@ -1,10 +1,10 @@
## Usage
```js
-var parse = require('{%= name %}');
+const parse = require('{%= name %}');
// sync
-var config = parse.sync();
+const config = parse.sync();
// or async
parse(function (err, config) {
@@ -51,8 +51,8 @@ Converts ini-style keys into objects:
**Example 1**
```js
-var parse = require('parse-git-config');
-var config = {
+const parse = require('parse-git-config');
+const config = {
'foo "bar"': { doStuff: true },
'foo "baz"': { doStuff: true }
};
@@ -74,8 +74,8 @@ Results in:
**Example 2**
```js
-var parse = require('parse-git-config');
-var config = {
+const parse = require('parse-git-config');
+const config = {
'remote "origin"': {
url: 'https://github.com/jonschlinkert/normalize-pkg.git',
fetch: '+refs/heads/*:refs/remotes/origin/*'
diff --git a/LICENSE b/LICENSE
index 1e49edf..f8de063 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2015-2016, Jon Schlinkert.
+Copyright (c) 2015-2018, Jon Schlinkert.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 2244ccc..48c7ffc 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,9 @@
-# parse-git-config [![NPM version](https://img.shields.io/npm/v/parse-git-config.svg?style=flat)](https://www.npmjs.com/package/parse-git-config) [![NPM monthly downloads](https://img.shields.io/npm/dm/parse-git-config.svg?style=flat)](https://npmjs.org/package/parse-git-config) [![NPM total downloads](https://img.shields.io/npm/dt/parse-git-config.svg?style=flat)](https://npmjs.org/package/parse-git-config) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/parse-git-config.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/parse-git-config)
+# parse-git-config [![NPM version](https://img.shields.io/npm/v/parse-git-config.svg?style=flat)](https://www.npmjs.com/package/parse-git-config) [![NPM monthly downloads](https://img.shields.io/npm/dm/parse-git-config.svg?style=flat)](https://npmjs.org/package/parse-git-config) [![NPM total downloads](https://img.shields.io/npm/dt/parse-git-config.svg?style=flat)](https://npmjs.org/package/parse-git-config) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/parse-git-config.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/parse-git-config)
> Parse `.git/config` into a JavaScript object. sync or async.
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
## Install
Install with [npm](https://www.npmjs.com/):
@@ -13,10 +15,10 @@ $ npm install --save parse-git-config
## Usage
```js
-var parse = require('parse-git-config');
+const parse = require('parse-git-config');
// sync
-var config = parse.sync();
+const config = parse.sync();
// or async
parse(function (err, config) {
@@ -55,10 +57,16 @@ Config object will be something like:
## API
-### [parse](index.js#L33)
+### [parse](index.js#L35)
Asynchronously parse a `.git/config` file. If only the callback is passed, the `.git/config` file relative to `process.cwd()` is used.
+**Params**
+
+* `options` **{Object|String|Function}**: Options with `cwd` or `path`, the cwd to use, or the callback function.
+* `cb` **{Function}**: callback function if the first argument is options or cwd.
+* `returns` **{Object}**
+
**Example**
```js
@@ -68,43 +76,53 @@ parse(function(err, config) {
});
```
-**Params**
+### [.sync](index.js#L64)
-* `options` **{Object|String|Function}**: Options with `cwd` or `path`, the cwd to use, or the callback function.
-* `cb` **{Function}**: callback function if the first argument is options or cwd.
-* `returns` **{Object}**
+Parse the given
-### [.sync](index.js#L71)
+**Params**
-Synchronously parse a `.git/config` file. If no arguments are passed, the `.git/config` file relative to `process.cwd()` is used.
+* `options` **{Object|String}**: Options with `cwd` or `path`, or the cwd to use.
+* `returns` **{Object}**
**Example**
```js
-var config = parse.sync();
+parse.promise({ path: '/path/to/.gitconfig' })
+ .then(config => console.log(config));
```
+### [.sync](index.js#L98)
+
+Synchronously parse a `.git/config` file. If no arguments are passed, the `.git/config` file relative to `process.cwd()` is used.
+
**Params**
* `options` **{Object|String}**: Options with `cwd` or `path`, or the cwd to use.
* `returns` **{Object}**
-### [.keys](index.js#L109)
-
-Returns an object with only the properties that had ini-style keys converted to objects (example below).
-
**Example**
```js
-var config = parse.sync();
-var obj = parse.keys(config);
+const config = parse.sync();
```
+### [.keys](index.js#L150)
+
+Returns an object with only the properties that had ini-style keys converted to objects (example below).
+
**Params**
* `config` **{Object}**: The parsed git config object.
* `returns` **{Object}**
+**Example**
+
+```js
+const config = parse.sync();
+const obj = parse.keys(config);
+```
+
### .keys examples
Converts ini-style keys into objects:
@@ -112,8 +130,8 @@ Converts ini-style keys into objects:
**Example 1**
```js
-var parse = require('parse-git-config');
-var config = {
+const parse = require('parse-git-config');
+const config = {
'foo "bar"': { doStuff: true },
'foo "baz"': { doStuff: true }
};
@@ -135,8 +153,8 @@ Results in:
**Example 2**
```js
-var parse = require('parse-git-config');
-var config = {
+const parse = require('parse-git-config');
+const config = {
'remote "origin"': {
url: 'https://github.com/jonschlinkert/normalize-pkg.git',
fetch: '+refs/heads/*:refs/remotes/origin/*'
@@ -181,57 +199,68 @@ Results in:
## About
-### Related projects
+
+Contributing
-* [git-user-name](https://www.npmjs.com/package/git-user-name): Get a user's name from git config at the project or global scope, depending on… [more](https://github.com/jonschlinkert/git-user-name) | [homepage](https://github.com/jonschlinkert/git-user-name "Get a user's name from git config at the project or global scope, depending on what git uses in the current context.")
-* [git-username](https://www.npmjs.com/package/git-username): Get the username from a git remote origin URL. | [homepage](https://github.com/jonschlinkert/git-username "Get the username from a git remote origin URL.")
-* [parse-author](https://www.npmjs.com/package/parse-author): Parse a string into an object with `name`, `email` and `url` properties following npm conventions… [more](https://github.com/jonschlinkert/parse-author) | [homepage](https://github.com/jonschlinkert/parse-author "Parse a string into an object with `name`, `email` and `url` properties following npm conventions. Useful for the `authors` property in package.json or for parsing an AUTHORS file into an array of authors objects.")
-* [parse-authors](https://www.npmjs.com/package/parse-authors): Parse a string into an array of objects with `name`, `email` and `url` properties following… [more](https://github.com/jonschlinkert/parse-authors) | [homepage](https://github.com/jonschlinkert/parse-authors "Parse a string into an array of objects with `name`, `email` and `url` properties following npm conventions. Useful for the `authors` property in package.json or for parsing an AUTHORS file into an array of authors objects.")
-* [parse-github-url](https://www.npmjs.com/package/parse-github-url): Parse a github URL into an object. | [homepage](https://github.com/jonschlinkert/parse-github-url "Parse a github URL into an object.")
-* [parse-gitignore](https://www.npmjs.com/package/parse-gitignore): Parse a gitignore file into an array of patterns. Comments and empty lines are stripped. | [homepage](https://github.com/jonschlinkert/parse-gitignore "Parse a gitignore file into an array of patterns. Comments and empty lines are stripped.")
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
-### Contributing
+
-Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+Running Tests
-### Contributors
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
-| **Commits** | **Contributor**
|
-| --- | --- |
-| 48 | [jonschlinkert](https://github.com/jonschlinkert) |
-| 1 | [sam3d](https://github.com/sam3d) |
-| 1 | [jsdnxx](https://github.com/jsdnxx) |
+```sh
+$ npm install && npm test
+```
-### Building docs
+
+
+Building docs
-_(This document was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme) (a [verb](https://github.com/verbose/verb) generator), please don't edit the readme directly. Any changes to the readme must be made in [.verb.md](.verb.md).)_
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
-To generate the readme and API documentation with [verb](https://github.com/verbose/verb):
+To generate the readme, run the following command:
```sh
-$ npm install -g verb verb-generate-readme && verb
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
```
-### Running tests
+
-Install dev dependencies:
+### Related projects
-```sh
-$ npm install -d && npm test
-```
+You might also be interested in these projects:
+
+* [git-user-name](https://www.npmjs.com/package/git-user-name): Get a user's name from git config at the project or global scope, depending on… [more](https://github.com/jonschlinkert/git-user-name) | [homepage](https://github.com/jonschlinkert/git-user-name "Get a user's name from git config at the project or global scope, depending on what git uses in the current context.")
+* [git-username](https://www.npmjs.com/package/git-username): Get the username from a git remote origin URL. | [homepage](https://github.com/jonschlinkert/git-username "Get the username from a git remote origin URL.")
+* [parse-author](https://www.npmjs.com/package/parse-author): Parse an author, contributor, maintainer or other 'person' string into an object with name, email… [more](https://github.com/jonschlinkert/parse-author) | [homepage](https://github.com/jonschlinkert/parse-author "Parse an author, contributor, maintainer or other 'person' string into an object with name, email and url properties following npm conventions.")
+* [parse-authors](https://www.npmjs.com/package/parse-authors): Parse a string into an array of objects with `name`, `email` and `url` properties following… [more](https://github.com/jonschlinkert/parse-authors) | [homepage](https://github.com/jonschlinkert/parse-authors "Parse a string into an array of objects with `name`, `email` and `url` properties following npm conventions. Useful for the `authors` property in package.json or for parsing an AUTHORS file into an array of authors objects.")
+* [parse-github-url](https://www.npmjs.com/package/parse-github-url): Parse a github URL into an object. | [homepage](https://github.com/jonschlinkert/parse-github-url "Parse a github URL into an object.")
+* [parse-gitignore](https://www.npmjs.com/package/parse-gitignore): Parse a gitignore file into an array of patterns. Comments and empty lines are stripped. | [homepage](https://github.com/jonschlinkert/parse-gitignore "Parse a gitignore file into an array of patterns. Comments and empty lines are stripped.")
+
+### Contributors
+
+| **Commits** | **Contributor** |
+| --- | --- |
+| 51 | [jonschlinkert](https://github.com/jonschlinkert) |
+| 1 | [sam3d](https://github.com/sam3d) |
+| 1 | [js-n](https://github.com/js-n) |
### Author
**Jon Schlinkert**
+* [linkedin/in/jonschlinkert](https://linkedin.com/in/jonschlinkert)
* [github/jonschlinkert](https://github.com/jonschlinkert)
-* [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
### License
-Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert).
-Released under the [MIT license](https://github.com/jonschlinkert/parse-git-config/blob/master/LICENSE).
+Copyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
***
-_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.2.0, on December 14, 2016._
\ No newline at end of file
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on January 23, 2018._
\ No newline at end of file
diff --git a/example.js b/example.js
index 6ee3ba2..50597f2 100644
--- a/example.js
+++ b/example.js
@@ -1,7 +1,8 @@
'use strict';
-var parse = require('./');
-var config = {
+const parse = require('./');
+const gitconfig = {
+ email: 'email',
'remote "origin"': {
url: 'https://github.com/jonschlinkert/normalize-pkg.git',
fetch: '+refs/heads/*:refs/remotes/origin/*'
@@ -14,4 +15,5 @@ var config = {
}
};
-console.log(parse.keys(config));
+const config = parse.expandKeys(gitconfig);
+console.log(config);
diff --git a/index.js b/index.js
index 85e9f87..bd3e409 100644
--- a/index.js
+++ b/index.js
@@ -1,18 +1,20 @@
/*!
* parse-git-config
*
- * Copyright (c) 2015 Jon Schlinkert.
- * Licensed under the MIT license.
+ * Copyright (c) 2015-2018, Jon Schlinkert.
+ * Released under the MIT License.
*/
'use strict';
-var fs = require('fs');
-var path = require('path');
-var exists = require('fs-exists-sync');
-var extend = require('extend-shallow');
-var configPath = require('git-config-path');
-var ini = require('ini');
+const fs = require('fs');
+const path = require('path');
+const util = require('util');
+const ini = require('ini');
+const configPath = require('git-config-path');
+const expand = require('expand-tilde');
+const read = util.promisify(fs.readFile);
+const stat = util.promisify(fs.stat);
/**
* Asynchronously parse a `.git/config` file. If only the callback is passed,
@@ -33,33 +35,58 @@ var ini = require('ini');
function parse(options, cb) {
if (typeof options === 'function') {
cb = options;
- options = {};
+ options = null;
}
if (typeof cb !== 'function') {
- throw new TypeError('parse-git-config async expects a callback function.');
+ return parse.promise(options);
}
- options = options || {};
- var filepath = parse.resolve(options);
+ return parse.promise(options)
+ .then(config => cb(null, config))
+ .catch(cb);
+}
- fs.stat(filepath, function(err, stat) {
- if (err) return cb(err);
+/**
+ * Parse the given
+ *
+ * ```js
+ * parse.promise({ path: '/path/to/.gitconfig' })
+ * .then(config => console.log(config));
+ * ```
+ *
+ * @name .sync
+ * @param {Object|String} `options` Options with `cwd` or `path`, or the cwd to use.
+ * @return {Object}
+ * @api public
+ */
+
+parse.promise = function(options) {
+ const opts = Object.assign({}, options);
+ const filepath = parse.resolveConfigPath(opts);
+
+ if (!filepath) {
+ return Promise.resolve(null);
+ }
- fs.readFile(filepath, 'utf8', function(err, str) {
- if (err) return cb(err);
- var parsed = ini.parse(str);
- cb(null, parsed);
+ return stat(filepath)
+ .then(() => {
+ return read(filepath, 'utf8');
+ })
+ .then(str => {
+ if (opts.include === true) {
+ str = injectInclude(str, path.resolve(path.dirname(filepath)));
+ }
+ return parseIni(str, opts);
});
- });
-}
+};
/**
* Synchronously parse a `.git/config` file. If no arguments are passed,
* the `.git/config` file relative to `process.cwd()` is used.
*
* ```js
- * var config = parse.sync();
+ * const config = parse.sync();
* ```
*
* @name .sync
@@ -68,13 +95,19 @@ function parse(options, cb) {
* @api public
*/
-parse.sync = function parseSync(options) {
- options = options || {};
- var filepath = parse.resolve(options);
+parse.sync = function(options) {
+ const opts = Object.assign({}, options);
+ const filepath = parse.resolveConfigPath(opts);
+ if (filepath && fs.existsSync(filepath)) {
+ const input = fs.readFileSync(filepath, 'utf8');
- if (filepath && exists(filepath)) {
- var str = fs.readFileSync(filepath, 'utf8');
- return ini.parse(str);
+ if (opts.include === true) {
+ const cwd = path.resolve(path.dirname(filepath));
+ const str = injectInclude(input, cwd);
+ return parseIni(str, opts);
+ }
+
+ return parseIni(input, opts);
}
return {};
};
@@ -83,41 +116,79 @@ parse.sync = function parseSync(options) {
* Resolve the git config path
*/
-parse.resolve = function resolve(options) {
+parse.resolveConfigPath = function(options) {
if (typeof options === 'string') {
options = { type: options };
}
- var opts = extend({cwd: process.cwd()}, options);
- var fp = opts.path || configPath(opts.type);
+ const opts = Object.assign({cwd: process.cwd()}, options);
+ const fp = opts.path ? expand(opts.path) : configPath(opts.type);
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
- * converted to objects (example below).
+ * converted to objects.
*
* ```js
- * var config = parse.sync();
- * var obj = parse.keys(config);
+ * const config = parse.sync({ path: '/path/to/.gitconfig' });
+ * const obj = parse.expandKeys(config);
* ```
- * @name .keys
* @param {Object} `config` The parsed git config object.
* @return {Object}
* @api public
*/
-parse.keys = function parseKeys(config) {
- var res = {};
- for (var key in config) {
- var m = /(\S+) "(.*)"/.exec(key);
+parse.expandKeys = function(config) {
+ for (const key of Object.keys(config)) {
+ const m = /(\S+) "(.*)"/.exec(key);
if (!m) continue;
- var prop = m[1];
- res[prop] = res[prop] || {};
- res[prop][m[2]] = config[key];
+ const prop = m[1];
+ config[prop] = config[prop] || {};
+ config[prop][m[2]] = config[key];
+ delete config[key];
}
- return res;
+ return config;
};
+function parseIni(str, options) {
+ const opts = Object.assign({}, options);
+ const config = ini.parse(str);
+ if (opts.expandKeys === true) {
+ return parse.expandKeys(config);
+ }
+ return config;
+}
+
+function injectInclude(input, cwd) {
+ const lines = input.split('\n').filter(function(line) {
+ return line.trim() !== '';
+ });
+
+ const len = lines.length;
+ const res = [];
+
+ for (let i = 0; i < len; i++) {
+ const line = lines[i];
+ if (line.indexOf('[include]') === 0) {
+ const filepath = lines[i + 1].replace(/^\s*path\s*=\s*/, '');
+ const fp = path.resolve(cwd, expand(filepath));
+ res.push(fs.readFileSync(fp));
+
+ } else {
+ res.push(line);
+ }
+ }
+ return res.join('\n');
+}
+
/**
* Expose `parse`
*/
diff --git a/package.json b/package.json
index d855a40..78c0e35 100644
--- a/package.json
+++ b/package.json
@@ -5,9 +5,9 @@
"homepage": "https://github.com/jonschlinkert/parse-git-config",
"author": "Jon Schlinkert (https://github.com/jonschlinkert)",
"contributors": [
- "Jason Denizac (https://jden.us)",
- "Jon Schlinkert (http://twitter.com/jonschlinkert)",
- "Sam Holmes (https://samholmes.net)"
+ "Jon Schlinkert (http://twitter.com/jonschlinkert)",
+ "Sam Holmes (https://samholmes.net)",
+ "(https://github.com/js-n)"
],
"repository": "jonschlinkert/parse-git-config",
"bugs": {
@@ -19,21 +19,22 @@
],
"main": "index.js",
"engines": {
- "node": ">=0.10.0"
+ "node": ">=8"
},
"scripts": {
"test": "mocha"
},
"dependencies": {
- "extend-shallow": "^2.0.1",
+ "expand-tilde": "^2.0.2",
+ "extend-shallow": "^3.0.2",
"fs-exists-sync": "^0.1.0",
"git-config-path": "^1.0.1",
- "ini": "^1.3.4"
+ "ini": "^1.3.5"
},
"devDependencies": {
- "gulp-format-md": "^0.1.11",
- "homedir-polyfill": "^1.0.1",
- "mocha": "^3.2.0"
+ "gulp-format-md": "^1.0.0",
+ "mocha": "^3.5.3",
+ "homedir-polyfill": "^1.0.1"
},
"keywords": [
"config",
@@ -60,9 +61,6 @@
"parse-gitignore"
]
},
- "reflinks": [
- "verb"
- ],
"lint": {
"reflinks": true
}
diff --git a/test.js b/test.js
deleted file mode 100644
index 1f63fc3..0000000
--- a/test.js
+++ /dev/null
@@ -1,91 +0,0 @@
-/*!
- * parse-git-config
- *
- * Copyright (c) 2015 Jon Schlinkert.
- * Licensed under the MIT license.
- */
-
-'use strict';
-
-require('mocha');
-var isTravis = process.env.TRAVIS || process.env.CLI;
-var os = require('os');
-var assert = require('assert');
-var path = require('path');
-var homedir = require('homedir-polyfill');
-var parse = require('./');
-
-describe('sync:', function() {
- it('should return an object', function() {
- assert(parse.sync().hasOwnProperty('core'));
- });
-});
-
-describe('async:', function() {
- it('should throw a callback is not passed:', function(cb) {
- try {
- parse();
- cb(new Error('expected an error'));
- } catch (err) {
- assert.equal(err.message, 'parse-git-config async expects a callback function.');
- cb();
- }
- });
-
- it('should parse .git/config', function(cb) {
- parse(function(err, config) {
- assert(!err);
- assert(config.hasOwnProperty('core'));
- cb();
- });
- });
-
- it('should throw an error when .git/config does not exist:', function(cb) {
- parse({path: 'foo'}, function(err, config) {
- assert(err instanceof Error);
- assert(/ENOENT.*parse-git-config/.test(err.message));
- cb();
- });
- });
-});
-
-describe('resolve:', function() {
- it('should resolve the git config in the cwd by default', function() {
- assert.equal(parse.resolve(), path.resolve(process.cwd(), '.git/config'));
- });
-
- it('should allow override path', function() {
- var fp = path.resolve(homedir(), '.gitconfig');
- assert.equal(parse.resolve({path: fp}), fp);
- });
-
- it('should resolve relative path to cwd', function() {
- 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() {
- if (isTravis && os.platform() === 'darwin') return this.skip();
- assert.equal(parse.resolve('global'), path.resolve(homedir(), '.gitconfig'));
- });
-
- it('should allow override of cwd', function() {
- var actual = parse.resolve({path: '.config', cwd: '/opt/config'});
- assert.equal(actual, path.resolve('/opt/config/.config'));
- });
-});
-
-describe('.keys:', function() {
- it('should parse ini-style keys', function() {
- var config = {
- 'foo "bar"': { doStuff: true },
- 'foo "baz"': { doStuff: true }
- };
-
- assert.deepEqual(parse.keys(config), {
- foo: {
- bar: { doStuff: true },
- baz: { doStuff: true }
- }
- });
- });
-});
diff --git a/test/expected/_gitconfig.js b/test/expected/_gitconfig.js
new file mode 100644
index 0000000..70dd302
--- /dev/null
+++ b/test/expected/_gitconfig.js
@@ -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
+ }
+};
diff --git a/test/fixtures/_gitconfig b/test/fixtures/_gitconfig
new file mode 100644
index 0000000..7b999ac
--- /dev/null
+++ b/test/fixtures/_gitconfig
@@ -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
diff --git a/test/fixtures/_gitconfig.local b/test/fixtures/_gitconfig.local
new file mode 100644
index 0000000..afa9a19
--- /dev/null
+++ b/test/fixtures/_gitconfig.local
@@ -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
\ No newline at end of file
diff --git a/test/test.js b/test/test.js
new file mode 100644
index 0000000..61090b0
--- /dev/null
+++ b/test/test.js
@@ -0,0 +1,134 @@
+'use strict';
+
+require('mocha');
+const isTravis = process.env.TRAVIS || process.env.CLI;
+const fs = require('fs');
+const os = require('os');
+const assert = require('assert');
+const path = require('path');
+const homedir = require('homedir-polyfill');
+const parse = require('..');
+
+const cwd = (...args) => path.resolve(__dirname, ...args);
+const fixture = name => cwd('fixtures', name);
+
+function read(filepath) {
+ return fs.readFileSync(path.join(__dirname, filepath), 'utf8');
+}
+
+describe('parse-git-config', function() {
+ describe('async', function() {
+ it('should return a promise when callback is not passed', function(cb) {
+ parse({ path: fixture('_gitconfig') })
+ .then(config => {
+ assert(config.hasOwnProperty('core'));
+ cb();
+ })
+ .catch(cb);
+ });
+
+ it('should parse .git/config', function(cb) {
+ parse({ path: fixture('_gitconfig') }, function(err, config) {
+ assert(!err);
+ assert(config.hasOwnProperty('core'));
+ cb();
+ });
+ });
+
+ it('should expand keys in config', function(cb) {
+ parse({ path: fixture('_gitconfig'), expandKeys: true })
+ .then(config => {
+ assert(config.hasOwnProperty('color'));
+ assert(config.color.hasOwnProperty('diff'));
+ cb();
+ })
+ .catch(cb);
+ });
+
+ it('should include other config sources', function(cb) {
+ parse({ path: fixture('_gitconfig'), 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) {
+ parse({ path: 'foo' }, function(err, config) {
+ assert(err instanceof Error);
+ assert(/ENOENT.*parse-git-config/.test(err.message));
+ cb();
+ });
+ });
+ });
+
+ describe('promise', function() {
+ it('should return a promise', function(cb) {
+ parse.promise({ path: fixture('_gitconfig') })
+ .then(config => {
+ assert(config.hasOwnProperty('core'));
+ cb();
+ });
+ });
+
+ it('should include other config sources', function() {
+ return parse.promise({ path: fixture('_gitconfig'), include: true })
+ .then(config => {
+ assert.deepEqual(config, require('./expected/_gitconfig.js'));
+ });
+ });
+ });
+
+ describe('sync', function() {
+ it('should return an object', function() {
+ assert(parse.sync({path: fixture('_gitconfig') }).hasOwnProperty('core'));
+ });
+ });
+
+ describe('.expandKeys', function() {
+ it('should expand ini-style keys', function() {
+ const config = {
+ 'foo "bar"': { doStuff: true },
+ 'foo "baz"': { doStuff: true }
+ };
+
+ assert.deepEqual(parse.expandKeys(config), {
+ foo: {
+ bar: { doStuff: true },
+ baz: { doStuff: true }
+ }
+ });
+ });
+ });
+
+ describe('resolve', function() {
+ it('should resolve the git config in the cwd by default', function() {
+ assert.equal(parse.resolve(), path.resolve(process.cwd(), '.git/config'));
+ });
+
+ it('should allow override path', function() {
+ const fp = path.resolve(homedir(), '.gitconfig');
+ assert.equal(parse.resolve({ path: fp }), fp);
+ });
+
+ it('should include other config sources', function() {
+ const fp = path.join(__dirname, 'fixtures/_gitconfig');
+ const actual = parse.sync({ path: fp, include: true });
+ assert.deepEqual(actual, require('./expected/_gitconfig.js'));
+ });
+
+ it('should resolve relative path to cwd', function() {
+ 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() {
+ if (isTravis && os.platform() === 'darwin') return this.skip();
+ assert.equal(parse.resolve('global'), path.resolve(homedir(), '.gitconfig'));
+ });
+
+ it('should allow override of cwd', function() {
+ const actual = parse.resolve({ path: '.config', cwd: '/opt/config' });
+ assert.equal(actual, path.resolve('/opt/config/.config'));
+ });
+ });
+});