mgit 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/mgit/commands/fetch.rb +23 -4
- data/lib/mgit/commands/statistics.rb +100 -0
- data/lib/mgit/commands/status.rb +17 -20
- data/lib/mgit/commands/tags.rb +1 -1
- data/lib/mgit/registry.rb +1 -1
- data/lib/mgit/repository.rb +11 -0
- data/lib/mgit/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8174b6f645364ef888f498ffa24274882cf9dd39
|
4
|
+
data.tar.gz: b6752daa7ac077dae28c7c46a47785e05b5b430a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4d6463d5a85e932aaa3d575b5c440b2a1b13f352a2efc3a2e366afe6cc81ac782ab66a2efb60e4cf62ddafaa21fdc3cb1d02ef3cc8ee8dc5fc7c85f52f2d671
|
7
|
+
data.tar.gz: fbc6b246c055889649963d7b06d1f82618068d8f27817af27aa6a03394b2ae3fd0f99bc13a912e7d70997b76a9a1f359cc5879df31f114e33d84befdfadd4799
|
data/lib/mgit/commands/fetch.rb
CHANGED
@@ -1,12 +1,31 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
1
3
|
module MGit
|
2
4
|
class FetchCommand < Command
|
3
5
|
def execute(args)
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
threads = []
|
7
|
+
Registry.each do |repo|
|
8
|
+
threads << Thread.new do
|
9
|
+
remotes, st = Open3.capture2('git remote', :chdir => repo.path)
|
10
|
+
|
11
|
+
if st.exitstatus != 0
|
12
|
+
perror "Failed to read remotes for repository #{repo.name}! Abort."
|
13
|
+
Thread.exit
|
14
|
+
end
|
15
|
+
|
16
|
+
remotes.split.each do |remote|
|
17
|
+
sout, st = Open3.capture2("git fetch #{remote}", :chdir => repo.path)
|
18
|
+
if st.exitstatus == 0
|
19
|
+
pinfo "Fetched #{remote} in repository #{repo.name}."
|
20
|
+
else
|
21
|
+
perror "Failed to fetch #{remote} in repository #{repo.name}! Abort."
|
22
|
+
break
|
23
|
+
end
|
24
|
+
end
|
8
25
|
end
|
9
26
|
end
|
27
|
+
|
28
|
+
threads.each { |t| t.join }
|
10
29
|
end
|
11
30
|
|
12
31
|
def arity
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module MGit
|
4
|
+
class StatisticsCommand < Command
|
5
|
+
def execute(args)
|
6
|
+
total_authors = {}
|
7
|
+
total_punchcard = {}
|
8
|
+
Registry.chdir_each do |repo|
|
9
|
+
current_authors = {}
|
10
|
+
current_punchcard = {}
|
11
|
+
|
12
|
+
collect do |author, time, changes|
|
13
|
+
current_authors[author] ||= 0
|
14
|
+
current_authors[author] += changes
|
15
|
+
|
16
|
+
total_punchcard[time.wday] ||= {}
|
17
|
+
total_punchcard[time.wday][time.hour / 4] ||= 0
|
18
|
+
total_punchcard[time.wday][time.hour / 4] += changes
|
19
|
+
end
|
20
|
+
|
21
|
+
print_authors current_authors, repo.name
|
22
|
+
puts
|
23
|
+
|
24
|
+
current_authors.each do |author, changes|
|
25
|
+
total_authors[author] ||= 0
|
26
|
+
total_authors[author] += changes
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
print_authors total_authors, 'TOTAL'
|
31
|
+
puts
|
32
|
+
print_punchcard total_punchcard, 'TOTAL'
|
33
|
+
end
|
34
|
+
|
35
|
+
def arity
|
36
|
+
[nil, 0]
|
37
|
+
end
|
38
|
+
|
39
|
+
def usage
|
40
|
+
'statistics'
|
41
|
+
end
|
42
|
+
|
43
|
+
def description
|
44
|
+
'display authorship statistics for each repository and in total'
|
45
|
+
end
|
46
|
+
|
47
|
+
register_command :statistics
|
48
|
+
|
49
|
+
# Too close to :status?
|
50
|
+
#register_alias :stats
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def collect
|
55
|
+
log = `git log --format='<><>%ct %aN' --shortstat --all`.strip
|
56
|
+
commits = log.split('<><>').drop(1)
|
57
|
+
|
58
|
+
commits.each do |c|
|
59
|
+
lines = c.split("\n")
|
60
|
+
|
61
|
+
time = lines[0].split(' ')[0]
|
62
|
+
author = lines[0].split(' ')[1..-1].join(' ')
|
63
|
+
|
64
|
+
if lines.size >= 3
|
65
|
+
m = /changed(?:, (\d+) insertion(?:s)?\(\+\))?(?:, (\d+) deletion(?:s)?\(\-\))?/.match(lines[2])
|
66
|
+
changes = (m.captures[0] || 0).to_i + (m.captures[1] || 0).to_i
|
67
|
+
else
|
68
|
+
changes = 0
|
69
|
+
end
|
70
|
+
|
71
|
+
yield author, Time.at(time.to_i), changes
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def print_authors(data, name)
|
76
|
+
pinfo "Authorship statistics (#{name}):"
|
77
|
+
ptable (data.to_a.sort_by { |v| v[1] }.reverse), :columns => [24, nil]
|
78
|
+
end
|
79
|
+
|
80
|
+
def print_punchcard(data, name)
|
81
|
+
pinfo "Punchcard (#{name}):"
|
82
|
+
|
83
|
+
t = []
|
84
|
+
t << ['', '0-4', '4-8', '8-12', '12-16', '16-20', '20-24']
|
85
|
+
['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'].each_with_index do |day, wday|
|
86
|
+
l = [day]
|
87
|
+
6.times do |h|
|
88
|
+
if (data[wday] && data[wday][h])
|
89
|
+
l << data[wday][h].to_s
|
90
|
+
else
|
91
|
+
l << '0'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
t << l
|
95
|
+
end
|
96
|
+
|
97
|
+
ptable t
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/lib/mgit/commands/status.rb
CHANGED
@@ -4,7 +4,7 @@ module MGit
|
|
4
4
|
class StatusCommand < Command
|
5
5
|
def execute(args)
|
6
6
|
t = []
|
7
|
-
Registry.chdir_each { |repo| t << [repo.name, repo.current_branch,
|
7
|
+
Registry.chdir_each { |repo| t << [repo.name, repo.current_branch, decorate_flags(repo)] }
|
8
8
|
ptable t, :columns => [24, nil, nil]
|
9
9
|
end
|
10
10
|
|
@@ -17,7 +17,7 @@ module MGit
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def description
|
20
|
-
'display status for each
|
20
|
+
'display status for each repository'
|
21
21
|
end
|
22
22
|
|
23
23
|
register_command :status
|
@@ -25,27 +25,24 @@ module MGit
|
|
25
25
|
|
26
26
|
private
|
27
27
|
|
28
|
-
def
|
29
|
-
flags =
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
flags << 'Detached'.yellow if fs.include?(:detached)
|
28
|
+
def decorate_flags(repo)
|
29
|
+
flags = repo.flags
|
30
|
+
labels = decorate_simple_flags(flags)
|
31
|
+
labels.concat(decorate_divergence_flags(repo.divergence)) if flags.include?(:diverged)
|
32
|
+
labels = ['Clean'.green] if labels.empty?
|
33
|
+
labels.to_a.join(', ')
|
34
|
+
end
|
36
35
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
36
|
+
def decorate_simple_flags(flags)
|
37
|
+
{ :index => :red, :dirty => :red, :untracked => :yellow, :detached => :yellow }
|
38
|
+
.select { |f,_| flags.include?(f) }
|
39
|
+
.map { |f,c| f.to_s.capitalize.send(c) }
|
40
|
+
end
|
43
41
|
|
44
|
-
|
45
|
-
|
42
|
+
def decorate_divergence_flags(divergence)
|
43
|
+
divergence.map do |d|
|
44
|
+
"#{d.first[0].to_s.capitalize} of #{d.first[1][:branch]} by #{d.first[1][:by]}".blue
|
46
45
|
end
|
47
|
-
|
48
|
-
flags
|
49
46
|
end
|
50
47
|
end
|
51
48
|
end
|
data/lib/mgit/commands/tags.rb
CHANGED
data/lib/mgit/registry.rb
CHANGED
data/lib/mgit/repository.rb
CHANGED
@@ -2,6 +2,8 @@ require 'set'
|
|
2
2
|
|
3
3
|
module MGit
|
4
4
|
class Repository
|
5
|
+
include Output
|
6
|
+
|
5
7
|
attr_reader :name, :path
|
6
8
|
|
7
9
|
def initialize(name, path)
|
@@ -9,6 +11,15 @@ module MGit
|
|
9
11
|
@path = path
|
10
12
|
end
|
11
13
|
|
14
|
+
def available?
|
15
|
+
if !File.directory?(path)
|
16
|
+
pwarn "Repository #{name} is not available anymore. Failed to read #{path}."
|
17
|
+
return false
|
18
|
+
end
|
19
|
+
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
12
23
|
def current_branch
|
13
24
|
in_repo {
|
14
25
|
b = `git rev-parse --abbrev-ref HEAD 2>&1`.strip
|
data/lib/mgit/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mgit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- FlavourSys Technology GmbH
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -83,6 +83,7 @@ files:
|
|
83
83
|
- lib/mgit/commands/list.rb
|
84
84
|
- lib/mgit/commands/grep.rb
|
85
85
|
- lib/mgit/commands/remove_all.rb
|
86
|
+
- lib/mgit/commands/statistics.rb
|
86
87
|
- lib/mgit/commands/version.rb
|
87
88
|
- lib/mgit/commands/fetch.rb
|
88
89
|
- lib/mgit/commands/head.rb
|