mgit 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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: []