diff --git a/README.md b/README.md index 835b198..7edfe20 100644 --- a/README.md +++ b/README.md @@ -95,9 +95,31 @@ If you are use [GitHub Enterprise](https://enterprise.github.com/), [GitLab Community Edition (CE), GitLab Enterprise Edition (EE)](https://gitlab.org/), [Atlassian Stash](https://www.atlassian.com/software/stash), ~~[GitCafe Enterprise](https://enterprise.gitcafe.com/)~~ -you need config like: +You need config in ~/.gitconfig file: -~/.gitopenrc +``` +[gitopen "github.company.com"] + type = github + protocol = https +[gitopen "gitlab.company.net"] + type = gitlab + protocol = http +``` + +You can config it by git command-line: + +```bash +; global +$ git config --global gitopen.github.company.com.type github +$ git config --global gitopen.github.company.com.protocol https + +; set local repo default remote name. +$ git remote add gitlabRemote git@gitlab.com:hotoo/gitopen.git +$ git config gitopen.remote gitlabRemote +``` + + +Also you can config it in ~/.gitopenrc file for global settings: ```yaml github.company.com: diff --git a/bin/gitopen b/bin/gitopen index 04c7664..eee855f 100755 --- a/bin/gitopen +++ b/bin/gitopen @@ -36,11 +36,16 @@ commander(process.argv, { } // 5. git/hg/svn remote url. + var remote = gitremote.getRemoteName({ + cwd: process.cwd(), + remote: command.remote, + }); + var uri; try { uri = gitremote.getRemoteUrl({ cwd: process.cwd(), - remote: command.remote, + remote, }); } catch (ex) { if (command.category === 'snippets/new') { @@ -52,10 +57,14 @@ commander(process.argv, { } } // 6. get openrc - var config = getConfig(uri); + var config = getConfig(uri, { + cwd: process.cwd(), + remote, + }); command.type = config.type; command.scheme = config.scheme; command.protocol = config.protocol; + command.remote = remote; // 6. resolve paths. url = gitresolve(uri, command); // 7. open diff --git a/bin/open-commander.js b/bin/open-commander.js index 43810b2..a2bd81c 100644 --- a/bin/open-commander.js +++ b/bin/open-commander.js @@ -91,7 +91,7 @@ module.exports = function(argv, option, callback) { category: 'home', cwd: commander.path ? path.dirname(commander.path) : option.cwd || process.cwd(), hash: commander.branch || option.cwb || 'master', - remote: commander.remote || 'origin', + remote: commander.remote, protocol: 'https', verbose: commander.verbose, }; diff --git a/bin/openrc.js b/bin/openrc.js index 9901de1..3923d00 100644 --- a/bin/openrc.js +++ b/bin/openrc.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); +var child_process = require('child_process'); var yaml = require('js-yaml'); var gitresolve = require('../lib/index'); var DEFAULT_CONFIG = require('../lib/gitopenrc'); @@ -13,7 +14,7 @@ function getUserHome() { var $HOME = getUserHome(); -function openrc(uri) { +function openrc(uri, options) { var HOSTNAME = gitresolve.parse(uri).hostname; var config = DEFAULT_CONFIG[HOSTNAME]; @@ -25,36 +26,75 @@ function openrc(uri) { }; } + // get config from .gitopenrc + var gitopenConfig = {}; var gitopenrc = path.join($HOME, '.gitopenrc'); - var result = {}; if (fs.existsSync(gitopenrc)) { try { config = yaml.safeLoad(fs.readFileSync(gitopenrc, 'utf8')); Object.keys(config).some(function(hostname) { if (HOSTNAME === hostname) { - result.protocol = config[hostname].protocol || 'https'; - result.type = config[hostname].type; + gitopenConfig.protocol = config[hostname].protocol || 'https'; + gitopenConfig.type = config[hostname].type; var type = config[hostname].type; if (type === 'custom') { - result.scheme = config[hostname].scheme || {}; + gitopenConfig.scheme = config[hostname].scheme || {}; } else { - result.scheme = require('../lib/scheme/' + config[hostname].type); + gitopenConfig.scheme = require('../lib/scheme/' + config[hostname].type); } return true; } }); - return result; } catch (ex) { console.error('Read %s error: %s', gitopenrc, ex.message); process.exit(1); return {}; } - } else { - console.error('Not found gitopenrc file: %s', gitopenrc); + } + + let gitConfig = {}; + var cwd = options.cwd || process.cwd(); + + // parse config from global .gitconfig + child_process.execSync( + 'git config --list --global | grep "^gitopen\\.' + HOSTNAME.replace(/\./g, '\\.') + '\\."', + {cwd: cwd} + ).toString().trim().split(/\r\n|\r|\n/).forEach(item => { + var kv = item.split('='); + if (kv.length < 2) { return; } + var key = kv.shift().trim().replace('gitopen.' + HOSTNAME + '.', ''); + var val = kv.join('=').trim(); + gitConfig[key] = val; + }); + + // parse config from local repo .gitconfig + child_process.execSync( + 'git config --list --local | grep "^gitopen\\."', + {cwd: cwd} + ).toString().trim().split(/\r\n|\r|\n/).forEach(item => { + var kv = item.split('='); + if (kv.length < 2) { return; } + var key = kv.shift().trim().replace(/^gitopen\./, ''); + var val = kv.join('=').trim(); + gitConfig[key] = val; + }); + + // 当 .gitopenrc 中定义为 type=custom,.gitconfig 中定义 type!=custom 时, + // 将 schema 改回 .gitconfig 中定义的 scheme 配置。 + if (gitConfig.type && gitConfig.type !== 'custom') { + gitConfig.scheme = require('../lib/scheme/' + gitConfig.type); + } + + // 优先使用 gitconfig 的配置。 + const mergeConfig = Object.assign({}, gitopenConfig, gitConfig); + + if (!mergeConfig.type) { + console.error('Not found gitopen configs.'); console.error('Please read [Configuration](https://github.com/hotoo/gitopen#configuration) for more information.'); process.exit(1); - return {}; } + + return mergeConfig; } module.exports = openrc; diff --git a/lib/gitremote.js b/lib/gitremote.js index f25588c..f86ea96 100644 --- a/lib/gitremote.js +++ b/lib/gitremote.js @@ -3,6 +3,26 @@ var child_process = require('child_process'); +/** + * 获取 remote name。 + * remote 不同,URL 就完全不同,后面所有的配置等都会受影响。 + * @param {Object} options 参数配置 + * @return {String} remote name + */ +exports.getRemoteName = function(options) { + if (options.remote) { + return options.remote; + } + try { + return child_process.execSync( + 'git config gitopen.remote', + { cwd: options.cwd || process.cwd() } + ).toString().trim() || 'origin'; + } catch (ex) { + return 'origin'; + } +}; + exports.getRemoteUrl = function getRemoteUrl(options) { if (!options) { options = {};