123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- /*!
- * parse-git-config <https://github.com/jonschlinkert/parse-git-config>
- *
- * Copyright (c) 2015-present, Jon Schlinkert.
- * Released under the MIT License.
- */
- 'use strict';
- const fs = require('fs');
- const os = require('os');
- const path = require('path');
- const util = require('util');
- const ini = require('ini');
- const configPath = require('git-config-path');
- const expand = str => (str ? str.replace(/^~/, os.homedir()) : '');
- /**
- * Asynchronously parse a `.git/config` file. If only the callback is passed,
- * the `.git/config` file relative to `process.cwd()` is used.
- *
- * ```js
- * parse((err, config) => {
- * if (err) throw err;
- * // do stuff with config
- * });
- *
- * // or, using async/await
- * (async () => {
- * console.log(await parse());
- * console.log(await parse({ cwd: 'foo' }));
- * console.log(await parse({ cwd: 'foo', path: 'some/.git/config' }));
- * })();
- * ```
- * @name parse
- * @param {Object|String|Function} `options` Options with `cwd` or `path`, the cwd to use, or the callback function.
- * @param {Function} `callback` callback function if the first argument is options or cwd.
- * @return {Object}
- * @api public
- */
- const parse = (options, callback) => {
- if (typeof options === 'function') {
- callback = options;
- options = null;
- }
- if (typeof callback !== 'function') {
- return parse.promise(options);
- }
- return parse.promise(options)
- .then(config => callback(null, config))
- .catch(callback);
- };
- parse.promise = options => {
- let filepath = parse.resolveConfigPath(options);
- let read = util.promisify(fs.readFile);
- let stat = util.promisify(fs.stat);
- if (!filepath) return Promise.resolve(null);
- return stat(filepath)
- .then(() => read(filepath, 'utf8'))
- .then(str => {
- if (options && options.include === true) {
- str = injectInclude(str, path.resolve(path.dirname(filepath)));
- }
- return parseIni(str, options);
- });
- };
- /**
- * Synchronously parse a `.git/config` file. If no arguments are passed,
- * the `.git/config` file relative to `process.cwd()` is used.
- *
- * ```js
- * console.log(parse.sync());
- * console.log(parse.sync({ cwd: 'foo' }));
- * console.log(parse.sync({ cwd: 'foo', path: 'some/.git/config' }));
- * ```
- * @name .sync
- * @param {Object|String} `options` Options with `cwd` or `path`, or the cwd to use.
- * @return {Object}
- * @api public
- */
- parse.sync = options => {
- let filepath = parse.resolveConfigPath(options);
- if (filepath && fs.existsSync(filepath)) {
- let input = fs.readFileSync(filepath, 'utf8');
- if (options && options.include === true) {
- let cwd = path.resolve(path.dirname(filepath));
- input = injectInclude(input, cwd);
- }
- return parseIni(input, options);
- }
- return {};
- };
- /**
- * Resolve the git config path
- */
- parse.resolveConfigPath = options => {
- if (typeof options === 'string') options = { type: options };
- 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 = options => parse.resolveConfigPath(options);
- /**
- * Returns an object with only the properties that had ini-style keys
- * converted to objects.
- *
- * ```js
- * const config = parse.sync({ path: '/path/to/.gitconfig' });
- * const obj = parse.expandKeys(config);
- * ```
- * @name .expandKeys
- * @param {Object} `config` The parsed git config object.
- * @return {Object}
- * @api public
- */
- parse.expandKeys = config => {
- for (let key of Object.keys(config)) {
- let m = /(\S+) "(.*)"/.exec(key);
- if (!m) continue;
- let prop = m[1];
- config[prop] = config[prop] || {};
- config[prop][m[2]] = config[key];
- delete config[key];
- }
- return config;
- };
- function parseIni(str, options) {
- let opts = Object.assign({}, options);
- str = str.replace(/\[(\S+) "(.*)"\]/g, (m, $1, $2) => {
- return $1 && $2 ? `[${$1} "${$2.split('.').join('\\.')}"]` : m;
- });
- let config = ini.parse(str);
- if (opts.expandKeys === true) {
- return parse.expandKeys(config);
- }
- return config;
- }
- function injectInclude(input, cwd) {
- let lines = input.split('\n').filter(line => line.trim() !== '');
- let len = lines.length;
- let res = [];
- for (let i = 0; i < len; i++) {
- let line = lines[i];
- if (line.indexOf('[include]') === 0) {
- let filepath = lines[i + 1].replace(/^\s*path\s*=\s*/, '');
- let fp = path.resolve(cwd, expand(filepath));
- res.push(fs.readFileSync(fp));
- } else {
- res.push(line);
- }
- }
- return res.join('\n');
- }
- /**
- * Expose `parse`
- */
- module.exports = parse;
|