rspec-tracer 0.6.2 → 0.9.1

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.
@@ -0,0 +1,175 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpecTracer
4
+ module RemoteCache
5
+ class Repo
6
+ class RepoError < StandardError; end
7
+
8
+ attr_reader :branch_name, :branch_ref, :branch_refs, :ancestry_refs, :cache_refs
9
+
10
+ def initialize(aws)
11
+ @aws = aws
12
+ @branch_name = ENV['GIT_BRANCH'].chomp
13
+
14
+ raise RepoError, 'GIT_BRANCH environment variable is not set' if @branch_name.nil?
15
+
16
+ fetch_head_ref
17
+ fetch_branch_ref
18
+ fetch_ancestry_refs
19
+ fetch_branch_refs
20
+ generate_cache_refs
21
+ end
22
+
23
+ private
24
+
25
+ def fetch_head_ref
26
+ @head_ref = `git rev-parse HEAD`.chomp
27
+
28
+ raise RepoError, 'Could not find HEAD commit sha' unless $CHILD_STATUS.success?
29
+ end
30
+
31
+ def fetch_branch_ref
32
+ @merged_parents = []
33
+ @ignored_refs = []
34
+
35
+ unless merged?
36
+ @branch_ref = @head_ref
37
+
38
+ return
39
+ end
40
+
41
+ @ignored_refs << @head_ref
42
+
43
+ fetch_merged_parents
44
+ fetch_merged_branch_ref
45
+ end
46
+
47
+ def fetch_ancestry_refs
48
+ ref_list = `git rev-list --max-count=25 #{@branch_ref}`.chomp.split
49
+
50
+ raise RepoError, 'Could not find ancestry refs' unless $CHILD_STATUS.success?
51
+
52
+ ref_list = ref_list.to_set - @ignored_refs
53
+ @ancestry_refs = refs_committer_timestamp(ref_list.to_a)
54
+
55
+ return if @ancestry_refs.empty?
56
+
57
+ print_refs(@ancestry_refs, 'ancestry')
58
+ end
59
+
60
+ def fetch_branch_refs
61
+ unless @aws.branch_refs?(@branch_name)
62
+ puts "No branch refs for #{@branch_name} branch found in S3"
63
+
64
+ @branch_refs = {}
65
+
66
+ return
67
+ end
68
+
69
+ download_branch_refs
70
+ end
71
+
72
+ def generate_cache_refs
73
+ ref_list = @ancestry_refs.merge(@branch_refs)
74
+
75
+ if ref_list.empty?
76
+ @cache_refs = {}
77
+
78
+ return
79
+ end
80
+
81
+ @cache_refs = ref_list.sort_by { |_, timestamp| -timestamp }.to_h
82
+
83
+ print_refs(@cache_refs, 'cache')
84
+ end
85
+
86
+ def merged?
87
+ system('git', 'rev-parse', 'HEAD^2', out: File::NULL, err: File::NULL)
88
+ end
89
+
90
+ def fetch_merged_parents
91
+ first_parent = `git rev-parse HEAD^1`.chomp
92
+ @merged_parents << first_parent if $CHILD_STATUS.success?
93
+
94
+ second_parent = `git rev-parse HEAD^2`.chomp
95
+ @merged_parents << second_parent if $CHILD_STATUS.success?
96
+
97
+ raise RepoError, 'Could not find merged commit parents' if @merged_parents.length != 2
98
+ end
99
+
100
+ def fetch_merged_branch_ref
101
+ @origin_head_ref = `git rev-parse origin/HEAD`.chomp
102
+ @branch_ref = nil
103
+
104
+ if @merged_parents.first != @origin_head_ref
105
+ @branch_ref = @head_ref
106
+ @ignored_refs = []
107
+
108
+ return
109
+ end
110
+
111
+ @branch_ref = @merged_parents.last
112
+ @ignored_refs = @ignored_refs.to_set | `git rev-list #{@branch_ref}..origin/HEAD`.chomp.split
113
+
114
+ raise RepoError, 'Could not find ignored refs' unless $CHILD_STATUS.success?
115
+ end
116
+
117
+ def refs_committer_timestamp(ref_list)
118
+ return {} if ref_list.empty?
119
+
120
+ command = <<-COMMAND.strip.gsub(/\s+/, ' ')
121
+ git show
122
+ --no-patch
123
+ --format="%H %ct"
124
+ #{ref_list.join(' ')}
125
+ COMMAND
126
+
127
+ ref_list = `#{command}`.chomp
128
+
129
+ raise RepoError, 'Could not find ancestry refs' unless $CHILD_STATUS.success?
130
+
131
+ ref_list.split("\n").map(&:split).to_h.transform_values(&:to_i)
132
+ end
133
+
134
+ def download_branch_refs
135
+ file_name = File.join(RSpecTracer.cache_path, 'branch_refs.json')
136
+
137
+ if @aws.download_branch_refs(branch_name, file_name)
138
+ @branch_refs = JSON.parse(File.read(file_name)).transform_values(&:to_i)
139
+
140
+ return if @branch_refs.empty?
141
+
142
+ filter_branch_refs
143
+ print_refs(@branch_refs, 'branch')
144
+ else
145
+ @branch_refs = {}
146
+
147
+ File.rm_f(file_name)
148
+
149
+ puts "Failed to fetch branch refs for #{@branch_name} branch"
150
+ end
151
+ end
152
+
153
+ def filter_branch_refs
154
+ if @ancestry_refs.empty?
155
+ @branch_refs = @branch_refs.sort_by { |_, timestamp| -timestamp }.first(25).to_h
156
+
157
+ return
158
+ end
159
+
160
+ oldest_ancestry_time = @ancestry_refs.values.min
161
+
162
+ @branch_refs = @branch_refs
163
+ .select { |_, timestamp| timestamp >= oldest_ancestry_time }
164
+ .sort_by { |_, timestamp| -timestamp }
165
+ .first(25)
166
+ .to_h
167
+ end
168
+
169
+ def print_refs(refs, type)
170
+ puts "Fetched the following #{type} refs for #{@branch_name} branch:"
171
+ puts refs.map { |ref, timestamp| " * #{ref} (commit timestamp: #{timestamp})" }.join("\n")
172
+ end
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpecTracer
4
+ module RemoteCache
5
+ class Validator
6
+ CACHE_FILES_PER_TEST_SUITE = 8
7
+
8
+ def initialize
9
+ @test_suite_id = ENV['TEST_SUITE_ID']
10
+ @test_suites = ENV['TEST_SUITES']
11
+
12
+ if @test_suite_id.nil? ^ @test_suites.nil?
13
+ raise(
14
+ ValidationError,
15
+ 'Both the enviornment variables TEST_SUITE_ID and TEST_SUITES are not set'
16
+ )
17
+ end
18
+
19
+ setup
20
+ end
21
+
22
+ def valid?(ref, cache_files)
23
+ last_run_regex = Regexp.new(format(@last_run_files_regex, ref: ref))
24
+
25
+ return false if cache_files.count { |file| file.match?(last_run_regex) } != @last_run_files_count
26
+
27
+ cache_regex = Regexp.new(format(@cached_files_regex, ref: ref))
28
+
29
+ cache_files.count { |file| file.match?(cache_regex) } == @cached_files_count
30
+ end
31
+
32
+ private
33
+
34
+ def setup
35
+ if @test_suites.nil?
36
+ @last_run_files_count = 1
37
+ @last_run_files_regex = '/%<ref>s/last_run.json$'
38
+ @cached_files_count = CACHE_FILES_PER_TEST_SUITE
39
+ @cached_files_regex = '/%<ref>s/[0-9a-f]{32}/.+.json'
40
+ else
41
+ @test_suites = @test_suites.to_i
42
+ @test_suites_regex = (1..@test_suites).to_a.join('|')
43
+
44
+ @last_run_files_count = @test_suites
45
+ @last_run_files_regex = "/%<ref>s/(#{@test_suites_regex})/last_run.json$"
46
+ @cached_files_count = CACHE_FILES_PER_TEST_SUITE * @test_suites
47
+ @cached_files_regex = "/%<ref>s/(#{@test_suites_regex})/[0-9a-f]{32}/.+.json$"
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -15,6 +15,7 @@ module RSpecTracer
15
15
 
16
16
  def register_example(example)
17
17
  @all_examples[example[:example_id]] = example
18
+ @duplicate_examples[example[:example_id]] << example
18
19
  end
19
20
 
20
21
  def on_example_skipped(example_id)
@@ -106,6 +107,17 @@ module RSpecTracer
106
107
  file_deleted?(file_name) || file_modified?(file_name)
107
108
  end
108
109
 
110
+ def incorrect_analysis?
111
+ @duplicate_examples.select! { |_, examples| examples.count > 1 }
112
+
113
+ return false if @duplicate_examples.empty?
114
+
115
+ print_not_use_notice
116
+ print_duplicate_examples
117
+
118
+ true
119
+ end
120
+
109
121
  def register_dependency(example_id, file_name)
110
122
  @dependency[example_id] << file_name
111
123
  end
@@ -169,6 +181,7 @@ module RSpecTracer
169
181
 
170
182
  def initialize_examples
171
183
  @all_examples = {}
184
+ @duplicate_examples = Hash.new { |examples, example_id| examples[example_id] = [] }
172
185
  @passed_examples = Set.new
173
186
  @possibly_flaky_examples = Set.new
174
187
  @flaky_examples = Set.new
@@ -226,6 +239,45 @@ module RSpecTracer
226
239
  @reverse_dependency = report.to_h
227
240
  end
228
241
 
242
+ def print_not_use_notice
243
+ justify = ' ' * 4
244
+ four_justify = justify * 4
245
+
246
+ puts '=' * 80
247
+ puts "#{four_justify}IMPORTANT NOTICE -- DO NOT USE RSPEC TRACER"
248
+ puts '=' * 80
249
+ puts "#{justify}It would be best to make changes so that the RSpec tracer can uniquely"
250
+ puts "#{justify}identify all the examples, and then you can enable the RSpec tracer back."
251
+ puts '=' * 80
252
+ puts
253
+ end
254
+
255
+ # rubocop:disable Metrics/AbcSize
256
+ def print_duplicate_examples
257
+ total = @duplicate_examples.sum { |_, examples| examples.length }
258
+
259
+ puts "RSpec tracer could not uniquely identify the following #{total} examples:"
260
+
261
+ justify = ' ' * 2
262
+ nested_justify = justify * 3
263
+
264
+ @duplicate_examples.each_pair do |example_id, examples|
265
+ puts "#{justify}- Example ID: #{example_id} (#{examples.count} examples)"
266
+
267
+ examples.each do |example|
268
+ description = example[:full_description].strip
269
+ file_name = example[:rerun_file_name].sub(%r{^/}, '')
270
+ line_number = example[:rerun_line_number]
271
+ location = "#{file_name}:#{line_number}"
272
+
273
+ puts "#{nested_justify}* #{description} (#{location})"
274
+ end
275
+ end
276
+
277
+ puts
278
+ end
279
+ # rubocop:enable Metrics/AbcSize
280
+
229
281
  def write_all_examples_report
230
282
  file_name = File.join(@cache_dir, 'all_examples.json')
231
283
 
@@ -3,13 +3,23 @@
3
3
  module RSpecTracer
4
4
  module RSpecRunner
5
5
  # rubocop:disable Metrics/AbcSize
6
- def run_specs(_example_groups)
6
+ def run_specs(example_groups)
7
7
  actual_count = RSpec.world.example_count
8
+ RSpecTracer.no_examples = actual_count.zero?
9
+
10
+ if RSpecTracer.no_examples
11
+ RSpecTracer.running = true
12
+
13
+ super(example_groups)
14
+
15
+ return
16
+ end
17
+
8
18
  starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
9
- filtered_examples, example_groups = RSpecTracer.filter_examples
19
+ filtered_examples, filtered_example_groups = RSpecTracer.filter_examples
10
20
 
11
21
  RSpec.world.instance_variable_set(:@filtered_examples, filtered_examples)
12
- RSpec.world.instance_variable_set(:@example_groups, example_groups)
22
+ RSpec.world.instance_variable_set(:@example_groups, filtered_example_groups)
13
23
 
14
24
  current_count = RSpec.world.example_count
15
25
  ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
@@ -23,7 +33,7 @@ module RSpecTracer
23
33
 
24
34
  RSpecTracer.running = true
25
35
 
26
- super(example_groups)
36
+ super(filtered_example_groups)
27
37
  end
28
38
  # rubocop:enable Metrics/AbcSize
29
39
  end
@@ -63,6 +63,10 @@ module RSpecTracer
63
63
  @reporter.register_deleted_examples(@cache.all_examples)
64
64
  end
65
65
 
66
+ def incorrect_analysis?
67
+ @reporter.incorrect_analysis?
68
+ end
69
+
66
70
  # rubocop:disable Metrics/AbcSize
67
71
  def generate_missed_coverage
68
72
  missed_coverage = Hash.new do |files_coverage, file_path|
@@ -183,6 +187,7 @@ module RSpecTracer
183
187
  @cache.flaky_examples.each do |example_id|
184
188
  @filtered_examples[example_id] = EXAMPLE_RUN_REASON[:flaky_example]
185
189
 
190
+ next unless @cache.dependency.key?(example_id)
186
191
  next unless (@changed_files & @cache.dependency[example_id]).empty?
187
192
 
188
193
  @reporter.register_possibly_flaky_example(example_id)
@@ -195,6 +200,7 @@ module RSpecTracer
195
200
 
196
201
  @filtered_examples[example_id] = EXAMPLE_RUN_REASON[:failed_example]
197
202
 
203
+ next unless @cache.dependency.key?(example_id)
198
204
  next unless (@changed_files & @cache.dependency[example_id]).empty?
199
205
 
200
206
  @reporter.register_possibly_flaky_example(example_id)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RSpecTracer
4
- VERSION = '0.6.2'
4
+ VERSION = '0.9.1'
5
5
  end
data/lib/rspec_tracer.rb CHANGED
@@ -28,7 +28,7 @@ require_relative 'rspec_tracer/version'
28
28
 
29
29
  module RSpecTracer
30
30
  class << self
31
- attr_accessor :running, :pid
31
+ attr_accessor :running, :pid, :no_examples
32
32
 
33
33
  def start(&block)
34
34
  RSpecTracer.running = false
@@ -74,7 +74,11 @@ module RSpecTracer
74
74
  def at_exit_behavior
75
75
  return unless RSpecTracer.pid == Process.pid && RSpecTracer.running
76
76
 
77
+ ::Kernel.exit(1) if runner.incorrect_analysis?
78
+
77
79
  run_exit_tasks
80
+ ensure
81
+ RSpecTracer.running = false
78
82
  end
79
83
 
80
84
  def start_example_trace
@@ -154,15 +158,11 @@ module RSpecTracer
154
158
  def setup_coverage
155
159
  @simplecov = defined?(SimpleCov) && SimpleCov.running
156
160
 
157
- if simplecov?
158
- # rubocop:disable Lint/EmptyBlock
159
- SimpleCov.at_exit {}
160
- # rubocop:enable Lint/EmptyBlock
161
- else
162
- require 'coverage'
161
+ return if simplecov?
163
162
 
164
- ::Coverage.start
165
- end
163
+ require 'coverage'
164
+
165
+ ::Coverage.start
166
166
  end
167
167
 
168
168
  def setup_trace_point
@@ -175,11 +175,13 @@ module RSpecTracer
175
175
  end
176
176
 
177
177
  def run_exit_tasks
178
- generate_reports
178
+ if RSpecTracer.no_examples
179
+ puts 'Skipped reports generation since all examples were filtered out'
180
+ else
181
+ generate_reports
182
+ end
179
183
 
180
184
  simplecov? ? run_simplecov_exit_task : run_coverage_exit_task
181
- ensure
182
- RSpecTracer.running = false
183
185
  end
184
186
 
185
187
  def generate_reports
@@ -224,12 +226,13 @@ module RSpecTracer
224
226
 
225
227
  puts 'SimpleCov will now generate coverage report (<3 RSpec tracer)'
226
228
 
227
- SimpleCov.result.format!
229
+ coverage_reporter.record_coverage if RSpecTracer.no_examples
228
230
  end
229
231
 
230
232
  def run_coverage_exit_task
231
233
  starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
232
234
 
235
+ coverage_reporter.record_coverage if RSpecTracer.no_examples
233
236
  coverage_reporter.generate_final_coverage
234
237
 
235
238
  file_name = File.join(RSpecTracer.coverage_path, 'coverage.json')
metadata CHANGED
@@ -1,58 +1,60 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-tracer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abhimanyu Singh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-07 00:00:00.000000000 Z
11
+ date: 2021-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: docile
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: 1.1.0
20
17
  - - "~>"
21
18
  - !ruby/object:Gem::Version
22
19
  version: '1.1'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.1.0
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- version: 1.1.0
30
27
  - - "~>"
31
28
  - !ruby/object:Gem::Version
32
29
  version: '1.1'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.1.0
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: rspec-core
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- version: 3.6.0
40
37
  - - "~>"
41
38
  - !ruby/object:Gem::Version
42
39
  version: '3.6'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 3.6.0
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
46
46
  requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: 3.6.0
50
47
  - - "~>"
51
48
  - !ruby/object:Gem::Version
52
49
  version: '3.6'
53
- description: RSpec Tracer is a specs dependency analysis tool and a test skipper for
54
- RSpec. It maintains a list of files for each test, enabling itself to skip tests
55
- in the subsequent runs if none of the dependent files are changed.
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 3.6.0
53
+ description: RSpec Tracer is a specs dependency analyzer, flaky tests detector, tests
54
+ accelerator, and coverage reporter tool for RSpec. It maintains a list of files
55
+ for each test, enabling itself to skip tests in the subsequent runs if none of the
56
+ dependent files are changed. It uses Ruby's built-in coverage library to keep track
57
+ of the coverage for each test.
56
58
  email:
57
59
  - abhisinghabhimanyu@gmail.com
58
60
  executables: []
@@ -69,6 +71,7 @@ files:
69
71
  - lib/rspec_tracer/defaults.rb
70
72
  - lib/rspec_tracer/example.rb
71
73
  - lib/rspec_tracer/filter.rb
74
+ - lib/rspec_tracer/html_reporter/Rakefile
72
75
  - lib/rspec_tracer/html_reporter/assets/javascripts/application.js
73
76
  - lib/rspec_tracer/html_reporter/assets/javascripts/libraries/jquery.js
74
77
  - lib/rspec_tracer/html_reporter/assets/javascripts/plugins/datatables.js
@@ -92,8 +95,11 @@ files:
92
95
  - lib/rspec_tracer/html_reporter/views/files_dependency.erb
93
96
  - lib/rspec_tracer/html_reporter/views/flaky_examples.erb
94
97
  - lib/rspec_tracer/html_reporter/views/layout.erb
98
+ - lib/rspec_tracer/remote_cache/Rakefile
99
+ - lib/rspec_tracer/remote_cache/aws.rb
95
100
  - lib/rspec_tracer/remote_cache/cache.rb
96
- - lib/rspec_tracer/remote_cache/git.rb
101
+ - lib/rspec_tracer/remote_cache/repo.rb
102
+ - lib/rspec_tracer/remote_cache/validator.rb
97
103
  - lib/rspec_tracer/reporter.rb
98
104
  - lib/rspec_tracer/rspec_reporter.rb
99
105
  - lib/rspec_tracer/rspec_runner.rb
@@ -107,7 +113,7 @@ licenses:
107
113
  - MIT
108
114
  metadata:
109
115
  homepage_uri: https://github.com/avmnu-sng/rspec-tracer
110
- source_code_uri: https://github.com/avmnu-sng/rspec-tracer/tree/v0.6.2
116
+ source_code_uri: https://github.com/avmnu-sng/rspec-tracer/tree/v0.9.1
111
117
  changelog_uri: https://github.com/avmnu-sng/rspec-tracer/blob/main/CHANGELOG.md
112
118
  bug_tracker_uri: https://github.com/avmnu-sng/rspec-tracer/issues
113
119
  post_install_message:
@@ -125,8 +131,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
131
  - !ruby/object:Gem::Version
126
132
  version: '0'
127
133
  requirements: []
128
- rubygems_version: 3.0.9
134
+ rubygems_version: 3.2.26
129
135
  signing_key:
130
136
  specification_version: 4
131
- summary: RSpec Tracer is a specs dependency analysis tool and a test skipper for RSpec
137
+ summary: RSpec Tracer is a specs dependency analyzer, flaky tests detector, tests
138
+ accelerator, and coverage reporter tool.
132
139
  test_files: []
@@ -1,113 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RSpecTracer
4
- module RemoteCache
5
- class Git
6
- class GitOperationError < StandardError; end
7
-
8
- attr_reader :branch_ref, :ref_list
9
-
10
- def initialize
11
- fetch_head_ref
12
- fetch_branch_ref
13
- end
14
-
15
- def prepare_for_download
16
- fetch_unreachable_refs
17
- fetch_ancestry_refs
18
- fetch_ordered_refs
19
- end
20
-
21
- private
22
-
23
- def fetch_head_ref
24
- @head_ref = `git rev-parse HEAD`.chomp
25
-
26
- raise GitOperationError, 'Could not find HEAD commit sha' unless $CHILD_STATUS.success?
27
- end
28
-
29
- def fetch_branch_ref
30
- @merged_parents = []
31
- @ignored_refs = []
32
-
33
- unless merged?
34
- @branch_ref = @head_ref
35
-
36
- return
37
- end
38
-
39
- @ignored_refs << @head_ref
40
-
41
- fetch_merged_parents
42
- fetch_merged_branch_ref
43
- end
44
-
45
- def merged?
46
- system('git', 'rev-parse', 'HEAD^2', out: File::NULL, err: File::NULL)
47
- end
48
-
49
- def fetch_merged_parents
50
- first_parent = `git rev-parse HEAD^1`.chomp
51
- @merged_parents << first_parent if $CHILD_STATUS.success?
52
-
53
- second_parent = `git rev-parse HEAD^2`.chomp
54
- @merged_parents << second_parent if $CHILD_STATUS.success?
55
-
56
- raise GitOperationError, 'Could not find merged commit parents' if @merged_parents.length != 2
57
- end
58
-
59
- def fetch_merged_branch_ref
60
- @origin_head_ref = `git rev-parse origin/HEAD`.chomp
61
- @branch_ref = nil
62
-
63
- if @merged_parents.first != @origin_head_ref
64
- @branch_ref = @head_ref
65
- @ignored_refs = []
66
-
67
- return
68
- end
69
-
70
- @branch_ref = @merged_parents.last
71
- @ignored_refs = @ignored_refs.to_set | `git rev-list #{@branch_ref}..origin/HEAD`.chomp.split
72
-
73
- raise GitOperationError, 'Could not find ignored refs' unless $CHILD_STATUS.success?
74
- end
75
-
76
- def fetch_unreachable_refs
77
- command = <<-COMMAND.strip.gsub(/\s+/, ' ')
78
- git fsck
79
- --no-progress
80
- --unreachable
81
- --connectivity-only #{@branch_ref}
82
- | awk '/commit/ { print $3 }'
83
- | head -n 25
84
- COMMAND
85
-
86
- @unreachable_refs = `#{command}`.chomp.split
87
-
88
- raise GitOperationError, 'Could not find unreachable refs' unless $CHILD_STATUS.success?
89
- end
90
-
91
- def fetch_ancestry_refs
92
- @ancestry_refs = `git rev-list --max-count=25 #{@branch_ref}`.chomp.split
93
-
94
- raise GitOperationError, 'Could not find ancestry refs' unless $CHILD_STATUS.success?
95
- end
96
-
97
- def fetch_ordered_refs
98
- unordered_refs = (@unreachable_refs.to_set | @ancestry_refs) - @ignored_refs
99
-
100
- command = <<-COMMAND.strip.gsub(/\s+/, ' ')
101
- git rev-list
102
- --topo-order
103
- --no-walk=sorted
104
- #{unordered_refs.to_a.join(' ')}
105
- COMMAND
106
-
107
- @ref_list = `#{command}`.chomp.split
108
-
109
- raise GitOperationError, 'Could not find refs to download cache' unless $CHILD_STATUS.success?
110
- end
111
- end
112
- end
113
- end