mgit 0.4.5 → 0.4.6
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 +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
|