Created
October 1, 2010 16:20
-
-
Save shyouhei/606432 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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