update_repo 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.reek +3 -0
- data/.rubocop.yml +2 -0
- data/.travis.yml +2 -2
- data/README.md +28 -6
- data/Rakefile +13 -5
- data/lib/update_repo/helpers.rb +50 -0
- data/lib/update_repo/version.rb +1 -1
- data/lib/update_repo.rb +84 -33
- data/update_repo.gemspec +4 -2
- metadata +25 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4b02b9ed1895164abe441378e107c240e0d0884a
|
4
|
+
data.tar.gz: 4b78e9cb4620576e1cca044ee2c617b0e25bb9b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f2fc8b75b84ff8db5c18949150b3a209d6341fbfda3e07a4fc6ca3900453297425479d8d1d10bb50057579e07a35ef7eec438bc78b24d2cdbf80126a6e8abb7
|
7
|
+
data.tar.gz: 270140f7a98ba431a88a87e1c93ec191f0206ca157e058b52cfbd8a669e3ea42c444bb791c59e0273c7ba2d04e807ef144d572d04bd6400a0979f74bcce2a981
|
data/.reek
CHANGED
data/.rubocop.yml
ADDED
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -38,7 +38,22 @@ $ update_repo
|
|
38
38
|
|
39
39
|
## Configuration
|
40
40
|
#### Configuration file
|
41
|
-
|
41
|
+
The configuration file defaults to `~/.updaterepo` and is a standard [YAML](http://yaml.org/)-formatted text file. The first line must contain the YAML frontmatter of 3 dashes (`---`). After that, the following sections can follow in any order. Only the `location:` section is compulsory, and that must contain at least one entry.
|
42
|
+
|
43
|
+
`location:` - at least one directory which contains the locally cloned repository(s) to update. There is no limit on how many directories can be listed :
|
44
|
+
```yaml
|
45
|
+
---
|
46
|
+
location:
|
47
|
+
- /media/myuser/git-repos
|
48
|
+
- /data/RepoDir
|
49
|
+
```
|
50
|
+
|
51
|
+
`exceptions:` - an (optional) list of repositories that will NOT be updated automatically. Use this for repositories that need special handling, or should only be manually updated. Note that the name specified is that of the __directory__ holding the repository (has the `.git` directory inside)
|
52
|
+
```yaml
|
53
|
+
exceptions:
|
54
|
+
- ubuntu-trusty
|
55
|
+
- update_repo
|
56
|
+
```
|
42
57
|
|
43
58
|
#### Command line switches
|
44
59
|
Options are not required. If none are specified then the program will read from the standard configuration file (~/.updaterepo) and automatically update the specified Repositories.
|
@@ -47,6 +62,11 @@ Enter `update_repo --help` at the command prompt to get a list of available opti
|
|
47
62
|
```
|
48
63
|
Options:
|
49
64
|
-c, --color, --no-color Use colored output (default: true)
|
65
|
+
-d, --dump Dump a list of Directories and Git URL's to STDOUT in CSV format
|
66
|
+
-p, --prune=<i> Number of directory levels to remove from the --dump output.
|
67
|
+
Only valid when --dump or -d specified (Default: 0)
|
68
|
+
-i, --import Import a previous dump of directories and Git repository URL's,
|
69
|
+
(created using --dump) then proceed to clone them locally.
|
50
70
|
-v, --version Print version and exit
|
51
71
|
-h, --help Show this message
|
52
72
|
```
|
@@ -57,11 +77,13 @@ Not in any specific order :
|
|
57
77
|
- Improve error-checking and recovery while parsing the configuration file
|
58
78
|
* Ignore and report invalid or missing directories
|
59
79
|
- Either add an option 'variants' or similar to allow non-standard git pull commands (eg Ubuntu kernel), or update the 'exceptions' option to do same.
|
60
|
-
- Error checking and reporting for the git processes
|
80
|
+
- Error checking and reporting for the git processes `[IN PROGRESS]`
|
81
|
+
* Add more failure cases, not all git errors fail with "fatal:"
|
82
|
+
- retry for connection issues etc (config setting).
|
61
83
|
- Add extra (optional) stats / info at end-of-job :
|
62
|
-
|
63
|
-
|
64
|
-
|
84
|
+
* list of changed repos
|
85
|
+
* errors or connection problems `[IN PROGRESS]`
|
86
|
+
* _more..._
|
65
87
|
- Add command line options to override configuration, and even specify an alternate config file. Any options so specified will have precedence over settings specified in the configuration file.
|
66
88
|
- Add command line options for verbose or quiet, with same options in config file.
|
67
89
|
- Add ability to specify a new directory (containing Git repos) to search from the command line, and optionally save this to the standard configuration.
|
@@ -69,7 +91,7 @@ Not in any specific order :
|
|
69
91
|
- Add flag for 'default' repo directory (or another specific directory - if it does not already exist it will be created and added to the standard list) which will be used for new additions.
|
70
92
|
- Option to save log file for each run.
|
71
93
|
- Add option to only display a (text) tree of the discovered git repositories, not updating them; Similar option to just dump a list of the remote git locations.
|
72
|
-
- Add ability to export a text dump of each repo location and then re-import this on a different machine or after reinstall
|
94
|
+
- Add ability to export a text dump of each repo location `[DONE]` and then re-import this on a different machine or after reinstall `[TODO]`
|
73
95
|
- Document configuration file format and options.
|
74
96
|
- Add testing!
|
75
97
|
|
data/Rakefile
CHANGED
@@ -1,20 +1,28 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
2
|
require 'rspec/core/rake_task'
|
3
|
-
require 'rubocop/rake_task'
|
4
3
|
require 'inch/rake'
|
5
4
|
|
6
5
|
RSpec::Core::RakeTask.new(:spec)
|
7
6
|
|
8
|
-
|
9
|
-
|
7
|
+
# rubocop is not compatible with Ruby < 2.0
|
8
|
+
if RUBY_VERSION >= '2.0'
|
9
|
+
require 'rubocop/rake_task'
|
10
|
+
RuboCop::RakeTask.new do |task|
|
11
|
+
task.options << 'lib' << 'exe'
|
12
|
+
task.fail_on_error = false
|
13
|
+
end
|
14
|
+
else
|
15
|
+
task :rubocop do
|
16
|
+
# Empty task
|
17
|
+
end
|
10
18
|
end
|
11
19
|
|
12
20
|
Inch::Rake::Suggest.new do |suggest|
|
13
21
|
suggest.args << '--pedantic'
|
14
22
|
end
|
15
23
|
|
16
|
-
# reek is not compatible with Ruby < 2.0
|
17
|
-
if RUBY_VERSION
|
24
|
+
# reek is not compatible with Ruby < 2.0
|
25
|
+
if RUBY_VERSION >= '2.0'
|
18
26
|
require 'reek/rake/task'
|
19
27
|
Reek::Rake::Task.new do |t|
|
20
28
|
t.fail_on_error = false
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# Module 'Helpers' containing assorted helper functions required elsewhere
|
2
|
+
module Helpers
|
3
|
+
# will remove the FIRST 'how_many' root levels from a directory path 'dir'..
|
4
|
+
# @param dir [string] Path to be truncated
|
5
|
+
# @param how_many [integer] How many levels to be dropped from path.
|
6
|
+
# @return [string] the properly truncated path
|
7
|
+
def trunc_dir(dir, how_many)
|
8
|
+
# make sure we don't lose any root slash if '--prune' is NOT specified
|
9
|
+
return dir if how_many.zero?
|
10
|
+
# convert to array then lose the first 'how_many' parts
|
11
|
+
path_array = Pathname(dir).each_filename.to_a
|
12
|
+
path_array = path_array.drop(how_many)
|
13
|
+
# join it all back up again and return it
|
14
|
+
File.join(path_array)
|
15
|
+
end
|
16
|
+
|
17
|
+
# mark these as private simply so that 'reek' wont flag as utility function.
|
18
|
+
private
|
19
|
+
|
20
|
+
# true if we are dumping the file structure and git urls instead of updating.
|
21
|
+
def dumping?
|
22
|
+
param_set('dump')
|
23
|
+
end
|
24
|
+
|
25
|
+
# true if we are importing a previously dumped list of Git repos.
|
26
|
+
def importing?
|
27
|
+
param_set('import')
|
28
|
+
end
|
29
|
+
|
30
|
+
def gitdir?(dirpath)
|
31
|
+
gitpath = dirpath + '/.git'
|
32
|
+
File.exist?(gitpath) && File.directory?(gitpath)
|
33
|
+
end
|
34
|
+
|
35
|
+
def show_time(duration)
|
36
|
+
time_taken = Time.at(duration).utc
|
37
|
+
time_taken.strftime('%-H hours, %-M Minutes and %-S seconds.')
|
38
|
+
end
|
39
|
+
|
40
|
+
# we cant use --dump and --import on the same command line
|
41
|
+
def no_import_export
|
42
|
+
Trollop.die 'update_repo : Cannot specify both --dump and --import'
|
43
|
+
end
|
44
|
+
|
45
|
+
# print the specified summary metric, called from the footer.
|
46
|
+
def summary(which, color, event)
|
47
|
+
output = "#{which} #{event}"
|
48
|
+
print ' / ', output.send(color.to_sym) unless which.zero?
|
49
|
+
end
|
50
|
+
end
|
data/lib/update_repo/version.rb
CHANGED
data/lib/update_repo.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'update_repo/version'
|
2
|
+
require 'update_repo/helpers'
|
2
3
|
require 'yaml'
|
3
4
|
require 'colorize'
|
4
5
|
require 'confoog'
|
5
6
|
require 'trollop'
|
7
|
+
require 'open3'
|
6
8
|
|
7
9
|
# Overall module with classes performing the functionality
|
8
10
|
# Contains Class UpdateRepo::WalkRepo
|
@@ -14,15 +16,11 @@ module UpdateRepo
|
|
14
16
|
# repositories found therein.
|
15
17
|
# rubocop:disable Metrics/ClassLength
|
16
18
|
class WalkRepo
|
19
|
+
include Helpers
|
17
20
|
# Class constructor. No parameters required.
|
18
21
|
# @return [void]
|
19
22
|
def initialize
|
20
|
-
|
21
|
-
@counter = 0
|
22
|
-
# @skip_counter - will count all repos deliberately skipped
|
23
|
-
@skip_count = 0
|
24
|
-
# @ start_time - will be used to get elapsed time
|
25
|
-
@start_time = 0
|
23
|
+
@metrics = { count: 0, skipped: 0, failed: 0, updated: 0, start_time: 0 }
|
26
24
|
# read the options from Trollop and store in temp variable.
|
27
25
|
# we do it this way around otherwise if configuration file is missing it
|
28
26
|
# gives the error messages even on '--help' and '--version'
|
@@ -43,10 +41,15 @@ module UpdateRepo
|
|
43
41
|
# walk_repo = UpdateRepo::WalkRepo.new
|
44
42
|
# walk_repo.start
|
45
43
|
def start
|
46
|
-
String.disable_colorization = true unless
|
47
|
-
|
48
|
-
|
49
|
-
|
44
|
+
String.disable_colorization = true unless param_set('color')
|
45
|
+
no_import_export if dumping? && importing?
|
46
|
+
show_header
|
47
|
+
if importing?
|
48
|
+
|
49
|
+
else
|
50
|
+
@config['location'].each do |loc|
|
51
|
+
recurse_dir(loc)
|
52
|
+
end
|
50
53
|
end
|
51
54
|
# print out an informative footer...
|
52
55
|
footer
|
@@ -54,6 +57,12 @@ module UpdateRepo
|
|
54
57
|
|
55
58
|
private
|
56
59
|
|
60
|
+
# Determine options from the command line and configuration file. Command
|
61
|
+
# line takes precedence
|
62
|
+
def param_set(option)
|
63
|
+
@config['cmd'][option.to_sym] || @config[option]
|
64
|
+
end
|
65
|
+
|
57
66
|
def config_error
|
58
67
|
if @config.status[:errors] == Status::ERR_CANT_LOAD
|
59
68
|
print 'Note that the the default configuration file was '.red,
|
@@ -63,6 +72,7 @@ module UpdateRepo
|
|
63
72
|
end
|
64
73
|
|
65
74
|
# rubocop:disable Metrics/MethodLength
|
75
|
+
# rubocop:disable Metrics/LineLength
|
66
76
|
def set_options
|
67
77
|
Trollop.options do
|
68
78
|
version "update_repo version #{VERSION} (C)2016 G. Ramsay\n"
|
@@ -80,12 +90,16 @@ specified Repositories.
|
|
80
90
|
Options:
|
81
91
|
EOS
|
82
92
|
opt :color, 'Use colored output', default: true
|
93
|
+
opt :dump, 'Dump a list of Directories and Git URL\'s to STDOUT in CSV format', default: false
|
94
|
+
opt :prune, "Number of directory levels to remove from the --dump output.\nOnly valid when --dump or -d specified", default: 0
|
95
|
+
opt :import, "Import a previous dump of directories and Git repository URL's,\n(created using --dump) then proceed to clone them locally.", default: false
|
83
96
|
# opt :quiet, 'Only minimal output to the terminal', default: false
|
84
97
|
# opt :silent, 'Completely silent, no output to terminal at all.',
|
85
98
|
# default: false
|
86
99
|
end
|
87
100
|
end
|
88
101
|
# rubocop:enable Metrics/MethodLength
|
102
|
+
# rubocop:enable Metrics/LineLength
|
89
103
|
|
90
104
|
# take each directory contained in the Repo directory, if it is detected as
|
91
105
|
# a Git repository then update it (or as directed by command line)
|
@@ -93,7 +107,14 @@ EOS
|
|
93
107
|
def recurse_dir(dirname)
|
94
108
|
Dir.chdir(dirname) do
|
95
109
|
Dir['**/'].each do |dir|
|
96
|
-
|
110
|
+
next unless gitdir?(dir)
|
111
|
+
if dumping?
|
112
|
+
dump_repo(File.join(dirname, dir))
|
113
|
+
elsif importing?
|
114
|
+
# placeholder
|
115
|
+
else
|
116
|
+
notexception?(dir) ? update_repo(dir) : skip_repo(dir)
|
117
|
+
end
|
97
118
|
end
|
98
119
|
end
|
99
120
|
end
|
@@ -107,31 +128,45 @@ EOS
|
|
107
128
|
|
108
129
|
# Display a simple header to the console
|
109
130
|
# @example
|
110
|
-
# show_header
|
131
|
+
# show_header
|
111
132
|
# @return [void]
|
112
|
-
def show_header
|
133
|
+
def show_header
|
113
134
|
# print an informative header before starting
|
135
|
+
# unless we are dumping the repo information
|
136
|
+
return if dumping?
|
114
137
|
print "\nGit Repo update utility (v", VERSION, ')',
|
115
138
|
" \u00A9 Grant Ramsay <seapagan@gmail.com>\n"
|
116
139
|
print "Using Configuration from '#{@config.config_path}'\n"
|
140
|
+
print "Command line is : #{@config['cmd']}\n"
|
141
|
+
# list out the locations that will be searched
|
117
142
|
list_locations
|
118
|
-
|
119
|
-
|
120
|
-
exceptions.join(', ').yellow, "\n"
|
121
|
-
end
|
143
|
+
# list any exceptions that we have from the config file
|
144
|
+
list_exceptions
|
122
145
|
# save the start time for later display in the footer...
|
123
|
-
@start_time = Time.now
|
146
|
+
@metrics[:start_time] = Time.now
|
124
147
|
print "\n" # blank line before processing starts
|
125
148
|
end
|
126
149
|
|
127
150
|
# print out a brief footer. This will be expanded later.
|
128
151
|
# @return [void]
|
129
152
|
def footer
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
print
|
134
|
-
|
153
|
+
# no footer if we are dumping the repo information
|
154
|
+
return if dumping?
|
155
|
+
duration = Time.now - @metrics[:start_time]
|
156
|
+
print "\nUpdates completed : ", @metrics[:count].to_s.green,
|
157
|
+
' repositories processed'.green
|
158
|
+
summary(@metrics[:updated], 'cyan', 'updated')
|
159
|
+
summary(@metrics[:skipped], 'yellow', 'skipped')
|
160
|
+
summary(@metrics[:failed], 'red', 'failed')
|
161
|
+
print ' in ', show_time(duration).cyan, "\n\n"
|
162
|
+
end
|
163
|
+
|
164
|
+
def list_exceptions
|
165
|
+
exceptions = @config['exceptions']
|
166
|
+
if exceptions
|
167
|
+
print "\nExclusions:".underline, ' ',
|
168
|
+
exceptions.join(', ').yellow, "\n"
|
169
|
+
end
|
135
170
|
end
|
136
171
|
|
137
172
|
def list_locations
|
@@ -145,27 +180,43 @@ EOS
|
|
145
180
|
Dir.chdir(dirpath.chomp!('/')) do
|
146
181
|
repo_url = `git config remote.origin.url`.chomp
|
147
182
|
print '* Skipping ', Dir.pwd.yellow, " (#{repo_url})\n"
|
148
|
-
@
|
183
|
+
@metrics[:skipped] += 1
|
149
184
|
end
|
150
185
|
end
|
151
186
|
|
152
187
|
def update_repo(dirname)
|
153
188
|
Dir.chdir(dirname.chomp!('/')) do
|
154
189
|
repo_url = `git config remote.origin.url`.chomp
|
155
|
-
|
156
|
-
|
157
|
-
@counter += 1
|
190
|
+
do_update(repo_url)
|
191
|
+
@metrics[:count] += 1
|
158
192
|
end
|
159
193
|
end
|
160
194
|
|
161
|
-
def
|
162
|
-
|
163
|
-
|
195
|
+
def do_update(repo_url)
|
196
|
+
print '* Checking ', Dir.pwd.green, " (#{repo_url})\n"
|
197
|
+
Open3.popen3('git pull') do |_stdin, stdout, stderr, thread|
|
198
|
+
{ out: stdout, err: stderr }.each do |key, stream|
|
199
|
+
Thread.new do
|
200
|
+
until (line = stream.gets).nil?
|
201
|
+
if key == :err && line =~ /^fatal:/
|
202
|
+
print ' ', line.red
|
203
|
+
@metrics[:failed] += 1
|
204
|
+
else
|
205
|
+
print ' ', line.cyan
|
206
|
+
@metrics[:updated] += 1 if line =~ /files?\schanged/
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
thread.join
|
212
|
+
end
|
164
213
|
end
|
165
214
|
|
166
|
-
def
|
167
|
-
|
168
|
-
|
215
|
+
def dump_repo(dir)
|
216
|
+
Dir.chdir(dir.chomp!('/')) do
|
217
|
+
repo_url = `git config remote.origin.url`.chomp
|
218
|
+
print "#{trunc_dir(dir, @config['cmd'][:prune])},#{repo_url}\n"
|
219
|
+
end
|
169
220
|
end
|
170
221
|
end
|
171
222
|
end
|
data/update_repo.gemspec
CHANGED
@@ -25,8 +25,8 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
26
26
|
spec.add_development_dependency 'pry'
|
27
27
|
spec.add_development_dependency 'fakefs'
|
28
|
+
spec.add_development_dependency 'json', '= 1.8.3'
|
28
29
|
spec.add_development_dependency 'coveralls'
|
29
|
-
spec.add_development_dependency 'rubocop'
|
30
30
|
spec.add_development_dependency 'inch'
|
31
31
|
spec.add_development_dependency 'simplecov', '~> 0.10'
|
32
32
|
spec.add_development_dependency 'pullreview-coverage'
|
@@ -38,5 +38,7 @@ Gem::Specification.new do |spec|
|
|
38
38
|
spec.add_dependency 'trollop'
|
39
39
|
|
40
40
|
# Depends on Ruby version if we can use 'Reek'
|
41
|
-
spec.add_development_dependency 'reek', '~> 3.3' if RUBY_VERSION
|
41
|
+
spec.add_development_dependency 'reek', '~> 3.3' if RUBY_VERSION >= '2.0'
|
42
|
+
# Depends on Ruby version if we can use 'rubocop'
|
43
|
+
spec.add_development_dependency 'rubocop' if RUBY_VERSION >= '2.0'
|
42
44
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: update_repo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Grant Ramsay
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -81,21 +81,21 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: json
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - '='
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
89
|
+
version: 1.8.3
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - '='
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
96
|
+
version: 1.8.3
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: coveralls
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
@@ -234,6 +234,20 @@ dependencies:
|
|
234
234
|
- - "~>"
|
235
235
|
- !ruby/object:Gem::Version
|
236
236
|
version: '3.3'
|
237
|
+
- !ruby/object:Gem::Dependency
|
238
|
+
name: rubocop
|
239
|
+
requirement: !ruby/object:Gem::Requirement
|
240
|
+
requirements:
|
241
|
+
- - ">="
|
242
|
+
- !ruby/object:Gem::Version
|
243
|
+
version: '0'
|
244
|
+
type: :development
|
245
|
+
prerelease: false
|
246
|
+
version_requirements: !ruby/object:Gem::Requirement
|
247
|
+
requirements:
|
248
|
+
- - ">="
|
249
|
+
- !ruby/object:Gem::Version
|
250
|
+
version: '0'
|
237
251
|
description:
|
238
252
|
email:
|
239
253
|
- seapagan@gmail.com
|
@@ -246,6 +260,7 @@ files:
|
|
246
260
|
- ".pullreview.yml"
|
247
261
|
- ".reek"
|
248
262
|
- ".rspec"
|
263
|
+
- ".rubocop.yml"
|
249
264
|
- ".travis.yml"
|
250
265
|
- Gemfile
|
251
266
|
- LICENSE.txt
|
@@ -256,6 +271,7 @@ files:
|
|
256
271
|
- bin/update_repo
|
257
272
|
- exe/update_repo
|
258
273
|
- lib/update_repo.rb
|
274
|
+
- lib/update_repo/helpers.rb
|
259
275
|
- lib/update_repo/version.rb
|
260
276
|
- update_repo.gemspec
|
261
277
|
homepage: http://opensource.seapagan.net
|
@@ -278,9 +294,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
278
294
|
version: '0'
|
279
295
|
requirements: []
|
280
296
|
rubyforge_project:
|
281
|
-
rubygems_version: 2.6.
|
297
|
+
rubygems_version: 2.6.6
|
282
298
|
signing_key:
|
283
299
|
specification_version: 4
|
284
300
|
summary: A Simple Gem to keep multiple locally-cloned Git Repositories up to date
|
285
301
|
test_files: []
|
286
|
-
has_rdoc:
|