mgit 0.4.5 → 0.4.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/mgit/appdata.rb +15 -17
- data/lib/mgit/cli.rb +2 -2
- data/lib/mgit/command.rb +6 -8
- data/lib/mgit/commands/add.rb +11 -11
- data/lib/mgit/commands/clone.rb +4 -3
- data/lib/mgit/commands/fetch.rb +6 -6
- data/lib/mgit/commands/ffmerge.rb +7 -7
- data/lib/mgit/commands/foreach.rb +3 -2
- data/lib/mgit/commands/grep.rb +1 -1
- data/lib/mgit/commands/head.rb +2 -2
- data/lib/mgit/commands/help.rb +2 -2
- data/lib/mgit/commands/list.rb +2 -2
- data/lib/mgit/commands/log.rb +2 -2
- data/lib/mgit/commands/remove.rb +4 -4
- data/lib/mgit/commands/remove_all.rb +2 -4
- data/lib/mgit/commands/show.rb +5 -5
- data/lib/mgit/commands/status.rb +6 -6
- data/lib/mgit/commands/tags.rb +8 -5
- data/lib/mgit/commands/version.rb +2 -2
- data/lib/mgit/configuration.rb +24 -23
- data/lib/mgit/output.rb +6 -6
- data/lib/mgit/registry.rb +11 -11
- data/lib/mgit/repository.rb +29 -28
- data/lib/mgit/system.rb +14 -16
- data/lib/mgit/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 701280b683790872b7dec9ba0bb84c1c8af87556
|
4
|
+
data.tar.gz: 65ecbe1775dca509ff2e49f43898bb734f25b179
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 60f46155d0bec27d85a1612c65739ac7771cf6f91279610b3a481ee2f4262e26cbf2196b0572d5a7cb6da1b8f48fbd0d2ca9d3c73d0b48dcefecdad4c7e9b5dd
|
7
|
+
data.tar.gz: ad4dcb31ff9a501b5cf09ef9102ba2ff7727a5fbbf2c7076fa4dbc3481c3386c6e5eca3c4ab488ac68517e5d876d0345637214a1abca69b8de66d37b4d7cccd0
|
data/lib/mgit/appdata.rb
CHANGED
@@ -3,7 +3,6 @@ require 'yaml'
|
|
3
3
|
|
4
4
|
module MGit
|
5
5
|
module AppData
|
6
|
-
|
7
6
|
####################
|
8
7
|
# Module interface #
|
9
8
|
####################
|
@@ -29,27 +28,26 @@ module MGit
|
|
29
28
|
#########################################
|
30
29
|
|
31
30
|
class AppDataVersion
|
32
|
-
@@versions = []
|
33
|
-
|
34
31
|
def self.inherited(version)
|
35
|
-
|
32
|
+
@versions ||= []
|
33
|
+
@versions << version.new
|
36
34
|
super
|
37
35
|
end
|
38
36
|
|
39
37
|
def self.sorted
|
40
|
-
|
38
|
+
@versions.sort_by { |v| v.version }
|
41
39
|
end
|
42
40
|
|
43
41
|
def self.updates
|
44
|
-
|
42
|
+
sorted.drop_while { |v| !v.active? }.drop(1)
|
45
43
|
end
|
46
44
|
|
47
45
|
def self.active
|
48
|
-
|
46
|
+
sorted.find { |v| v.active? }
|
49
47
|
end
|
50
48
|
|
51
49
|
def self.latest
|
52
|
-
|
50
|
+
sorted.last
|
53
51
|
end
|
54
52
|
|
55
53
|
include Comparable
|
@@ -60,7 +58,7 @@ module MGit
|
|
60
58
|
|
61
59
|
[:version, :active?, :load, :save!, :migrate!].each do |meth|
|
62
60
|
define_method(meth) do
|
63
|
-
|
61
|
+
fail ImplementationError, "AppDataVersion #{self.class.name} doesn't implement the #{meth} method."
|
64
62
|
end
|
65
63
|
end
|
66
64
|
end
|
@@ -83,17 +81,17 @@ module MGit
|
|
83
81
|
end
|
84
82
|
|
85
83
|
def load(key, default)
|
86
|
-
|
84
|
+
fail ImplementationError, "LegacyAppData::load called with unknown key #{key}." if key != :repositories
|
87
85
|
repos = YAML.load_file(repofile)
|
88
86
|
repos ? repos : default
|
89
87
|
end
|
90
88
|
|
91
89
|
def save!(key, value)
|
92
|
-
|
90
|
+
fail ImplementationError, "LegacyAppData::save! called with unknown key #{key}." if key != :repositories
|
93
91
|
File.open(repofile, 'w') { |fd| fd.write value.to_yaml }
|
94
92
|
end
|
95
93
|
|
96
|
-
|
94
|
+
private
|
97
95
|
|
98
96
|
def repofile
|
99
97
|
XDG['CONFIG_HOME'].to_path.join('mgit.yml')
|
@@ -118,7 +116,7 @@ module MGit
|
|
118
116
|
|
119
117
|
def setup!
|
120
118
|
FileUtils.mkdir_p(config_dir)
|
121
|
-
File.open(config_file, 'w') { |fd| fd.write
|
119
|
+
File.open(config_file, 'w') { |fd| fd.write({ version: '1' }.to_yaml) }
|
122
120
|
FileUtils.touch(repo_file)
|
123
121
|
end
|
124
122
|
|
@@ -129,9 +127,9 @@ module MGit
|
|
129
127
|
repos ? repos : default
|
130
128
|
when *Configuration::KEYS.keys, :version
|
131
129
|
config = YAML.load_file(config_file)
|
132
|
-
(config && config.
|
130
|
+
(config && config.key?(key)) ? config[key] : default
|
133
131
|
else
|
134
|
-
|
132
|
+
fail ImplementationError, "AppDataVersion1::load called with unknown key #{key}."
|
135
133
|
end
|
136
134
|
end
|
137
135
|
|
@@ -144,11 +142,11 @@ module MGit
|
|
144
142
|
config[key] = value
|
145
143
|
File.open(config_file, 'w') { |fd| fd.write config.to_yaml }
|
146
144
|
else
|
147
|
-
|
145
|
+
fail ImplementationError, "AppDataVersion1::save! called with unknown key #{key}."
|
148
146
|
end
|
149
147
|
end
|
150
148
|
|
151
|
-
|
149
|
+
private
|
152
150
|
|
153
151
|
def config_dir
|
154
152
|
XDG['CONFIG_HOME'].to_path.join('mgit')
|
data/lib/mgit/cli.rb
CHANGED
@@ -3,12 +3,12 @@ module MGit
|
|
3
3
|
include Output
|
4
4
|
|
5
5
|
def start
|
6
|
-
|
6
|
+
fail NoCommandError if ARGV.size == 0
|
7
7
|
|
8
8
|
MGit.init
|
9
9
|
|
10
10
|
# Run command, consuming its name from the list of arguments.
|
11
|
-
|
11
|
+
Command.execute(ARGV.shift, ARGV)
|
12
12
|
rescue UsageError => e
|
13
13
|
perror e.to_s
|
14
14
|
rescue GitError => e
|
data/lib/mgit/command.rb
CHANGED
@@ -11,7 +11,7 @@ module MGit
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def self.execute(name, args)
|
14
|
-
cmd =
|
14
|
+
cmd = create(name)
|
15
15
|
cmd.check_arity(args)
|
16
16
|
cmd.execute(args)
|
17
17
|
end
|
@@ -35,26 +35,24 @@ module MGit
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def check_arity(args)
|
38
|
-
arity_min, arity_max =
|
39
|
-
|
40
|
-
|
38
|
+
arity_min, arity_max = arity
|
39
|
+
fail TooFewArgumentsError, self if arity_min && args.size < arity_min
|
40
|
+
fail TooManyArgumentsError, self if arity_max && args.size > arity_max
|
41
41
|
end
|
42
42
|
|
43
43
|
[:arity, :usage, :help, :description].each do |meth|
|
44
44
|
define_method(meth) do
|
45
|
-
|
45
|
+
fail ImplementationError, "Command #{self.class.name} doesn't implement the #{meth} method."
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
private
|
50
|
-
|
51
49
|
def self.create(cmd)
|
52
50
|
cmd = cmd.downcase.to_sym
|
53
51
|
klass = @@commands[cmd] || @@aliases[cmd]
|
54
52
|
if klass
|
55
53
|
klass.new
|
56
54
|
else
|
57
|
-
|
55
|
+
fail UnknownCommandError, cmd
|
58
56
|
end
|
59
57
|
end
|
60
58
|
|
data/lib/mgit/commands/add.rb
CHANGED
@@ -2,13 +2,13 @@ module MGit
|
|
2
2
|
class AddCommand < Command
|
3
3
|
def execute(args)
|
4
4
|
path = File.expand_path(args[0])
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
fail CommandUsageError.new('First argument must be a path to a directory.', self) unless File.directory?(path)
|
6
|
+
fail CommandUsageError.new('First argument must be a path to a git repository.', self) unless git_dir?(path)
|
7
|
+
fail CommandUsageError.new('Sorry, mgit can not handle bare repositories.', self) if bare?(path)
|
8
8
|
|
9
9
|
name = (args.size == 2) ? args[1] : File.basename(path)
|
10
|
-
|
11
|
-
|
10
|
+
fail CommandUsageError.new("Repository named #{name} already exists with different path.", self) unless new_or_same?(name, path)
|
11
|
+
|
12
12
|
Registry.add(name, path)
|
13
13
|
end
|
14
14
|
|
@@ -26,19 +26,19 @@ module MGit
|
|
26
26
|
|
27
27
|
register_command :add
|
28
28
|
|
29
|
-
|
29
|
+
private
|
30
30
|
|
31
|
-
def
|
31
|
+
def new_or_same?(name, path)
|
32
32
|
repo = Registry.find { |r| r.name == name }
|
33
33
|
repo.nil? || repo.path == path
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
37
|
-
System
|
36
|
+
def git_dir?(path)
|
37
|
+
System.git('status', chdir: path) !~ /fatal: Not a git repository/
|
38
38
|
end
|
39
39
|
|
40
|
-
def
|
41
|
-
System
|
40
|
+
def bare?(path)
|
41
|
+
System.git('status', chdir: path) =~ /fatal: This operation must be run in a work tree/
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
data/lib/mgit/commands/clone.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
module MGit
|
2
2
|
class CloneCommand < Command
|
3
3
|
def execute(args)
|
4
|
-
log = System
|
5
|
-
|
4
|
+
log = System.git("clone #{args.join(' ')}", raise: true, print_stderr: true)
|
5
|
+
.stdout
|
6
|
+
|
6
7
|
m = /Cloning into '(.*)'/.match(log.split("\n").first)
|
7
8
|
Command.execute('add', [m[1]])
|
8
9
|
end
|
@@ -21,7 +22,7 @@ module MGit
|
|
21
22
|
|
22
23
|
register_command :clone
|
23
24
|
|
24
|
-
|
25
|
+
private
|
25
26
|
|
26
27
|
def option?(arg)
|
27
28
|
arg.start_with?('-')
|
data/lib/mgit/commands/fetch.rb
CHANGED
@@ -2,10 +2,10 @@ require 'open3'
|
|
2
2
|
|
3
3
|
module MGit
|
4
4
|
class FetchCommand < Command
|
5
|
-
def execute(
|
5
|
+
def execute(_)
|
6
6
|
thread_class = Configuration.threads ? Thread : NullThread
|
7
7
|
|
8
|
-
threads = Registry.
|
8
|
+
threads = Registry.map do |repo|
|
9
9
|
thread_class.new { fetch(repo) }
|
10
10
|
end
|
11
11
|
|
@@ -26,18 +26,18 @@ module MGit
|
|
26
26
|
|
27
27
|
register_command :fetch
|
28
28
|
|
29
|
-
|
29
|
+
private
|
30
30
|
|
31
31
|
def fetch(repo)
|
32
|
-
sc = System
|
32
|
+
sc = System.git('remote', chdir: repo.path)
|
33
33
|
|
34
|
-
|
34
|
+
unless sc.success?
|
35
35
|
perror "Failed to read remotes for repository #{repo.name}! Abort."
|
36
36
|
return
|
37
37
|
end
|
38
38
|
|
39
39
|
sc.stdout.strip.split.each do |remote|
|
40
|
-
if System
|
40
|
+
if System.git("fetch #{remote}", chdir: repo.path).success?
|
41
41
|
pinfo "Fetched #{remote} in repository #{repo.name}."
|
42
42
|
else
|
43
43
|
perror "Failed to fetch #{remote} in repository #{repo.name}! Abort."
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module MGit
|
2
2
|
class FFMergeCommand < Command
|
3
|
-
def execute(
|
3
|
+
def execute(_)
|
4
4
|
Registry.chdir_each do |repo|
|
5
5
|
branches = mergable_branches(repo)
|
6
6
|
next if branches.empty?
|
@@ -28,12 +28,12 @@ module MGit
|
|
28
28
|
|
29
29
|
register_command :ffmerge
|
30
30
|
|
31
|
-
|
31
|
+
private
|
32
32
|
|
33
33
|
def mergable_branches(repo)
|
34
34
|
repo.remote_tracking_branches.select do |branch, upstream|
|
35
35
|
!repo.unmerged_commits(branch, upstream).empty?
|
36
|
-
end.
|
36
|
+
end.keys
|
37
37
|
end
|
38
38
|
|
39
39
|
def merge_branches(repo, branches)
|
@@ -45,15 +45,15 @@ module MGit
|
|
45
45
|
branches.each { |b| merge_branch(b) }
|
46
46
|
rescue GitError
|
47
47
|
perror "Failed to merge a branch in repository #{repo.name}."
|
48
|
-
pwarn
|
48
|
+
pwarn 'Please visit this repository and check that everything\'s alright. Trying to set back to original working branch.'
|
49
49
|
ensure
|
50
|
-
System
|
50
|
+
System.git("checkout -q #{cb}", print_stderr: true)
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
54
|
def merge_branch(branch)
|
55
|
-
System
|
56
|
-
System
|
55
|
+
System.git("checkout -q #{branch}", raise: true, print_stderr: true)
|
56
|
+
System.git('merge --ff-only @{u}', raise: true, print_stderr: true)
|
57
57
|
end
|
58
58
|
end
|
59
59
|
end
|
@@ -6,9 +6,10 @@ module MGit
|
|
6
6
|
Registry.each do |repo|
|
7
7
|
pinfo "Executing command in repository #{repo.name}..."
|
8
8
|
|
9
|
-
sc = System
|
9
|
+
sc = System.run(command, chdir: repo.path, print_stdout: true, print_stderr: true)
|
10
|
+
next if sc.success?
|
10
11
|
|
11
|
-
|
12
|
+
unless agree("Executing command '#{command}' in repository '#{repo.name}' failed. Would you like to continue anyway?".red)
|
12
13
|
break
|
13
14
|
end
|
14
15
|
end
|
data/lib/mgit/commands/grep.rb
CHANGED
@@ -5,7 +5,7 @@ module MGit
|
|
5
5
|
|
6
6
|
Registry.each do |repo|
|
7
7
|
pinfo "Looking for pattern '#{ptrn}' in repository #{repo.name}..."
|
8
|
-
System
|
8
|
+
System.git("grep #{ptrn}", chdir: repo.path, print_stdout: true)
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
data/lib/mgit/commands/head.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
module MGit
|
2
2
|
class HeadCommand < Command
|
3
|
-
def execute(
|
3
|
+
def execute(_)
|
4
4
|
t = []
|
5
5
|
Registry.each { |repo| t << [repo.name, repo.current_branch, repo.current_head] }
|
6
|
-
ptable t, :
|
6
|
+
ptable t, columns: [24, nil, nil]
|
7
7
|
end
|
8
8
|
|
9
9
|
def arity
|
data/lib/mgit/commands/help.rb
CHANGED
@@ -2,9 +2,9 @@ module MGit
|
|
2
2
|
class HelpCommand < Command
|
3
3
|
def execute(args)
|
4
4
|
if args.size == 0
|
5
|
-
pinfo
|
5
|
+
pinfo 'M[eta]Git - manage multiple git repositories at the same time'
|
6
6
|
pinfo ''
|
7
|
-
pinfo
|
7
|
+
pinfo 'Usage:'
|
8
8
|
Command.instance_each do |cmd|
|
9
9
|
pinfo "mgit #{cmd.usage}"
|
10
10
|
pinfo "\t- #{cmd.description}"
|
data/lib/mgit/commands/list.rb
CHANGED
data/lib/mgit/commands/log.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
module MGit
|
2
2
|
class LogCommand < Command
|
3
|
-
def execute(
|
3
|
+
def execute(_)
|
4
4
|
Registry.chdir_each do |repo|
|
5
5
|
repo.remote_tracking_branches.each do |branch, upstream|
|
6
6
|
uc = repo.unmerged_commits(branch, upstream)
|
7
7
|
next if uc.empty?
|
8
8
|
|
9
9
|
pinfo "In repository #{repo.name}, branch #{upstream} the following commits were made:"
|
10
|
-
|
10
|
+
|
11
11
|
t = []
|
12
12
|
uc.each { |c| t << [c[:commit], c[:author], c[:subject]] }
|
13
13
|
ptable t
|
data/lib/mgit/commands/remove.rb
CHANGED
@@ -3,11 +3,11 @@ module MGit
|
|
3
3
|
def execute(args)
|
4
4
|
ptrn = args[0]
|
5
5
|
|
6
|
-
repo = Registry.find do |
|
7
|
-
|
6
|
+
repo = Registry.find do |r|
|
7
|
+
r.name == ptrn || r.path == File.expand_path(ptrn)
|
8
8
|
end
|
9
|
-
|
10
|
-
|
9
|
+
|
10
|
+
fail CommandUsageError.new("Couldn't find repository matching '#{ptrn}'.", self) unless repo
|
11
11
|
|
12
12
|
Registry.remove(repo.name)
|
13
13
|
pinfo "Removed repository #{repo.name}."
|
@@ -1,9 +1,7 @@
|
|
1
1
|
module MGit
|
2
2
|
class RemoveAllCommand < Command
|
3
|
-
def execute(
|
4
|
-
if agree('This will delete all repositories from mgit. Are you sure?'.red)
|
5
|
-
Registry.clean
|
6
|
-
end
|
3
|
+
def execute(_)
|
4
|
+
Registry.clean if agree('This will delete all repositories from mgit. Are you sure?'.red)
|
7
5
|
end
|
8
6
|
|
9
7
|
def arity
|
data/lib/mgit/commands/show.rb
CHANGED
@@ -27,24 +27,24 @@ module MGit
|
|
27
27
|
|
28
28
|
register_command :show
|
29
29
|
|
30
|
-
|
30
|
+
private
|
31
31
|
|
32
32
|
def repos
|
33
33
|
@rs || begin
|
34
34
|
@rs = []
|
35
35
|
Registry.chdir_each do |r|
|
36
|
-
@rs << r if
|
36
|
+
@rs << r if commit?
|
37
37
|
end
|
38
38
|
@rs
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
def
|
43
|
-
!(System
|
42
|
+
def commit?
|
43
|
+
!(System.git("rev-parse --quiet --verify #{@commit}").stdout.empty?)
|
44
44
|
end
|
45
45
|
|
46
46
|
def show_commit(repo)
|
47
|
-
System
|
47
|
+
System.git("show #{@commit}", chdir: repo.path, print_stdout: true)
|
48
48
|
end
|
49
49
|
|
50
50
|
def show_menu
|
data/lib/mgit/commands/status.rb
CHANGED
@@ -2,10 +2,10 @@ require 'set'
|
|
2
2
|
|
3
3
|
module MGit
|
4
4
|
class StatusCommand < Command
|
5
|
-
def execute(
|
5
|
+
def execute(_)
|
6
6
|
t = []
|
7
7
|
Registry.chdir_each { |repo| t << [repo.name, repo.current_branch, decorate_flags(repo)] }
|
8
|
-
ptable t, :
|
8
|
+
ptable t, columns: [24, nil, nil]
|
9
9
|
end
|
10
10
|
|
11
11
|
def arity
|
@@ -23,7 +23,7 @@ module MGit
|
|
23
23
|
register_command :status
|
24
24
|
register_alias :st
|
25
25
|
|
26
|
-
|
26
|
+
private
|
27
27
|
|
28
28
|
def decorate_flags(repo)
|
29
29
|
flags = repo.flags
|
@@ -34,9 +34,9 @@ module MGit
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def decorate_simple_flags(flags)
|
37
|
-
{ :
|
38
|
-
.select { |f,_| flags.include?(f) }
|
39
|
-
.map { |f,c| f.to_s.capitalize.send(c) }
|
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
40
|
end
|
41
41
|
|
42
42
|
def decorate_divergence_flags(divergence)
|
data/lib/mgit/commands/tags.rb
CHANGED
@@ -2,10 +2,10 @@ require 'open3'
|
|
2
2
|
|
3
3
|
module MGit
|
4
4
|
class TagsCommand < Command
|
5
|
-
def execute(
|
5
|
+
def execute(_)
|
6
6
|
t = []
|
7
7
|
Registry.each { |repo| t << print_latest_tag(repo) }
|
8
|
-
ptable t, :
|
8
|
+
ptable t, columns: [24, nil, nil]
|
9
9
|
end
|
10
10
|
|
11
11
|
def arity
|
@@ -22,15 +22,18 @@ module MGit
|
|
22
22
|
|
23
23
|
register_command :tags
|
24
24
|
|
25
|
-
|
25
|
+
private
|
26
26
|
|
27
27
|
def latest_tag(path)
|
28
|
-
sc = System
|
28
|
+
sc = System.git('describe --tags --abbrev=0 master', chdir: path)
|
29
29
|
sc =~ /fatal:/ ? 'none' : sc.stdout.strip
|
30
30
|
end
|
31
31
|
|
32
32
|
def latest_tag_time(path, tag)
|
33
|
-
Time.at(
|
33
|
+
Time.at(
|
34
|
+
System.git("log -n 1 --format='%at' #{tag}", chdir: path)
|
35
|
+
.stdout.strip.to_i
|
36
|
+
).strftime('%Y-%m-%d')
|
34
37
|
end
|
35
38
|
|
36
39
|
def print_latest_tag(repo)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module MGit
|
2
2
|
class VersionCommand < Command
|
3
|
-
def execute(
|
3
|
+
def execute(_)
|
4
4
|
pinfo "mgit version #{MGit::VERSION}"
|
5
5
|
end
|
6
6
|
|
@@ -16,6 +16,6 @@ module MGit
|
|
16
16
|
'display mgit version'
|
17
17
|
end
|
18
18
|
|
19
|
-
register_command :version
|
19
|
+
register_command :version
|
20
20
|
end
|
21
21
|
end
|
data/lib/mgit/configuration.rb
CHANGED
@@ -3,19 +3,19 @@ module MGit
|
|
3
3
|
extend Enumerable
|
4
4
|
|
5
5
|
KEYS = {
|
6
|
-
:
|
7
|
-
:
|
8
|
-
:
|
6
|
+
threads: {
|
7
|
+
default: true,
|
8
|
+
description: 'set to true if you want the fetch command to be threaded'
|
9
9
|
},
|
10
10
|
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
11
|
+
plugindir: {
|
12
|
+
default: File.join(AppData::AppDataVersion.latest.send(:config_dir), 'plugins'),
|
13
|
+
description: 'directory from where plugin commands are loaded'
|
14
14
|
},
|
15
15
|
|
16
|
-
:
|
17
|
-
:
|
18
|
-
:
|
16
|
+
colors: {
|
17
|
+
default: true,
|
18
|
+
description: 'set to false to disable all colored output'
|
19
19
|
}
|
20
20
|
}
|
21
21
|
|
@@ -25,11 +25,11 @@ module MGit
|
|
25
25
|
AppData.load(k, v[:default])
|
26
26
|
end
|
27
27
|
|
28
|
-
define_method("#{k
|
28
|
+
define_method("#{k}=") do |value|
|
29
29
|
AppData.save!(k, value)
|
30
30
|
end
|
31
31
|
|
32
|
-
private "#{k
|
32
|
+
private "#{k}="
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
@@ -38,35 +38,36 @@ module MGit
|
|
38
38
|
when 'threads', 'colors'
|
39
39
|
set_boolean(key, value)
|
40
40
|
when 'plugindir'
|
41
|
-
|
42
|
-
|
41
|
+
unless File.directory?(value)
|
42
|
+
fail ConfigurationError, 'Illegal value for key plugindir. Has to be a directory.'
|
43
43
|
end
|
44
44
|
self.plugindir = File.expand_path(value)
|
45
45
|
else
|
46
|
-
|
46
|
+
fail ConfigurationError, "Unknown key: #{key}."
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
50
|
def self.each
|
51
51
|
KEYS.each do |key|
|
52
|
-
yield [key.first.to_s,
|
52
|
+
yield [key.first.to_s, send(key.first).to_s]
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
def self.method_missing(meth, *
|
57
|
-
|
56
|
+
def self.method_missing(meth, *)
|
57
|
+
fail ConfigurationError, "Unknown key: #{meth}"
|
58
58
|
end
|
59
59
|
|
60
|
-
|
60
|
+
private
|
61
61
|
|
62
62
|
def self.set_boolean(key, value)
|
63
|
-
unless
|
64
|
-
|
63
|
+
unless %w( true, false, on, off ).include?(value)
|
64
|
+
fail ConfigurationError, "Illegal value for key #{key}."
|
65
65
|
end
|
66
|
-
|
67
|
-
|
66
|
+
|
67
|
+
if %w( true, on ).include?(value)
|
68
|
+
send("#{key}=", true)
|
68
69
|
else
|
69
|
-
|
70
|
+
send("#{key}=", false)
|
70
71
|
end
|
71
72
|
end
|
72
73
|
end
|
data/lib/mgit/output.rb
CHANGED
@@ -20,7 +20,7 @@ module MGit
|
|
20
20
|
print_to_screen TableOutputter.new(table, options).to_s
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
private
|
24
24
|
|
25
25
|
def print_to_screen(s)
|
26
26
|
if Configuration.colors
|
@@ -37,7 +37,7 @@ module MGit
|
|
37
37
|
@table = table
|
38
38
|
@options = options
|
39
39
|
@options[:columns] = []
|
40
|
-
|
40
|
+
fail ImplementationError, 'ptable called with invalid table' unless valid_table?
|
41
41
|
end
|
42
42
|
|
43
43
|
def to_s
|
@@ -46,7 +46,7 @@ module MGit
|
|
46
46
|
cw = column_widths
|
47
47
|
|
48
48
|
table.map do |row|
|
49
|
-
row.map.with_index do |cell, i|
|
49
|
+
row.map.with_index do |cell, i|
|
50
50
|
# Only justify the column if it is not the last one.
|
51
51
|
# This avoids too many line breaks.
|
52
52
|
i < (columns - 1) ? justify(cell, cw[i]) : cell
|
@@ -54,7 +54,7 @@ module MGit
|
|
54
54
|
end.join("\n")
|
55
55
|
end
|
56
56
|
|
57
|
-
|
57
|
+
private
|
58
58
|
|
59
59
|
def valid_table?
|
60
60
|
table.empty? || table.all? { |c| c.is_a?(Array) && c.size == table.first.size }
|
@@ -73,7 +73,7 @@ module MGit
|
|
73
73
|
end
|
74
74
|
|
75
75
|
def column_widths
|
76
|
-
column_max_widths.each_with_index.map do |c, i|
|
76
|
+
column_max_widths.each_with_index.map do |c, i|
|
77
77
|
(options[:columns].size > i && options[:columns][i]) ? options[:columns][i] : c
|
78
78
|
end
|
79
79
|
end
|
@@ -85,7 +85,7 @@ module MGit
|
|
85
85
|
end
|
86
86
|
|
87
87
|
def justify(s, n)
|
88
|
-
|
88
|
+
(s.size > n) ? (s[0..(n - 3)] + '...') : s.ljust(n, ' ')
|
89
89
|
end
|
90
90
|
end
|
91
91
|
end
|
data/lib/mgit/registry.rb
CHANGED
@@ -3,19 +3,19 @@ module MGit
|
|
3
3
|
extend Enumerable
|
4
4
|
|
5
5
|
def self.all
|
6
|
-
|
6
|
+
load.map { |name, path| Repository.new(name, path) }.sort_by(&:path)
|
7
7
|
end
|
8
8
|
|
9
9
|
def self.available
|
10
|
-
|
10
|
+
all.select(&:available?)
|
11
11
|
end
|
12
12
|
|
13
13
|
def self.each(&block)
|
14
|
-
|
14
|
+
available.each(&block)
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.chdir_each
|
18
|
-
|
18
|
+
available.select(&:available?).each do |repo|
|
19
19
|
Dir.chdir(repo.path) do
|
20
20
|
yield repo
|
21
21
|
end
|
@@ -23,26 +23,26 @@ module MGit
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def self.find(&block)
|
26
|
-
|
26
|
+
all.find(&block)
|
27
27
|
end
|
28
28
|
|
29
29
|
def self.add(name, path)
|
30
|
-
repos =
|
30
|
+
repos = load
|
31
31
|
repos[name] = path
|
32
|
-
|
32
|
+
save! repos
|
33
33
|
end
|
34
34
|
|
35
35
|
def self.remove(name)
|
36
|
-
repos =
|
36
|
+
repos = load
|
37
37
|
repos.delete name
|
38
|
-
|
38
|
+
save! repos
|
39
39
|
end
|
40
40
|
|
41
41
|
def self.clean
|
42
|
-
|
42
|
+
save!({})
|
43
43
|
end
|
44
44
|
|
45
|
-
|
45
|
+
private
|
46
46
|
|
47
47
|
def self.load
|
48
48
|
AppData.load(:repositories)
|
data/lib/mgit/repository.rb
CHANGED
@@ -12,7 +12,7 @@ module MGit
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def available?
|
15
|
-
|
15
|
+
unless File.directory?(path)
|
16
16
|
pwarn "Repository #{name} is not available anymore. Failed to read #{path}."
|
17
17
|
return false
|
18
18
|
end
|
@@ -21,71 +21,72 @@ module MGit
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def current_branch
|
24
|
-
in_repo
|
25
|
-
sc = System
|
24
|
+
in_repo do
|
25
|
+
sc = System.git('rev-parse --abbrev-ref HEAD')
|
26
26
|
sc.success? ? sc.stdout.strip : 'HEAD'
|
27
|
-
|
27
|
+
end
|
28
28
|
end
|
29
29
|
|
30
30
|
def current_head
|
31
|
-
in_repo { System
|
31
|
+
in_repo { System.git('rev-parse --verify --short HEAD').stdout.strip }
|
32
32
|
end
|
33
33
|
|
34
34
|
def remote_tracking_branches(upstream_exists_only = true)
|
35
35
|
rb = remote_branches
|
36
36
|
|
37
37
|
a = in_repo do
|
38
|
-
System
|
38
|
+
System.git("for-each-ref --format='%(refname:short) %(upstream:short)' refs/heads")
|
39
39
|
.stdout
|
40
40
|
.split("\n")
|
41
41
|
.map { |b| b.split(' ') }
|
42
42
|
.reject { |b| b.size != 2 }
|
43
43
|
.select { |b| !upstream_exists_only || rb.include?(b[1]) }
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
Hash[a]
|
47
47
|
end
|
48
48
|
|
49
49
|
def remote_branches
|
50
50
|
in_repo do
|
51
|
-
System
|
51
|
+
System.git('branch -r').stdout.split("\n").map { |a| a.split(' ')[0] }
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
55
|
def unmerged_commits(branch, upstream)
|
56
56
|
in_repo do
|
57
|
-
System
|
57
|
+
System.git("log --pretty=format:'%h#%an#%s' --reverse --relative-date #{branch}..#{upstream}")
|
58
58
|
.stdout
|
59
59
|
.split("\n")
|
60
60
|
.map { |line| line.split('#') }
|
61
|
-
.map do |words|
|
61
|
+
.map do |words|
|
62
62
|
{
|
63
|
-
:
|
64
|
-
:
|
65
|
-
:
|
63
|
+
commit: words[0],
|
64
|
+
author: words[1],
|
65
|
+
subject: words[2..-1].join('#')
|
66
66
|
}
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
+
SIMPLE_FLAGS = { 'A' => :index, 'M' => :dirty, '??' => :untracked }
|
72
|
+
|
71
73
|
def flags
|
72
74
|
flags = Set.new
|
73
75
|
status_lines do |s|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
when
|
78
|
-
flags <<
|
79
|
-
when '??'
|
80
|
-
flags << :untracked
|
76
|
+
indicator = s.split[0]
|
77
|
+
|
78
|
+
case indicator
|
79
|
+
when *SIMPLE_FLAGS.keys
|
80
|
+
flags << SIMPLE_FLAGS[indicator]
|
81
81
|
when '##'
|
82
|
-
if
|
82
|
+
if %r{## [\w,/]+\.\.\.[\w,/]+ \[.+\]} =~ s
|
83
83
|
flags << :diverged
|
84
84
|
elsif /## HEAD \(no branch\)/ =~ s
|
85
85
|
flags << :detached
|
86
86
|
end
|
87
87
|
end
|
88
88
|
end
|
89
|
+
|
89
90
|
flags
|
90
91
|
end
|
91
92
|
|
@@ -93,13 +94,13 @@ module MGit
|
|
93
94
|
divergence = []
|
94
95
|
status_lines do |s|
|
95
96
|
if s.split[0] == '##'
|
96
|
-
if(m =
|
97
|
-
divergence << { :
|
98
|
-
elsif(m =
|
97
|
+
if (m = %r{## ([\w,/]+)\.\.\.([\w,/]+) \[ahead (\d+), behind (\d+)\]}.match(s))
|
98
|
+
divergence << { ahead: { branch: m[2], by: m[3] }, behind: { branch: m[2], by: m[4] } }
|
99
|
+
elsif (m = %r{## ([\w,/]+)\.\.\.([\w,/]+) \[(\w+) (\d+)\]}.match(s))
|
99
100
|
if m[3] =~ /behind/
|
100
|
-
divergence << { :
|
101
|
+
divergence << { behind: { branch: m[2], by: m[4] } }
|
101
102
|
else
|
102
|
-
divergence << { :
|
103
|
+
divergence << { ahead: { branch: m[2], by: m[4] } }
|
103
104
|
end
|
104
105
|
end
|
105
106
|
end
|
@@ -117,10 +118,10 @@ module MGit
|
|
117
118
|
|
118
119
|
alias_method :chdir, :in_repo
|
119
120
|
|
120
|
-
|
121
|
+
private
|
121
122
|
|
122
123
|
def status
|
123
|
-
@status ||= in_repo { System
|
124
|
+
@status ||= in_repo { System.git('status --short --branch --ignore-submodules').stdout.split("\n") }
|
124
125
|
end
|
125
126
|
|
126
127
|
def status_lines
|
data/lib/mgit/system.rb
CHANGED
@@ -13,26 +13,26 @@ module MGit
|
|
13
13
|
|
14
14
|
psystem(stdout.strip) if opts[:print_stdout]
|
15
15
|
|
16
|
-
if
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
return if success?
|
17
|
+
|
18
|
+
psystem(stderr.strip) if opts[:print_stderr]
|
19
|
+
fail SystemCommandError.new(cmd, opts[:error]) if opts[:raise]
|
20
20
|
end
|
21
21
|
|
22
22
|
def success?
|
23
23
|
@st.exitstatus == 0
|
24
24
|
end
|
25
25
|
|
26
|
-
def =~(
|
27
|
-
(@stdout =~
|
26
|
+
def =~(other)
|
27
|
+
(@stdout =~ other) || (@stderr =~ other)
|
28
28
|
end
|
29
29
|
|
30
30
|
def default_options
|
31
31
|
{
|
32
|
-
:
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:
|
32
|
+
print_stdout: false,
|
33
|
+
print_stderr: false,
|
34
|
+
raise: false,
|
35
|
+
error: 'Command failed.'
|
36
36
|
}
|
37
37
|
end
|
38
38
|
|
@@ -41,7 +41,7 @@ module MGit
|
|
41
41
|
|
42
42
|
opts = Hash[
|
43
43
|
default_options.map do |k, v|
|
44
|
-
[k, popen_opts.
|
44
|
+
[k, popen_opts.key?(k) ? popen_opts.delete(k) : v]
|
45
45
|
end
|
46
46
|
]
|
47
47
|
|
@@ -51,11 +51,9 @@ module MGit
|
|
51
51
|
|
52
52
|
class GitCommand < SystemCommand
|
53
53
|
def initialize(cmd, opts)
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
raise GitError.new(e.error)
|
58
|
-
end
|
54
|
+
super("git #{cmd}", opts)
|
55
|
+
rescue SystemCommandError => e
|
56
|
+
raise GitError, e.error
|
59
57
|
end
|
60
58
|
end
|
61
59
|
|
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.4.
|
4
|
+
version: 0.4.6
|
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: 2014-
|
11
|
+
date: 2014-06-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|