update_repo 0.8.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +2 -1
- data/Rakefile +1 -1
- data/lib/update_repo/cmd_config.rb +25 -8
- data/lib/update_repo/helpers.rb +2 -0
- data/lib/update_repo/version.rb +1 -1
- data/lib/update_repo.rb +90 -21
- data/update_repo.gemspec +2 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b68ac5a08795af79e528b813aa2e74fe628a816f
|
4
|
+
data.tar.gz: 5efdbb27dc053c02f4bfb76dcfd2f353b7f3b290
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 47348f246c0c6e179da7e689f2fb1b35ffacf3e0da72b2b798c1536815fce3d50d6f2859565ecd9bec06bfb9aba7a20a9f1839c08dcf10d5ca28c389b13ccce2
|
7
|
+
data.tar.gz: ddc661515526cbc5414deb1de0f8bb5f6eaea8057c6efba573b743a5e94c95231cefdf64efc8288a8285f188c60a4d87a17d1726dd974578432ac1b1e6da08aa
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -101,6 +101,7 @@ Add functionality, not in any specific order :
|
|
101
101
|
- 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.
|
102
102
|
- Improve the stats / info at end-of-job :
|
103
103
|
* errors or connection problems `[IN PROGRESS]`
|
104
|
+
* List the skipped / failed repos. Later make this dependant on 'verbose' status.
|
104
105
|
* _more..._
|
105
106
|
- 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. `[IN PROGRESS]`
|
106
107
|
- Add command line options for verbose or quiet, with same options in config file.
|
@@ -110,7 +111,7 @@ Add functionality, not in any specific order :
|
|
110
111
|
- Add option to only display a (text) tree of the discovered git repositories, not updating them.
|
111
112
|
- Add Import & Export functionality :
|
112
113
|
* ability to export a text dump of each repo location and remote as a CSV file. `[DONE]`
|
113
|
-
* re-import the above dump on a different machine or after reinstall
|
114
|
+
* re-import the above dump on a different machine or after reinstall. Modify the '--prune' command to apply to this function also, removing the required number of directory levels before importing.
|
114
115
|
- Add option to use alternative git command if required, either globally or on a case-by-case basis (see also comments on 'variants' above). Currently the script just uses a blanket `git pull` command on all repositories.
|
115
116
|
- Document configuration file format and options. `[IN PROGRESS]`
|
116
117
|
|
data/Rakefile
CHANGED
@@ -26,13 +26,18 @@ module UpdateRepo
|
|
26
26
|
end
|
27
27
|
|
28
28
|
# return the configuration hash variable
|
29
|
+
# @param [none]
|
30
|
+
# @return [Class] Returns the base 'confoog' class to the caller.
|
31
|
+
# @example
|
32
|
+
# @config = @cmd.getconfig
|
29
33
|
def getconfig
|
30
34
|
@conf
|
31
35
|
end
|
32
36
|
|
33
37
|
# This will return the 'true' version of a command, taking into account
|
34
38
|
# both command line (given preference) and the configuration file.
|
35
|
-
#
|
39
|
+
# @param command [symbol] The symbol of the defined command
|
40
|
+
# @return [various] Returns the true value of the comamnd symbol
|
36
41
|
def true_cmd(command)
|
37
42
|
cmd_given = @conf['cmd'][(command.to_s + '_given').to_sym]
|
38
43
|
cmd_line = @conf['cmd'][command.to_sym]
|
@@ -49,18 +54,26 @@ module UpdateRepo
|
|
49
54
|
end
|
50
55
|
end
|
51
56
|
|
52
|
-
#
|
57
|
+
# rubocop:disable Metrics/LineLength
|
58
|
+
# make sure the parameter combinations are valid, terminating otherwise.
|
59
|
+
# @param [none]
|
60
|
+
# @return [void]
|
53
61
|
def check_params
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
62
|
+
return unless true_cmd(:dump)
|
63
|
+
# if true_cmd(:import)
|
64
|
+
Trollop.die 'You cannot use --dump AND --import'.red if true_cmd(:import)
|
65
|
+
# end
|
66
|
+
# if true_cmd(:dump_remote)
|
67
|
+
Trollop.die 'You cannot use --dump AND --dump-remote'.red if true_cmd(:dump_remote)
|
68
|
+
# end
|
60
69
|
end
|
70
|
+
# rubocop:enable Metrics/LineLength
|
61
71
|
|
62
72
|
private
|
63
73
|
|
74
|
+
# terminate if we cannot load the configuration file for any reason.
|
75
|
+
# @param [none]
|
76
|
+
# @return [integer] exit code 1
|
64
77
|
def config_error
|
65
78
|
if @conf.status[:errors] == Status::ERR_CANT_LOAD
|
66
79
|
print_log 'Note that the the default configuration file was '.red,
|
@@ -69,6 +82,9 @@ module UpdateRepo
|
|
69
82
|
exit 1
|
70
83
|
end
|
71
84
|
|
85
|
+
# Set up the Trollop options and banner
|
86
|
+
# @param [none]
|
87
|
+
# @return [void]
|
72
88
|
# rubocop:disable Metrics/MethodLength
|
73
89
|
# rubocop:disable Metrics/LineLength
|
74
90
|
def set_options
|
@@ -94,6 +110,7 @@ EOS
|
|
94
110
|
opt :log, "Create a logfile of all program output to './update_repo.log'. Any older logs will be overwritten.", default: false
|
95
111
|
opt :timestamp, 'Timestamp the logfile instead of overwriting. Does nothing unless the --log option is also specified.', default: false
|
96
112
|
opt :dump_remote, 'Create a dump to screen or log listing all the git remote URLS found in the specified directories.', default: false, short: 'r'
|
113
|
+
opt :dump_tree, 'Create a dump to screen or log listing all subdirectories found below the specified locations in tree format.', default: false, short: 'u'
|
97
114
|
# opt :quiet, 'Only minimal output to the terminal', default: false
|
98
115
|
# opt :silent, 'Completely silent, no output to terminal at all.', default: false
|
99
116
|
end
|
data/lib/update_repo/helpers.rb
CHANGED
@@ -16,6 +16,8 @@ module Helpers
|
|
16
16
|
|
17
17
|
# this function will simply pass the given string to 'print', and also
|
18
18
|
# log to file if that is specified.
|
19
|
+
# @param string [array] Array of strings for print formatting
|
20
|
+
# @return [void]
|
19
21
|
def print_log(*string)
|
20
22
|
# log to screen regardless
|
21
23
|
print(*string)
|
data/lib/update_repo/version.rb
CHANGED
data/lib/update_repo.rb
CHANGED
@@ -22,7 +22,7 @@ module UpdateRepo
|
|
22
22
|
# @return [void]
|
23
23
|
def initialize
|
24
24
|
@metrics = { processed: 0, skipped: 0, failed: 0, updated: 0,
|
25
|
-
start_time: 0 }
|
25
|
+
start_time: 0, failed_list: [] }
|
26
26
|
@summary = { processed: 'green', updated: 'cyan', skipped: 'yellow',
|
27
27
|
failed: 'red' }
|
28
28
|
# create a new instance of the CmdConfig class then read the config var
|
@@ -38,28 +38,44 @@ module UpdateRepo
|
|
38
38
|
def start
|
39
39
|
String.disable_colorization = !cmd(:color)
|
40
40
|
# make sure we dont have bad cmd-line parameter combinations ...
|
41
|
-
@cmd.check_params
|
41
|
+
@cmd.check_params # TODO - check this since is already called in @cmd.init
|
42
42
|
# print out our header unless we are dumping / importing ...
|
43
|
-
|
44
|
-
show_header unless no_header
|
43
|
+
show_header unless dumping?
|
45
44
|
config['location'].each do |loc|
|
46
|
-
recurse_dir(loc)
|
45
|
+
cmd(:dump_tree) ? dump_tree(File.join(loc)) : recurse_dir(loc)
|
47
46
|
end
|
48
47
|
# print out an informative footer unless dump / import ...
|
49
|
-
footer unless
|
48
|
+
footer unless dumping?
|
50
49
|
end
|
51
50
|
|
52
|
-
|
51
|
+
private
|
52
|
+
|
53
|
+
def dumping?
|
54
|
+
cmd(:dump) || cmd(:dump_remote) || cmd(:dump_tree)
|
55
|
+
end
|
53
56
|
|
54
57
|
# returns the Confoog class which can then be used to access any config var
|
58
|
+
# @return [void]
|
59
|
+
# @param [none]
|
55
60
|
def config
|
56
61
|
@cmd.getconfig
|
57
62
|
end
|
58
63
|
|
64
|
+
# Return the true value of the specified configuration parameter. This is a
|
65
|
+
# helper function that simply calls the 'true_cmd' function in the @cmd
|
66
|
+
# class
|
67
|
+
# @param command [symbol] The defined command symbol that is to be returned
|
68
|
+
# @return [various] The value of the requested command option
|
69
|
+
# @example
|
70
|
+
# logging = cmd(:log)
|
59
71
|
def cmd(command)
|
60
72
|
@cmd.true_cmd(command.to_sym)
|
61
73
|
end
|
62
74
|
|
75
|
+
# Set up the log file - determine if we need to timestamp the filename and
|
76
|
+
# then actually open it and set to sync.
|
77
|
+
# @param [none]
|
78
|
+
# @return [void]
|
63
79
|
def setup_logfile
|
64
80
|
filename = if cmd(:timestamp)
|
65
81
|
'updaterepo-' + Time.new.strftime('%y%m%d-%H%M%S') + '.log'
|
@@ -72,12 +88,13 @@ module UpdateRepo
|
|
72
88
|
|
73
89
|
# take each directory contained in the Repo directory, if it is detected as
|
74
90
|
# a Git repository then update it (or as directed by command line)
|
75
|
-
# @param dirname [string] Contains the directory to search for Git repos.
|
91
|
+
# @param dirname [string] Contains the directory to search for Git repos.]
|
92
|
+
# @return [void]
|
76
93
|
def recurse_dir(dirname)
|
77
94
|
Dir.chdir(dirname) do
|
78
95
|
Dir['**/'].each do |dir|
|
79
96
|
next unless gitdir?(dir)
|
80
|
-
if
|
97
|
+
if dumping?
|
81
98
|
dump_repo(File.join(dirname, dir))
|
82
99
|
else
|
83
100
|
notexception?(dir) ? update_repo(dir) : skip_repo(dir)
|
@@ -97,12 +114,13 @@ module UpdateRepo
|
|
97
114
|
# @example
|
98
115
|
# show_header
|
99
116
|
# @return [void]
|
117
|
+
# @param [none]
|
100
118
|
def show_header
|
101
119
|
# print an informative header before starting
|
102
120
|
print_log "\nGit Repo update utility (v", VERSION, ')',
|
103
121
|
" \u00A9 Grant Ramsay <seapagan@gmail.com>\n"
|
104
122
|
print_log "Using Configuration from '#{config.config_path}'\n"
|
105
|
-
print_log "Command line is : #{config['cmd']}\n"
|
123
|
+
# print_log "Command line is : #{config['cmd']}\n"
|
106
124
|
# list out the locations that will be searched
|
107
125
|
list_locations
|
108
126
|
# list any exceptions that we have from the config file
|
@@ -114,31 +132,49 @@ module UpdateRepo
|
|
114
132
|
|
115
133
|
# print out a brief footer. This will be expanded later.
|
116
134
|
# @return [void]
|
135
|
+
# @param [none]
|
117
136
|
def footer
|
118
137
|
duration = Time.now - @metrics[:start_time]
|
119
138
|
print_log "\nUpdates completed in ", show_time(duration).cyan
|
120
139
|
print_metrics
|
121
|
-
print_log "
|
140
|
+
print_log " \n\n"
|
122
141
|
# close the log file now as we are done, just to be sure ...
|
123
142
|
@logfile.close if @logfile
|
124
143
|
end
|
125
144
|
|
145
|
+
# Print end-of-run metrics to console / log
|
146
|
+
# @return [void]
|
147
|
+
# @param [none]
|
126
148
|
def print_metrics
|
127
149
|
@summary.each do |metric, color|
|
128
150
|
metric_value = @metrics[metric]
|
129
151
|
output = "#{metric_value} #{metric.capitalize}"
|
130
152
|
print_log ' | ', output.send(color.to_sym) unless metric_value.zero?
|
131
153
|
end
|
154
|
+
print_log ' |'
|
155
|
+
return if @metrics[:failed_list].empty?
|
156
|
+
print_log "\n\n!! Note : The following repositories ",
|
157
|
+
'FAILED'.red.underline, ' during this run :'
|
158
|
+
@metrics[:failed_list].each do |failed|
|
159
|
+
print_log "\n [", 'x'.red, "] #{failed}"
|
160
|
+
end
|
132
161
|
end
|
133
162
|
|
163
|
+
# Print a list of any defined expections that will not be updated.
|
164
|
+
# @return [void]
|
165
|
+
# @param [none]
|
134
166
|
def list_exceptions
|
135
167
|
exceptions = config['exceptions']
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
168
|
+
return unless exceptions
|
169
|
+
# if exceptions
|
170
|
+
print_log "\nExclusions:".underline, ' ',
|
171
|
+
exceptions.join(', ').yellow, "\n"
|
172
|
+
# end
|
140
173
|
end
|
141
174
|
|
175
|
+
# Print a list of all top-level directories that will be searched and any
|
176
|
+
# Git repos contained within updated.
|
177
|
+
# @return [void]
|
142
178
|
def list_locations
|
143
179
|
print_log "\nRepo location(s):\n".underline
|
144
180
|
config['location'].each do |loc|
|
@@ -146,6 +182,12 @@ module UpdateRepo
|
|
146
182
|
end
|
147
183
|
end
|
148
184
|
|
185
|
+
# Takes the specified Repo and does not update it, outputing a note to the
|
186
|
+
# console / log to this effect.
|
187
|
+
# @param dirpath [string] The directory with Git repository to be skipped
|
188
|
+
# @return [void]
|
189
|
+
# @example
|
190
|
+
# skip_repo('/Repo/Personal/work-in-progress')
|
149
191
|
def skip_repo(dirpath)
|
150
192
|
Dir.chdir(dirpath.chomp!('/')) do
|
151
193
|
repo_url = `git config remote.origin.url`.chomp
|
@@ -154,30 +196,49 @@ module UpdateRepo
|
|
154
196
|
end
|
155
197
|
end
|
156
198
|
|
199
|
+
# Takes the specified Repo outputs information and the repo URL then calls
|
200
|
+
# #do_update to actually update it.
|
201
|
+
# @param dirname [string] The directory that will be updated
|
202
|
+
# @return [void]
|
203
|
+
# @example
|
204
|
+
# update_repo('/Repo/linux/stable')
|
157
205
|
def update_repo(dirname)
|
158
206
|
Dir.chdir(dirname.chomp!('/')) do
|
159
|
-
repo_url = `git config remote.origin.url`.chomp
|
160
|
-
do_update
|
207
|
+
# repo_url = `git config remote.origin.url`.chomp
|
208
|
+
do_update
|
161
209
|
@metrics[:processed] += 1
|
162
210
|
end
|
163
211
|
end
|
164
212
|
|
165
|
-
|
213
|
+
# Actually perform the update of this specific repository, calling the
|
214
|
+
# function #do_threads to handle the output to screen and log.
|
215
|
+
# @param none
|
216
|
+
# @return [void]
|
217
|
+
def do_update
|
218
|
+
repo_url = `git config remote.origin.url`.chomp
|
166
219
|
print_log '* Checking ', Dir.pwd.green, " (#{repo_url})\n"
|
167
220
|
Open3.popen3('git pull') do |stdin, stdout, stderr, thread|
|
168
221
|
stdin.close
|
169
|
-
do_threads(stdout, stderr)
|
222
|
+
do_threads(stdout, stderr, repo_url)
|
170
223
|
thread.join
|
171
224
|
end
|
172
225
|
end
|
173
226
|
|
174
|
-
|
227
|
+
# Create 2 individual threads to handle both STDOUT and STDERR streams,
|
228
|
+
# writing to console and log if specified.
|
229
|
+
# @param stdout [stream] STDOUT Stream from the popen3 call
|
230
|
+
# @param stderr [stream] STDERR Stream from the popen3 call
|
231
|
+
# @param repo_url [string] URL of the associated repository
|
232
|
+
# @return [void]
|
233
|
+
def do_threads(stdout, stderr, repo_url)
|
175
234
|
{ out: stdout, err: stderr }.each do |key, stream|
|
176
235
|
Thread.new do
|
177
236
|
while (line = stream.gets)
|
178
|
-
if key == :err && line =~ /^fatal:/
|
237
|
+
if key == :err && line =~ /^fatal:|^error:/
|
179
238
|
print_log ' ', line.red
|
180
239
|
@metrics[:failed] += 1
|
240
|
+
fullpath = Dir.pwd.red
|
241
|
+
@metrics[:failed_list].push("#{fullpath} (#{repo_url})")
|
181
242
|
else
|
182
243
|
print_log ' ', line.cyan
|
183
244
|
@metrics[:updated] += 1 if line =~ %r{^From\s(?:https?|git)://}
|
@@ -189,6 +250,8 @@ module UpdateRepo
|
|
189
250
|
|
190
251
|
# this function will either dump out a CSV with the directory and remote,
|
191
252
|
# or just the remote depending if we called --dump or --dump-remote
|
253
|
+
# @param dir [string] The local directory for the repository
|
254
|
+
# @return [void]
|
192
255
|
def dump_repo(dir)
|
193
256
|
Dir.chdir(dir.chomp!('/')) do
|
194
257
|
repo_url = `git config remote.origin.url`.chomp
|
@@ -196,5 +259,11 @@ module UpdateRepo
|
|
196
259
|
print_log "#{repo_url}\n"
|
197
260
|
end
|
198
261
|
end
|
262
|
+
|
263
|
+
# This function will recurse though all the subdirectories of the specified
|
264
|
+
# directory and print only the directory name in a tree format.
|
265
|
+
def dump_tree(dir)
|
266
|
+
print "here for #{dir}\n"
|
267
|
+
end
|
199
268
|
end
|
200
269
|
end
|
data/update_repo.gemspec
CHANGED
@@ -37,6 +37,8 @@ Gem::Specification.new do |spec|
|
|
37
37
|
spec.add_dependency 'colorize'
|
38
38
|
spec.add_dependency 'confoog'
|
39
39
|
spec.add_dependency 'trollop'
|
40
|
+
# on Ruby 1.9.3 we lock the 'term-ansicolor' gem to very 1.3.2
|
41
|
+
spec.add_dependency 'term-ansicolor', '= 1.3.2' if RUBY_VERSION < '2.0'
|
40
42
|
|
41
43
|
# Depends on Ruby version if we can use 'Reek'
|
42
44
|
spec.add_development_dependency 'reek', '~> 3.3' if RUBY_VERSION >= '2.0'
|
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.8.
|
4
|
+
version: 0.8.1
|
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-08
|
11
|
+
date: 2016-10-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -314,3 +314,4 @@ signing_key:
|
|
314
314
|
specification_version: 4
|
315
315
|
summary: A Simple Gem to keep multiple locally-cloned Git Repositories up to date
|
316
316
|
test_files: []
|
317
|
+
has_rdoc:
|