this_is_ruby 0.1.0 → 0.2.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/CHANGELOG.md +22 -15
- data/README.md +21 -14
- data/lib/this_is_ruby/cli.rb +6 -3
- data/lib/this_is_ruby/plan.rb +8 -4
- data/lib/this_is_ruby/repo.rb +26 -0
- data/lib/this_is_ruby/rule.rb +4 -4
- data/lib/this_is_ruby/rules.rb +3 -3
- data/lib/this_is_ruby/version.rb +1 -1
- metadata +6 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 70cb32fbaddf28dbdae4e21b4b8e009fbda116b02c967ddf08b9618db5df4a0c
|
|
4
|
+
data.tar.gz: fe332fb48d5d355a59cb13b7ff1efe4aa403f2ed031aaa5e7f66924bd179bb62
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 71f21c362ac2d542b6329f3082dd6de70b6f6b37d2c78c00a0a334ba371d20b76093673f23cb18bd5d9b86838c6c1647d4cf0527fc29f474794dbfc04d783a48
|
|
7
|
+
data.tar.gz: 28d66d7abd69c80304bc01ee5c848cbc35b918854c014dd81b38ed859a4e9dc985c00834a954b3a171b3a4ee88ded33794862c1a860350efc522fd3d9ff916e6
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
- Frontend sources are vendored by default. Telling GitHub a project is Ruby is
|
|
6
|
+
what the gem is for, and it read oddly to name that after a flag most people
|
|
7
|
+
would never pass. `--fair` keeps them counted, marking only what a tool wrote
|
|
8
|
+
or a generator copied in, for a repository whose frontend really is the point. `--all-frontend` is still accepted and does
|
|
9
|
+
nothing, so an existing CI step keeps working.
|
|
10
|
+
- Reword the summary and description.
|
|
11
|
+
|
|
12
|
+
## 0.1.1
|
|
13
|
+
|
|
14
|
+
- The "now" column no longer counts files that are already out of GitHub's
|
|
15
|
+
language bar. It asks `git check-attr`, so Rails' own `db/schema.rb` line and
|
|
16
|
+
anything written by hand are honoured, and it subtracts only what this run
|
|
17
|
+
claims, so re-running on a repository already converted still shows the
|
|
18
|
+
contrast rather than reporting that nothing would change.
|
|
19
|
+
|
|
3
20
|
## 0.1.0
|
|
4
21
|
|
|
5
22
|
Initial release.
|
|
@@ -8,18 +25,8 @@ Initial release.
|
|
|
8
25
|
Webpacker and Vite builds, SimpleCov reports, SQL structure dumps and
|
|
9
26
|
shadcn/ui components.
|
|
10
27
|
- Writes a managed block in `.gitattributes`, leaving the rest of the file
|
|
11
|
-
untouched, and stays quiet about anything already
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
- Exit 1 on an unknown command or option instead of 0, so a typo in a CI step
|
|
17
|
-
fails rather than silently skipping `check`.
|
|
18
|
-
- Leave a path alone when its Linguist attribute is already decided, including
|
|
19
|
-
when it was explicitly unset (`-linguist-generated`) or made unspecified
|
|
20
|
-
(`!linguist-generated`). Writing our line after such a declaration reversed
|
|
21
|
-
it, because the last match wins.
|
|
22
|
-
- Rewrite the managed block where it already sits, so content below it stays
|
|
23
|
-
below it.
|
|
24
|
-
- Read `git rev-parse` from stdout alone: with `GIT_TRACE` set, or on any git
|
|
25
|
-
warning, the merged stream became part of the repository root.
|
|
28
|
+
untouched, and stays quiet about anything already decided there, including an
|
|
29
|
+
attribute the owner explicitly unset.
|
|
30
|
+
- Rewrites the block where it sits, so content below it stays below it.
|
|
31
|
+
- `plan`, `apply` and `check` commands; `--all-frontend` opt-in, which uses
|
|
32
|
+
`linguist-vendored` so diffs keep working.
|
data/README.md
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
# this_is_ruby
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://rubygems.org/gems/this_is_ruby)
|
|
4
|
+
[](https://github.com/evilmartians/this_is_ruby/actions/workflows/ci.yml)
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
Ruby is one of the most eloquent and efficient languages, but it gets punished for it by GitHub's language attribution. A repository's language there is whichever one has the most bytes, and a Rails app, carefully designed to require next to no boilerplate code, easily ends up with less Ruby than JS, TS or HTML (ERB).
|
|
7
|
+
|
|
8
|
+
This gem tells GitHub: this is Ruby, by marking your frontend as `linguist-vendored`. No side effects on diffs or other DX.
|
|
6
9
|
|
|
7
10
|
## Install
|
|
8
11
|
|
|
@@ -12,6 +15,9 @@ group :development do
|
|
|
12
15
|
end
|
|
13
16
|
```
|
|
14
17
|
|
|
18
|
+
Or `gem install this_is_ruby` to run it against any repository without adding
|
|
19
|
+
it to a project.
|
|
20
|
+
|
|
15
21
|
## Use
|
|
16
22
|
|
|
17
23
|
```console
|
|
@@ -34,24 +40,26 @@ $ this_is_ruby check # exit 1 when .gitattributes is out of date
|
|
|
34
40
|
| SimpleCov HTML reports, found by the report's own title | `linguist-generated` |
|
|
35
41
|
| `db/structure.sql`, matching how Rails already treats `db/schema.rb` | `linguist-generated` |
|
|
36
42
|
| shadcn/ui components, when `components.json` shows a generator put them there | `linguist-vendored` |
|
|
43
|
+
| your frontend sources: `app/javascript/`, `app/frontend/`, `frontend/` | `linguist-vendored` |
|
|
37
44
|
|
|
38
45
|
|
|
39
|
-
|
|
46
|
+
[irinanazarova/react-starter-kit-this-is-ruby][demo] is a fork of the Inertia Rails starter kit whose only change is the sixteen lines `this_is_ruby` wrote. Upstream, GitHub counts it as 60.6% TypeScript and 21.2% Ruby. The fork reads **82.6% Ruby, 1.1% TypeScript**. Compare its language bar with [the upstream one][irsk].
|
|
40
47
|
|
|
41
|
-
##
|
|
48
|
+
## If your frontend really is the point
|
|
42
49
|
|
|
43
|
-
|
|
50
|
+
Some repositories genuinely are TypeScript projects, and for those:
|
|
44
51
|
|
|
45
52
|
```console
|
|
46
|
-
$ this_is_ruby --
|
|
53
|
+
$ this_is_ruby --fair
|
|
47
54
|
```
|
|
48
|
-
On the same repository that marks `app/javascript/` as `linguist-vendored`, and
|
|
49
|
-
GitHub then counts it as **82.6% Ruby, 1.1% TypeScript**. That is not an
|
|
50
|
-
estimate: [irinanazarova/react-starter-kit-this-is-ruby][demo] is a fork of the
|
|
51
|
-
kit whose only change is the sixteen lines this command wrote. Compare its
|
|
52
|
-
language bar with [the upstream one][irsk].
|
|
53
55
|
|
|
54
|
-
|
|
56
|
+
That marks only the files nobody in the project wrote: every generated row in
|
|
57
|
+
the table above, plus the shadcn components a generator copied in. Your own
|
|
58
|
+
frontend keeps counting.
|
|
59
|
+
|
|
60
|
+
## Why vendored and not generated
|
|
61
|
+
|
|
62
|
+
The one line that matters is which attribute it uses. [Generated files are suppressed in diffs][docs]; vendored files are not. So your frontend is marked `linguist-vendored`, every source file keeps showing up in full in pull requests, and the only thing that changes is the color of the bar at the top of the page:
|
|
55
63
|
|
|
56
64
|
```console
|
|
57
65
|
$ git check-attr linguist-vendored linguist-generated -- app/javascript/pages/home/index.tsx
|
|
@@ -71,8 +79,7 @@ On GitHub itself:
|
|
|
71
79
|
plainly: these files "are suppressed in diffs". Reviewers get a "Load diff"
|
|
72
80
|
button instead of the patch. The gem uses this attribute only for tool
|
|
73
81
|
output; everything hand-written gets `linguist-vendored`, which leaves diffs
|
|
74
|
-
alone. That is why
|
|
75
|
-
marking it generated.
|
|
82
|
+
alone. That is why your frontend is vendored rather than marked generated.
|
|
76
83
|
- **Code search still indexes the files.** They stay findable, and GitHub adds
|
|
77
84
|
`is:generated` and `is:vendored` filters, so a query written as
|
|
78
85
|
`-is:vendored` will skip them.
|
data/lib/this_is_ruby/cli.rb
CHANGED
|
@@ -27,7 +27,7 @@ module ThisIsRuby
|
|
|
27
27
|
@argv = argv
|
|
28
28
|
@out = out
|
|
29
29
|
@err = err
|
|
30
|
-
@options = {path: ".",
|
|
30
|
+
@options = {path: ".", frontend: true, color: out.tty?}
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def call
|
|
@@ -38,7 +38,7 @@ module ThisIsRuby
|
|
|
38
38
|
|
|
39
39
|
repo = Repo.at(@options[:path])
|
|
40
40
|
attributes = AttributesFile.new(repo.root.join(".gitattributes"))
|
|
41
|
-
plan = Plan.build(repo, attributes:,
|
|
41
|
+
plan = Plan.build(repo, attributes:, frontend: @options[:frontend])
|
|
42
42
|
report = Report.new(plan, out: @out, color: @options[:color])
|
|
43
43
|
|
|
44
44
|
send(command, plan, attributes, report)
|
|
@@ -78,7 +78,10 @@ module ThisIsRuby
|
|
|
78
78
|
parser = OptionParser.new do |opts|
|
|
79
79
|
opts.banner = USAGE
|
|
80
80
|
opts.on("--path DIR", "repository to inspect (default: .)") { |dir| @options[:path] = dir }
|
|
81
|
-
opts.on("--
|
|
81
|
+
opts.on("--fair", "exclude only what a tool wrote or a generator copied in") { @options[:frontend] = false }
|
|
82
|
+
# 0.1.x asked for today's default with a flag. Accept the old name and
|
|
83
|
+
# do nothing, rather than break a CI step that still passes it.
|
|
84
|
+
opts.on("--all-frontend", "deprecated alias, now the default") { @options[:frontend] = true }
|
|
82
85
|
opts.on("--[no-]color", "colourise output") { |on| @options[:color] = on }
|
|
83
86
|
opts.on("-v", "--version", "print the version") do
|
|
84
87
|
@out.puts VERSION
|
data/lib/this_is_ruby/plan.rb
CHANGED
|
@@ -7,9 +7,9 @@ module ThisIsRuby
|
|
|
7
7
|
|
|
8
8
|
attr_reader :repo, :emissions, :declared
|
|
9
9
|
|
|
10
|
-
def self.build(repo, attributes:,
|
|
10
|
+
def self.build(repo, attributes:, frontend: true)
|
|
11
11
|
spoken_for = spoken_for(attributes.existing_attributes)
|
|
12
|
-
found = Rules.for_level(
|
|
12
|
+
found = Rules.for_level(frontend:).flat_map { |rule| rule.apply(repo) }
|
|
13
13
|
declared, emissions = found.partition do |emission|
|
|
14
14
|
spoken_for.any? { |pattern| covers?(pattern, emission.pattern) }
|
|
15
15
|
end
|
|
@@ -65,8 +65,12 @@ module ThisIsRuby
|
|
|
65
65
|
@claimed_paths ||= emissions.flat_map(&:paths).to_set
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
# The bar without our block: what GitHub reports today, minus the paths this
|
|
69
|
+
# run is claiming. Asking git means Rails' own `db/schema.rb` line and
|
|
70
|
+
# anything hand-written are honoured, while re-running on a repository we
|
|
71
|
+
# already converted still shows the contrast rather than "nothing changes".
|
|
72
|
+
def before = @before ||= LanguageEstimate.of(repo, excluding: repo.already_excluded - claimed_paths)
|
|
69
73
|
|
|
70
|
-
def after = @after ||= LanguageEstimate.of(repo, excluding: claimed_paths)
|
|
74
|
+
def after = @after ||= LanguageEstimate.of(repo, excluding: repo.already_excluded | claimed_paths)
|
|
71
75
|
end
|
|
72
76
|
end
|
data/lib/this_is_ruby/repo.rb
CHANGED
|
@@ -17,6 +17,9 @@ module ThisIsRuby
|
|
|
17
17
|
# markers we check for all sit in the first few lines.
|
|
18
18
|
PEEK_BYTES = 4096
|
|
19
19
|
|
|
20
|
+
# The attributes that take a file out of GitHub's language statistics.
|
|
21
|
+
LINGUIST_EXCLUSIONS = %w[linguist-generated linguist-vendored linguist-documentation].freeze
|
|
22
|
+
|
|
20
23
|
attr_reader :root
|
|
21
24
|
|
|
22
25
|
def self.at(path)
|
|
@@ -55,6 +58,17 @@ module ThisIsRuby
|
|
|
55
58
|
full.open("rb") { |io| io.read(PEEK_BYTES) }
|
|
56
59
|
end
|
|
57
60
|
|
|
61
|
+
# Paths git already reports as excluded from Linguist's counts, whoever
|
|
62
|
+
# declared them: our own block, the lines Rails generates, or something
|
|
63
|
+
# written by hand. Resolving the patterns ourselves would mean
|
|
64
|
+
# reimplementing gitignore matching, so ask git, which owns the answer.
|
|
65
|
+
def already_excluded
|
|
66
|
+
@already_excluded ||= begin
|
|
67
|
+
paths = tracked
|
|
68
|
+
paths.empty? ? Set.new : Set.new(check_attr(paths))
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
58
72
|
def size(path)
|
|
59
73
|
full = root.join(path)
|
|
60
74
|
full.file? ? full.size : 0
|
|
@@ -62,6 +76,18 @@ module ThisIsRuby
|
|
|
62
76
|
|
|
63
77
|
private
|
|
64
78
|
|
|
79
|
+
# `check-attr --stdin -z` reads NUL-separated paths and answers with
|
|
80
|
+
# NUL-separated (path, attribute, value) triples.
|
|
81
|
+
def check_attr(paths)
|
|
82
|
+
out, _err, status = Open3.capture3(
|
|
83
|
+
"git", "-C", root.to_s, "check-attr", "--stdin", "-z", *LINGUIST_EXCLUSIONS,
|
|
84
|
+
stdin_data: paths.join("\0")
|
|
85
|
+
)
|
|
86
|
+
return [] unless status.success?
|
|
87
|
+
|
|
88
|
+
out.split("\0").each_slice(3).filter_map { |path, _attribute, value| path if value == "set" }
|
|
89
|
+
end
|
|
90
|
+
|
|
65
91
|
def tracked_set
|
|
66
92
|
@tracked_set ||= tracked.to_set
|
|
67
93
|
end
|
data/lib/this_is_ruby/rule.rb
CHANGED
|
@@ -7,10 +7,10 @@ module ThisIsRuby
|
|
|
7
7
|
# Rules never guess: when the evidence is not on disk they return nothing,
|
|
8
8
|
# so a project that has no coverage report gets no line about one.
|
|
9
9
|
#
|
|
10
|
-
# :safe rules find files a tool produced
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
10
|
+
# :safe rules find files a tool produced. :frontend rules find hand-written
|
|
11
|
+
# sources, which is a claim about what the repository is rather than about
|
|
12
|
+
# who typed the file; both run by default, and --fair drops the second group
|
|
13
|
+
# for a project whose frontend really is the point.
|
|
14
14
|
class Rule
|
|
15
15
|
LEVELS = %i[safe frontend].freeze
|
|
16
16
|
|
data/lib/this_is_ruby/rules.rb
CHANGED
|
@@ -121,7 +121,7 @@ module ThisIsRuby
|
|
|
121
121
|
Rule.new(
|
|
122
122
|
key: :frontend_sources,
|
|
123
123
|
attribute: "linguist-vendored",
|
|
124
|
-
summary: "frontend sources
|
|
124
|
+
summary: "frontend sources (pass --fair to keep them counted)",
|
|
125
125
|
level: :frontend
|
|
126
126
|
) do |repo|
|
|
127
127
|
present = FRONTEND_ROOTS.select { |dir| under(repo, dir).any? }
|
|
@@ -129,8 +129,8 @@ module ThisIsRuby
|
|
|
129
129
|
end
|
|
130
130
|
].freeze
|
|
131
131
|
|
|
132
|
-
def for_level(
|
|
133
|
-
|
|
132
|
+
def for_level(frontend:)
|
|
133
|
+
frontend ? ALL : ALL.select(&:safe?)
|
|
134
134
|
end
|
|
135
135
|
end
|
|
136
136
|
end
|
data/lib/this_is_ruby/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: this_is_ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Irina Nazarova
|
|
@@ -9,12 +9,10 @@ bindir: exe
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies: []
|
|
12
|
-
description:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
they routinely outweigh the app's own Ruby. this_is_ruby finds them and
|
|
17
|
-
writes the .gitattributes overrides Linguist already understands.
|
|
12
|
+
description: |-
|
|
13
|
+
Ruby is one of the most eloquent and efficient languages, but it gets punished for it by GitHub's language attribution. Even more so, a Rails app, carefully designed to require next to no boilerplate code, easily ends up with less Ruby than JS, TS or HTML (ERB).
|
|
14
|
+
|
|
15
|
+
This gem tells GitHub: this is Ruby, by marking your frontend as "linguist-vendored". No side effects on diffs or other DX.
|
|
18
16
|
email:
|
|
19
17
|
- inazarova@evilmartians.com
|
|
20
18
|
executables:
|
|
@@ -61,5 +59,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
61
59
|
requirements: []
|
|
62
60
|
rubygems_version: 3.6.7
|
|
63
61
|
specification_version: 4
|
|
64
|
-
summary: Tell GitHub
|
|
62
|
+
summary: Tell GitHub your project is Ruby.
|
|
65
63
|
test_files: []
|