Skip to content

Instantly share code, notes, and snippets.

@walf443
Created October 1, 2009 17:15
Show Gist options
  • Save walf443/199109 to your computer and use it in GitHub Desktop.
Save walf443/199109 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
require 'pathname'
require 'logger'
require 'thread'
require 'open3'
class App
def initialize args
@logger = args[:logger] or raise "no logger"
@is_check_push = args[:is_check_push]
@ignore = args[:ignore] || []
end
def run base
targets = Pathname.glob("#{base}/**/.git").sort
threads = []
targets.each do |dir|
next if @ignore.any? {|i| i =~ dir.to_s }
threads << Thread.new do |t|
@logger.debug("start update #{dir}")
git_update dir.parent.realpath
@logger.debug("end update #{dir}")
end
sleep 1 # stop too many access to github.
# for avoiding fork bomb
if threads.length >= 10
while th = threads.pop
th.join
end
end
end
threads.each {|th| th.join }
end
private
def git_update dir
git_cmd = "git --git-dir=#{dir}/.git"
Open3.popen3 "#{git_cmd} remote update && #{git_cmd} config --get-regexp svn-remote > /dev/null && #{git_cmd} svn fetch" do |stdin, stdout, stderr|
stdout.each_line do |line|
if line =~ /^Updating / # 必ず出るので特別扱い。
@logger.debug("update: #{dir}: #{line}")
else
@logger.info("update: #{dir}: #{line}")
end
end
stderr.each_line do |line|
@logger.error("update: #{dir}: #{line}")
end
end
if @is_check_push
pushable_remotes = `#{git_cmd} remote -v | grep @ | cut -f 1`.split(/\n/)
pushable_remotes.each do |remote|
# master固定なのに注意
# TODO: git-svnでもチェックしたい
check_cmd = "#{git_cmd} log --name-status --pretty=oneline --abbrev-commit #{remote}/master..HEAD"
Open3.popen3 (check_cmd) do |stdin,stdout,stderr|
counter = 0
stdout.each_line do |line|
counter += 1
# 必要以上の情報が出てるので詳しく知りたかったらユーザーが実行する方がよさそう
# @logger.info("push_check: #{dir}: #{line}")
end
if counter > 0
@logger.info("push_check: #{dir}'s #{remote} is need to push!!! do \"#{check_cmd}\"")
end
stderr.each_line do |line|
# ignore error
end
end
end
end
end
end
def main
logger = Logger.new($stderr)
logger.level = Logger::INFO
app = App.new(
:logger => logger,
:is_check_push => true,
:ignore => [ %r{ruby/(pathobserver|rubycocoa)} ]
)
app.run Pathname(__FILE__).parent.realpath
end
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment