Adds git-to-tikz script
This commit is contained in:
parent
ab56c7bdd0
commit
353bb99097
1 changed files with 149 additions and 0 deletions
149
bin/.bin/git/git-to-tikz
Executable file
149
bin/.bin/git/git-to-tikz
Executable file
|
@ -0,0 +1,149 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# A small ruby script to extract a git history to a tikz picture
|
||||
# Author: Michael Hauspie <Michael.Hauspie@lifl.fr>
|
||||
#
|
||||
# Not clean code, not always working well, but does its job in most of the cases I needed :)
|
||||
|
||||
# A commit object
|
||||
class Commit
|
||||
attr_accessor :hash
|
||||
attr_accessor :children
|
||||
attr_accessor :parents
|
||||
attr_accessor :message
|
||||
attr_reader :node_pos
|
||||
|
||||
# Construct a commit from a line
|
||||
# A line is commit_hash [child1_hash ... childN_hash] message
|
||||
def initialize()
|
||||
@hash = nil
|
||||
@children = Hash.new()
|
||||
@parents = Hash.new()
|
||||
@message = ""
|
||||
@node_pos = 0
|
||||
@message_pos = 0
|
||||
end
|
||||
def build(line)
|
||||
# Parse each word to match a hash or the commmit message
|
||||
pos=0
|
||||
line.split(" ").each do |word|
|
||||
if word =~ /[a-f0-9]{7}/ && @message == "" # match a short sha-1 commit tag
|
||||
if ! @hash
|
||||
@hash = word
|
||||
else
|
||||
@parents[word] = nil
|
||||
end
|
||||
elsif word == '*' # Position of the node
|
||||
@node_pos = pos
|
||||
elsif word =~ /[^|\/\\]/
|
||||
@message_pos = pos
|
||||
@message << " #{word}"
|
||||
end
|
||||
pos = pos + 1
|
||||
end
|
||||
@message.delete!("!")
|
||||
@message.lstrip!()
|
||||
if !@hash
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
# sets a child object
|
||||
def set_parent(c)
|
||||
@parents[c.hash] = c
|
||||
c.children[@hash] = self
|
||||
end
|
||||
|
||||
def export_to_tikz(ypos)
|
||||
puts "\\node[commit] (#{@hash}) at (#{0.5*@node_pos},#{ypos}) {};"
|
||||
puts "\\node[right,xshift=#{@message_pos*0.5}] (label_#{@hash}) at (#{@hash}.east) {\\verb!#{@hash} #{@message}!};"
|
||||
@children.each_value do |child|
|
||||
puts "\\draw[->] (#{@hash}) -- (#{child.hash});"
|
||||
end
|
||||
end
|
||||
|
||||
def to_s()
|
||||
"#{@hash}: #{@message} #{@node_pos} #{@message_pos}"
|
||||
end
|
||||
end
|
||||
|
||||
class Branch
|
||||
attr_accessor :name
|
||||
attr_accessor :hash
|
||||
attr_accessor :commit
|
||||
|
||||
def initialize(line)
|
||||
words = line.split(" ")
|
||||
@name = words[0]
|
||||
@hash = words[1]
|
||||
@commit = nil
|
||||
end
|
||||
end
|
||||
|
||||
# A repository, which is a collection of commit objects and branches
|
||||
class Repository
|
||||
def initialize()
|
||||
@commits = Hash.new()
|
||||
@branches = Array.new()
|
||||
end
|
||||
|
||||
def add_commit(commit)
|
||||
@commits[commit.hash] = commit
|
||||
end
|
||||
|
||||
def add_branch(branch)
|
||||
if ! @commits.has_key?(branch.hash)
|
||||
return false
|
||||
end
|
||||
c = @commits.fetch(branch.hash)
|
||||
branch.commit = c
|
||||
@branches << branch
|
||||
return true
|
||||
end
|
||||
|
||||
# This iterates other commits and resolves its parents
|
||||
def resolve_parents()
|
||||
@commits.each_value do |commit|
|
||||
commit.parents.keys.each do |parent_hash|
|
||||
c = @commits.fetch(parent_hash)
|
||||
commit.set_parent(c) # Link the commit object to its parent
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def export_to_tikz
|
||||
puts "\\begin{tikzpicture}"
|
||||
ypos=0
|
||||
ystep=-0.5
|
||||
@commits.each_value do |commit|
|
||||
commit.export_to_tikz(ypos)
|
||||
ypos = ypos + ystep
|
||||
end
|
||||
@branches.each do |branch|
|
||||
puts "\\node[branch,right,xshift=.1] (#{branch.name}) at (label_#{branch.hash}.east) {\\texttt{#{branch.name}}};"
|
||||
end
|
||||
puts "\\end{tikzpicture}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
r = Repository.new()
|
||||
|
||||
# Extract commits
|
||||
`git log --graph --branches --oneline --parents`.lines().each do |line|
|
||||
c = Commit.new()
|
||||
if c.build(line)
|
||||
r.add_commit(c)
|
||||
end
|
||||
end
|
||||
r.resolve_parents()
|
||||
|
||||
# Extract branches
|
||||
`git branch -av | cut -b 3-`.lines().each do |line|
|
||||
r.add_branch(Branch.new(line))
|
||||
end
|
||||
|
||||
r.export_to_tikz()
|
Loading…
Add table
Add a link
Reference in a new issue