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 +15 -0
- data/lib/mgit.rb +1 -0
- data/lib/mgit/commands/add.rb +1 -1
- data/lib/mgit/commands/fetch.rb +2 -2
- data/lib/mgit/commands/ffmerge.rb +48 -0
- data/lib/mgit/commands/foreach.rb +3 -3
- data/lib/mgit/commands/grep.rb +2 -2
- data/lib/mgit/commands/list.rb +4 -2
- data/lib/mgit/commands/log.rb +56 -0
- data/lib/mgit/commands/remove.rb +2 -2
- data/lib/mgit/commands/status.rb +20 -19
- data/lib/mgit/registry.rb +51 -0
- data/lib/mgit/repository.rb +50 -37
- data/lib/mgit/version.rb +1 -1
- metadata +7 -10
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
data/lib/mgit/commands/add.rb
CHANGED
data/lib/mgit/commands/fetch.rb
CHANGED
@@ -3,9 +3,9 @@ module MGit
|
|
3
3
|
def execute(args)
|
4
4
|
raise TooManyArgumentsError.new(self) if args.size != 0
|
5
5
|
|
6
|
-
|
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
|
-
|
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
|
data/lib/mgit/commands/grep.rb
CHANGED
@@ -6,8 +6,8 @@ module MGit
|
|
6
6
|
|
7
7
|
ptrn = args[0]
|
8
8
|
|
9
|
-
|
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
|
data/lib/mgit/commands/list.rb
CHANGED
@@ -3,8 +3,10 @@ module MGit
|
|
3
3
|
def execute(args)
|
4
4
|
raise TooManyArgumentsError.new(self) if args.size != 0
|
5
5
|
|
6
|
-
|
7
|
-
|
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
|
data/lib/mgit/commands/remove.rb
CHANGED
@@ -6,8 +6,8 @@ module MGit
|
|
6
6
|
|
7
7
|
ptrn = args[0]
|
8
8
|
|
9
|
-
repo =
|
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
|
data/lib/mgit/commands/status.rb
CHANGED
@@ -5,10 +5,10 @@ module MGit
|
|
5
5
|
def execute(args)
|
6
6
|
raise TooManyArgumentsError.new(self) if args.size != 0
|
7
7
|
|
8
|
-
|
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 =
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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?
|
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
|
data/lib/mgit/repository.rb
CHANGED
@@ -1,47 +1,60 @@
|
|
1
|
-
require '
|
1
|
+
require 'set'
|
2
2
|
|
3
3
|
module MGit
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
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.
|
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.
|
87
|
+
rubygems_version: 2.1.10
|
91
88
|
signing_key:
|
92
|
-
specification_version:
|
89
|
+
specification_version: 4
|
93
90
|
summary: MGit meta repository tool
|
94
91
|
test_files: []
|