Skip to content

Instantly share code, notes, and snippets.

@sri
Created February 16, 2016 23:36
Show Gist options
  • Save sri/49c248d9da80d76fc641 to your computer and use it in GitHub Desktop.
Save sri/49c248d9da80d76fc641 to your computer and use it in GitHub Desktop.
a better git grep
#! /usr/bin/env ruby
USAGE = "gg <git-repos> pattern [-r]
Git grep for pattern using:
- <git-repos> are passed in, or
- the current dir is in a git repo, or,
- git repos that are subdirs ofthe current dir
If `-r' is specified, git grep from the repo's
root directory. Only works if the current dir
is a git repo."
class GitGrep
CMD = "git grep --break -n %s"
def initialize(pattern, repos, options = {})
@pattern = pattern
@repos = repos
@options = options
end
def grep
@repos.each do |repo|
if @options[:grep_from_root]
Dir.chdir(repo) { grep_repo repo }
else
grep_repo repo
end
end
end
private
def grep_repo(repo)
IO.popen(CMD % @pattern).each do |line|
puts line
end
end
end
def main
pattern = nil
grep_from_root = nil
repos = []
argv = ARGV.dup
if argv.member?("-r")
argv.delete "-r"
grep_from_root = true
end
if argv.size == 0
puts USAGE
exit 1
elsif argv.size == 1
pattern = argv.first
else
*repos, pattern = argv
end
if repos.empty?
# No repos passed in
in_git_repo = begin
`git rev-parse 2>/dev/null`
$?.exitstatus.zero?
end
if in_git_repo
repos << `git rev-parse --show-toplevel`.chomp
else
Dir['*'].each do |x|
next unless File.directory? File.join(x, ".git")
repos << x
end
end
end
GitGrep.new(pattern, repos,
grep_from_root: grep_from_root).grep
end
if $0 == __FILE__
main
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment