git-visualiser 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/bin/git_vis +19 -0
- data/lib/application/application.rb +82 -0
- data/lib/application/coffee_engine.rb +20 -0
- data/lib/application/images/ajax-loader.gif +0 -0
- data/lib/application/javascripts/branch_graph.coffee +424 -0
- data/lib/application/javascripts/commit_graph.coffee +442 -0
- data/lib/application/javascripts/common.coffee +50 -0
- data/lib/application/javascripts/d3.min.js +5 -0
- data/lib/application/javascripts/data_convert.coffee +56 -0
- data/lib/application/javascripts/jquery.min.js +6 -0
- data/lib/application/javascripts/moment.min.js +6 -0
- data/lib/application/javascripts/namespace.coffee +2 -0
- data/lib/application/sass_engine.rb +14 -0
- data/lib/application/stylesheets/scss/app.scss +172 -0
- data/lib/application/stylesheets/scss/flat_ui/_config.sass +16 -0
- data/lib/application/stylesheets/scss/flat_ui/_icon-font-24.sass +91 -0
- data/lib/application/stylesheets/scss/flat_ui/_icon-font.sass +91 -0
- data/lib/application/stylesheets/scss/flat_ui/_mixins.sass +96 -0
- data/lib/application/stylesheets/scss/flat_ui/_spaces.sass +129 -0
- data/lib/application/stylesheets/scss/flat_ui/flat-ui.sass +39 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_btn.sass +73 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_checkbox-and-radio.sass +86 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_demo.sass +228 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_footer.sass +57 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_input.sass +66 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_login.sass +95 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_navbar.sass +152 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_pager.sass +56 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_pagination.sass +75 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_palette.sass +88 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_progress.sass +29 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_select.sass +163 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_share.sass +34 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_tagsinput.sass +91 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_tile.sass +42 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_todo.sass +77 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_toggle.sass +85 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_tooltip.sass +45 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_type.sass +43 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_ui-slider.sass +44 -0
- data/lib/application/stylesheets/scss/flat_ui/modules/_video.sass +358 -0
- data/lib/application/views/authors_list.haml +11 -0
- data/lib/application/views/index.haml +48 -0
- data/lib/application/visualisation.rb +156 -0
- metadata +87 -0
@@ -0,0 +1,11 @@
|
|
1
|
+
#author-list
|
2
|
+
%h4 Top Authors
|
3
|
+
- @authors.each do |author|
|
4
|
+
- author = author.split(',')
|
5
|
+
.author-row.clearfix
|
6
|
+
.author-gravatar
|
7
|
+
=gravatar_image(author[2])
|
8
|
+
.author_details
|
9
|
+
%p.author-name= author[1]
|
10
|
+
%p.author-email= author[2]
|
11
|
+
%p.author-commits= "#{author[0]} commits"
|
@@ -0,0 +1,48 @@
|
|
1
|
+
!!! 5
|
2
|
+
%head
|
3
|
+
%link(rel="stylesheet" type="text/css" href="stylesheets/app.css")
|
4
|
+
%link(rel="stylesheet" type="text/css" href="stylesheets/flat_ui.css")
|
5
|
+
|
6
|
+
%body
|
7
|
+
#sidebar-branches.sidebar
|
8
|
+
%h1 Branches
|
9
|
+
#branches-controls
|
10
|
+
%label{:for => "filter_merged"}
|
11
|
+
%input#filter_merged_checkbox{:name => "filter_merged", :type => "checkbox"}
|
12
|
+
Filter merged with master
|
13
|
+
%br
|
14
|
+
%label{:for => "filter_remotes"}
|
15
|
+
%input#filter_merged_checkbox{:name => "filter_remotes", :type => "checkbox"}
|
16
|
+
Filter remote branches
|
17
|
+
%input#filter_names_input{:name => "filter_names", :placeholder => "Filter branch names", :type => "text"}
|
18
|
+
%input#show_commit_input.commit_filters_input{:name => "show_commit", :placeholder => "Show commit", :type => "text"}
|
19
|
+
%input#exclude_commit_input.commit_filters_input{:name => "exclude_commit", :placeholder => "Exclude commit", :type => "text"}
|
20
|
+
%a#apply-filters-btn.btn.btn-large.btn-block.apply-btn{:href => "#"}
|
21
|
+
Apply Filters
|
22
|
+
#authors-list
|
23
|
+
#branches-display
|
24
|
+
#vis-loading
|
25
|
+
%h4 Loading Repository Data...
|
26
|
+
%img{:alt => "Ajax-loader", :src => "images/ajax-loader.gif"}
|
27
|
+
#commits-toolbar{:style => "display: none"}
|
28
|
+
#commit-details
|
29
|
+
%h3{:id => "branch_name"}
|
30
|
+
%a#back-to-branches-btn{:href => "#"}
|
31
|
+
Back to branches
|
32
|
+
%p{:id => "commit_sha"}
|
33
|
+
%p{:class => "small"}
|
34
|
+
%span{:id => "commit_author"}
|
35
|
+
%br
|
36
|
+
%span{:id => "commit_message"}
|
37
|
+
#history-graph
|
38
|
+
%a{:id => "clear_history_filters", :href => '#'} Clear filter
|
39
|
+
#commits-display
|
40
|
+
|
41
|
+
%script(src="javascripts/jquery.min.js" type="text/javascript")
|
42
|
+
%script(src="javascripts/d3.min.js" type="text/javascript")
|
43
|
+
%script(src="javascripts/moment.min.js" type="text/javascript")
|
44
|
+
%script(src="javascripts/namespace.js" type="text/javascript")
|
45
|
+
%script(src="javascripts/common.js" type="text/javascript")
|
46
|
+
%script(src="javascripts/data_convert.js" type="text/javascript")
|
47
|
+
%script(src="javascripts/commit_graph.js" type="text/javascript")
|
48
|
+
%script(src="javascripts/branch_graph.js" type="text/javascript")
|
@@ -0,0 +1,156 @@
|
|
1
|
+
module Visualisation
|
2
|
+
require 'csv'
|
3
|
+
|
4
|
+
def self.branches
|
5
|
+
branches_arr = []
|
6
|
+
total_additions = total_deletions = 0
|
7
|
+
remotes_arr = Visualisation.remotes
|
8
|
+
Visualisation.branches_with_remotes.each do |branch|
|
9
|
+
diff = Visualisation.branch_diff_size(branch)
|
10
|
+
head_commit = Visualisation.head_commit_sha(branch)
|
11
|
+
merged_with_master = Visualisation.branch_contains_commit("master", head_commit)
|
12
|
+
total_additions += diff.first
|
13
|
+
total_deletions += diff.last
|
14
|
+
remote = remotes_arr.include?(branch)
|
15
|
+
branches_arr << {:name => branch, :diff => {:add => diff.first, :del => diff.last},
|
16
|
+
:merged_with_master => merged_with_master, :hidden => false, :remote => remote}
|
17
|
+
end
|
18
|
+
result = {:branches => branches_arr, :diff => {:add => total_additions, :del => total_deletions}}
|
19
|
+
result
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.branches_with_remotes
|
23
|
+
`git branch -a`.split("\n").each { |b| b.gsub!(/[*]?\s/, '') and b.gsub!(/remotes\//, '') }
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.remotes
|
27
|
+
`git branch -r`.split("\n").each { |b| b.gsub!(/[*]?\s/, '') }
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.head_commit_sha(branch)
|
31
|
+
`git rev-parse #{branch}`
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.branch_contains_commit(branch, commit_sha)
|
35
|
+
`git branch --contains #{commit_sha}`.split("\n").each {|b| b.gsub!(/[*]?\s/, '')}.include?(branch)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.branches_containing_commit(commit_sha, remotes = true)
|
39
|
+
if remotes
|
40
|
+
return `git branch -a --contains #{commit_sha}`.split("\n").each { |b| b.gsub!(/[*]?\s/, '') and b.gsub!(/remotes\//, '') }
|
41
|
+
else
|
42
|
+
return `git branch --contains #{commit_sha}`.split("\n").each { |b| b.gsub!(/[*]?\s/, '') }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.branches_excluding_commit(commit_sha, remotes = true)
|
47
|
+
if remotes
|
48
|
+
return branches_with_remotes - `git branch --contains #{commit_sha}`.split("\n").each { |b| b.gsub!(/[*]?\s/, '') }
|
49
|
+
else
|
50
|
+
# TODO fix this
|
51
|
+
# return branches - `git branch --contains #{commit_sha}`.split("\n").each { |b| b.gsub!(/[*]?\s/, '') }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.branch_diff_number_commits(branch)
|
56
|
+
`git cherry master #{branch}`.split("\n").size
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.repo_branches_merged(show_remotes = true)
|
60
|
+
merged_branches = {}
|
61
|
+
compare_branches = branches_with_remotes
|
62
|
+
compare_branches.each do |b1|
|
63
|
+
b1_merges = {}
|
64
|
+
compare_branches.each do |b2|
|
65
|
+
next if b1 == b2 || b2.split("/").last == b1 ||
|
66
|
+
(merged_branches.has_key?(b2.to_sym) && merged_branches[b2.to_sym].has_key?(b1.to_sym))
|
67
|
+
directions = {}
|
68
|
+
directions.merge!(:left => true) if branch_merged_with_base?(b1, b2, remotes)
|
69
|
+
directions.merge!(:right => true) if right = branch_merged_with_base?(b2, b1, remotes)
|
70
|
+
b1_merges.merge!(b2.to_sym => directions)
|
71
|
+
end
|
72
|
+
merged_branches.merge!(b1.to_sym => b1_merges)
|
73
|
+
end
|
74
|
+
merged_branches
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.branch_merged_with_base?(base, branch, remotes)
|
78
|
+
if remotes
|
79
|
+
`git branch -a --merged #{base} #{branch}`.length > 0
|
80
|
+
else
|
81
|
+
`git branch --merged #{base} #{branch}`.length > 0
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
#printout merge commits between base and topic branch
|
86
|
+
#`git log #{branch} #{base} --oneline --date-order --merges --reverse -1`
|
87
|
+
|
88
|
+
def self.branch_diff_size(branch)
|
89
|
+
merge_base_commit = `git merge-base master #{branch}`.gsub("/\n/", '').strip!
|
90
|
+
raw_diff_stats = `git diff --numstat #{merge_base_commit} #{branch}`
|
91
|
+
diff_stats = raw_diff_stats.split(/\n/)
|
92
|
+
additions = deletions = 0
|
93
|
+
diff_stats.each do |line|
|
94
|
+
cols = line.split
|
95
|
+
additions += cols[0].to_i
|
96
|
+
deletions += cols[1].to_i
|
97
|
+
end
|
98
|
+
|
99
|
+
return additions, deletions
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.commits_for_branch(branch_name)
|
103
|
+
commits = []
|
104
|
+
raw_log = `git log master..#{branch_name} --max-count 15 --date=short --pretty="%H, %an, %ad, %s"`
|
105
|
+
commit_lines = CSV.parse(raw_log)
|
106
|
+
i = 1
|
107
|
+
last_date = nil
|
108
|
+
commit_lines.each_with_index do |commit, id|
|
109
|
+
sha1 = commit[0]
|
110
|
+
author = commit[1].strip!
|
111
|
+
commit_date = commit[2].strip!
|
112
|
+
message = commit.slice(3..commit.length-1).join(",").strip!
|
113
|
+
if !last_date.nil? && commit_date.to_date == last_date.to_date
|
114
|
+
i += 1
|
115
|
+
else
|
116
|
+
i = 1
|
117
|
+
end
|
118
|
+
last_date = commit_date
|
119
|
+
commit_stats = {:id => id, :date => commit_date, :num => i, :sha => sha1,
|
120
|
+
:author => author, :message => message}
|
121
|
+
commits << commit_stats
|
122
|
+
puts commits
|
123
|
+
end
|
124
|
+
commits
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.merge_base_file_stats(branch_name)
|
128
|
+
`git log master..#{branch_name} --numstat --no-merges --format="%n"`
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.commit_diff_stats(commit_sha)
|
132
|
+
`git show #{commit_sha} --numstat --no-merges --pretty="%n"`.strip!
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
def self.branch_diff_commit_files(commit_sha = nil)
|
137
|
+
merge_base_commit = `git merge-base master #{commit_sha}`.gsub("/\n/", '').strip!
|
138
|
+
diff_stats = `git diff --numstat #{merge_base_commit} #{commit_sha}`.split(/\n/)
|
139
|
+
files = {}
|
140
|
+
additions = deletions = 0
|
141
|
+
diff_stats.each do |line|
|
142
|
+
cols = line.split
|
143
|
+
additions += cols[0].to_i
|
144
|
+
deletions += cols[1].to_i
|
145
|
+
files.merge!(cols[2].to_sym => { :add => additions, :del => deletions })
|
146
|
+
end
|
147
|
+
files.merge!(:total => { :add => additions, :del => deletions })
|
148
|
+
end
|
149
|
+
|
150
|
+
def self.branch_author_stats(branch)
|
151
|
+
`git log master..#{branch} --pretty=format:%an,%ae \
|
152
|
+
| awk '{ ++c[$0]; } END { for(cc in c) printf "%5d,%s\\n",c[cc],cc; }'\
|
153
|
+
| sort -r`.split(/\n/).each { |c| c.strip! }
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: git-visualiser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James McCann
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-05-18 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A Sinatra app for loading D3-based visualisations of a local Git repository
|
14
|
+
email: jmccnz@gmail.com
|
15
|
+
executables:
|
16
|
+
- git_vis
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- bin/git_vis
|
21
|
+
- lib/application/application.rb
|
22
|
+
- lib/application/coffee_engine.rb
|
23
|
+
- lib/application/images/ajax-loader.gif
|
24
|
+
- lib/application/javascripts/branch_graph.coffee
|
25
|
+
- lib/application/javascripts/commit_graph.coffee
|
26
|
+
- lib/application/javascripts/common.coffee
|
27
|
+
- lib/application/javascripts/d3.min.js
|
28
|
+
- lib/application/javascripts/data_convert.coffee
|
29
|
+
- lib/application/javascripts/jquery.min.js
|
30
|
+
- lib/application/javascripts/moment.min.js
|
31
|
+
- lib/application/javascripts/namespace.coffee
|
32
|
+
- lib/application/sass_engine.rb
|
33
|
+
- lib/application/stylesheets/scss/app.scss
|
34
|
+
- lib/application/stylesheets/scss/flat_ui/_config.sass
|
35
|
+
- lib/application/stylesheets/scss/flat_ui/_icon-font-24.sass
|
36
|
+
- lib/application/stylesheets/scss/flat_ui/_icon-font.sass
|
37
|
+
- lib/application/stylesheets/scss/flat_ui/_mixins.sass
|
38
|
+
- lib/application/stylesheets/scss/flat_ui/_spaces.sass
|
39
|
+
- lib/application/stylesheets/scss/flat_ui/flat-ui.sass
|
40
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_btn.sass
|
41
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_checkbox-and-radio.sass
|
42
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_demo.sass
|
43
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_footer.sass
|
44
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_input.sass
|
45
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_login.sass
|
46
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_navbar.sass
|
47
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_pager.sass
|
48
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_pagination.sass
|
49
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_palette.sass
|
50
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_progress.sass
|
51
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_select.sass
|
52
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_share.sass
|
53
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_tagsinput.sass
|
54
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_tile.sass
|
55
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_todo.sass
|
56
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_toggle.sass
|
57
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_tooltip.sass
|
58
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_type.sass
|
59
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_ui-slider.sass
|
60
|
+
- lib/application/stylesheets/scss/flat_ui/modules/_video.sass
|
61
|
+
- lib/application/views/authors_list.haml
|
62
|
+
- lib/application/views/index.haml
|
63
|
+
- lib/application/visualisation.rb
|
64
|
+
homepage: http://rubygems.org/gems/git-visualiser
|
65
|
+
licenses: []
|
66
|
+
metadata: {}
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options: []
|
69
|
+
require_paths:
|
70
|
+
- lib
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ! '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
requirements: []
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 2.0.3
|
84
|
+
signing_key:
|
85
|
+
specification_version: 4
|
86
|
+
summary: Sinatra app for Git Visualisation
|
87
|
+
test_files: []
|