From 26d9c920a4aad45c8dd825b6cd41b426459968b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Tue, 29 Mar 2011 15:13:36 +0200 Subject: [PATCH] preserve global flags to git such as `--bare` and `--git-dir=/some/path` Supply these global flags to subcommands. Closes #69 --- lib/hub/args.rb | 7 +++++- lib/hub/commands.rb | 54 +++++++++++++++++++++++++++++++++++++++++---- lib/hub/context.rb | 20 +++++++++++++++-- test/fakebin/git | 2 +- test/hub_test.rb | 10 ++++++++- 5 files changed, 84 insertions(+), 9 deletions(-) diff --git a/lib/hub/args.rb b/lib/hub/args.rb index 7df98e0a..3f1530b7 100644 --- a/lib/hub/args.rb +++ b/lib/hub/args.rb @@ -54,7 +54,7 @@ module Hub # Array of `executable` followed by all args suitable as arguments # for `exec` or `system` calls. def to_exec(args = self) - [*executable].concat args + Array(executable) + args end # All the words (as opposed to flags) contained in this argument @@ -80,6 +80,11 @@ module Hub chained? or self != @original_args end + def has_flag?(*flags) + pattern = flags.flatten.map { |f| Regexp.escape(f) }.join('|') + !grep(/^#{pattern}(?:=|$)/).empty? + end + private def normalize_callback(cmd_or_args, args, block) diff --git a/lib/hub/commands.rb b/lib/hub/commands.rb index 09854ce9..48574884 100644 --- a/lib/hub/commands.rb +++ b/lib/hub/commands.rb @@ -42,8 +42,10 @@ module Hub API_CREATE = 'http://github.com/api/v2/yaml/repos/create' def run(args) + slurp_global_flags(args) + # Hack to emulate git-style - args.unshift 'help' if args.grep(/^[^-]|version|exec-path$|html-path/).empty? + args.unshift 'help' if args.empty? cmd = args[0] expanded_args = expand_alias(cmd) @@ -493,13 +495,13 @@ module Hub # $ hub help # (print improved help text) def help(args) - command = args.grep(/^[^-]/)[1] + command = args.words[1] if command == 'hub' puts hub_manpage exit - elsif command.nil? && args.grep(/^--?a/).empty? - ENV['GIT_PAGER'] = '' if args.grep(/^-{1,2}p/).empty? # Use `cat`. + elsif command.nil? && !args.has_flag?('-a', '--all') + ENV['GIT_PAGER'] = '' unless args.has_flag?('-p', '--paginate') # Use `cat`. puts improved_help_text exit end @@ -556,6 +558,50 @@ help # from the command line. # + # Extract global flags from the front of the arguments list. + # Makes sure important ones are supplied for calls to subcommands. + # + # Known flags are: + # --version --exec-path= --html-path + # -p|--paginate|--no-pager --no-replace-objects + # --bare --git-dir= --work-tree= + # -c name=value --help + # + # Special: `--version`, `--help` are replaced with "version" and "help". + # Ignored: `--exec-path`, `--html-path` are kept in args list untouched. + def slurp_global_flags(args) + flags = %w[ -c -p --paginate --no-pager --no-replace-objects --bare --version --help ] + flags2 = %w[ --exec-path= --git-dir= --work-tree= ] + + # flags that should be present in subcommands, too + globals = [] + # flags that apply only to main command + locals = [] + + while args[0] && (flags.include?(args[0]) || flags2.any? {|f| args[0].index(f) == 0 }) + flag = args.shift + case flag + when '--version', '--help' + args.unshift flag.sub('--', '') + when '-c' + # slurp one additional argument + config_pair = args.shift + # add configuration to our local cache + key, value = config_pair.split('=', 2) + Context::GIT_CONFIG["config #{key}"] = value.to_s + + globals << flag << config_pair + when '-p', '--paginate', '--no-pager' + locals << flag + else + globals << flag + end + end + + Context::GIT_CONFIG.executable = Array(Context::GIT_CONFIG.executable).concat(globals) + args.executable = Array(args.executable).concat(globals).concat(locals) + end + # Handles common functionality of browser commands like `browse` # and `compare`. Yields a block that returns params for `github_url`. def browse_command(args) diff --git a/lib/hub/context.rb b/lib/hub/context.rb index e872f9e6..391fe795 100644 --- a/lib/hub/context.rb +++ b/lib/hub/context.rb @@ -1,12 +1,28 @@ +require 'shellwords' + module Hub # Provides methods for inspecting the environment, such as GitHub user/token # settings, repository info, and similar. module Context private + class ShellOutCache < Hash + attr_accessor :executable + + def initialize(executable = nil, &block) + super(&block) + @executable = executable + end + + def to_exec(args) + args = args.shellsplit if args.respond_to? :shellsplit + Array(executable) + Array(args) + end + end + # Caches output when shelling out to git - GIT_CONFIG = Hash.new do |cache, cmd| - result = %x{git #{cmd}}.chomp + GIT_CONFIG = ShellOutCache.new(ENV['GIT'] || 'git') do |cache, cmd| + result = %x{#{cache.to_exec(cmd).shelljoin}}.chomp cache[cmd] = $?.success? && !result.empty? ? result : nil end diff --git a/test/fakebin/git b/test/fakebin/git index 229e7431..7d05aa84 100755 --- a/test/fakebin/git +++ b/test/fakebin/git @@ -1,5 +1,5 @@ #!/bin/sh -if [ "$1" = "--version" ]; then +if [ "$1" = "--version" ] || [ "$1" = "version" ]; then echo "git version 1.7.0.4" elif [ "$1" = "--exec-path" ]; then echo "/usr/lib/git-core" diff --git a/test/hub_test.rb b/test/hub_test.rb index 6865414b..33d2bed6 100644 --- a/test/hub_test.rb +++ b/test/hub_test.rb @@ -30,6 +30,8 @@ class HubTest < Test::Unit::TestCase Hub::Context::DIRNAME.replace 'hub' Hub::Context::REMOTES.clear + Hub::Context::GIT_CONFIG.executable = 'git' + @git = Hub::Context::GIT_CONFIG.replace(Hash.new { |h, k| unless k.index('config alias.') == 0 raise ArgumentError, "`git #{k}` not stubbed" @@ -557,7 +559,7 @@ class HubTest < Test::Unit::TestCase def test_exec_path_arg out = hub('--exec-path=/home/wombat/share/my-l33t-git-core') - assert_equal Hub::Commands.improved_help_text, hub("") + assert_equal Hub::Commands.improved_help_text, out end def test_html_path @@ -760,6 +762,12 @@ config assert_command "browse", "open https://github.com/my/repo" end + def test_global_flags_preserved + cmd = '--no-pager --bare -c core.awesome=true -c name=value --git-dir=/srv/www perform' + assert_command cmd, 'git --bare -c core.awesome=true -c name=value --git-dir=/srv/www --no-pager perform' + assert_equal %w[git --bare -c core.awesome=true -c name=value --git-dir=/srv/www], @git.executable + end + protected def stub_github_user(name) -- GitLab