ohloh_scm 4.0.4 → 5.0.0
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/.rubocop.yml +14 -3
- data/.ruby-version +1 -1
- data/Dockerfile +8 -8
- data/Gemfile +1 -1
- data/Gemfile.lock +48 -33
- data/lib/ohloh_scm/activity.rb +1 -1
- data/lib/ohloh_scm/bzr/activity.rb +12 -12
- data/lib/ohloh_scm/bzr/validation.rb +1 -1
- data/lib/ohloh_scm/commit.rb +2 -4
- data/lib/ohloh_scm/core.rb +2 -1
- data/lib/ohloh_scm/cvs/activity.rb +74 -60
- data/lib/ohloh_scm/cvs/scm.rb +12 -12
- data/lib/ohloh_scm/cvs/status.rb +1 -1
- data/lib/ohloh_scm/cvs/validation.rb +5 -5
- data/lib/ohloh_scm/diff.rb +1 -1
- data/lib/ohloh_scm/factory.rb +7 -1
- data/lib/ohloh_scm/git/activity.rb +111 -55
- data/lib/ohloh_scm/git/scm.rb +6 -8
- data/lib/ohloh_scm/git/status.rb +1 -1
- data/lib/ohloh_scm/git/validation.rb +1 -1
- data/lib/ohloh_scm/git_svn/activity.rb +5 -5
- data/lib/ohloh_scm/git_svn/scm.rb +5 -5
- data/lib/ohloh_scm/hg/activity.rb +13 -13
- data/lib/ohloh_scm/hg/scm.rb +3 -3
- data/lib/ohloh_scm/hg/validation.rb +1 -1
- data/lib/ohloh_scm/parser/branch_number.rb +7 -6
- data/lib/ohloh_scm/parser/bzr_xml_parser.rb +15 -15
- data/lib/ohloh_scm/parser/cvs_parser.rb +7 -6
- data/lib/ohloh_scm/parser/git_parser.rb +18 -15
- data/lib/ohloh_scm/parser/hg_parser.rb +8 -6
- data/lib/ohloh_scm/parser/svn_parser.rb +7 -6
- data/lib/ohloh_scm/py_bridge/hg_client.rb +1 -1
- data/lib/ohloh_scm/svn/activity.rb +17 -18
- data/lib/ohloh_scm/svn/scm.rb +4 -6
- data/lib/ohloh_scm/svn/validation.rb +2 -2
- data/lib/ohloh_scm/system.rb +1 -1
- data/lib/ohloh_scm/validation.rb +4 -6
- data/lib/ohloh_scm/version.rb +1 -1
- data/ohloh_scm.gemspec +5 -5
- data/security.md +30 -0
- data/spec/.rubocop.yml +2 -5
- data/spec/benchmarks/process_spawn_benchmark.rb +1 -1
- data/spec/helpers/assert_scm_attr_helper.rb +4 -4
- data/spec/helpers/generic_helper.rb +2 -2
- data/spec/helpers/repository_helper.rb +1 -1
- data/spec/ohloh_scm/activity_spec.rb +2 -2
- data/spec/ohloh_scm/bzr/activity_spec.rb +60 -60
- data/spec/ohloh_scm/bzr/validation_spec.rb +1 -1
- data/spec/ohloh_scm/cvs/activity_spec.rb +20 -21
- data/spec/ohloh_scm/cvs/scm_spec.rb +36 -36
- data/spec/ohloh_scm/cvs/validation_spec.rb +4 -4
- data/spec/ohloh_scm/factory_spec.rb +2 -2
- data/spec/ohloh_scm/git/activity_spec.rb +111 -110
- data/spec/ohloh_scm/git/scm_spec.rb +11 -11
- data/spec/ohloh_scm/git/status_spec.rb +3 -3
- data/spec/ohloh_scm/git/validation_spec.rb +7 -7
- data/spec/ohloh_scm/git_svn/activity_spec.rb +14 -14
- data/spec/ohloh_scm/git_svn/scm_spec.rb +1 -1
- data/spec/ohloh_scm/hg/activity_spec.rb +99 -99
- data/spec/ohloh_scm/hg/scm_spec.rb +5 -5
- data/spec/ohloh_scm/hg/validation_spec.rb +1 -1
- data/spec/ohloh_scm/parser/array_writer_spec.rb +7 -7
- data/spec/ohloh_scm/parser/branch_number_spec.rb +3 -3
- data/spec/ohloh_scm/parser/cvs_parser_spec.rb +31 -31
- data/spec/ohloh_scm/parser/git_parser_spec.rb +29 -32
- data/spec/ohloh_scm/parser/hg_parser_spec.rb +60 -60
- data/spec/ohloh_scm/svn/activity_spec.rb +11 -12
- data/spec/ohloh_scm/svn/scm_spec.rb +24 -24
- data/spec/ohloh_scm/svn/validation_spec.rb +6 -6
- data/spec/ohloh_scm/svn_parser_spec.rb +29 -29
- data/spec/ohloh_scm/system_spec.rb +5 -5
- data/spec/ohloh_scm/version_spec.rb +1 -1
- data/spec/string_encoder_spec.rb +4 -4
- metadata +8 -81
data/lib/ohloh_scm/factory.rb
CHANGED
@@ -4,7 +4,13 @@ module OhlohScm
|
|
4
4
|
module Factory
|
5
5
|
module_function
|
6
6
|
|
7
|
-
def get_core(
|
7
|
+
def get_core(opts = {})
|
8
|
+
scm_type = opts.fetch(:scm_type, :git)
|
9
|
+
url = opts.fetch(:url) { raise ArgumentError, 'URL is required' }
|
10
|
+
branch_name = opts[:branch_name]
|
11
|
+
username = opts[:username]
|
12
|
+
password = opts[:password]
|
13
|
+
|
8
14
|
OhlohScm::Core.new(scm_type, url, branch_name, username, password)
|
9
15
|
end
|
10
16
|
end
|
@@ -10,7 +10,7 @@ module OhlohScm
|
|
10
10
|
return [] if no_tags?
|
11
11
|
|
12
12
|
flags = "--format='%(creatordate:iso-strict) %(objectname) %(refname)'"
|
13
|
-
tag_strings = run("cd #{url} && git tag #{flags} | sed 's/refs\\/tags\\///'").split(
|
13
|
+
tag_strings = run("cd #{url} && git tag #{flags} | sed 's/refs\\/tags\\///'").split("\n")
|
14
14
|
tag_strings.map do |tag_string|
|
15
15
|
timestamp_string, commit_hash, tag_name = tag_string.split(/\s/)
|
16
16
|
[tag_name, dereferenced_sha(tag_name) || commit_hash, time_object(timestamp_string)]
|
@@ -42,39 +42,16 @@ module OhlohScm
|
|
42
42
|
|
43
43
|
# Yields each commit in the repository following the commit with SHA1 'after'.
|
44
44
|
# These commits are populated with diffs.
|
45
|
-
def each_commit(opts = {})
|
46
|
-
# Bug fix (hack) follows.
|
47
|
-
#
|
48
|
-
# git-whatchanged emits a merge commit multiple times, once for each parent, giving the
|
49
|
-
# delta to each parent in turn.
|
50
|
-
#
|
51
|
-
# This causes us to emit too many commits, with repeated merge commits.
|
52
|
-
#
|
53
|
-
# To fix this, we track the previous commit, and emit a new commit only if it is distinct
|
54
|
-
# from the previous.
|
55
|
-
#
|
56
|
-
# This means that the diffs for a merge commit yielded by this method will be the diffs
|
57
|
-
# vs. the first parent only, and diffs vs. other parents are lost.
|
58
|
-
# For OpenHub, this is fine because OpenHub ignores merge diffs anyway.
|
59
|
-
previous = nil
|
45
|
+
def each_commit(opts = {}, &block)
|
60
46
|
safe_open_log_file(opts) do |io|
|
61
|
-
|
62
|
-
io.each do |commit_sha|
|
63
|
-
yield verbose_commit(commit_sha.chomp)
|
64
|
-
end
|
65
|
-
else
|
66
|
-
OhlohScm::GitParser.parse(io) do |e|
|
67
|
-
yield fixup_null_merge(e) unless previous && previous.token == e.token
|
68
|
-
previous = e
|
69
|
-
end
|
70
|
-
end
|
47
|
+
process_commits(io, opts, &block)
|
71
48
|
end
|
72
49
|
end
|
73
50
|
|
74
51
|
# Returns a single commit, including its diffs
|
75
52
|
def verbose_commit(token)
|
76
|
-
cmd = "cd '#{url}' && #{OhlohScm::GitParser.whatchanged} #{token}"\
|
77
|
-
"
|
53
|
+
cmd = "cd '#{url}' && #{OhlohScm::GitParser.whatchanged} #{token} " \
|
54
|
+
"| #{string_encoder_path}"
|
78
55
|
commit = OhlohScm::GitParser.parse(run(cmd)).first
|
79
56
|
fixup_null_merge(commit)
|
80
57
|
end
|
@@ -118,7 +95,7 @@ module OhlohScm
|
|
118
95
|
|
119
96
|
def branches
|
120
97
|
cmd = "cd '#{url}' && git branch | #{string_encoder_path}"
|
121
|
-
run(cmd).split.
|
98
|
+
run(cmd).split.grep(/\b(.+)$/)
|
122
99
|
end
|
123
100
|
|
124
101
|
# Commit all changes in the working directory, using metadata from the passed commit.
|
@@ -159,6 +136,35 @@ module OhlohScm
|
|
159
136
|
|
160
137
|
private
|
161
138
|
|
139
|
+
def process_commits(io, opts, &block)
|
140
|
+
return process_expensive_commits(io, opts, &block) if expensive_commits?(opts)
|
141
|
+
|
142
|
+
process_standard_commits(io, &block)
|
143
|
+
end
|
144
|
+
|
145
|
+
def expensive_commits?(opts)
|
146
|
+
ENV.fetch('EXPENSIVE_COMMIT_COUNT',
|
147
|
+
nil) && commit_count(opts) > ENV['EXPENSIVE_COMMIT_COUNT'].to_i
|
148
|
+
end
|
149
|
+
|
150
|
+
def process_expensive_commits(io, _opts)
|
151
|
+
io.each do |commit_sha|
|
152
|
+
yield verbose_commit(commit_sha.chomp)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def process_standard_commits(io)
|
157
|
+
previous = nil
|
158
|
+
OhlohScm::GitParser.parse(io) do |e|
|
159
|
+
yield fixup_null_merge(e) unless duplicate_commit?(previous, e)
|
160
|
+
previous = e
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def duplicate_commit?(previous, current)
|
165
|
+
previous && previous.token == current.token
|
166
|
+
end
|
167
|
+
|
162
168
|
def cat(sha1)
|
163
169
|
return '' if sha1 == NULL_SHA1
|
164
170
|
|
@@ -175,24 +181,50 @@ module OhlohScm
|
|
175
181
|
run("cd #{url} && git cat-file commit #{token} | grep '^tree' | cut -d ' ' -f 2").strip
|
176
182
|
end
|
177
183
|
|
178
|
-
def safe_open_log_file(opts = {})
|
184
|
+
def safe_open_log_file(opts = {}, &block)
|
179
185
|
return '' unless status.branch?
|
180
186
|
return '' if opts[:after] && opts[:after] == head_token
|
181
187
|
|
182
|
-
open_log_file(opts)
|
188
|
+
open_log_file(opts, &block)
|
183
189
|
end
|
184
190
|
|
185
|
-
def open_log_file(opts)
|
186
|
-
|
187
|
-
|
188
|
-
else
|
189
|
-
cmd = "#{rev_list_command(opts)} | xargs -n 1 #{OhlohScm::GitParser.whatchanged}"\
|
190
|
-
" | #{string_encoder_path} > #{log_filename}"
|
191
|
-
end
|
192
|
-
run(cmd)
|
193
|
-
File.open(log_filename, 'r') { |io| yield io }
|
191
|
+
def open_log_file(opts, &block)
|
192
|
+
prepare_log_file(opts)
|
193
|
+
process_log_file(&block)
|
194
194
|
ensure
|
195
|
-
|
195
|
+
cleanup_log_file
|
196
|
+
end
|
197
|
+
|
198
|
+
def prepare_log_file(opts)
|
199
|
+
cmd = select_log_command(opts)
|
200
|
+
run(cmd)
|
201
|
+
end
|
202
|
+
|
203
|
+
def select_log_command(opts)
|
204
|
+
return expensive_log_command(opts) if expensive_commits?(opts)
|
205
|
+
|
206
|
+
standard_log_command(opts)
|
207
|
+
end
|
208
|
+
|
209
|
+
def expensive_commit_processing?(expensive_count, opts)
|
210
|
+
expensive_count && commit_count(opts) > expensive_count.to_i
|
211
|
+
end
|
212
|
+
|
213
|
+
def expensive_log_command(opts)
|
214
|
+
"#{rev_list_command(opts)} > #{log_filename}"
|
215
|
+
end
|
216
|
+
|
217
|
+
def standard_log_command(opts)
|
218
|
+
"#{rev_list_command(opts)} | xargs -n 1 #{OhlohScm::GitParser.whatchanged} " \
|
219
|
+
"| #{string_encoder_path} > #{log_filename}"
|
220
|
+
end
|
221
|
+
|
222
|
+
def process_log_file(&block)
|
223
|
+
File.open(log_filename, 'r', &block)
|
224
|
+
end
|
225
|
+
|
226
|
+
def cleanup_log_file
|
227
|
+
FileUtils.rm_f(log_filename)
|
196
228
|
end
|
197
229
|
|
198
230
|
def rev_list_command(opts = {})
|
@@ -216,8 +248,8 @@ module OhlohScm
|
|
216
248
|
|
217
249
|
def dereferenced_tag_strings
|
218
250
|
# Pattern: b6e9220c3cabe53a4ed7f32952aeaeb8a822603d refs/tags/v1.0.0^{}
|
219
|
-
run("cd #{url} && git show-ref --tags -d | grep '\\^{}' | sed 's/\\^{}//'"\
|
220
|
-
|
251
|
+
run("cd #{url} && git show-ref --tags -d | grep '\\^{}' | sed 's/\\^{}//' " \
|
252
|
+
"| sed 's/refs\\/tags\\///'").split("\n")
|
221
253
|
end
|
222
254
|
|
223
255
|
def time_object(timestamp_string)
|
@@ -239,30 +271,54 @@ module OhlohScm
|
|
239
271
|
# This is a one-off fix for DrJava, which includes some escape characters
|
240
272
|
# in one of its Subversion messages. This might lead to a more generalized
|
241
273
|
# cleanup of message text, but for now...
|
242
|
-
commit.message = commit.message&.gsub(
|
274
|
+
commit.message = commit.message&.gsub('\\027', '')
|
243
275
|
|
244
276
|
# Git requires a non-empty message
|
245
277
|
commit.message = '[no message]' if commit.message.nil? || commit.message =~ /\A\s*\z/
|
246
278
|
|
247
279
|
# We need to store the message in a file in case it contains crazy characters
|
248
280
|
# that would corrupt a bash command line.
|
249
|
-
File.
|
250
|
-
f.write commit.message
|
251
|
-
end
|
281
|
+
File.write(message_filename, commit.message)
|
252
282
|
message_filename
|
253
283
|
end
|
254
284
|
|
255
285
|
def configure_git_environment_variables(commit)
|
256
|
-
|
257
|
-
|
286
|
+
configure_committer_details(commit)
|
287
|
+
configure_author_details(commit)
|
288
|
+
configure_commit_dates(commit)
|
289
|
+
end
|
258
290
|
|
259
|
-
|
260
|
-
ENV['
|
291
|
+
def configure_committer_details(commit)
|
292
|
+
ENV['GIT_COMMITTER_NAME'] = fallback_committer_name(commit)
|
293
|
+
ENV['GIT_COMMITTER_EMAIL'] = fallback_committer_email(commit)
|
294
|
+
end
|
295
|
+
|
296
|
+
def configure_author_details(commit)
|
297
|
+
ENV['GIT_AUTHOR_NAME'] = fallback_author_name(commit)
|
298
|
+
ENV['GIT_AUTHOR_EMAIL'] = fallback_author_email(commit)
|
299
|
+
end
|
261
300
|
|
301
|
+
def configure_commit_dates(commit)
|
262
302
|
ENV['GIT_COMMITTER_DATE'] = commit.committer_date.to_s
|
263
303
|
ENV['GIT_AUTHOR_DATE'] = (commit.author_date || commit.committer_date).to_s
|
264
304
|
end
|
265
305
|
|
306
|
+
def fallback_committer_name(commit)
|
307
|
+
commit.committer_name || '[anonymous]'
|
308
|
+
end
|
309
|
+
|
310
|
+
def fallback_committer_email(commit)
|
311
|
+
commit.committer_email || ENV.fetch('GIT_COMMITTER_NAME', nil)
|
312
|
+
end
|
313
|
+
|
314
|
+
def fallback_author_name(commit)
|
315
|
+
commit.author_name || ENV.fetch('GIT_COMMITTER_NAME', nil)
|
316
|
+
end
|
317
|
+
|
318
|
+
def fallback_author_email(commit)
|
319
|
+
commit.author_email || ENV.fetch('GIT_AUTHOR_NAME', nil)
|
320
|
+
end
|
321
|
+
|
266
322
|
# By hiding the message file inside the .git directory, we
|
267
323
|
# avoid it being found by the commit-all.
|
268
324
|
def message_filename
|
@@ -271,7 +327,7 @@ module OhlohScm
|
|
271
327
|
|
272
328
|
# True if there are pending changes to commit.
|
273
329
|
def anything_to_commit?
|
274
|
-
|
330
|
+
!/nothing to commit/.match?(run("cd '#{url}' && git status | tail -1"))
|
275
331
|
end
|
276
332
|
|
277
333
|
# Ensures that the repository directory exists, and that the git db has been initialized.
|
@@ -295,6 +351,7 @@ module OhlohScm
|
|
295
351
|
end
|
296
352
|
end
|
297
353
|
|
354
|
+
# rubocop:disable Lint/LiteralAsCondition
|
298
355
|
def check_if_ignored(gitignore_filename, filespec)
|
299
356
|
File.open(gitignore_filename, File::CREAT | File::RDONLY) do |io|
|
300
357
|
io.readlines.each do |l|
|
@@ -302,6 +359,7 @@ module OhlohScm
|
|
302
359
|
end
|
303
360
|
end
|
304
361
|
end
|
362
|
+
# rubocop:enable Lint/LiteralAsCondition
|
305
363
|
|
306
364
|
def token_filename
|
307
365
|
'ohloh_token'
|
@@ -316,9 +374,7 @@ module OhlohScm
|
|
316
374
|
def write_token(token)
|
317
375
|
return unless token && !token.to_s.empty?
|
318
376
|
|
319
|
-
File.
|
320
|
-
f.write token.to_s
|
321
|
-
end
|
377
|
+
File.write(token_path, token.to_s)
|
322
378
|
end
|
323
379
|
end
|
324
380
|
end
|
data/lib/ohloh_scm/git/scm.rb
CHANGED
@@ -47,8 +47,8 @@ module OhlohScm
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def fetch_new_commits(remote_scm)
|
50
|
-
run "cd '#{url}' && git fetch --tags --force --update-head-ok "\
|
51
|
-
|
50
|
+
run "cd '#{url}' && git fetch --tags --force --update-head-ok " \
|
51
|
+
"'#{remote_scm.url}' #{branch_name}:#{branch_name}"
|
52
52
|
end
|
53
53
|
|
54
54
|
def clone_and_create_tracking_branch(remote_scm)
|
@@ -61,7 +61,6 @@ module OhlohScm
|
|
61
61
|
end
|
62
62
|
|
63
63
|
# We need very high reliability and this sequence gets the job done every time.
|
64
|
-
# rubocop:disable Metrics/AbcSize
|
65
64
|
def clean_and_checkout_branch
|
66
65
|
return unless status.scm_dir_exist?
|
67
66
|
|
@@ -72,13 +71,12 @@ module OhlohScm
|
|
72
71
|
run "cd '#{url}' && git checkout #{branch_name} --"
|
73
72
|
run "cd '#{url}' && git reset --hard heads/#{branch_name} --"
|
74
73
|
end
|
75
|
-
# rubocop:enable Metrics/AbcSize
|
76
74
|
|
77
75
|
def create_tracking_branch(branch_name)
|
78
76
|
return if branch_name.to_s.empty?
|
79
77
|
return if activity.branches.include?(branch_name)
|
80
78
|
|
81
|
-
run("cd '#{url}' && git remote update && "\
|
79
|
+
run("cd '#{url}' && git remote update && " \
|
82
80
|
"git branch -f #{branch_name} origin/#{branch_name}")
|
83
81
|
end
|
84
82
|
|
@@ -86,9 +84,9 @@ module OhlohScm
|
|
86
84
|
def clean_up_disk
|
87
85
|
return unless Dir.exist?(url)
|
88
86
|
|
89
|
-
run "cd #{url} && "\
|
90
|
-
|
91
|
-
|
87
|
+
run "cd #{url} && " \
|
88
|
+
"find . -maxdepth 1 -not -name .git -not -name '*.nfs*' -not -name . -print0 " \
|
89
|
+
'| xargs -0 rm -rf --'
|
92
90
|
end
|
93
91
|
|
94
92
|
def convert_to_git(remote_scm, callback)
|
data/lib/ohloh_scm/git/status.rb
CHANGED
@@ -23,8 +23,8 @@ module OhlohScm
|
|
23
23
|
git_svn_log(cmd: cmd, oneline: false).split.map(&:to_i)
|
24
24
|
end
|
25
25
|
|
26
|
-
def each_commit(opts = {})
|
27
|
-
commits(opts).each
|
26
|
+
def each_commit(opts = {}, &block)
|
27
|
+
commits(opts).each(&block)
|
28
28
|
end
|
29
29
|
|
30
30
|
def head_token
|
@@ -46,14 +46,14 @@ module OhlohScm
|
|
46
46
|
|
47
47
|
private
|
48
48
|
|
49
|
-
def open_log_file(opts = {})
|
49
|
+
def open_log_file(opts = {}, &block)
|
50
50
|
cmd = "-v #{after_revision(opts)} | #{string_encoder_path} > #{log_filename}"
|
51
51
|
git_svn_log(cmd: cmd, oneline: false)
|
52
|
-
File.open(log_filename, 'r')
|
52
|
+
File.open(log_filename, 'r', &block)
|
53
53
|
end
|
54
54
|
|
55
55
|
def log_filename
|
56
|
-
File.join(temp_folder, url.gsub(/\W/, '')
|
56
|
+
File.join(temp_folder, "#{url.gsub(/\W/, '')}.log")
|
57
57
|
end
|
58
58
|
|
59
59
|
def after_revision(opts)
|
@@ -49,8 +49,8 @@ module OhlohScm
|
|
49
49
|
prepare_dest_dir
|
50
50
|
accept_certificate_if_prompted
|
51
51
|
|
52
|
-
cmd = "#{password_prompt} git svn clone --quiet #{username_opts}"\
|
53
|
-
|
52
|
+
cmd = "#{password_prompt} git svn clone --quiet #{username_opts} " \
|
53
|
+
"'#{@source_scm.url}' '#{url}'"
|
54
54
|
run(cmd)
|
55
55
|
end
|
56
56
|
|
@@ -88,9 +88,9 @@ module OhlohScm
|
|
88
88
|
def clean_up_disk
|
89
89
|
return unless File.exist?(url)
|
90
90
|
|
91
|
-
run "cd #{url} && "\
|
92
|
-
|
93
|
-
|
91
|
+
run "cd #{url} && " \
|
92
|
+
"find . -maxdepth 1 -not -name .git -not -name '*.nfs*' -not -name . -print0 " \
|
93
|
+
'| xargs -0 rm -rf --'
|
94
94
|
end
|
95
95
|
end
|
96
96
|
end
|
@@ -40,8 +40,8 @@ module OhlohScm
|
|
40
40
|
|
41
41
|
# Returns a single commit, including its diffs
|
42
42
|
def verbose_commit(token)
|
43
|
-
cmd = "cd '#{url}' && hg log -v -r #{token}
|
44
|
-
"
|
43
|
+
cmd = "cd '#{url}' && hg log -v -r #{token} " \
|
44
|
+
"--style #{OhlohScm::HgParser.verbose_style_path} | #{string_encoder_path}"
|
45
45
|
OhlohScm::HgParser.parse(run(cmd)).first
|
46
46
|
end
|
47
47
|
|
@@ -67,13 +67,13 @@ module OhlohScm
|
|
67
67
|
|
68
68
|
# Hg leaves a little cookie crumb in the export directory. Remove it.
|
69
69
|
file_path = File.join(dest_dir, '.hg_archival.txt')
|
70
|
-
|
70
|
+
FileUtils.rm_f(file_path)
|
71
71
|
end
|
72
72
|
|
73
73
|
def tags
|
74
|
-
tag_strings = run("cd '#{url}' && hg tags").split(
|
74
|
+
tag_strings = run("cd '#{url}' && hg tags").split("\n")
|
75
75
|
tag_strings.map do |tag_string|
|
76
|
-
parsed_str = tag_string.split
|
76
|
+
parsed_str = tag_string.split
|
77
77
|
rev_number_and_hash = parsed_str.pop
|
78
78
|
tag_name = parsed_str.join(' ')
|
79
79
|
rev = rev_number_and_hash.slice(/\A\d+/)
|
@@ -99,7 +99,7 @@ module OhlohScm
|
|
99
99
|
|
100
100
|
# Recent versions of Hg now somtimes append a '+' char to the token.
|
101
101
|
# Strip the trailing '+', if any.
|
102
|
-
token = token[0..-2] if token[-1
|
102
|
+
token = token[0..-2] if token[-1..] == '+'
|
103
103
|
|
104
104
|
token
|
105
105
|
end
|
@@ -117,11 +117,11 @@ module OhlohScm
|
|
117
117
|
# Our standards require +opts={ after: ... }+ to include everything AFTER +after+.
|
118
118
|
# However, hg returns everything after and INCLUDING +after+.
|
119
119
|
# Therefore, consumers of this endpoint must check for and reject the duplicate commit.
|
120
|
-
def open_log_file(opts = {})
|
120
|
+
def open_log_file(opts = {}, &block)
|
121
121
|
get_hg_log(opts)
|
122
|
-
File.open(log_filename, 'r')
|
122
|
+
File.open(log_filename, 'r', &block)
|
123
123
|
ensure
|
124
|
-
|
124
|
+
FileUtils.rm_f(log_filename)
|
125
125
|
end
|
126
126
|
|
127
127
|
def get_hg_log(opts)
|
@@ -131,9 +131,9 @@ module OhlohScm
|
|
131
131
|
# just create an empty file rather than fetch a log we know will be empty.
|
132
132
|
File.write(log_filename, '')
|
133
133
|
else
|
134
|
-
cmd = "cd '#{url}' && #{hg_log_with_opts}"\
|
135
|
-
"
|
136
|
-
"
|
134
|
+
cmd = "cd '#{url}' && #{hg_log_with_opts} " \
|
135
|
+
"--style #{OhlohScm::HgParser.verbose_style_path} | #{string_encoder_path} " \
|
136
|
+
"> #{log_filename}"
|
137
137
|
run cmd
|
138
138
|
end
|
139
139
|
end
|
@@ -144,7 +144,7 @@ module OhlohScm
|
|
144
144
|
|
145
145
|
def cat(revision, path)
|
146
146
|
out, err = run_with_err("cd '#{url}' && hg cat -r #{revision} #{escape(path)}")
|
147
|
-
return if
|
147
|
+
return if /No such file in rev/i.match?(err)
|
148
148
|
raise err unless err&.empty?
|
149
149
|
|
150
150
|
out
|
data/lib/ohloh_scm/hg/scm.rb
CHANGED
@@ -48,9 +48,9 @@ module OhlohScm
|
|
48
48
|
def clean_up_disk
|
49
49
|
return unless FileTest.exist?(url)
|
50
50
|
|
51
|
-
run "cd #{url} && "\
|
52
|
-
|
53
|
-
|
51
|
+
run "cd #{url} && " \
|
52
|
+
"find . -maxdepth 1 -not -name .hg -not -name '*.nfs*' -not -name . -print0 " \
|
53
|
+
'| xargs -0 rm -rf --'
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
@@ -20,11 +20,12 @@ module OhlohScm
|
|
20
20
|
# b and a have the same number of branch events.
|
21
21
|
# If either one inherits from the other then they
|
22
22
|
# are on the same line.
|
23
|
-
return
|
23
|
+
return inherits_from?(branch_number) || branch_number.inherits_from?(self)
|
24
24
|
end
|
25
|
+
|
25
26
|
# b has not been branched as often as this object.
|
26
27
|
# That's OK if b is an ancestor of this object.
|
27
|
-
|
28
|
+
inherits_from?(branch_number) if b.size < @num.size
|
28
29
|
end
|
29
30
|
|
30
31
|
def to_a
|
@@ -35,7 +36,7 @@ module OhlohScm
|
|
35
36
|
|
36
37
|
# Returns true if <branch_number> is an ancestor of this object.
|
37
38
|
# Also returns true if <branch_number> is the same as this object.
|
38
|
-
# rubocop:disable Metrics/AbcSize
|
39
|
+
# rubocop:disable Metrics/AbcSize
|
39
40
|
def inherits_from?(branch_number)
|
40
41
|
b = branch_number.to_a
|
41
42
|
|
@@ -51,13 +52,13 @@ module OhlohScm
|
|
51
52
|
end
|
52
53
|
true
|
53
54
|
end
|
54
|
-
# rubocop:enable Metrics/AbcSize
|
55
|
+
# rubocop:enable Metrics/AbcSize
|
55
56
|
|
56
57
|
private
|
57
58
|
|
58
59
|
def descendant?(branch_number)
|
59
|
-
|
60
|
-
|
60
|
+
true if branch_number[0] > @num[0] ||
|
61
|
+
((branch_number[0] == @num[0]) && (branch_number[1] > @num[1]))
|
61
62
|
end
|
62
63
|
end
|
63
64
|
end
|
@@ -17,7 +17,7 @@ module OhlohScm
|
|
17
17
|
@authors = []
|
18
18
|
end
|
19
19
|
|
20
|
-
# rubocop:disable Metrics/
|
20
|
+
# rubocop:disable Metrics/MethodLength
|
21
21
|
def tag_start(name, attrs)
|
22
22
|
case name
|
23
23
|
when 'log'
|
@@ -38,7 +38,7 @@ module OhlohScm
|
|
38
38
|
@authors = []
|
39
39
|
end
|
40
40
|
end
|
41
|
-
# rubocop:enable Metrics/
|
41
|
+
# rubocop:enable Metrics/MethodLength
|
42
42
|
|
43
43
|
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
|
44
44
|
def tag_end(name)
|
@@ -76,7 +76,7 @@ module OhlohScm
|
|
76
76
|
end
|
77
77
|
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
|
78
78
|
|
79
|
-
#
|
79
|
+
# # Cannot use attr_writer; we need cdata not cdata=.
|
80
80
|
def cdata(data)
|
81
81
|
@cdata = data
|
82
82
|
end
|
@@ -84,7 +84,6 @@ module OhlohScm
|
|
84
84
|
def text(text)
|
85
85
|
@text = text
|
86
86
|
end
|
87
|
-
# rubocop:enable Style/TrivialAccessors
|
88
87
|
|
89
88
|
private
|
90
89
|
|
@@ -116,7 +115,7 @@ module OhlohScm
|
|
116
115
|
# rubocop:enable Metrics/MethodLength
|
117
116
|
|
118
117
|
def strip_trailing_asterisk(path)
|
119
|
-
path[-1
|
118
|
+
path[-1..] == '*' ? path[0..-2] : path
|
120
119
|
end
|
121
120
|
|
122
121
|
def remove_dupes(diffs)
|
@@ -125,7 +124,7 @@ module OhlohScm
|
|
125
124
|
end
|
126
125
|
|
127
126
|
class BzrXmlParser < Parser
|
128
|
-
NAME_REGEX = /^(.+?)(\s+<(.+)>\s*)
|
127
|
+
NAME_REGEX = /^(.+?)(\s+<(.+)>\s*)?$/
|
129
128
|
def self.internal_parse(buffer, _)
|
130
129
|
buffer = '<?xml?>' if buffer.is_a?(StringIO) && buffer.length < 2
|
131
130
|
REXML::Document.parse_stream(buffer,
|
@@ -138,21 +137,22 @@ module OhlohScm
|
|
138
137
|
'bzr'
|
139
138
|
end
|
140
139
|
|
141
|
-
# rubocop:disable Metrics/AbcSize
|
142
140
|
def self.remove_dupes(diffs)
|
143
|
-
|
144
|
-
# Reduce these cases to a single 'A' action.
|
145
|
-
diffs.delete_if do |d|
|
146
|
-
d.action == 'M' && diffs.select { |x| x.path == d.path && x.action == 'A' }.any?
|
147
|
-
end
|
148
|
-
|
141
|
+
remove_modified_after_added!(diffs)
|
149
142
|
# Bazaar may report that a file was both deleted and added in a single commit.
|
150
143
|
# Reduce these cases to a single 'M' action.
|
151
144
|
diffs.each do |d|
|
152
|
-
d.action = 'M' if diffs.
|
145
|
+
d.action = 'M' if diffs.count { |x| x.path == d.path } > 1
|
153
146
|
end.uniq
|
154
147
|
end
|
155
|
-
|
148
|
+
|
149
|
+
# Bazaar may report that a file was added and modified in a single commit.
|
150
|
+
# Reduce these cases to a single 'A' action.
|
151
|
+
def self.remove_modified_after_added!(diffs)
|
152
|
+
diffs.delete_if do |d|
|
153
|
+
d.action == 'M' && diffs.any? { |x| x.path == d.path && x.action == 'A' }
|
154
|
+
end
|
155
|
+
end
|
156
156
|
|
157
157
|
# Bazaar expects committer/author to be specified in this format
|
158
158
|
# Name <email>, or John Doe <jdoe@example.com>
|
@@ -7,7 +7,7 @@ module OhlohScm
|
|
7
7
|
# commits (developer/date/message).
|
8
8
|
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
9
9
|
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
10
|
-
def internal_parse(io, _opts)
|
10
|
+
def internal_parse(io, _opts, &block)
|
11
11
|
commits = {}
|
12
12
|
|
13
13
|
read_files(io) do |c|
|
@@ -25,7 +25,7 @@ module OhlohScm
|
|
25
25
|
# a number of separate times, we may end up with several timestamps for
|
26
26
|
# that combination.
|
27
27
|
|
28
|
-
key = c.committer_name
|
28
|
+
key = "#{c.committer_name}:#{c.message}"
|
29
29
|
if commits.key? key
|
30
30
|
# We have already seen this developer/message combination
|
31
31
|
match = false
|
@@ -61,7 +61,7 @@ module OhlohScm
|
|
61
61
|
result.delete_at(i) if result[i].committer_date == result[i - 1].committer_date
|
62
62
|
end
|
63
63
|
|
64
|
-
result.each
|
64
|
+
result.each(&block) if block
|
65
65
|
end
|
66
66
|
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
67
67
|
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
@@ -86,9 +86,10 @@ module OhlohScm
|
|
86
86
|
def read_file(io, filename, &block)
|
87
87
|
branch_number = nil
|
88
88
|
io.each_line do |l|
|
89
|
-
|
89
|
+
case l
|
90
|
+
when /^head: ([\d.]+)/
|
90
91
|
branch_number = BranchNumber.new(Regexp.last_match(1))
|
91
|
-
|
92
|
+
when /^----------------------------/
|
92
93
|
read_commits(io, branch_number, filename, &block)
|
93
94
|
end
|
94
95
|
end
|
@@ -125,7 +126,7 @@ module OhlohScm
|
|
125
126
|
def build_commit(committer_date, committer_name, message, filename)
|
126
127
|
commit = OhlohScm::Commit.new
|
127
128
|
commit.token = committer_date[0..18]
|
128
|
-
commit.committer_date = Time.parse(committer_date[0..18] +
|
129
|
+
commit.committer_date = Time.parse("#{committer_date[0..18]} +0000").utc
|
129
130
|
commit.committer_name = committer_name
|
130
131
|
commit.message = message
|
131
132
|
commit.directories = [File.dirname(filename).intern]
|