rspec-tracer 0.6.2 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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