git 5.1.0 → 5.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 +45 -0
- data/CONTRIBUTING.md +185 -165
- data/LICENSE +1 -1
- data/README.md +151 -151
- data/git.gemspec +35 -3
- data/lib/git/command_line/base.rb +1 -2
- data/lib/git/commands/base.rb +1 -1
- data/lib/git/commands/cat_file/raw.rb +8 -7
- data/lib/git/repository/branching.rb +79 -5
- data/lib/git/version.rb +1 -1
- metadata +5 -94
- data/.claude/commands/address-copilot-reviews.md +0 -14
- data/.claude/settings.json +0 -16
- data/.claude/skills +0 -1
- data/.commitlintrc.yml +0 -38
- data/.dockerignore +0 -27
- data/.github/copilot-instructions.md +0 -30
- data/.github/hooks/bin-setup-on-worktree.json +0 -11
- data/.github/hooks/run-bin-setup-once.sh +0 -20
- data/.github/issue_template.md +0 -15
- data/.github/prompts/iteratively-address-copilot-reviews.prompt.md +0 -188
- data/.github/pull_request_template.md +0 -21
- data/.github/skills/breaking-change-analysis/SKILL.md +0 -99
- data/.github/skills/ci-cd-troubleshooting/SKILL.md +0 -264
- data/.github/skills/command-implementation/REFERENCE.md +0 -994
- data/.github/skills/command-implementation/SKILL.md +0 -230
- data/.github/skills/command-test-conventions/SKILL.md +0 -664
- data/.github/skills/command-yard-documentation/SKILL.md +0 -434
- data/.github/skills/dependency-management/SKILL.md +0 -72
- data/.github/skills/development-workflow/SKILL.md +0 -512
- data/.github/skills/facade-implementation/REFERENCE.md +0 -837
- data/.github/skills/facade-implementation/SKILL.md +0 -269
- data/.github/skills/facade-test-conventions/SKILL.md +0 -391
- data/.github/skills/facade-yard-documentation/SKILL.md +0 -435
- data/.github/skills/make-skill-template/SKILL.md +0 -226
- data/.github/skills/pr-readiness-review/SKILL.md +0 -205
- data/.github/skills/project-context/SKILL.md +0 -306
- data/.github/skills/pull-request-review/SKILL.md +0 -168
- data/.github/skills/rebase/SKILL.md +0 -148
- data/.github/skills/refactor-command-to-commandlineresult/SKILL.md +0 -131
- data/.github/skills/release-management/SKILL.md +0 -125
- data/.github/skills/resolve-feedback/SKILL.md +0 -288
- data/.github/skills/review-arguments-dsl/CHECKLIST.md +0 -788
- data/.github/skills/review-arguments-dsl/SKILL.md +0 -214
- data/.github/skills/review-cross-command-consistency/SKILL.md +0 -139
- data/.github/skills/reviewing-skills/SKILL.md +0 -214
- data/.github/skills/rspec-unit-testing-standards/SKILL.md +0 -685
- data/.github/skills/tdd-refactor-step/SKILL.md +0 -236
- data/.github/skills/test-debugging/SKILL.md +0 -161
- data/.github/skills/yard-documentation/SKILL.md +0 -981
- data/.github/skills/yard-documentation/element-rules.md +0 -162
- data/.github/skills-deprecated/README.md +0 -21
- data/.github/skills-deprecated/extract-command-from-lib/SKILL.md +0 -487
- data/.github/skills-deprecated/extract-facade-from-base-lib/KEYWORD_ARG_REMEDIATION.md +0 -22
- data/.github/skills-deprecated/extract-facade-from-base-lib/SKILL.md +0 -600
- data/.github/skills-deprecated/review-backward-compatibility/SKILL.md +0 -275
- data/.github/workflows/continuous_integration.yml +0 -358
- data/.github/workflows/enforce_conventional_commits.yml +0 -35
- data/.github/workflows/experimental_continuous_integration.yml +0 -59
- data/.github/workflows/release.yml +0 -52
- data/.github/workflows/warm_bundler_caches.yml +0 -82
- data/.gitignore +0 -30
- data/.husky/commit-msg +0 -1
- data/.husky/pre-commit +0 -13
- data/.release-please-config.json +0 -36
- data/.release-please-manifest.json +0 -3
- data/.rspec +0 -2
- data/.rubocop.yml +0 -44
- data/.rubocop_todo.yml +0 -30
- data/.yard-lint.yml +0 -75
- data/CLAUDE.md +0 -11
- data/Gemfile +0 -22
- data/Rakefile +0 -41
- data/docker/test/Dockerfile +0 -32
- data/docker/test/docker-compose.yml +0 -0
- data/package.json +0 -10
- data/redesign/1_architecture_existing.md +0 -102
- data/redesign/2_architecture_redesign.md +0 -449
- data/redesign/3_architecture_implementation.md +0 -1623
- data/redesign/Phase 4 - Step A.md +0 -366
- data/redesign/Phase 4 - Step B.md +0 -921
- data/redesign/Phase 4 - Step C.md +0 -833
- data/redesign/beta_release.md +0 -107
- data/redesign/branch_parse_refactor_plan.md +0 -163
- data/redesign/c1a-public-api-scope.tsv +0 -256
- data/redesign/c1c2_audit.md +0 -566
- data/redesign/c1c2_bucket6_lib_orphans.md +0 -626
- data/redesign/config_design.rb +0 -501
- data/redesign/index.md +0 -34
- data/redesign/info_object_migration_plan.md +0 -126
- data/redesign/integration_test_analysis.md +0 -521
- data/redesign/phase-4-step-b-test-audit.tsv +0 -485
- data/redesign/remote_refactor_plan.md +0 -164
- data/redesign/reverse_dependencies.sql +0 -44
- data/tasks/gem_tasks.rake +0 -14
- data/tasks/npm_tasks.rake +0 -7
- data/tasks/rspec.rake +0 -111
- data/tasks/rubocop.rake +0 -5
- data/tasks/test_gem.rake +0 -12
- data/tasks/yard.rake +0 -57
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
# Plan: RemoteInfo + RemoteOperations API Modernization
|
|
2
|
-
|
|
3
|
-
> **Note:** Issue #919 fix (`BranchInfo#remote_name` for slash-containing remotes) is
|
|
4
|
-
> deferred to a separate effort and is not part of this plan.
|
|
5
|
-
|
|
6
|
-
## TL;DR
|
|
7
|
-
|
|
8
|
-
Three PRs in order:
|
|
9
|
-
|
|
10
|
-
- **PR 1** (smallest, independent): `remote_add` / `remote_set_url` return `nil`
|
|
11
|
-
- **PR 2** (data layer foundation): `Git::RemoteInfo` value object + `Parsers::Remote`
|
|
12
|
-
- **PR 3** (depends on PR 2): `remote_list` facade method + deprecate `remotes`
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## PR 1 — `remote_add` / `remote_set_url` return `nil` *(independent, smallest)*
|
|
17
|
-
|
|
18
|
-
**Step A.** `remote_add` — remove `Git::Remote.new(self, name)`, return `nil` explicitly
|
|
19
|
-
- File: `lib/git/repository/remote_operations.rb`
|
|
20
|
-
|
|
21
|
-
**Step B.** `remote_set_url` — same change
|
|
22
|
-
|
|
23
|
-
**Step C.** Fix deprecated wrappers (can no longer just forward the return value):
|
|
24
|
-
- `add_remote` → call `remote_add(...)` then `Git::Remote.new(self, name)`
|
|
25
|
-
- `set_remote_url` → call `remote_set_url(...)` then `Git::Remote.new(self, name)`
|
|
26
|
-
|
|
27
|
-
**Step D.** Update YARD `@return` on `remote_add` and `remote_set_url` to `@return [void]`
|
|
28
|
-
(per project convention: methods with no meaningful return value use `@return [void]`,
|
|
29
|
-
matching `remote_set_branches` and other mutation-only methods)
|
|
30
|
-
|
|
31
|
-
**Step E.** Update specs that assert `remote_add` / `remote_set_url` return a `Git::Remote`
|
|
32
|
-
|
|
33
|
-
### Files changed in PR 1
|
|
34
|
-
|
|
35
|
-
- `lib/git/repository/remote_operations.rb`
|
|
36
|
-
- `spec/unit/git/repository/remote_operations_spec.rb`
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
|
-
## PR 2 — `Git::RemoteInfo` data class + `Parsers::Remote` *(data layer foundation)*
|
|
41
|
-
|
|
42
|
-
**Step 1.** Create `lib/git/remote_info.rb`:
|
|
43
|
-
|
|
44
|
-
```ruby
|
|
45
|
-
module Git
|
|
46
|
-
RemoteInfo = Data.define(
|
|
47
|
-
:name, # String — required
|
|
48
|
-
:url, # Array<String>
|
|
49
|
-
:push_url, # Array<String>
|
|
50
|
-
:fetch, # Array<String>
|
|
51
|
-
:push, # Array<String>
|
|
52
|
-
:mirror, # Boolean | nil
|
|
53
|
-
:skip_default_update, # Boolean | nil
|
|
54
|
-
:tag_opt, # String | nil
|
|
55
|
-
:prune, # Boolean | nil (nil = inherit global fetch.prune)
|
|
56
|
-
:prune_tags, # Boolean | nil (nil = inherit global fetch.pruneTags)
|
|
57
|
-
:receivepack, # String | nil
|
|
58
|
-
:uploadpack, # String | nil
|
|
59
|
-
:promisor, # Boolean | nil
|
|
60
|
-
:partial_clone_filter, # String | nil
|
|
61
|
-
:vcs # String | nil
|
|
62
|
-
)
|
|
63
|
-
end
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
- Multi-value fields (`:url`, `:push_url`, `:fetch`, `:push`) are always `Array<String>` (never
|
|
67
|
-
`nil`; may be empty). All other fields are nilable except `:name`.
|
|
68
|
-
- Use **snake_case** field names throughout
|
|
69
|
-
|
|
70
|
-
**Step 2.** Create `lib/git/parsers/remote.rb`:
|
|
71
|
-
|
|
72
|
-
- `Git::Parsers::Remote.parse_list(config_entries)` — accepts an
|
|
73
|
-
`Array<Git::ConfigEntryInfo>` (as returned by `Git::Configuring#config_list`),
|
|
74
|
-
groups entries by remote name, and builds `RemoteInfo` objects
|
|
75
|
-
- Using `Array<Git::ConfigEntryInfo>` as input naturally preserves duplicate keys
|
|
76
|
-
(e.g., multiple `remote.<name>.fetch` refspecs or multiple `url` values),
|
|
77
|
-
which a flat `Hash{String=>String}` cannot represent
|
|
78
|
-
- Multi-value fields (`:url`, `:push_url`, `:fetch`, `:push`) are collected into arrays
|
|
79
|
-
- Boolean fields are coerced matching git's own boolean rules:
|
|
80
|
-
- **True values**: `"true"`, `"yes"`, `"on"`, `"1"`, `""` (key present without a value) → `true`
|
|
81
|
-
- **False values**: `"false"`, `"no"`, `"off"`, `"0"` → `false`
|
|
82
|
-
- **Absent** (key not present in config at all) → `nil`
|
|
83
|
-
- **Unrecognized value**: raise `ArgumentError` (mirrors git's fatal error behavior)
|
|
84
|
-
- Config key → Ruby field mapping (for keys that differ from the field name):
|
|
85
|
-
|
|
86
|
-
| git config key | `RemoteInfo` field |
|
|
87
|
-
|---|---|
|
|
88
|
-
| `url` | `:url` (Array) |
|
|
89
|
-
| `pushurl` | `:push_url` (Array) |
|
|
90
|
-
| `fetch` | `:fetch` (Array) |
|
|
91
|
-
| `push` | `:push` (Array) |
|
|
92
|
-
| `tagOpt` | `:tag_opt` |
|
|
93
|
-
| `partialclonefilter` | `:partial_clone_filter` |
|
|
94
|
-
| `skipDefaultUpdate` | `:skip_default_update` |
|
|
95
|
-
| `pruneTags` | `:prune_tags` |
|
|
96
|
-
| `promisor` | `:promisor` (no case change, but in the mapping table) |
|
|
97
|
-
| `mirror`, `prune`, `receivepack`, `uploadpack`, `vcs` | direct lowercase match |
|
|
98
|
-
|
|
99
|
-
**Step 3.** Unit tests for `Parsers::Remote`:
|
|
100
|
-
- Single remote with only required fields
|
|
101
|
-
- Remote with multiple URLs and fetch specs
|
|
102
|
-
- Multiple remotes in one config entry array
|
|
103
|
-
- Empty input → empty array
|
|
104
|
-
- Boolean field coercion (true/false/nil/raise on unrecognized value)
|
|
105
|
-
|
|
106
|
-
### Files changed in PR 2
|
|
107
|
-
|
|
108
|
-
- `lib/git/remote_info.rb` — new file
|
|
109
|
-
- `lib/git/parsers/remote.rb` — new file
|
|
110
|
-
- `spec/unit/git/remote_info_spec.rb` — new
|
|
111
|
-
- `spec/unit/git/parsers/remote_spec.rb` — new
|
|
112
|
-
|
|
113
|
-
---
|
|
114
|
-
|
|
115
|
-
## PR 3 — `remote_list` facade method + `remotes` deprecation *(depends on PR 2)*
|
|
116
|
-
|
|
117
|
-
**Step 4.** Add `remote_list` to `Git::Repository::RemoteOperations`:
|
|
118
|
-
- Calls `config_list` (the `Git::Configuring` instance method, already mixed into
|
|
119
|
-
`Git::Repository`) to get all config entries as `Array<Git::ConfigEntryInfo>`
|
|
120
|
-
- Filters for entries whose key starts with `remote.`, passes to
|
|
121
|
-
`Git::Parsers::Remote.parse_list`
|
|
122
|
-
- Returns `Array<Git::RemoteInfo>`
|
|
123
|
-
- File: `lib/git/repository/remote_operations.rb`
|
|
124
|
-
- Note: this replaces the use of `Private.config_list` (which returns a flat hash
|
|
125
|
-
that loses duplicate keys and cannot represent multi-value config fields)
|
|
126
|
-
|
|
127
|
-
**Step 5.** Deprecate `remotes`:
|
|
128
|
-
- Add `Git::Deprecation.warn(...)` pointing to `remote_list`
|
|
129
|
-
- Keep returning `Array<Git::Remote>` for backward compat
|
|
130
|
-
|
|
131
|
-
**Step 6.** Unit + integration tests for `remote_list`
|
|
132
|
-
|
|
133
|
-
### Files changed in PR 3
|
|
134
|
-
|
|
135
|
-
- `lib/git/repository/remote_operations.rb`
|
|
136
|
-
- `spec/unit/git/repository/remote_operations_spec.rb`
|
|
137
|
-
- `spec/integration/git/repository/remote_operations_spec.rb`
|
|
138
|
-
|
|
139
|
-
---
|
|
140
|
-
|
|
141
|
-
## Decisions
|
|
142
|
-
|
|
143
|
-
- `remote_show(name)` deferred — add after `remote_list` lands
|
|
144
|
-
- `remotes` deprecated (not removed) — still returns `Array<Git::Remote>` for compat
|
|
145
|
-
- `remote_add` / `remote_set_url` return `nil` — breaking change acceptable in beta
|
|
146
|
-
- Deprecated wrappers (`add_remote`, `set_remote_url`) still return `Git::Remote`
|
|
147
|
-
- `RemoteInfo` fields are **snake_case** (not camelCase)
|
|
148
|
-
- Data source for `remote_list`: `Git::Configuring#config_list` (the instance method
|
|
149
|
-
mixed into `Git::Repository`), which returns `Array<Git::ConfigEntryInfo>` and
|
|
150
|
-
preserves duplicate keys — **not** `Private.config_list` (which returns a flat
|
|
151
|
-
`Hash{String=>String}` and cannot represent multi-value fields)
|
|
152
|
-
- **Boolean fields** are three-state `true`/`false`/`nil`; `nil` means "not configured"
|
|
153
|
-
and is semantically distinct from `false` for `:prune` and `:prune_tags`
|
|
154
|
-
(those inherit from global `fetch.prune` / `fetch.pruneTags` when `nil`)
|
|
155
|
-
- **Multi-value fields**: `:url`, `:push_url`, `:fetch`, `:push` are all `Array<String>`
|
|
156
|
-
- **`require` statements** are an implementation detail; add as needed
|
|
157
|
-
- **`config_remote`** — its relationship to `remote_list` is not addressed in this plan
|
|
158
|
-
|
|
159
|
-
## Out of scope
|
|
160
|
-
|
|
161
|
-
- Issue #919 fix (`BranchInfo#remote_name` for slash remotes) — separate effort
|
|
162
|
-
- `Git::Remote#branch` deprecation — not part of this plan
|
|
163
|
-
- `Git::Remote` and `Git::Branch` deprecation — separate future effort
|
|
164
|
-
- `remote_show(name)` single-remote lookup — deferred until after `remote_list` lands
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
WITH matching_dependencies AS (
|
|
2
|
-
SELECT
|
|
3
|
-
dependent_gem.name AS dependent_gem_name,
|
|
4
|
-
dependent_version.number AS dependent_version_number,
|
|
5
|
-
dependent_version.canonical_number AS dependent_version_canonical_number,
|
|
6
|
-
COALESCE(dependent_version.built_at, dependent_version.created_at) AS dependent_version_released_at,
|
|
7
|
-
dependencies.requirements,
|
|
8
|
-
COALESCE(linksets.code, linksets.home) AS url
|
|
9
|
-
FROM rubygems target_gem
|
|
10
|
-
JOIN dependencies
|
|
11
|
-
ON dependencies.rubygem_id = target_gem.id
|
|
12
|
-
JOIN versions dependent_version
|
|
13
|
-
ON dependent_version.id = dependencies.version_id
|
|
14
|
-
JOIN rubygems dependent_gem
|
|
15
|
-
ON dependent_gem.id = dependent_version.rubygem_id
|
|
16
|
-
LEFT JOIN linksets
|
|
17
|
-
ON linksets.rubygem_id = dependent_gem.id
|
|
18
|
-
WHERE target_gem.name = 'git'
|
|
19
|
-
AND (
|
|
20
|
-
dependencies.requirements LIKE '~> 4.%'
|
|
21
|
-
OR dependencies.requirements LIKE '>= %'
|
|
22
|
-
)
|
|
23
|
-
),
|
|
24
|
-
latest_dependencies AS (
|
|
25
|
-
SELECT DISTINCT ON (dependent_gem_name)
|
|
26
|
-
dependent_gem_name,
|
|
27
|
-
dependent_version_number,
|
|
28
|
-
dependent_version_released_at,
|
|
29
|
-
requirements,
|
|
30
|
-
url
|
|
31
|
-
FROM matching_dependencies
|
|
32
|
-
ORDER BY
|
|
33
|
-
dependent_gem_name,
|
|
34
|
-
dependent_version_canonical_number DESC NULLS LAST,
|
|
35
|
-
dependent_version_number DESC
|
|
36
|
-
)
|
|
37
|
-
SELECT
|
|
38
|
-
dependent_gem_name,
|
|
39
|
-
dependent_version_number,
|
|
40
|
-
dependent_version_released_at,
|
|
41
|
-
requirements,
|
|
42
|
-
url
|
|
43
|
-
FROM latest_dependencies
|
|
44
|
-
ORDER BY dependent_version_released_at DESC;
|
data/tasks/gem_tasks.rake
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'bundler/gem_tasks'
|
|
4
|
-
|
|
5
|
-
# Make it so that calling `rake release` just calls `rake release:rubygem_push` to
|
|
6
|
-
# avoid creating and pushing a new tag.
|
|
7
|
-
|
|
8
|
-
Rake::Task['release'].clear
|
|
9
|
-
desc 'Customized release task to avoid creating a new tag'
|
|
10
|
-
task release: 'release:rubygem_push'
|
|
11
|
-
|
|
12
|
-
require 'rake/clean'
|
|
13
|
-
CLOBBER << 'pkg'
|
|
14
|
-
CLOBBER << 'Gemfile.lock'
|
data/tasks/npm_tasks.rake
DELETED
data/tasks/rspec.rake
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Skip parallel test execution when the PARALLEL_TESTS environment variable is set to a falsy value
|
|
4
|
-
def parallel_tests_disabled_via_env?
|
|
5
|
-
parallel_tests_env = ENV.fetch('PARALLEL_TESTS', 'true').strip.downcase
|
|
6
|
-
%w[false 0 no off].include?(parallel_tests_env)
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
# Use parallel test execution for MRI where it cuts build times by 30-48%.
|
|
10
|
-
# JRuby and TruffleRuby are slower with parallel_tests because each worker
|
|
11
|
-
# process pays JVM/Truffle startup and warm-up overhead independently,
|
|
12
|
-
# resulting in 18-28% slower builds vs. serial execution.
|
|
13
|
-
def parallel_tests?
|
|
14
|
-
RUBY_ENGINE == 'ruby' && !parallel_tests_disabled_via_env?
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# SPEC lets a developer target one or more specific files, e.g.
|
|
18
|
-
# `SPEC=spec/unit/git/version_spec.rb rake spec:unit`, running just those files
|
|
19
|
-
# instead of the whole directory. Both rspec and parallel_rspec recurse a bare
|
|
20
|
-
# directory argument using their own default *_spec.rb pattern, so no explicit
|
|
21
|
-
# --pattern flag is needed for the non-SPEC case.
|
|
22
|
-
#
|
|
23
|
-
# Matches are filtered to dir so that each task only ever runs the specs it owns,
|
|
24
|
-
# no matter how broad SPEC is. This keeps every task self-consistent (a unit spec
|
|
25
|
-
# can never be run by spec:integration under integration's runner and env) and lets
|
|
26
|
-
# a single cross-layer glob drive `rake spec`, e.g.
|
|
27
|
-
# `SPEC=spec/**/git/commands/add_spec.rb rake spec` runs the unit file under
|
|
28
|
-
# spec:unit and the integration file under spec:integration. A SPEC that matches
|
|
29
|
-
# files elsewhere in spec/ but none under dir yields no targets, and the caller
|
|
30
|
-
# skips the task rather than falling back to running all of dir.
|
|
31
|
-
def spec_targets(dir)
|
|
32
|
-
spec_files = ENV.fetch('SPEC', nil)&.strip
|
|
33
|
-
return [dir] if spec_files.nil? || spec_files.empty?
|
|
34
|
-
|
|
35
|
-
targets = FileList[spec_files].sort
|
|
36
|
-
raise "SPEC=#{spec_files.inspect} did not match any files" if targets.empty?
|
|
37
|
-
|
|
38
|
-
targets.select { |target| target.delete_prefix('./').start_with?(dir) }
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# True when targets name exactly one spec file (as opposed to a directory, or
|
|
42
|
-
# several files).
|
|
43
|
-
def single_spec_file?(targets)
|
|
44
|
-
targets.one? && File.file?(targets.first)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# The runner for targets: parallel_rspec only when the task runs in parallel and
|
|
48
|
-
# there is more than one spec file to spread across workers.
|
|
49
|
-
#
|
|
50
|
-
# A single file always uses plain rspec. Worker startup is pure overhead with nothing
|
|
51
|
-
# to divide, and parallel_tests sets TEST_ENV_NUMBER in every worker, which makes
|
|
52
|
-
# spec_helper fall back from the documentation formatter to plain dots -- the opposite
|
|
53
|
-
# of what a run narrowed to one file wants.
|
|
54
|
-
def spec_runner(targets, parallel:)
|
|
55
|
-
parallel && !single_spec_file?(targets) ? 'parallel_rspec' : 'rspec'
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# Run the SPEC-filtered targets for dir, or announce a skip when SPEC selected nothing
|
|
59
|
-
# under dir. Silently doing nothing would read as a passing run of the whole directory.
|
|
60
|
-
def run_spec_task(name, dir, env, parallel:)
|
|
61
|
-
targets = spec_targets(dir)
|
|
62
|
-
|
|
63
|
-
if targets.empty?
|
|
64
|
-
puts "Skipping #{name}: SPEC=#{ENV.fetch('SPEC', nil)} matched no files under #{dir}"
|
|
65
|
-
else
|
|
66
|
-
sh env, 'bundle', 'exec', spec_runner(targets, parallel: parallel), *targets
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def define_parallel_spec_task(name, dir, env: {})
|
|
71
|
-
task name do
|
|
72
|
-
run_spec_task(name, dir, env, parallel: true)
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def define_serial_spec_task(name, dir, env: {})
|
|
77
|
-
task name do
|
|
78
|
-
run_spec_task(name, dir, env, parallel: false)
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# Define a spec task that runs in parallel (via parallel_tests) when parallel_tests? is
|
|
83
|
-
# true, and serially (via a direct `bundle exec rspec` call) otherwise. env, when given,
|
|
84
|
-
# is passed to `sh` and scoped to just the spawned test subprocess(es).
|
|
85
|
-
def define_spec_task(name, dir, desc_text, env: {})
|
|
86
|
-
desc desc_text
|
|
87
|
-
parallel_tests? ? define_parallel_spec_task(name, dir, env: env) : define_serial_spec_task(name, dir, env: env)
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# Run only unit specs. These run in a few seconds, so parallel_tests startup
|
|
91
|
-
# overhead isn't worth it - always run serially.
|
|
92
|
-
desc 'Run unit RSpec tests (mocked, fast; SPEC=<glob> to run specific files)'
|
|
93
|
-
define_serial_spec_task('spec:unit', 'spec/unit/')
|
|
94
|
-
|
|
95
|
-
# Run only integration specs. Coverage is forced off (regardless of the COVERAGE
|
|
96
|
-
# env var): integration tests intentionally aren't exhaustive, so tracking or
|
|
97
|
-
# reporting coverage for them would misleadingly suggest that low integration
|
|
98
|
-
# coverage is a problem to fix.
|
|
99
|
-
define_spec_task(
|
|
100
|
-
'spec:integration', 'spec/integration/',
|
|
101
|
-
'Run integration RSpec tests (real git, slower; SPEC=<glob> to run specific files)',
|
|
102
|
-
env: { 'COVERAGE' => 'false' }
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
# Run all specs, keeping unit and integration output clearly separated
|
|
106
|
-
desc 'Run unit and integration RSpec tests (SPEC=<glob> to run specific files)'
|
|
107
|
-
task spec: %w[spec:unit spec:integration]
|
|
108
|
-
|
|
109
|
-
CLEAN << 'coverage'
|
|
110
|
-
CLEAN << '.rspec_status'
|
|
111
|
-
CLEAN << 'rspec-report.xml'
|
data/tasks/rubocop.rake
DELETED
data/tasks/test_gem.rake
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'English'
|
|
4
|
-
|
|
5
|
-
desc 'Build and install the git gem and run a sanity check'
|
|
6
|
-
task 'test:gem': :install do
|
|
7
|
-
output = `ruby -e "require 'git'; g = Git.open('.'); puts g.log.size"`.chomp
|
|
8
|
-
raise 'Gem test failed' unless $CHILD_STATUS.success?
|
|
9
|
-
raise 'Expected gem test to return an integer' unless output =~ /^\d+$/
|
|
10
|
-
|
|
11
|
-
puts 'Gem Test Succeeded'
|
|
12
|
-
end
|
data/tasks/yard.rake
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# YARD documentation for this project can NOT be built with JRuby or TruffleRuby.
|
|
4
|
-
# This project uses the redcarpet gem which can not be installed on JRuby.
|
|
5
|
-
#
|
|
6
|
-
unless RUBY_PLATFORM == 'java' || RUBY_ENGINE == 'truffleruby'
|
|
7
|
-
# yard:build
|
|
8
|
-
|
|
9
|
-
require 'yard'
|
|
10
|
-
|
|
11
|
-
YARD::Rake::YardocTask.new('yard:build') do |t|
|
|
12
|
-
t.files = %w[lib/**/*.rb]
|
|
13
|
-
t.stats_options = ['--list-undoc']
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
CLEAN << '.yardoc'
|
|
17
|
-
CLEAN << 'doc'
|
|
18
|
-
|
|
19
|
-
# yard:lint
|
|
20
|
-
|
|
21
|
-
# Lints YARD documentation against the project's standards and enforces the
|
|
22
|
-
# minimum documentation coverage threshold. Configuration lives in
|
|
23
|
-
# .yard-lint.yml.
|
|
24
|
-
#
|
|
25
|
-
# yard-lint requires Ruby >= 3.3, so the lint task is only defined and only
|
|
26
|
-
# included in the aggregate `yard` task on Ruby 3.3+.
|
|
27
|
-
#
|
|
28
|
-
yard_lint_supported = Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.3.0')
|
|
29
|
-
|
|
30
|
-
if yard_lint_supported
|
|
31
|
-
desc 'Lint YARD documentation with yard-lint'
|
|
32
|
-
task :'yard:lint' do
|
|
33
|
-
sh 'bundle exec yard-lint lib/'
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# yard:example-test
|
|
38
|
-
|
|
39
|
-
require 'yard_example_test/rake'
|
|
40
|
-
|
|
41
|
-
YardExampleTest::RakeTask.new('yard:example-test') do |task|
|
|
42
|
-
task.pattern = 'lib/git/commands/arguments.rb'
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# yard
|
|
46
|
-
|
|
47
|
-
yard_tasks = %i[yard:build]
|
|
48
|
-
yard_tasks << :'yard:lint' if yard_lint_supported
|
|
49
|
-
yard_tasks << :'yard:example-test'
|
|
50
|
-
|
|
51
|
-
yard_steps = ['build']
|
|
52
|
-
yard_steps << 'lint' if yard_lint_supported
|
|
53
|
-
yard_steps << 'example-test'
|
|
54
|
-
|
|
55
|
-
desc "Run YARD documentation tasks (#{yard_steps.join(', ')})"
|
|
56
|
-
task yard: yard_tasks
|
|
57
|
-
end
|