mgit 0.1.0 → 0.1.1

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 ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YTg0NzVjMDFlNDEzNjNjZGE0ZjQ3ZGZhNGFlZjA0MDUxZGNlMDZmNw==
5
+ data.tar.gz: !binary |-
6
+ NGYxNWRlMjA4NTJiYjk5MTUwOWRkOThmYzEwMWFmMjNlYmQ3MDJmNQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MjNlM2NiZjExMzQ5MzdjMWEzZTAxZDFmYmVmNDQ0YmQyZjk2ZjQ3ZmMyY2Yz
10
+ ODYyYWQzZTM4OTk3NjhlMjUwZDZiYmJkNDg0MDIyMTc2ZWQ0OTQwNGFkMjE4
11
+ ZjI3M2Y0YmJmNDU3OTg1NmJkYWYzY2VmYTQxZGNkMDkzODA4Yjg=
12
+ data.tar.gz: !binary |-
13
+ ZTQyMGI2ZjNmZjY5ZDRlNzA3YTQxMzkwOWJmZmFjNjNmNGM2MDc5Y2RkNmZl
14
+ ZGNmN2JkNmUyZTcyYjQ1YmJmMzI2YzA0MGY2NDIzMWZlNmVkYThkMTE2M2Rl
15
+ ZWFlN2QyMzEzMmZiY2I0NmUzYWY3NjJhMDA2ODBjMGI3YjdmYTE=
data/lib/mgit.rb CHANGED
@@ -3,6 +3,7 @@ require 'highline/import'
3
3
 
4
4
  require 'mgit/version'
5
5
  require 'mgit/exceptions'
6
+ require 'mgit/registry'
6
7
  require 'mgit/repository'
7
8
 
8
9
  require 'mgit/cli'
@@ -9,7 +9,7 @@ module MGit
9
9
 
10
10
  name = (args.size == 2) ? args[1] : (ask('Name of the repository? ') { |q| q.default = File.basename(path) })
11
11
 
12
- Repository.add(name, path)
12
+ Registry.add(name, path)
13
13
  end
14
14
 
15
15
  def usage
@@ -3,9 +3,9 @@ module MGit
3
3
  def execute(args)
4
4
  raise TooManyArgumentsError.new(self) if args.size != 0
5
5
 
6
- Repository.chdir_each do |name, path|
6
+ Registry.chdir_each do |repo|
7
7
  `git remote`.split.each do |remote|
8
- puts "Fetching #{remote} in repository #{name}...".yellow
8
+ puts "Fetching #{remote} in repository #{repo.name}...".yellow
9
9
  `git fetch #{remote}`
10
10
  end
11
11
  end
@@ -0,0 +1,48 @@
1
+ module MGit
2
+ class FFMergeCommand < Command
3
+ def execute(args)
4
+ raise TooManyArgumentsError.new(self) if args.size != 0
5
+
6
+ Registry.chdir_each do |repo|
7
+ if repo.dirty?
8
+ puts "Skipping repository #{repo.name} since it's dirty.".red
9
+ next
10
+ end
11
+
12
+ puts "Fast-forward merging branches in repository #{repo.name}...".yellow
13
+
14
+ tb = tracking_branches
15
+ cb = current_branch
16
+ tb.each do |b|
17
+ `git checkout -q #{b}`
18
+ `git merge --ff-only @{u}`
19
+ end
20
+ `git checkout -q #{cb}`
21
+ end
22
+ end
23
+
24
+ def usage
25
+ 'ffmerge'
26
+ end
27
+
28
+ def description
29
+ 'merge all upstream tracking branches that can be fast-forwarded'
30
+ end
31
+
32
+ register_command :ffmerge
33
+
34
+ private
35
+
36
+ def tracking_branches
37
+ `git for-each-ref --format='%(refname:short) %(upstream:short)' refs/heads`.
38
+ split("\n").
39
+ map { |b| b.split(' ') }.
40
+ reject { |b| b.size != 2 }.
41
+ map(&:first)
42
+ end
43
+
44
+ def current_branch
45
+ `git rev-parse --abbrev-ref HEAD`
46
+ end
47
+ end
48
+ end
@@ -5,9 +5,9 @@ module MGit
5
5
 
6
6
  command = args.join(' ')
7
7
 
8
- Repository.chdir_each do |name, path|
9
- puts "Executing command in repository #{name}...".yellow
10
- if !system(command) && !ask("Executing command '#{command}' in repository '#{name}' failed. Would you like to continue anyway?".red)
8
+ Registry.chdir_each do |repo|
9
+ puts "Executing command in repository #{repo.name}...".yellow
10
+ if !system(command) && !ask("Executing command '#{command}' in repository '#{repo.name}' failed. Would you like to continue anyway?".red)
11
11
  break
12
12
  end
13
13
  end
@@ -6,8 +6,8 @@ module MGit
6
6
 
7
7
  ptrn = args[0]
8
8
 
9
- Repository.chdir_each do |name, path|
10
- puts "Looking for pattern '#{ptrn}' in repository #{name}...".yellow
9
+ Registry.chdir_each do |repo|
10
+ puts "Looking for pattern '#{ptrn}' in repository #{repo.name}...".yellow
11
11
  puts `git grep #{ptrn}`
12
12
  puts
13
13
  end
@@ -3,8 +3,10 @@ module MGit
3
3
  def execute(args)
4
4
  raise TooManyArgumentsError.new(self) if args.size != 0
5
5
 
6
- Repository.each do |name, path|
7
- puts "#{name} => #{path}"
6
+ Registry.each do |repo|
7
+ nc = 24
8
+ display = (repo.name.size > nc) ? (repo.name[0..(nc - 3)] + '...') : repo.name.ljust(nc, ' ')
9
+ puts "#{display} => #{repo.path}"
8
10
  end
9
11
  end
10
12
 
@@ -0,0 +1,56 @@
1
+ module MGit
2
+ class LogCommand < Command
3
+ def execute(args)
4
+ raise TooManyArgumentsError.new(self) if args.size > 1
5
+
6
+ days = 1
7
+
8
+ if args.size == 1
9
+ begin
10
+ days = Integer(args[0])
11
+ rescue ArgumentError => e
12
+ raise new CommandUsageError("First argument must be an integer", self)
13
+ end
14
+ end
15
+
16
+ Registry.chdir_each do |repo|
17
+ lc = latest_commits(days)#.sort_by { |c| c[:author] }
18
+ next if lc.empty?
19
+
20
+ puts "In repository #{repo.name} the following commits were made:".yellow
21
+
22
+ longest_name = lc.map { |c| c[:author].size }.max
23
+
24
+ lc.each do |c|
25
+ puts "#{c[:commit]} #{c[:author].ljust(longest_name, ' ')} #{c[:subject]}"
26
+ end
27
+ puts
28
+ end
29
+ end
30
+
31
+ def usage
32
+ 'log [number_of_days]'
33
+ end
34
+
35
+ def description
36
+ 'what happened since *n* days ago'
37
+ end
38
+
39
+ register_command :log
40
+
41
+ private
42
+
43
+ def latest_commits(days)
44
+ `git log --pretty=format:"%h#%an#%s" --reverse --all --since=#{days}.days.ago --relative-date`.
45
+ split("\n").
46
+ map { |line| line.split('#') }.
47
+ map do |words|
48
+ {
49
+ :commit => words[0],
50
+ :author => words[1],
51
+ :subject => words[2..-1].join('#')
52
+ }
53
+ end
54
+ end
55
+ end
56
+ end
@@ -6,8 +6,8 @@ module MGit
6
6
 
7
7
  ptrn = args[0]
8
8
 
9
- repo = Repository.find do |name, path|
10
- name == ptrn || path == File.expand_path(ptrn)
9
+ repo = Registry.find do |repo|
10
+ repo.name == ptrn || repo.path == File.expand_path(ptrn)
11
11
  end
12
12
 
13
13
  raise CommandUsageError.new("Couldn't find repository matching '#{ptrn}'.", self) unless repo
@@ -5,10 +5,10 @@ module MGit
5
5
  def execute(args)
6
6
  raise TooManyArgumentsError.new(self) if args.size != 0
7
7
 
8
- Repository.chdir_each do |name, path|
8
+ Registry.chdir_each do |repo|
9
9
  nc = 36
10
- display = (name.size > nc) ? (name[0..(nc - 3)] + '...') : name.ljust(nc, ' ')
11
- puts "#{display} => [#{flags.to_a.join(', ')}]"
10
+ display = (repo.name.size > nc) ? (repo.name[0..(nc - 3)] + '...') : repo.name.ljust(nc, ' ')
11
+ puts "#{display} => [#{flags(repo).to_a.join(', ')}]"
12
12
  end
13
13
  end
14
14
 
@@ -25,25 +25,26 @@ module MGit
25
25
 
26
26
  private
27
27
 
28
- def flags
29
- flags = Set.new
30
- status = `git status --short --branch --ignore-submodules`.split("\n")
31
- status.each do |s|
32
- case s.split[0]
33
- when 'A'
34
- flags << 'Index'.red
35
- when 'M'
36
- flags << 'Dirty'.red
37
- when '??'
38
- flags << 'Untracked'.yellow
39
- when '##'
40
- if(m = /## ([\w,\/]+)\.\.\.([\w,\/]+) \[(\w+) (\d+)\]/.match(s))
41
- flags << "#{m[3].capitalize} of #{m[2]} by #{m[4]}".blue
42
- end
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
+
36
+ if fs.include?(:diverged)
37
+ ds = repo.divergence
38
+ ds.each do |d|
39
+ flags << "#{d.first[0].to_s.capitalize} of #{d.first[1][:branch]} by #{d.first[1][:by]}".blue
43
40
  end
44
41
  end
45
42
 
46
- flags.empty? ? ['Clean'.green] : flags
43
+ if flags.empty?
44
+ flags << 'Clean'.green
45
+ end
46
+
47
+ flags
47
48
  end
48
49
  end
49
50
  end
@@ -0,0 +1,51 @@
1
+ require 'yaml'
2
+
3
+ module MGit
4
+ module Registry
5
+ def self.all
6
+ self.load.map { |name, path| Repository.new(name, path) }
7
+ end
8
+
9
+ def self.each(&block)
10
+ self.all.each(&block)
11
+ end
12
+
13
+ def self.chdir_each
14
+ self.all.each do |repo|
15
+ Dir.chdir(repo.path) do
16
+ yield repo
17
+ end
18
+ end
19
+ end
20
+
21
+ def self.find(&block)
22
+ self.all.find(&block)
23
+ end
24
+
25
+ def self.add(name, path)
26
+ repos = self.load
27
+ repos[name] = path
28
+ self.save! repos
29
+ end
30
+
31
+ def self.remove(name)
32
+ repos = self.load
33
+ repos.delete name
34
+ self.save! repos
35
+ end
36
+
37
+ private
38
+
39
+ def self.repofile
40
+ File.join(Dir.home, '.config/mgit.yml')
41
+ end
42
+
43
+ def self.load
44
+ File.exists?(self.repofile) ? YAML.load_file(self.repofile) : {}
45
+ end
46
+
47
+ def self.save!(repos)
48
+ File.open(self.repofile, 'w') { |fd| fd.write repos.to_yaml }
49
+ end
50
+ end
51
+ end
@@ -1,47 +1,60 @@
1
- require 'yaml'
1
+ require 'set'
2
2
 
3
3
  module MGit
4
- module Repository
5
- def self.all
6
- File.exists?(self.repofile) ? YAML.load_file(self.repofile) : {}
7
- end
8
-
9
- def self.each(&block)
10
- self.all.each(&block)
11
- end
12
-
13
- def self.chdir_each
14
- self.all.each do |name, path|
15
- Dir.chdir(path) do
16
- yield name, path
4
+ class Repository
5
+ attr_reader :name, :path
6
+
7
+ def initialize(name, path)
8
+ @name = name
9
+ @path = path
10
+ end
11
+
12
+ def dirty?
13
+ [:index, :dirty, :untracked].any? { |f| flags.include?(f) }
14
+ end
15
+
16
+ def flags
17
+ flags = Set.new
18
+ status_lines do |s|
19
+ case s.split[0]
20
+ when 'A'
21
+ flags << :index
22
+ when 'M'
23
+ flags << :dirty
24
+ when '??'
25
+ flags << :untracked
26
+ when '##'
27
+ flags << :diverged
17
28
  end
18
29
  end
19
- end
20
-
21
- def self.find(&block)
22
- self.all.find(&block)
23
- end
24
-
25
- def self.add(name, path)
26
- repos = self.all
27
- repos[name] = path
28
- self.save! repos
29
- end
30
-
31
- def self.remove(name)
32
- repos = self.all
33
- repos.delete name
34
- self.save! repos
30
+ flags
31
+ end
32
+
33
+ def divergence
34
+ divergence = []
35
+ status_lines do |s|
36
+ if s.split[0] == '##'
37
+ if(m = /## ([\w,\/]+)\.\.\.([\w,\/]+) \[(\w+) (\d+)\]/.match(s))
38
+ if m[3] =~ /behind/
39
+ divergence << { :behind => { :branch => m[2], :by => m[4] } }
40
+ else
41
+ divergence << { :ahead => { :branch => m[2], :by => m[4] } }
42
+ end
43
+ end
44
+ end
45
+ end
46
+ divergence
35
47
  end
36
48
 
37
49
  private
38
-
39
- def self.repofile
40
- File.join(Dir.home, '.config/mgit.yml')
41
- end
42
-
43
- def self.save!(repos)
44
- File.open(self.repofile, 'w') { |fd| fd.write repos.to_yaml }
50
+
51
+ def status_lines
52
+ Dir.chdir(path) do
53
+ status = `git status --short --branch --ignore-submodules`.split("\n")
54
+ status.each do |s|
55
+ yield s
56
+ end
57
+ end
45
58
  end
46
59
  end
47
60
  end
data/lib/mgit/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module MGit
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'
3
3
  end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mgit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
5
- prerelease:
4
+ version: 0.1.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - FlavourSys Technology GmbH
@@ -14,7 +13,6 @@ dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: colorize
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ! '>='
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ! '>='
28
25
  - !ruby/object:Gem::Version
@@ -30,7 +27,6 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: highline
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ! '>='
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ! '>='
44
39
  - !ruby/object:Gem::Version
@@ -59,36 +54,38 @@ files:
59
54
  - lib/mgit/commands/foreach.rb
60
55
  - lib/mgit/commands/remove.rb
61
56
  - lib/mgit/commands/fetch.rb
57
+ - lib/mgit/commands/log.rb
62
58
  - lib/mgit/commands/grep.rb
59
+ - lib/mgit/commands/ffmerge.rb
63
60
  - lib/mgit/commands/version.rb
64
61
  - lib/mgit/commands/status.rb
65
62
  - lib/mgit/repository.rb
63
+ - lib/mgit/registry.rb
66
64
  - lib/mgit/version.rb
67
65
  - lib/mgit.rb
68
66
  - bin/mgit
69
67
  homepage: http://github.com/flavoursys/mgit
70
68
  licenses:
71
69
  - MIT
70
+ metadata: {}
72
71
  post_install_message:
73
72
  rdoc_options: []
74
73
  require_paths:
75
74
  - lib
76
75
  required_ruby_version: !ruby/object:Gem::Requirement
77
- none: false
78
76
  requirements:
79
77
  - - ! '>='
80
78
  - !ruby/object:Gem::Version
81
79
  version: '0'
82
80
  required_rubygems_version: !ruby/object:Gem::Requirement
83
- none: false
84
81
  requirements:
85
82
  - - ! '>='
86
83
  - !ruby/object:Gem::Version
87
84
  version: '0'
88
85
  requirements: []
89
86
  rubyforge_project:
90
- rubygems_version: 1.8.23
87
+ rubygems_version: 2.1.10
91
88
  signing_key:
92
- specification_version: 3
89
+ specification_version: 4
93
90
  summary: MGit meta repository tool
94
91
  test_files: []