ratatui_ruby-devtools 0.2.0 → 0.3.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 +1 -1
- data/AGENTS.md +1 -1
- data/CHANGELOG.md +63 -6
- data/README.md +49 -21
- data/Rakefile +1 -1
- data/bin/setup +20 -6
- data/bin/setup.ps1 +74 -0
- data/doc/contributors/documentation_style.md +3 -4
- data/exe/scaffold +8 -342
- data/lib/ratatui_ruby/devtools/scaffold/scaffold_config.rb +67 -0
- data/lib/ratatui_ruby/devtools/scaffold/template_renderer.rb +282 -0
- data/lib/ratatui_ruby/devtools/site_tasks/build.rake +10 -15
- data/lib/ratatui_ruby/devtools/task_scope.rb +24 -0
- data/lib/ratatui_ruby/devtools/tasks/autodoc_tasks.rb +31 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/bump_workflow.rb +71 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/changelog.rb +60 -3
- data/lib/ratatui_ruby/devtools/tasks/bump/github_project.rb +26 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/history.rb +3 -3
- data/lib/ratatui_ruby/devtools/tasks/bump/links.rb +39 -24
- data/lib/ratatui_ruby/devtools/tasks/bump/manifest.rb +9 -17
- data/lib/ratatui_ruby/devtools/tasks/bump/no_crate.rb +19 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/no_links.rb +22 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/patch_release.rb +25 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/release_branch.rb +17 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/release_from_trunk.rb +48 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/repository.rb +143 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/ruby_gem.rb +65 -59
- data/lib/ratatui_ruby/devtools/tasks/bump/rust_crate.rb +42 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/sem_ver.rb +127 -10
- data/lib/ratatui_ruby/devtools/tasks/bump/source_hut_project.rb +26 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/unbranched_release.rb +20 -0
- data/lib/ratatui_ruby/devtools/tasks/bump/unreleased_section.rb +19 -1
- data/lib/ratatui_ruby/devtools/tasks/bump_tasks.rb +47 -0
- data/lib/ratatui_ruby/devtools/tasks/cargo_tasks.rb +57 -0
- data/lib/ratatui_ruby/devtools/tasks/doc/documentation.rb +59 -0
- data/lib/ratatui_ruby/devtools/tasks/doc/link/file_url.rb +30 -0
- data/lib/ratatui_ruby/devtools/tasks/doc/link/relative_path.rb +61 -0
- data/lib/ratatui_ruby/devtools/tasks/doc/link/web_url.rb +55 -0
- data/lib/ratatui_ruby/devtools/tasks/doc/link.rb +52 -0
- data/lib/ratatui_ruby/devtools/tasks/doc/link_audit.rb +116 -0
- data/lib/ratatui_ruby/devtools/tasks/doc/problem.rb +40 -0
- data/lib/ratatui_ruby/devtools/tasks/doc/source_file.rb +93 -0
- data/lib/ratatui_ruby/devtools/tasks/doc_tasks.rb +937 -0
- data/lib/ratatui_ruby/devtools/tasks/license/blame.rb +72 -0
- data/lib/ratatui_ruby/devtools/tasks/license/changed_files.rb +34 -0
- data/lib/ratatui_ruby/devtools/tasks/license/contribution.rb +12 -0
- data/lib/ratatui_ruby/devtools/tasks/license/copyright.rb +47 -0
- data/lib/ratatui_ruby/devtools/tasks/license/directory_licensing.rb +42 -0
- data/lib/ratatui_ruby/devtools/tasks/license/existing_header.rb +21 -0
- data/lib/ratatui_ruby/devtools/tasks/license/header_revision.rb +45 -0
- data/lib/ratatui_ruby/devtools/tasks/license/licensed_file.rb +39 -0
- data/lib/ratatui_ruby/devtools/tasks/license/licensing.rb +35 -0
- data/lib/ratatui_ruby/devtools/tasks/license/markdown_document.rb +23 -0
- data/lib/ratatui_ruby/devtools/tasks/license/markdown_files.rb +31 -0
- data/lib/ratatui_ruby/devtools/tasks/license/markdown_header_syntax.rb +104 -0
- data/lib/ratatui_ruby/devtools/tasks/license/markdown_snippet_syntax.rb +159 -0
- data/lib/ratatui_ruby/devtools/tasks/license/missing_header.rb +18 -0
- data/lib/ratatui_ruby/devtools/tasks/license/rbs_files.rb +27 -0
- data/lib/ratatui_ruby/devtools/tasks/license/rbs_header_syntax.rb +31 -0
- data/lib/ratatui_ruby/devtools/tasks/license/rdoc_comment.rb +51 -0
- data/lib/ratatui_ruby/devtools/tasks/license/rdoc_examples.rb +41 -0
- data/lib/ratatui_ruby/devtools/tasks/license/rdoc_snippet_syntax.rb +119 -0
- data/lib/ratatui_ruby/devtools/tasks/license/renewal.rb +17 -0
- data/lib/ratatui_ruby/devtools/tasks/license/reuse_annotated_file.rb +12 -0
- data/lib/ratatui_ruby/devtools/tasks/license/reuse_tool.rb +34 -0
- data/lib/ratatui_ruby/devtools/tasks/license/ruby_comment_header.rb +49 -0
- data/lib/ratatui_ruby/devtools/tasks/license/ruby_files.rb +36 -0
- data/lib/ratatui_ruby/devtools/tasks/license/ruby_header_syntax.rb +39 -0
- data/lib/ratatui_ruby/devtools/tasks/license/rust_files.rb +27 -0
- data/lib/ratatui_ruby/devtools/tasks/license/rust_header_syntax.rb +59 -0
- data/lib/ratatui_ruby/devtools/tasks/license/snippet.rb +44 -0
- data/lib/ratatui_ruby/devtools/tasks/license/snippet_file.rb +29 -0
- data/lib/ratatui_ruby/devtools/tasks/license/snippet_opening.rb +39 -0
- data/lib/ratatui_ruby/devtools/tasks/license/snippet_revision.rb +75 -0
- data/lib/ratatui_ruby/devtools/tasks/license/spdx_header.rb +42 -0
- data/lib/ratatui_ruby/devtools/tasks/license/unknown_file.rb +12 -0
- data/lib/ratatui_ruby/devtools/tasks/license/unlicensed_files.rb +69 -0
- data/lib/ratatui_ruby/devtools/tasks/license/wrapped_snippet.rb +30 -0
- data/lib/ratatui_ruby/devtools/tasks/license_tasks.rb +71 -0
- data/lib/ratatui_ruby/devtools/tasks/lint/gem_lockfile.rb +29 -0
- data/lib/ratatui_ruby/devtools/tasks/lint/supported_rubies.rb +18 -0
- data/lib/ratatui_ruby/devtools/tasks/lint_tasks.rb +100 -0
- data/lib/ratatui_ruby/devtools/tasks/release/platform_gem.rb +21 -12
- data/lib/ratatui_ruby/devtools/tasks/release/versioned_binary.rb +1 -1
- data/lib/ratatui_ruby/devtools/tasks/release_tasks.rb +80 -0
- data/lib/ratatui_ruby/devtools/tasks/reuse_tasks.rb +39 -0
- data/lib/ratatui_ruby/devtools/tasks/{test.rake → test_tasks.rb} +13 -4
- data/lib/ratatui_ruby/devtools/tasks/website/hosted_source_tree.rb +24 -0
- data/lib/ratatui_ruby/devtools/tasks/website/index_page.rb +1 -4
- data/lib/ratatui_ruby/devtools/tasks/website/source_tree.rb +63 -0
- data/lib/ratatui_ruby/devtools/tasks/website/versioned_documentation.rb +14 -13
- data/lib/ratatui_ruby/devtools/tasks/website_tasks.rb +49 -0
- data/lib/ratatui_ruby/devtools/templates/.github/workflows/build-gems.yml.erb +7 -1
- data/lib/ratatui_ruby/devtools/templates/.github/workflows/ci.yml.erb +2 -2
- data/lib/ratatui_ruby/devtools/templates/.gitignore.erb +2 -1
- data/lib/ratatui_ruby/devtools/templates/.rubocop.yml.erb +1 -1
- data/lib/ratatui_ruby/devtools/templates/AGENTS.md.erb +1 -1
- data/lib/ratatui_ruby/devtools/templates/CHANGELOG.md.erb +3 -1
- data/lib/ratatui_ruby/devtools/templates/CONTRIBUTING.md.erb +3 -3
- data/lib/ratatui_ruby/devtools/templates/Gemfile.erb +2 -3
- data/lib/ratatui_ruby/devtools/templates/README.md.erb +7 -7
- data/lib/ratatui_ruby/devtools/templates/REUSE.toml.erb +1 -1
- data/lib/ratatui_ruby/devtools/templates/bin/setup.erb +5 -1
- data/lib/ratatui_ruby/devtools/templates/bin/setup.ps1.erb +5 -1
- data/lib/ratatui_ruby/devtools/templates/doc/concepts/application_architecture.md.erb +2 -2
- data/lib/ratatui_ruby/devtools/templates/doc/concepts/application_testing.md.erb +3 -3
- data/lib/ratatui_ruby/devtools/templates/doc/getting_started/quickstart.md.erb +4 -4
- data/lib/ratatui_ruby/devtools/templates/ext/Cargo.toml.erb +1 -1
- data/lib/ratatui_ruby/devtools/templates/gemspec.erb +1 -1
- data/lib/ratatui_ruby/devtools/templates/mise.toml.erb +3 -3
- data/lib/ratatui_ruby/devtools/version.rb +1 -1
- data/lib/ratatui_ruby/devtools.rb +54 -71
- data/mise.toml +2 -2
- data/sig/ratatui_ruby/devtools.rbs +16 -1
- metadata +93 -34
- data/.builds/ruby-4.0.yml +0 -38
- data/lib/ratatui_ruby/devtools/tasks/autodoc.rake +0 -21
- data/lib/ratatui_ruby/devtools/tasks/bump.rake +0 -80
- data/lib/ratatui_ruby/devtools/tasks/cargo.rake +0 -47
- data/lib/ratatui_ruby/devtools/tasks/doc.rake +0 -887
- data/lib/ratatui_ruby/devtools/tasks/license/headers_md.rb +0 -276
- data/lib/ratatui_ruby/devtools/tasks/license/headers_rb.rb +0 -236
- data/lib/ratatui_ruby/devtools/tasks/license/license_utils.rb +0 -143
- data/lib/ratatui_ruby/devtools/tasks/license/snippets_md.rb +0 -353
- data/lib/ratatui_ruby/devtools/tasks/license/snippets_rdoc.rb +0 -186
- data/lib/ratatui_ruby/devtools/tasks/license.rake +0 -91
- data/lib/ratatui_ruby/devtools/tasks/lint.rake +0 -80
- data/lib/ratatui_ruby/devtools/tasks/release.rake +0 -87
- data/lib/ratatui_ruby/devtools/tasks/resources/rubies.yml +0 -7
- data/lib/ratatui_ruby/devtools/tasks/reuse.rake +0 -104
- data/lib/ratatui_ruby/devtools/tasks/website.rake +0 -37
- data/lib/ratatui_ruby/devtools/templates/.builds/ruby.yml.erb +0 -47
- data/lib/ratatui_ruby/devtools/templates/tasks/resources/index.html.erb +0 -45
- data/lib/ratatui_ruby/devtools/templates/tasks/resources/rubies.yml.erb +0 -8
|
@@ -1,353 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#--
|
|
4
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
-
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
6
|
-
#++
|
|
7
|
-
|
|
8
|
-
# Script to add SPDX snippet headers to fenced code blocks in markdown files.
|
|
9
|
-
#
|
|
10
|
-
# Usage: ruby tasks/license/snippets_md.rb [path...]
|
|
11
|
-
#
|
|
12
|
-
# If no paths are given, processes all .md files via git ls-files.
|
|
13
|
-
#
|
|
14
|
-
# Rules:
|
|
15
|
-
# - Wraps all fenced code blocks (``` or ````) with SPDX snippet headers (MIT-0)
|
|
16
|
-
# - For SYNC:START/SYNC:END blocks, wraps AROUND the sync markers (not inside)
|
|
17
|
-
# - Uses git blame to determine the latest edit year for the code lines
|
|
18
|
-
# - Skips blocks that are already properly wrapped with MIT-0 and Kerrick Long
|
|
19
|
-
# - Removes malformed existing SPDX-Snippet blocks and replaces with correct ones
|
|
20
|
-
|
|
21
|
-
require "open3"
|
|
22
|
-
require "date"
|
|
23
|
-
|
|
24
|
-
# The name for SPDX-FileCopyrightText in code snippets.
|
|
25
|
-
COPYRIGHT_HOLDER = "Kerrick Long"
|
|
26
|
-
|
|
27
|
-
# The SPDX license identifier for code snippets.
|
|
28
|
-
LICENSE = "MIT-0"
|
|
29
|
-
|
|
30
|
-
# Files to skip entirely (relative paths from repo root)
|
|
31
|
-
EXCLUDED_FILES = [
|
|
32
|
-
"doc/contributors/v1.0.0_blockers.md",
|
|
33
|
-
"doc/contributors/upstream_requests/tab_rects.md",
|
|
34
|
-
"doc/contributors/upstream_requests/title_rects.md",
|
|
35
|
-
].freeze
|
|
36
|
-
|
|
37
|
-
# Determines the latest edit year for a line range using git blame.
|
|
38
|
-
#
|
|
39
|
-
# Copyright years come from when code was last modified. Git blame provides
|
|
40
|
-
# per-line authorship. Extract and return the most recent year.
|
|
41
|
-
#
|
|
42
|
-
# [file] Path to the file.
|
|
43
|
-
# [start_line] First line number (1-indexed).
|
|
44
|
-
# [end_line] Last line number (1-indexed).
|
|
45
|
-
def get_latest_git_year(file, start_line, end_line)
|
|
46
|
-
cmd = %W[git blame -L #{start_line},#{end_line} --date=short -- #{file}]
|
|
47
|
-
output, _status = Open3.capture2(*cmd)
|
|
48
|
-
years = output.scan(/(\d{4})-\d{2}-\d{2}/).flatten.map(&:to_i)
|
|
49
|
-
years.empty? ? Date.today.year : years.max
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# Checks if an existing SPDX snippet header matches our required format.
|
|
53
|
-
#
|
|
54
|
-
# Already-correct snippets should be skipped. Re-wrapping wastes time and
|
|
55
|
-
# creates noisy diffs. This function validates existing headers.
|
|
56
|
-
#
|
|
57
|
-
# [lines] Array of line strings.
|
|
58
|
-
# [idx] Index of the SPDX-SnippetBegin line.
|
|
59
|
-
def is_our_snippet_header?(lines, idx)
|
|
60
|
-
# Check if the current SPDX-SnippetBegin block already has our copyright/license
|
|
61
|
-
i = idx + 1
|
|
62
|
-
has_our_copyright = false
|
|
63
|
-
has_mit0 = false
|
|
64
|
-
|
|
65
|
-
while i < lines.length && !lines[i].include?("-->")
|
|
66
|
-
line = lines[i]
|
|
67
|
-
has_our_copyright = true if line.include?(COPYRIGHT_HOLDER) && line.include?("SPDX-FileCopyrightText")
|
|
68
|
-
has_mit0 = true if line.include?("MIT-0") && line.include?("SPDX-License-Identifier")
|
|
69
|
-
i += 1
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
has_our_copyright && has_mit0
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
# Locates the SPDX-SnippetEnd marker for a snippet block.
|
|
76
|
-
#
|
|
77
|
-
# Snippet blocks have paired begin/end markers. Removing or replacing a block
|
|
78
|
-
# requires finding both. This scans forward from a start position.
|
|
79
|
-
#
|
|
80
|
-
# [lines] Array of line strings.
|
|
81
|
-
# [start_idx] Index to start searching from.
|
|
82
|
-
def find_snippet_end(lines, start_idx)
|
|
83
|
-
i = start_idx
|
|
84
|
-
while i < lines.length
|
|
85
|
-
return i if lines[i].include?("SPDX-SnippetEnd")
|
|
86
|
-
i += 1
|
|
87
|
-
end
|
|
88
|
-
nil
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# Wraps code blocks in a markdown file with SPDX snippet headers.
|
|
92
|
-
#
|
|
93
|
-
# Each code block needs MIT-0 licensing. Processing involves scanning for
|
|
94
|
-
# fenced blocks, removing malformed existing headers, and inserting correct
|
|
95
|
-
# ones. This function orchestrates that workflow.
|
|
96
|
-
#
|
|
97
|
-
# [filepath] Path to the markdown file.
|
|
98
|
-
def process_file(filepath)
|
|
99
|
-
# Skip excluded files
|
|
100
|
-
return if EXCLUDED_FILES.any? { |excluded| filepath.end_with?(excluded) }
|
|
101
|
-
|
|
102
|
-
content = File.read(filepath)
|
|
103
|
-
lines = content.lines
|
|
104
|
-
|
|
105
|
-
# Track code block ranges (to exclude from file header year calculation)
|
|
106
|
-
code_block_ranges = []
|
|
107
|
-
changes = []
|
|
108
|
-
removals = [] # existing malformed SPDX snippet blocks to remove
|
|
109
|
-
i = 0
|
|
110
|
-
|
|
111
|
-
while i < lines.length
|
|
112
|
-
line = lines[i]
|
|
113
|
-
|
|
114
|
-
# Check if we're at an existing SPDX-SnippetBegin
|
|
115
|
-
if line.include?("SPDX-SnippetBegin")
|
|
116
|
-
snippet_start = i
|
|
117
|
-
snippet_end = find_snippet_end(lines, i)
|
|
118
|
-
|
|
119
|
-
if snippet_end
|
|
120
|
-
# Check if this is already our proper snippet
|
|
121
|
-
if is_our_snippet_header?(lines, i)
|
|
122
|
-
# Skip this block entirely - it's already correct
|
|
123
|
-
i = snippet_end + 1
|
|
124
|
-
next
|
|
125
|
-
else
|
|
126
|
-
# Mark for removal - we'll re-wrap the inner content
|
|
127
|
-
removals << { start: snippet_start, end: snippet_end }
|
|
128
|
-
i = snippet_end + 1
|
|
129
|
-
next
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
# Check for SYNC:START pattern
|
|
135
|
-
if line =~ /<!--\s*SYNC:START/
|
|
136
|
-
sync_start_line = i
|
|
137
|
-
j = i + 1
|
|
138
|
-
code_start = nil
|
|
139
|
-
code_end = nil
|
|
140
|
-
sync_end_line = nil
|
|
141
|
-
|
|
142
|
-
while j < lines.length
|
|
143
|
-
if lines[j] =~ /^(````*)(\w*)$/
|
|
144
|
-
if code_start.nil?
|
|
145
|
-
code_start = j
|
|
146
|
-
else
|
|
147
|
-
code_end = j
|
|
148
|
-
end
|
|
149
|
-
elsif lines[j] =~ /<!--\s*SYNC:END/
|
|
150
|
-
sync_end_line = j
|
|
151
|
-
break
|
|
152
|
-
end
|
|
153
|
-
j += 1
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
if code_start && code_end && sync_end_line
|
|
157
|
-
year = get_latest_git_year(filepath, code_start + 1, code_end + 1)
|
|
158
|
-
changes << {
|
|
159
|
-
type: :sync_block,
|
|
160
|
-
start: sync_start_line,
|
|
161
|
-
end: sync_end_line,
|
|
162
|
-
year:,
|
|
163
|
-
}
|
|
164
|
-
code_block_ranges << (code_start..code_end)
|
|
165
|
-
i = sync_end_line + 1
|
|
166
|
-
next
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
# Check for standalone fenced code block
|
|
171
|
-
if line =~ /^(````*)(\w*)$/
|
|
172
|
-
fence_marker = $1
|
|
173
|
-
fence_start = i
|
|
174
|
-
re_end = /^#{Regexp.escape(fence_marker)}$/
|
|
175
|
-
|
|
176
|
-
j = i + 1
|
|
177
|
-
fence_end = nil
|
|
178
|
-
while j < lines.length
|
|
179
|
-
if lines[j] =~ re_end
|
|
180
|
-
fence_end = j
|
|
181
|
-
break
|
|
182
|
-
end
|
|
183
|
-
j += 1
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
if fence_end
|
|
187
|
-
year = get_latest_git_year(filepath, fence_start + 1, fence_end + 1)
|
|
188
|
-
changes << {
|
|
189
|
-
type: :code_block,
|
|
190
|
-
start: fence_start,
|
|
191
|
-
end: fence_end,
|
|
192
|
-
year:,
|
|
193
|
-
}
|
|
194
|
-
code_block_ranges << (fence_start..fence_end)
|
|
195
|
-
i = fence_end + 1
|
|
196
|
-
next
|
|
197
|
-
end
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
i += 1
|
|
201
|
-
end
|
|
202
|
-
|
|
203
|
-
# Handle removals and additions
|
|
204
|
-
has_changes = !changes.empty? || !removals.empty?
|
|
205
|
-
|
|
206
|
-
# Remove existing malformed SPDX blocks (in reverse order)
|
|
207
|
-
removals.sort_by { |r| -r[:start] }.each do |removal|
|
|
208
|
-
# Remove the SnippetEnd line
|
|
209
|
-
lines.delete_at(removal[:end])
|
|
210
|
-
# Remove lines from SnippetBegin through the --> closing the comment
|
|
211
|
-
close_idx = removal[:start]
|
|
212
|
-
while close_idx < lines.length && !lines[close_idx].include?("-->")
|
|
213
|
-
close_idx += 1
|
|
214
|
-
end
|
|
215
|
-
# Remove from start to close_idx inclusive
|
|
216
|
-
(close_idx - removal[:start] + 1).times { lines.delete_at(removal[:start]) }
|
|
217
|
-
end
|
|
218
|
-
|
|
219
|
-
# Recalculate content after removals
|
|
220
|
-
content = lines.join
|
|
221
|
-
lines = content.lines
|
|
222
|
-
|
|
223
|
-
# Re-scan for code blocks that need wrapping
|
|
224
|
-
changes = []
|
|
225
|
-
i = 0
|
|
226
|
-
|
|
227
|
-
while i < lines.length
|
|
228
|
-
line = lines[i]
|
|
229
|
-
|
|
230
|
-
# Skip if already inside an SPDX-SnippetBegin block
|
|
231
|
-
if line.include?("SPDX-SnippetBegin")
|
|
232
|
-
while i < lines.length && !lines[i].include?("SPDX-SnippetEnd")
|
|
233
|
-
i += 1
|
|
234
|
-
end
|
|
235
|
-
i += 1
|
|
236
|
-
next
|
|
237
|
-
end
|
|
238
|
-
|
|
239
|
-
# Check for SYNC:START pattern
|
|
240
|
-
if line =~ /<!--\s*SYNC:START/
|
|
241
|
-
sync_start_line = i
|
|
242
|
-
j = i + 1
|
|
243
|
-
code_start = nil
|
|
244
|
-
code_end = nil
|
|
245
|
-
sync_end_line = nil
|
|
246
|
-
|
|
247
|
-
while j < lines.length
|
|
248
|
-
if lines[j] =~ /^(````*)(\w*)$/
|
|
249
|
-
if code_start.nil?
|
|
250
|
-
code_start = j
|
|
251
|
-
else
|
|
252
|
-
code_end = j
|
|
253
|
-
end
|
|
254
|
-
elsif lines[j] =~ /<!--\s*SYNC:END/
|
|
255
|
-
sync_end_line = j
|
|
256
|
-
break
|
|
257
|
-
end
|
|
258
|
-
j += 1
|
|
259
|
-
end
|
|
260
|
-
|
|
261
|
-
if code_start && code_end && sync_end_line
|
|
262
|
-
year = get_latest_git_year(filepath, code_start + 1, code_end + 1)
|
|
263
|
-
changes << {
|
|
264
|
-
type: :sync_block,
|
|
265
|
-
start: sync_start_line,
|
|
266
|
-
end: sync_end_line,
|
|
267
|
-
year:,
|
|
268
|
-
}
|
|
269
|
-
i = sync_end_line + 1
|
|
270
|
-
next
|
|
271
|
-
end
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
# Check for standalone fenced code block
|
|
275
|
-
if line =~ /^(````*)(\w*)$/
|
|
276
|
-
fence_marker = $1
|
|
277
|
-
fence_start = i
|
|
278
|
-
re_end = /^#{Regexp.escape(fence_marker)}$/
|
|
279
|
-
|
|
280
|
-
j = i + 1
|
|
281
|
-
fence_end = nil
|
|
282
|
-
while j < lines.length
|
|
283
|
-
if lines[j] =~ re_end
|
|
284
|
-
fence_end = j
|
|
285
|
-
break
|
|
286
|
-
end
|
|
287
|
-
j += 1
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
if fence_end
|
|
291
|
-
year = get_latest_git_year(filepath, fence_start + 1, fence_end + 1)
|
|
292
|
-
changes << {
|
|
293
|
-
type: :code_block,
|
|
294
|
-
start: fence_start,
|
|
295
|
-
end: fence_end,
|
|
296
|
-
year:,
|
|
297
|
-
}
|
|
298
|
-
i = fence_end + 1
|
|
299
|
-
next
|
|
300
|
-
end
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
i += 1
|
|
304
|
-
end
|
|
305
|
-
|
|
306
|
-
return if changes.empty? && !has_changes
|
|
307
|
-
|
|
308
|
-
# Apply changes in reverse order to preserve line numbers
|
|
309
|
-
changes.sort_by { |c| -c[:start] }.each do |change|
|
|
310
|
-
# REUSE-IgnoreStart
|
|
311
|
-
snippet_begin = "<!-- SPDX-SnippetBegin -->\n<!--\n SPDX-FileCopyrightText: #{change[:year]} #{COPYRIGHT_HOLDER}\n SPDX-License-Identifier: #{LICENSE}\n-->\n"
|
|
312
|
-
snippet_end = "<!-- SPDX-SnippetEnd -->\n"
|
|
313
|
-
# REUSE-IgnoreEnd
|
|
314
|
-
|
|
315
|
-
# Insert end marker after the block
|
|
316
|
-
lines.insert(change[:end] + 1, snippet_end)
|
|
317
|
-
# Insert begin marker before the block
|
|
318
|
-
lines.insert(change[:start], snippet_begin)
|
|
319
|
-
end
|
|
320
|
-
|
|
321
|
-
File.write(filepath, lines.join)
|
|
322
|
-
puts "Updated: #{filepath} (#{changes.length} code block(s))"
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
# Finds markdown files to process.
|
|
326
|
-
#
|
|
327
|
-
# License automation runs on file sets. Users may specify paths or want all
|
|
328
|
-
# files. This handles both cases using git ls-files for tracking.
|
|
329
|
-
#
|
|
330
|
-
# [paths] Explicit paths to process, or empty for all tracked .md files.
|
|
331
|
-
def find_md_files(paths)
|
|
332
|
-
# Use git ls-files to respect .gitignore
|
|
333
|
-
if paths.empty?
|
|
334
|
-
`git ls-files '*.md'`.split("\n")
|
|
335
|
-
else
|
|
336
|
-
paths.flat_map do |path|
|
|
337
|
-
if File.directory?(path)
|
|
338
|
-
`git ls-files '#{path}/**/*.md'`.split("\n")
|
|
339
|
-
else
|
|
340
|
-
path
|
|
341
|
-
end
|
|
342
|
-
end
|
|
343
|
-
end
|
|
344
|
-
end
|
|
345
|
-
|
|
346
|
-
if __FILE__ == $0
|
|
347
|
-
paths = ARGV.empty? ? [] : ARGV
|
|
348
|
-
files = find_md_files(paths)
|
|
349
|
-
|
|
350
|
-
files.each do |file|
|
|
351
|
-
process_file(file)
|
|
352
|
-
end
|
|
353
|
-
end
|
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#--
|
|
4
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
-
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
6
|
-
#++
|
|
7
|
-
|
|
8
|
-
# Script to add SPDX snippet headers to RDoc code examples in Ruby files.
|
|
9
|
-
#
|
|
10
|
-
# Usage: ruby scripts/add_spdx_rdoc_snippets.rb [path...]
|
|
11
|
-
#
|
|
12
|
-
# If no paths are given, processes all .rb files via git ls-files.
|
|
13
|
-
#
|
|
14
|
-
# Rules:
|
|
15
|
-
# - Wraps RDoc code examples (indented comment lines) with SPDX snippet headers
|
|
16
|
-
# - Uses #-- and #++ to hide the SPDX headers from RDoc rendering
|
|
17
|
-
# - Uses git blame to determine the latest edit year for the code lines
|
|
18
|
-
# - Skips blocks that are already wrapped with SPDX-SnippetBegin
|
|
19
|
-
|
|
20
|
-
require "open3"
|
|
21
|
-
require "date"
|
|
22
|
-
|
|
23
|
-
COPYRIGHT_HOLDER = "Kerrick Long"
|
|
24
|
-
LICENSE = "MIT-0"
|
|
25
|
-
|
|
26
|
-
# Determines the latest edit year for a line range using git blame.
|
|
27
|
-
#
|
|
28
|
-
# Copyright years come from when code was last modified. Git blame provides
|
|
29
|
-
# per-line authorship. Extract and return the most recent year.
|
|
30
|
-
#
|
|
31
|
-
# [file] Path to the file.
|
|
32
|
-
# [start_line] First line number (1-indexed).
|
|
33
|
-
# [end_line] Last line number (1-indexed).
|
|
34
|
-
def get_latest_git_year(file, start_line, end_line)
|
|
35
|
-
cmd = %W[git blame -L #{start_line},#{end_line} --date=short -- #{file}]
|
|
36
|
-
output, _status = Open3.capture2(*cmd)
|
|
37
|
-
years = output.scan(/(\d{4})-\d{2}-\d{2}/).flatten.map(&:to_i)
|
|
38
|
-
years.empty? ? Date.today.year : years.max
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# Identifies RDoc code blocks in Ruby source files.
|
|
42
|
-
#
|
|
43
|
-
# RDoc code examples are indented comment lines. They need MIT-0 licensing
|
|
44
|
-
# separate from the file. This scans for the indentation pattern that
|
|
45
|
-
# identifies code blocks.
|
|
46
|
-
#
|
|
47
|
-
# [lines] Array of line strings from the file.
|
|
48
|
-
def find_rdoc_code_blocks(lines)
|
|
49
|
-
# Find all RDoc code blocks (indented comment lines)
|
|
50
|
-
# Returns array of {start:, end:, indent:} where indent is the comment prefix
|
|
51
|
-
blocks = []
|
|
52
|
-
i = 0
|
|
53
|
-
|
|
54
|
-
while i < lines.length
|
|
55
|
-
line = lines[i]
|
|
56
|
-
|
|
57
|
-
# Check if this is an indented code line in a comment
|
|
58
|
-
# Pattern: optional leading whitespace, #, then 3+ spaces (RDoc code indent)
|
|
59
|
-
if line =~ /^(\s*)#( +)(\S.*)$/
|
|
60
|
-
prefix = $1 # leading whitespace before #
|
|
61
|
-
block_start = i
|
|
62
|
-
|
|
63
|
-
# Find the extent of this code block
|
|
64
|
-
j = i
|
|
65
|
-
while j < lines.length
|
|
66
|
-
current = lines[j]
|
|
67
|
-
# Code block continues if line is indented code OR empty comment line
|
|
68
|
-
if current =~ /^#{Regexp.escape(prefix)}#( +|\s*$)/
|
|
69
|
-
j += 1
|
|
70
|
-
else
|
|
71
|
-
break
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
block_end = j - 1
|
|
76
|
-
|
|
77
|
-
# Only count as a block if it has actual code (not just empty lines)
|
|
78
|
-
has_code = (block_start..block_end).any? { |k| lines[k] =~ /^#{Regexp.escape(prefix)}# +\S/ }
|
|
79
|
-
|
|
80
|
-
if has_code && block_end > block_start
|
|
81
|
-
blocks << { start: block_start, end: block_end, prefix: }
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
i = j
|
|
85
|
-
else
|
|
86
|
-
i += 1
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
blocks
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# Checks if a code block already has SPDX snippet headers.
|
|
94
|
-
#
|
|
95
|
-
# Already-wrapped blocks should be skipped. Re-wrapping wastes time and
|
|
96
|
-
# creates noisy diffs. This checks for the #++ marker before a block.
|
|
97
|
-
#
|
|
98
|
-
# [lines] Array of line strings.
|
|
99
|
-
# [block_start] Index of the code block start.
|
|
100
|
-
# [prefix] The indentation prefix for this block.
|
|
101
|
-
def is_already_wrapped?(lines, block_start, prefix)
|
|
102
|
-
# Check if the line before the block is #++ (meaning it's already wrapped)
|
|
103
|
-
return false if block_start < 1
|
|
104
|
-
|
|
105
|
-
prev_line = lines[block_start - 1]
|
|
106
|
-
prev_line =~ /^#{Regexp.escape(prefix)}#\+\+\s*$/
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# Wraps RDoc code blocks in a Ruby file with SPDX snippet headers.
|
|
110
|
-
#
|
|
111
|
-
# Each code example needs MIT-0 licensing. Processing involves scanning for
|
|
112
|
-
# indented examples and inserting hidden SPDX headers. This function
|
|
113
|
-
# orchestrates that workflow.
|
|
114
|
-
#
|
|
115
|
-
# [filepath] Path to the Ruby file.
|
|
116
|
-
def process_file(filepath)
|
|
117
|
-
content = File.read(filepath)
|
|
118
|
-
lines = content.lines
|
|
119
|
-
|
|
120
|
-
blocks = find_rdoc_code_blocks(lines)
|
|
121
|
-
|
|
122
|
-
# Filter out already-wrapped blocks
|
|
123
|
-
blocks.reject! { |b| is_already_wrapped?(lines, b[:start], b[:prefix]) }
|
|
124
|
-
|
|
125
|
-
return if blocks.empty?
|
|
126
|
-
|
|
127
|
-
# Apply changes in reverse order to preserve line numbers
|
|
128
|
-
blocks.sort_by { |b| -b[:start] }.each do |block|
|
|
129
|
-
year = get_latest_git_year(filepath, block[:start] + 1, block[:end] + 1)
|
|
130
|
-
prefix = block[:prefix]
|
|
131
|
-
|
|
132
|
-
# Build the wrapper lines
|
|
133
|
-
# REUSE-IgnoreStart
|
|
134
|
-
begin_wrapper = [
|
|
135
|
-
"#{prefix}#--\n",
|
|
136
|
-
"#{prefix}# SPDX-SnippetBegin\n",
|
|
137
|
-
"#{prefix}# SPDX-FileCopyrightText: #{year} #{COPYRIGHT_HOLDER}\n",
|
|
138
|
-
"#{prefix}# SPDX-License-Identifier: #{LICENSE}\n",
|
|
139
|
-
"#{prefix}#++\n",
|
|
140
|
-
]
|
|
141
|
-
|
|
142
|
-
end_wrapper = [
|
|
143
|
-
"#{prefix}#--\n",
|
|
144
|
-
"#{prefix}# SPDX-SnippetEnd\n",
|
|
145
|
-
"#{prefix}#++\n",
|
|
146
|
-
]
|
|
147
|
-
# REUSE-IgnoreEnd
|
|
148
|
-
|
|
149
|
-
# Insert end wrapper after the block
|
|
150
|
-
lines.insert(block[:end] + 1, *end_wrapper)
|
|
151
|
-
# Insert begin wrapper before the block
|
|
152
|
-
lines.insert(block[:start], *begin_wrapper)
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
File.write(filepath, lines.join)
|
|
156
|
-
puts "Updated: #{filepath} (#{blocks.length} code block(s))"
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
# Finds Ruby files to process.
|
|
160
|
-
#
|
|
161
|
-
# License automation runs on file sets. Users may specify paths or want all
|
|
162
|
-
# files. This handles both cases using git ls-files for tracking.
|
|
163
|
-
#
|
|
164
|
-
# [paths] Explicit paths to process, or empty for all tracked .rb files.
|
|
165
|
-
def find_rb_files(paths)
|
|
166
|
-
if paths.empty?
|
|
167
|
-
`git ls-files '*.rb'`.split("\n")
|
|
168
|
-
else
|
|
169
|
-
paths.flat_map do |path|
|
|
170
|
-
if File.directory?(path)
|
|
171
|
-
`git ls-files '#{path}/**/*.rb'`.split("\n")
|
|
172
|
-
else
|
|
173
|
-
path
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
end
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
if __FILE__ == $0
|
|
180
|
-
paths = ARGV.empty? ? [] : ARGV
|
|
181
|
-
files = find_rb_files(paths)
|
|
182
|
-
|
|
183
|
-
files.each do |file|
|
|
184
|
-
process_file(file)
|
|
185
|
-
end
|
|
186
|
-
end
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#--
|
|
4
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
-
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
6
|
-
#++
|
|
7
|
-
|
|
8
|
-
namespace :license do
|
|
9
|
-
namespace :headers do
|
|
10
|
-
desc "Ensure markdown files have correct CC-BY-SA-4.0 headers"
|
|
11
|
-
task :md, [:files] do |_t, args|
|
|
12
|
-
files = args[:files] || ""
|
|
13
|
-
ruby "tasks/license/headers_md.rb #{files}"
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
desc "Ensure Ruby files have correct AGPL-3.0-or-later headers"
|
|
17
|
-
task :rb, [:files] do |_t, args|
|
|
18
|
-
files = args[:files] || ""
|
|
19
|
-
ruby "tasks/license/headers_rb.rb #{files}"
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
desc "Ensure all files have correct license headers"
|
|
23
|
-
task :all do
|
|
24
|
-
Rake::Task["license:headers:md"].invoke
|
|
25
|
-
Rake::Task["license:headers:rb"].invoke
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
namespace :snippets do
|
|
30
|
-
desc "Add MIT-0 SPDX snippet headers to markdown fenced code blocks"
|
|
31
|
-
task :md, [:files] do |_t, args|
|
|
32
|
-
files = args[:files] || ""
|
|
33
|
-
ruby "tasks/license/snippets_md.rb #{files}"
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
desc "Add MIT-0 SPDX snippet headers to RDoc code examples in Ruby files"
|
|
37
|
-
task :rdoc, [:files] do |_t, args|
|
|
38
|
-
files = args[:files] || "lib/"
|
|
39
|
-
ruby "tasks/license/snippets_rdoc.rb #{files}"
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
desc "Add MIT-0 SPDX snippet headers to all code examples"
|
|
43
|
-
task :all do
|
|
44
|
-
Rake::Task["license:snippets:md"].invoke
|
|
45
|
-
Rake::Task["license:snippets:rdoc"].invoke
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
desc "Run all license tasks (headers + snippets)"
|
|
50
|
-
task all: ["headers:all", "snippets:all"]
|
|
51
|
-
|
|
52
|
-
desc "Run license tasks on changed files only (staged + unstaged)"
|
|
53
|
-
task :new do
|
|
54
|
-
# Get changed .md and .rb files (staged and unstaged)
|
|
55
|
-
changed_md = `git diff --name-only --diff-filter=ACMR HEAD -- '*.md' 2>/dev/null`.split("\n")
|
|
56
|
-
staged_md = `git diff --name-only --cached --diff-filter=ACMR -- '*.md' 2>/dev/null`.split("\n")
|
|
57
|
-
changed_rb = `git diff --name-only --diff-filter=ACMR HEAD -- '*.rb' 2>/dev/null`.split("\n")
|
|
58
|
-
staged_rb = `git diff --name-only --cached --diff-filter=ACMR -- '*.rb' 2>/dev/null`.split("\n")
|
|
59
|
-
|
|
60
|
-
# Also get untracked new files
|
|
61
|
-
untracked = `git ls-files --others --exclude-standard`.split("\n")
|
|
62
|
-
untracked_md = untracked.select { |f| f.end_with?(".md") }
|
|
63
|
-
untracked_rb = untracked.select { |f| f.end_with?(".rb") }
|
|
64
|
-
|
|
65
|
-
md_files = (changed_md + staged_md + untracked_md).uniq.join(" ")
|
|
66
|
-
rb_files = (changed_rb + staged_rb + untracked_rb).uniq
|
|
67
|
-
|
|
68
|
-
# Filter rb files to only lib/
|
|
69
|
-
lib_rb_files = rb_files.select { |f| f.start_with?("lib/") }.join(" ")
|
|
70
|
-
|
|
71
|
-
if md_files.empty? && lib_rb_files.empty?
|
|
72
|
-
puts "No changed .md or lib/*.rb files to process"
|
|
73
|
-
else
|
|
74
|
-
unless md_files.empty?
|
|
75
|
-
puts "Processing #{md_files.split.count} changed .md file(s)..."
|
|
76
|
-
Rake::Task["license:headers:md"].invoke(md_files)
|
|
77
|
-
Rake::Task["license:headers:md"].reenable
|
|
78
|
-
Rake::Task["license:snippets:md"].invoke(md_files)
|
|
79
|
-
Rake::Task["license:snippets:md"].reenable
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
unless lib_rb_files.empty?
|
|
83
|
-
puts "Processing #{lib_rb_files.split.count} changed lib/*.rb file(s)..."
|
|
84
|
-
Rake::Task["license:headers:rb"].invoke(lib_rb_files)
|
|
85
|
-
Rake::Task["license:headers:rb"].reenable
|
|
86
|
-
Rake::Task["license:snippets:rdoc"].invoke(lib_rb_files)
|
|
87
|
-
Rake::Task["license:snippets:rdoc"].reenable
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#--
|
|
4
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
-
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
6
|
-
#++
|
|
7
|
-
|
|
8
|
-
require "rubocop/rake_task"
|
|
9
|
-
require "rubycritic/rake_task"
|
|
10
|
-
require "inch/rake"
|
|
11
|
-
|
|
12
|
-
RuboCop::RakeTask.new
|
|
13
|
-
|
|
14
|
-
# Run rubycritic in a shell to prevent it from exiting the rake process
|
|
15
|
-
task :rubycritic do
|
|
16
|
-
paths = []
|
|
17
|
-
paths << "exe" if Dir.exist?("exe")
|
|
18
|
-
paths << "lib" if Dir.exist?("lib")
|
|
19
|
-
paths << "sig" if Dir.exist?("sig")
|
|
20
|
-
sh "bundle exec rubycritic --no-browser #{paths.join(' ')}" unless paths.empty?
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
Inch::Rake::Suggest.new("doc:suggest", "exe/**/*.rb", "lib/**/*.rb", "sig/**/*.rbs") do |suggest|
|
|
24
|
-
suggest.args << ""
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
namespace :lint do
|
|
28
|
-
task :safe_rdoc_coverage do
|
|
29
|
-
if Rake::Task.task_defined?("rdoc:coverage")
|
|
30
|
-
sh "bundle exec rake rdoc:coverage"
|
|
31
|
-
else
|
|
32
|
-
puts "rdoc:coverage task not defined, skipping"
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Build dynamic task lists based on what's available
|
|
37
|
-
docs_tasks = %w[rubycritic]
|
|
38
|
-
docs_tasks.unshift("autodoc") if Rake::Task.task_defined?("autodoc")
|
|
39
|
-
docs_tasks << "safe_rdoc_coverage" if Rake::Task.task_defined?("rdoc:coverage")
|
|
40
|
-
|
|
41
|
-
code_tasks = %w[rubocop rubycritic]
|
|
42
|
-
code_tasks += %w[cargo:fmt cargo:clippy cargo:test] if Dir.exist?("ext")
|
|
43
|
-
|
|
44
|
-
task docs: docs_tasks
|
|
45
|
-
task code: code_tasks
|
|
46
|
-
task all: %w[docs code]
|
|
47
|
-
|
|
48
|
-
namespace :fix do
|
|
49
|
-
desc "Auto-fix RuboCop offenses (most aggressive)"
|
|
50
|
-
task :rubocop do
|
|
51
|
-
sh "bundle exec rubocop --autocorrect-all"
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
if Dir.exist?("ext")
|
|
55
|
-
desc "Auto-fix Clippy warnings (most aggressive: --fix --allow-dirty --allow-staged)"
|
|
56
|
-
task :clippy do
|
|
57
|
-
ext_dirs = Dir.glob("ext/*").select { |d| File.directory?(d) && File.exist?("#{d}/Cargo.toml") }
|
|
58
|
-
ext_dirs.each do |dir|
|
|
59
|
-
sh "cd #{dir} && cargo clippy --fix --allow-dirty --allow-staged"
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# Build dynamic fix:all task
|
|
65
|
-
fix_all_tasks = %w[lint:fix:rubocop]
|
|
66
|
-
fix_all_tasks.insert(1, "lint:fix:clippy") if Dir.exist?("ext")
|
|
67
|
-
|
|
68
|
-
desc "Run all auto-fix tasks"
|
|
69
|
-
task all: fix_all_tasks
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
desc "Run all lint auto-fix tasks"
|
|
74
|
-
task("lint:fix") { Rake::Task["lint:fix:all"].invoke }
|
|
75
|
-
|
|
76
|
-
# Aliases for convenience
|
|
77
|
-
task "rubocop:autocorrect_all" => "lint:fix:rubocop"
|
|
78
|
-
|
|
79
|
-
desc "Run all lint tasks"
|
|
80
|
-
task(:lint) { Rake::Task["lint:all"].invoke }
|