Skip to content

Instantly share code, notes, and snippets.

@shyouhei
Created October 1, 2010 16:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shyouhei/606432 to your computer and use it in GitHub Desktop.
Save shyouhei/606432 to your computer and use it in GitHub Desktop.
# Copyright(c) 2010 Urabe, Shyouhei. All rights Reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this code, to deal in the code without restriction, including without
# limitation the rights to use, copy, modify, merge, publish, distribute,
# sublicense, and/or sell copies of the code, and to permit persons to whom the
# code is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the code.
#
# THE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHOR OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE CODE OR THE USE OR OTHER DEALINGS IN THE
# CODE.
require 'fileutils'
require 'open-uri'
rexp = %r'<div class="repo">.*?>([^><]+)</a> / <a href="([^"]+)">[^><]+</a>(?:</span>)?</div>'u
dir = ARGV[0]
unless FileTest.directory? dir
FileUtils.mkpath dir
Dir.chdir dir do
%x[git --bare init]
open 'http://github.com/ruby/ruby/network/members' do |fp|
fp.read.scan rexp do |(who, where)|
url = "git://github.com#{where}.git"
pid = Process.spawn "git", "--bare", "remote", "add", who, url
Process.waitpid pid
end
end
end
end
Gitobj = Struct.new :hash, :parents, :children, :refs, :pretty, :canonp
class Gitobj
@@hash = Hash.new
def self.[] k
@@hash[k]
end
def self.delete k
@@hash.delete k
end
def self.new k
@@hash.fetch k do
obj = allocate
obj.send :initialize, k, [], [], nil, nil, false
@@hash.store k, obj
end
end
def self.each_key
for i in @@hash.keys.to_a.dup do yield i end
end
end
Dir.chdir dir do
#%x"git --bare remote --verbose update `git --bare remote`"
argv = ["git", "--bare", "log", "--pretty=%d|%H %P"]
IO.popen %w[git --bare for-each-ref --format=%(refname)], "rb" do |fp|
argv.concat fp.readlines.map {|i| i.chomp }.reject {|i| %r"/tags/" =~ i }
end
IO.popen argv, "rb" do |fp|
fp.each_line do |rhp|
r, hp = rhp.split "|", 2
h,*p = hp.chomp.split(' ').map {|i| i.hex }
obj = Gitobj.new h
for i in p do
j = Gitobj.new i
j.children << obj
obj.parents << j
end
tmp = r.scan(%r"[^( ,)]+").reject {|i| %r"/tags/" =~ i }
obj.refs = tmp unless tmp.empty?
end
end
flag = false
until flag
flag = true
Gitobj.each_key do |k|
next unless obj = Gitobj[k]
next if obj.refs and not obj.refs.grep(%r"\Aruby/").empty?
p = obj.parents
c = obj.children
next if p.size != 1
next if c.size != 1
p0 = p[0]
c0 = c[0]
pc = p0.children
cp = c0.parents
next if pc.any? {|i| i.hash == c0.hash }
next if cp.any? {|i| i.hash == p0.hash }
pc.delete obj
pc << c0
pc.uniq!
cp.delete obj
cp << p0
cp.uniq!
Gitobj.delete k
flag = true
end
end
IO.popen %w[git rev-list --all --header], "rb" do |fp|
fp.each_line "\0" do |h|
next unless obj = Gitobj[h.lines.first.hex]
case h
when /git-svn-id:.+@(\d+) b2dd03c8-39d4-4d8f-98ff-823fe69b080e/
obj.pretty = "r#$1"
obj.canonp = true
when /^author (.+?) </
obj.pretty = `git --bare log -1 --pretty=%h #{h.lines.first}`.chomp
end
end
end
end
puts "digraph RubyWorld {
graph [ overlap = scale, splines = true]
/* node [ label = \"\", shape = circle ] */
edge [ label = \"\" ]
"
Gitobj.each_key do |k|
obj = Gitobj[k]
if r = obj.refs
c = r.grep %r"\Aruby/"
if c.empty?
d = r.grep %r"\Ashyouhei/"
if d.empty?
if obj.canonp
label = obj.pretty
else
label = r.join "\\n"
end
else
label = d.join "\\n"
end
else
label = c.join "\\n"
end
elsif label = obj.pretty
# take it
else
label = "\", shape=circle\""
end
if obj.canonp
col = ", color=red, style=bold"
else
col = ""
end
printf "obj%040x [label=\"%s\"%s];\n", k, label, col
end
Gitobj.each_key do |k|
obj = Gitobj[k]
for i in obj.children do
if obj.canonp and i.canonp
col = "[color=red, style=bold, weight=2]"
else
col = ''
end
printf "obj%040x -> obj%040x%s;\n", k, i.hash, col
end
end
puts "}"
# Local Variables:
# mode: ruby
# coding: utf-8
# indent-tabs-mode: t
# tab-width: 3
# ruby-indent-level: 3
# fill-column: 127
# default-justification: full
# End:
# vi: ts=3 sw=3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment