mgit 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4447be436da4ce6283adfef2ca2e65f522715644
4
- data.tar.gz: 2b898725657dea57e19a3a28a7ec0691007fa234
3
+ metadata.gz: 8174b6f645364ef888f498ffa24274882cf9dd39
4
+ data.tar.gz: b6752daa7ac077dae28c7c46a47785e05b5b430a
5
5
  SHA512:
6
- metadata.gz: d1deafe5dfa39f02dbc3b2c9be66fe5830acb45c628fb7be70a27c32685d28f59efdd18c8b89e91427f27472cb05d5d7892389503014c08be01e59f3fed2e12d
7
- data.tar.gz: bf2c584feefe6d708e5f04ed660132f836322ad89e874a51ac5a4fe4babfe294c4e7e74352044e8658e79b0da78100866b47d61f31d01f2512cc2569b0f7f178
6
+ metadata.gz: b4d6463d5a85e932aaa3d575b5c440b2a1b13f352a2efc3a2e366afe6cc81ac782ab66a2efb60e4cf62ddafaa21fdc3cb1d02ef3cc8ee8dc5fc7c85f52f2d671
7
+ data.tar.gz: fbc6b246c055889649963d7b06d1f82618068d8f27817af27aa6a03394b2ae3fd0f99bc13a912e7d70997b76a9a1f359cc5879df31f114e33d84befdfadd4799
@@ -1,12 +1,31 @@
1
+ require 'open3'
2
+
1
3
  module MGit
2
4
  class FetchCommand < Command
3
5
  def execute(args)
4
- Registry.chdir_each do |repo|
5
- `git remote`.split.each do |remote|
6
- pinfo "Fetching #{remote} in repository #{repo.name}..."
7
- `git fetch #{remote}`
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
@@ -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, flags(repo).to_a.join(', ')] }
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 repositories'
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 flags(repo)
29
- flags = []
30
-
31
- fs = repo.flags
32
- flags << 'Index'.red if fs.include?(:index)
33
- flags << 'Dirty'.red if fs.include?(:dirty)
34
- flags << 'Untracked'.yellow if fs.include?(:untracked)
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
- if fs.include?(:diverged)
38
- ds = repo.divergence
39
- ds.each do |d|
40
- flags << "#{d.first[0].to_s.capitalize} of #{d.first[1][:branch]} by #{d.first[1][:by]}".blue
41
- end
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
- if flags.empty?
45
- flags << 'Clean'.green
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
@@ -3,7 +3,7 @@ module MGit
3
3
  def execute(args)
4
4
  t = []
5
5
  Registry.chdir_each { |repo| t << [repo.name, *latest_tag] }
6
- ptable t, :columns => [24, nil]
6
+ ptable t, :columns => [24, nil, nil]
7
7
  end
8
8
 
9
9
  def arity
data/lib/mgit/registry.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module MGit
2
2
  module Registry
3
3
  def self.all
4
- self.load.map { |name, path| Repository.new(name, path) }.sort_by(&:path)
4
+ self.load.map { |name, path| Repository.new(name, path) }.sort_by(&:path).select(&:available?)
5
5
  end
6
6
 
7
7
  def self.each(&block)
@@ -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
@@ -1,3 +1,3 @@
1
1
  module MGit
2
- VERSION = '0.3.2'
2
+ VERSION = '0.3.3'
3
3
  end
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.2
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: 2013-12-10 00:00:00.000000000 Z
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