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.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +45 -0
  3. data/CONTRIBUTING.md +185 -165
  4. data/LICENSE +1 -1
  5. data/README.md +151 -151
  6. data/git.gemspec +35 -3
  7. data/lib/git/command_line/base.rb +1 -2
  8. data/lib/git/commands/base.rb +1 -1
  9. data/lib/git/commands/cat_file/raw.rb +8 -7
  10. data/lib/git/repository/branching.rb +79 -5
  11. data/lib/git/version.rb +1 -1
  12. metadata +5 -94
  13. data/.claude/commands/address-copilot-reviews.md +0 -14
  14. data/.claude/settings.json +0 -16
  15. data/.claude/skills +0 -1
  16. data/.commitlintrc.yml +0 -38
  17. data/.dockerignore +0 -27
  18. data/.github/copilot-instructions.md +0 -30
  19. data/.github/hooks/bin-setup-on-worktree.json +0 -11
  20. data/.github/hooks/run-bin-setup-once.sh +0 -20
  21. data/.github/issue_template.md +0 -15
  22. data/.github/prompts/iteratively-address-copilot-reviews.prompt.md +0 -188
  23. data/.github/pull_request_template.md +0 -21
  24. data/.github/skills/breaking-change-analysis/SKILL.md +0 -99
  25. data/.github/skills/ci-cd-troubleshooting/SKILL.md +0 -264
  26. data/.github/skills/command-implementation/REFERENCE.md +0 -994
  27. data/.github/skills/command-implementation/SKILL.md +0 -230
  28. data/.github/skills/command-test-conventions/SKILL.md +0 -664
  29. data/.github/skills/command-yard-documentation/SKILL.md +0 -434
  30. data/.github/skills/dependency-management/SKILL.md +0 -72
  31. data/.github/skills/development-workflow/SKILL.md +0 -512
  32. data/.github/skills/facade-implementation/REFERENCE.md +0 -837
  33. data/.github/skills/facade-implementation/SKILL.md +0 -269
  34. data/.github/skills/facade-test-conventions/SKILL.md +0 -391
  35. data/.github/skills/facade-yard-documentation/SKILL.md +0 -435
  36. data/.github/skills/make-skill-template/SKILL.md +0 -226
  37. data/.github/skills/pr-readiness-review/SKILL.md +0 -205
  38. data/.github/skills/project-context/SKILL.md +0 -306
  39. data/.github/skills/pull-request-review/SKILL.md +0 -168
  40. data/.github/skills/rebase/SKILL.md +0 -148
  41. data/.github/skills/refactor-command-to-commandlineresult/SKILL.md +0 -131
  42. data/.github/skills/release-management/SKILL.md +0 -125
  43. data/.github/skills/resolve-feedback/SKILL.md +0 -288
  44. data/.github/skills/review-arguments-dsl/CHECKLIST.md +0 -788
  45. data/.github/skills/review-arguments-dsl/SKILL.md +0 -214
  46. data/.github/skills/review-cross-command-consistency/SKILL.md +0 -139
  47. data/.github/skills/reviewing-skills/SKILL.md +0 -214
  48. data/.github/skills/rspec-unit-testing-standards/SKILL.md +0 -685
  49. data/.github/skills/tdd-refactor-step/SKILL.md +0 -236
  50. data/.github/skills/test-debugging/SKILL.md +0 -161
  51. data/.github/skills/yard-documentation/SKILL.md +0 -981
  52. data/.github/skills/yard-documentation/element-rules.md +0 -162
  53. data/.github/skills-deprecated/README.md +0 -21
  54. data/.github/skills-deprecated/extract-command-from-lib/SKILL.md +0 -487
  55. data/.github/skills-deprecated/extract-facade-from-base-lib/KEYWORD_ARG_REMEDIATION.md +0 -22
  56. data/.github/skills-deprecated/extract-facade-from-base-lib/SKILL.md +0 -600
  57. data/.github/skills-deprecated/review-backward-compatibility/SKILL.md +0 -275
  58. data/.github/workflows/continuous_integration.yml +0 -358
  59. data/.github/workflows/enforce_conventional_commits.yml +0 -35
  60. data/.github/workflows/experimental_continuous_integration.yml +0 -59
  61. data/.github/workflows/release.yml +0 -52
  62. data/.github/workflows/warm_bundler_caches.yml +0 -82
  63. data/.gitignore +0 -30
  64. data/.husky/commit-msg +0 -1
  65. data/.husky/pre-commit +0 -13
  66. data/.release-please-config.json +0 -36
  67. data/.release-please-manifest.json +0 -3
  68. data/.rspec +0 -2
  69. data/.rubocop.yml +0 -44
  70. data/.rubocop_todo.yml +0 -30
  71. data/.yard-lint.yml +0 -75
  72. data/CLAUDE.md +0 -11
  73. data/Gemfile +0 -22
  74. data/Rakefile +0 -41
  75. data/docker/test/Dockerfile +0 -32
  76. data/docker/test/docker-compose.yml +0 -0
  77. data/package.json +0 -10
  78. data/redesign/1_architecture_existing.md +0 -102
  79. data/redesign/2_architecture_redesign.md +0 -449
  80. data/redesign/3_architecture_implementation.md +0 -1623
  81. data/redesign/Phase 4 - Step A.md +0 -366
  82. data/redesign/Phase 4 - Step B.md +0 -921
  83. data/redesign/Phase 4 - Step C.md +0 -833
  84. data/redesign/beta_release.md +0 -107
  85. data/redesign/branch_parse_refactor_plan.md +0 -163
  86. data/redesign/c1a-public-api-scope.tsv +0 -256
  87. data/redesign/c1c2_audit.md +0 -566
  88. data/redesign/c1c2_bucket6_lib_orphans.md +0 -626
  89. data/redesign/config_design.rb +0 -501
  90. data/redesign/index.md +0 -34
  91. data/redesign/info_object_migration_plan.md +0 -126
  92. data/redesign/integration_test_analysis.md +0 -521
  93. data/redesign/phase-4-step-b-test-audit.tsv +0 -485
  94. data/redesign/remote_refactor_plan.md +0 -164
  95. data/redesign/reverse_dependencies.sql +0 -44
  96. data/tasks/gem_tasks.rake +0 -14
  97. data/tasks/npm_tasks.rake +0 -7
  98. data/tasks/rspec.rake +0 -111
  99. data/tasks/rubocop.rake +0 -5
  100. data/tasks/test_gem.rake +0 -12
  101. data/tasks/yard.rake +0 -57
@@ -1,59 +0,0 @@
1
- name: CI Experimental
2
-
3
- on:
4
- push:
5
- branches: [main]
6
-
7
- workflow_dispatch:
8
-
9
- jobs:
10
- build:
11
- name: Ruby ${{ matrix.ruby }} on ${{ matrix.operating-system }}
12
-
13
- # Skip this job if triggered by pushing a release commit
14
- if: >-
15
- github.event_name == 'workflow_dispatch' ||
16
- (github.event_name == 'push' && !startsWith(github.event.head_commit.message, 'chore: release '))
17
-
18
- runs-on: ${{ matrix.operating-system }}
19
- continue-on-error: true
20
- env: { JAVA_OPTS: -Djdk.io.File.enableADS=true }
21
-
22
- strategy:
23
- fail-fast: false
24
- matrix:
25
- include:
26
- - # Building against head version of Ruby is considered experimental
27
- ruby: head
28
- operating-system: ubuntu-latest
29
- experimental: Yes
30
- java_version: ""
31
-
32
- - # Since JRuby on Windows is known to not work, consider this experimental
33
- ruby: jruby-head
34
- operating-system: windows-latest
35
- experimental: Yes
36
- java_version: "21"
37
-
38
- steps:
39
- - name: Checkout Code
40
- uses: actions/checkout@v6
41
-
42
- - name: Setup Java
43
- if: matrix.java_version != ''
44
- uses: actions/setup-java@v5
45
- with:
46
- distribution: 'temurin'
47
- java-version: ${{ matrix.java_version }}
48
-
49
- - name: Setup Ruby
50
- uses: ruby/setup-ruby@v1
51
- with:
52
- ruby-version: ${{ matrix.ruby }}
53
- bundler-cache: true # runs 'bundle install' and caches installed gems automatically
54
-
55
- - name: Run Build
56
- run: bundle exec rake default
57
-
58
- - name: Test Gem
59
- run: bundle exec rake test:gem
@@ -1,52 +0,0 @@
1
- ---
2
- name: Release Gem
3
-
4
- description: |
5
- This workflow creates a new release on GitHub and publishes the gem to
6
- RubyGems.org.
7
-
8
- The workflow uses the `googleapis/release-please-action` to handle the
9
- release creation process and the `rubygems/release-gem` action to publish
10
- the gem to rubygems.org
11
-
12
- on:
13
- push:
14
- branches: ["main", "4.x"]
15
-
16
- workflow_dispatch:
17
-
18
- jobs:
19
- release:
20
- runs-on: ubuntu-latest
21
-
22
- environment:
23
- name: RubyGems
24
- url: https://rubygems.org/gems/git
25
-
26
- permissions:
27
- contents: write
28
- pull-requests: write
29
- id-token: write
30
-
31
- steps:
32
- - name: Checkout project
33
- uses: actions/checkout@v6
34
-
35
- - name: Create release
36
- uses: googleapis/release-please-action@v5
37
- id: release
38
- with:
39
- token: ${{ secrets.AUTO_RELEASE_TOKEN }}
40
- config-file: .release-please-config.json
41
- manifest-file: .release-please-manifest.json
42
-
43
- - name: Setup ruby
44
- uses: ruby/setup-ruby@v1
45
- if: ${{ steps.release.outputs.release_created }}
46
- with:
47
- bundler-cache: true
48
- ruby-version: ruby
49
-
50
- - name: Push to RubyGems.org
51
- uses: rubygems/release-gem@v1
52
- if: ${{ steps.release.outputs.release_created }}
@@ -1,82 +0,0 @@
1
- name: Warm Bundler Caches
2
-
3
- # GitHub Actions scopes every cache to the ref that wrote it, and only caches
4
- # written at *default-branch* scope are readable from other refs. The CI workflow runs
5
- # on `pull_request`, where github.ref is refs/pull/<n>/merge, so the caches it writes
6
- # are visible to that one PR and nothing else. The result is that nearly every PR paid
7
- # a cold `bundle install` on nearly every job. See issue #1674 for the measurements.
8
- #
9
- # This workflow exists solely to write those caches from refs/heads/main so that a
10
- # PR's *first* run can read them. It does no checkout-and-test work beyond what
11
- # `bundler-cache: true` needs: no specs, no RuboCop, no YARD.
12
- #
13
- # The matrix below must stay in sync with continuous_integration.yml: setup-ruby's
14
- # cache key embeds the runner OS, the resolved Ruby version, and the Gemfile.lock hash,
15
- # so a pair that is not warmed here still starts cold in CI. That includes the lint
16
- # job's Ruby 3.4 and the Windows 3.2 job, neither of which appears in CI's main matrix
17
- # list. The head rubies from experimental_continuous_integration.yml are deliberately
18
- # absent: that workflow already runs on `push: [main]` and warms its own caches.
19
- #
20
- # Only `main` is listed below. A run's readable caches are its own ref, its base ref,
21
- # and the default branch, so warming 4.x would need this file backported to the 4.x
22
- # branch with that branch's own matrix -- the copy on main is never what runs for a
23
- # push to 4.x.
24
- on:
25
- push:
26
- branches: [main]
27
-
28
- workflow_dispatch:
29
-
30
- # Deliberately NOT cancel-in-progress. Two merges landing close together would
31
- # otherwise cancel the first one's warming mid-save, which is the opposite of the
32
- # point; queueing them costs a couple of runner-minutes and always leaves a warm cache
33
- # behind. This group is also distinct from CI's because github.workflow differs.
34
- concurrency:
35
- group: ${{ github.workflow }}-${{ github.ref }}
36
- cancel-in-progress: false
37
-
38
- permissions:
39
- contents: read
40
-
41
- jobs:
42
- warm:
43
- name: Warm Ruby ${{ matrix.ruby }} on ${{ matrix.operating-system }}
44
-
45
- runs-on: ${{ matrix.operating-system }}
46
- timeout-minutes: 15
47
-
48
- strategy:
49
- fail-fast: false
50
- matrix:
51
- include:
52
- - ruby: "3.2"
53
- operating-system: ubuntu-latest
54
-
55
- - # Hosts the lint and locale jobs in continuous_integration.yml
56
- ruby: "3.4"
57
- operating-system: ubuntu-latest
58
-
59
- - ruby: "4.0"
60
- operating-system: ubuntu-latest
61
-
62
- - ruby: "truffleruby-24.2.1"
63
- operating-system: ubuntu-latest
64
-
65
- - ruby: "jruby-10.0.0.1"
66
- operating-system: ubuntu-latest
67
-
68
- - ruby: "3.2"
69
- operating-system: windows-latest
70
-
71
- steps:
72
- - name: Checkout Code
73
- uses: actions/checkout@v6
74
-
75
- # No bundler-* inputs here on purpose. setup-ruby folds its `bundler`, `with`,
76
- # `without`, and `only` inputs into the cache key, so any option set here and not
77
- # in continuous_integration.yml would warm a key CI never looks up.
78
- - name: Setup Ruby
79
- uses: ruby/setup-ruby@v1
80
- with:
81
- ruby-version: ${{ matrix.ruby }}
82
- bundler-cache: true # runs 'bundle install' and caches installed gems automatically
data/.gitignore DELETED
@@ -1,30 +0,0 @@
1
- *.gem
2
- *.kpf
3
- *.sw?
4
- .DS_Store
5
- .bundle/
6
- vendor/bundle/
7
- coverage
8
- doc
9
- .yardoc
10
- pkg
11
- rdoc
12
- Gemfile.lock
13
- node_modules
14
- package-lock.json
15
- ai-prompt.erb
16
- rubocop-report.json
17
-
18
- # rspec failure tracking
19
- .rspec_status
20
-
21
- # generated git reference docs
22
- git-reference/
23
-
24
- # git versions built by bin/build-git-versions
25
- git-versions/
26
-
27
- tmp
28
-
29
- # per-developer Claude Code overrides (shared config is in .claude/settings.json)
30
- .claude/settings.local.json
data/.husky/commit-msg DELETED
@@ -1 +0,0 @@
1
- npx --no-install commitlint --edit "$1"
data/.husky/pre-commit DELETED
@@ -1,13 +0,0 @@
1
- #!/bin/sh
2
-
3
- branch=$(git branch --show-current)
4
-
5
- protected_branches="main 4.x"
6
-
7
- for protected in $protected_branches; do
8
- if [ "$branch" = "$protected" ]; then
9
- echo "ERROR: Direct commits to '$branch' are not allowed."
10
- echo " Create a topic branch first: git switch -c <type>/<short-description>"
11
- exit 1
12
- fi
13
- done
@@ -1,36 +0,0 @@
1
- {
2
- "bootstrap-sha": "31374263eafea4e23352494ef4f6bea3ce62c1b5",
3
- "packages": {
4
- ".": {
5
- "release-type": "ruby",
6
- "package-name": "git",
7
- "changelog-path": "CHANGELOG.md",
8
- "version-file": "lib/git/version.rb",
9
- "bump-minor-pre-major": true,
10
- "bump-patch-for-minor-pre-major": true,
11
- "draft": false,
12
- "prerelease": false,
13
- "include-component-in-tag": false,
14
- "pull-request-title-pattern": "chore: release v${version}",
15
- "changelog-sections": [
16
- { "type": "feat", "section": "Features", "hidden": false },
17
- { "type": "fix", "section": "Bug Fixes", "hidden": false },
18
- { "type": "build", "section": "Other Changes", "hidden": false },
19
- { "type": "chore", "section": "Other Changes", "hidden": false },
20
- { "type": "ci", "section": "Other Changes", "hidden": false },
21
- { "type": "docs", "section": "Other Changes", "hidden": false },
22
- { "type": "perf", "section": "Other Changes", "hidden": false },
23
- { "type": "refactor", "section": "Other Changes", "hidden": false },
24
- { "type": "revert", "section": "Other Changes", "hidden": false },
25
- { "type": "style", "section": "Other Changes", "hidden": false },
26
- { "type": "test", "section": "Other Changes", "hidden": false }
27
- ]
28
- }
29
- },
30
- "plugins": [
31
- {
32
- "type": "sentence-case"
33
- }
34
- ],
35
- "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json"
36
- }
@@ -1,3 +0,0 @@
1
- {
2
- ".": "5.1.0"
3
- }
data/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --require spec_helper
2
- --color
data/.rubocop.yml DELETED
@@ -1,44 +0,0 @@
1
- inherit_from: .rubocop_todo.yml
2
-
3
- inherit_gem:
4
- main_branch_shared_rubocop_config: config/rubocop.yml
5
-
6
- inherit_mode:
7
- merge:
8
- - Exclude
9
-
10
- # lib/git.rb is the gem's main entry-point module and is expected to be long
11
- Metrics/ModuleLength:
12
- Exclude:
13
- - "lib/git.rb"
14
-
15
- # gemspec and command DSL blocks are intentionally long
16
- Metrics/BlockLength:
17
- Exclude:
18
- - "*.gemspec"
19
- - "lib/git/commands/**/*.rb"
20
-
21
- # Allow gemspec to have long lines
22
- Layout/LineLength:
23
- Exclude:
24
- - "*.gemspec"
25
-
26
- Style/OneClassPerFile:
27
- Enabled: false
28
-
29
- # The repository is stored with LF line endings, but this cop defaults to `native`,
30
- # which expects CRLF on Windows and so reports every file in the project as an
31
- # offense there. Pinning it to `lf` makes the lint verdict identical on every
32
- # platform, which is the same reason CI runs RuboCop on one runtime only.
33
- Layout/EndOfLine:
34
- EnforcedStyle: lf
35
-
36
- AllCops:
37
- # Must match the floor of required_ruby_version in the gemspec: TargetRubyVersion
38
- # decides which syntax RuboCop permits and suggests, so a value above the floor
39
- # would let in code that does not parse on the oldest supported Ruby.
40
- #
41
- # Pinned explicitly rather than inferred because main_branch_shared_rubocop_config
42
- # sets 3.1, which is older than this gem supports, and a value inherited through
43
- # inherit_gem takes precedence over inference from the gemspec.
44
- TargetRubyVersion: 3.2
data/.rubocop_todo.yml DELETED
@@ -1,30 +0,0 @@
1
- # This configuration was generated by
2
- # `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 999`
3
- # on 2026-01-28 20:48:52 UTC using RuboCop version 1.82.1.
4
- # The point is for the user to remove these configuration records
5
- # one by one as the offenses are removed from the code base.
6
- # Note that changes in the inspected code, or installation of new
7
- # versions of RuboCop, may require this file to be generated again.
8
-
9
- # Offense count: 1
10
- # This cop supports safe autocorrection (--autocorrect).
11
- # Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
12
- # URISchemes: http, https
13
- Layout/LineLength:
14
- Exclude:
15
- - 'spec/unit/git/commands/tag/list_spec.rb'
16
-
17
- # Offense count: 4
18
- # Configuration parameters: CountComments, Max, CountAsOne.
19
- Metrics/ClassLength:
20
- Exclude:
21
- - 'lib/git/base.rb'
22
- - 'lib/git/branch.rb'
23
- - 'lib/git/commands/arguments.rb'
24
- - 'lib/git/lib.rb'
25
-
26
- # Offense count: 1
27
- # Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns.
28
- Metrics/MethodLength:
29
- Exclude:
30
- - 'lib/git/commands/tag/list.rb'
data/.yard-lint.yml DELETED
@@ -1,75 +0,0 @@
1
- # Configuration for yard-lint (https://github.com/mensfeld/yard-lint)
2
- #
3
- # This config enforces the project's YARD documentation standards as described
4
- # in .github/skills/yard-documentation/SKILL.md. It replaces the retired
5
- # yardstick audit/coverage tooling.
6
-
7
- AllValidators:
8
- # Lint private and protected objects too: the yard-documentation skill
9
- # requires YARD docs on all objects, including Ruby-private methods.
10
- YardOptions:
11
- - --private
12
- - --protected
13
-
14
- Exclude:
15
- - 'spec/**/*'
16
- - 'vendor/**/*'
17
-
18
- # Fail the run on any offense at convention severity or higher so that tag
19
- # ordering, collection style, and other convention-level skill rules gate CI.
20
- FailOnSeverity: convention
21
-
22
- # Replaces the retired yardstick coverage threshold (was 75).
23
- MinCoverage: 75.0
24
-
25
- # --- Overrides where yard-lint defaults conflict with the skill ---------------
26
-
27
- # The skill's templates end every doc block with a trailing blank comment line
28
- # (`#`) before the definition, so the default EmptyCommentLine validator would
29
- # flag the entire codebase. Disabled to preserve the project's house style.
30
- Documentation/EmptyCommentLine:
31
- Enabled: false
32
-
33
- # The skill uses angle-bracket parametrized collection types
34
- # (e.g. `Array<String>`, `Hash<Symbol, String>`). This validator enforces the
35
- # `Hash{K => V}` form instead, which conflicts with the documented convention.
36
- Tags/CollectionType:
37
- Enabled: false
38
-
39
- # Match the tag order documented in the skill's standard and overload templates.
40
- # Tags not listed here are left unordered (e.g. `overload`, `abstract`).
41
- Tags/Order:
42
- Enabled: true
43
- Severity: convention
44
- EnforcedOrder:
45
- - example
46
- - param
47
- - option
48
- - return
49
- - raise
50
- - yield
51
- - yieldparam
52
- - yieldreturn
53
- - note
54
- - deprecated
55
- - see
56
- - api
57
-
58
- # --- Opt-in validators that enforce the skill's house style ------------------
59
-
60
- # The skill's templates put a blank comment line between the description and the
61
- # first tag and between every tag, so that the source formatter keeps each tag
62
- # visually separated. The built-in Tags/TagGroupSeparator can only separate
63
- # different tag *groups* (it can never split two sibling @param tags), so this
64
- # project uses Tags/TagSeparator, which requires a blank line between every
65
- # consecutive tag. @option is exempt so it can cluster directly beneath the
66
- # @param hash it documents.
67
- #
68
- # Tags/TagSeparator is not yet part of a released yard-lint; it is sourced from a
69
- # fork branch via the Gemfile until it is merged upstream and published.
70
- Tags/TagSeparator:
71
- Enabled: true
72
- Severity: convention
73
- RequireAfterDescription: true
74
- Exempt:
75
- - option
data/CLAUDE.md DELETED
@@ -1,11 +0,0 @@
1
- # CLAUDE.md
2
-
3
- This file exists so Claude Code picks up the same project instructions as every
4
- other AI coding agent used in this repository.
5
-
6
- **Do not add project guidance here.** The canonical instructions live in
7
- [`.github/copilot-instructions.md`](.github/copilot-instructions.md) and are
8
- imported below. Edit that file so all agents stay in sync. Reserve this file for
9
- guidance that applies *only* to Claude Code.
10
-
11
- @.github/copilot-instructions.md
data/Gemfile DELETED
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source 'https://rubygems.org'
4
-
5
- gemspec name: 'git'
6
-
7
- # Temporarily source yard-lint from a fork branch that adds the
8
- # Tags/TagSeparator validator (enabled in .yard-lint.yml). Revert to the
9
- # released gem once the validator is merged upstream and published.
10
- # See: https://github.com/mensfeld/yard-lint
11
- #
12
- # Pinned to a specific commit (rather than the branch name) so installs stay
13
- # deterministic while the branch continues to move. Bump this ref
14
- # intentionally: https://github.com/jcouball/yard-lint/tree/feature/tag-separator
15
- #
16
- # Scope this to the same runtimes as the gemspec's yard-lint dependency: it is
17
- # excluded on JRuby (RUBY_PLATFORM == 'java') and TruffleRuby, and requires
18
- # Ruby >= 3.3.
19
- if !(RUBY_PLATFORM == 'java' || RUBY_ENGINE == 'truffleruby') &&
20
- Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.3.0')
21
- gem 'yard-lint', git: 'https://github.com/jcouball/yard-lint', ref: 'ef71742f2c88e2c296a20ab25fb4f25a4a384374'
22
- end
data/Rakefile DELETED
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rake/clean'
4
-
5
- # Load all .rake files from tasks and its subdirectories.
6
- Dir.glob('tasks/**/*.rake').each { |r| load r }
7
-
8
- default_tasks = %i[spec:unit spec:integration rubocop]
9
- default_tasks << :yard if Rake::Task.task_defined?(:yard)
10
- default_tasks << :build
11
-
12
- desc 'Run all CI tasks (tests, linters, yard, and build)'
13
- task default: default_tasks
14
-
15
- module Rake
16
- # Overload Rake::Task to add logging
17
- class Task
18
- # Store the original execute method
19
- alias original_execute execute
20
-
21
- # Override execute to add a print statement
22
- def execute(args = nil)
23
- # Only output the task name if it wasn't the only top-level task
24
- # rake default # => output task name for each task called by the default task
25
- # rake rubocop # => do not output the task name
26
- # rake rubocop yard # => output task name for rubocop and yard
27
- top_level_tasks = Rake.application.top_level_tasks
28
- box("rake #{name}") unless top_level_tasks.length == 1 && name == top_level_tasks[0]
29
- original_execute(args)
30
- end
31
-
32
- private
33
-
34
- def box(message)
35
- width = message.length + 2
36
- puts "┌#{'─' * width}┐"
37
- puts "│ #{message} │"
38
- puts "└#{'─' * width}┘"
39
- end
40
- end
41
- end
@@ -1,32 +0,0 @@
1
- FROM ruby
2
-
3
- WORKDIR /ruby-git
4
-
5
-
6
- ADD Gemfile git.gemspec ./
7
- ADD lib/git/version.rb ./lib/git/version.rb
8
-
9
- # `git.gemspec`'s `spec.files` shells out to `git ls-files`, which Bundler
10
- # evaluates below via the Gemfile's `gemspec` directive. Rather than relying
11
- # on the host's `.git` (which, for a build context copied from a linked git
12
- # worktree, is a file pointing at an absolute host path that doesn't exist
13
- # in the image — breaking every git command with "fatal: not a git
14
- # repository"), always initialize a throwaway repo scoped to the image. This
15
- # also keeps the image self-contained and avoids ever copying the
16
- # (potentially large) host `.git` directory in (see `.dockerignore`). A
17
- # second commit is added below once the full source tree is present, so the
18
- # final file list is complete.
19
- RUN git init -q && \
20
- git -c user.email=docker@example.com -c user.name=docker add -A && \
21
- git -c user.email=docker@example.com -c user.name=docker commit -q -m 'Throwaway repo for Docker test run'
22
-
23
- RUN bundle install
24
-
25
- ADD . .
26
-
27
- # Refresh the throwaway repo now that the full source tree is present, so
28
- # `git ls-files` reflects every file for `rake build`'s `spec.files`.
29
- RUN git -c user.email=docker@example.com -c user.name=docker add -A && \
30
- git -c user.email=docker@example.com -c user.name=docker commit -q -m 'Add full source' --allow-empty
31
-
32
- ENTRYPOINT ["bundle", "exec", "rake", "default"]
File without changes
data/package.json DELETED
@@ -1,10 +0,0 @@
1
- {
2
- "devDependencies": {
3
- "@commitlint/cli": "^19.8.0",
4
- "@commitlint/config-conventional": "^19.8.0",
5
- "husky": "^9.1.7"
6
- },
7
- "scripts": {
8
- "prepare": "husky"
9
- }
10
- }
@@ -1,102 +0,0 @@
1
- # Analysis of the Current Git Gem Architecture and Its Challenges
2
-
3
- This document provides an in-depth look at the current architecture of the `git` gem,
4
- outlining its primary components and the design challenges that have emerged over
5
- time. Understanding these challenges is the key motivation for the proposed
6
- architectural redesign.
7
-
8
- - [1. Overview of the Current Architecture](#1-overview-of-the-current-architecture)
9
- - [2. Key Architectural Challenges](#2-key-architectural-challenges)
10
- - [A. Unclear Separation of Concerns](#a-unclear-separation-of-concerns)
11
- - [B. Circular Dependency](#b-circular-dependency)
12
- - [C. Undefined Public API Boundary](#c-undefined-public-api-boundary)
13
- - [D. Slow and Brittle Test Suite](#d-slow-and-brittle-test-suite)
14
-
15
- ## 1. Overview of the Current Architecture
16
-
17
- The gem's current design is centered around three main classes: `Git`, `Git::Base`,
18
- and `Git::Lib`.
19
-
20
- - **`Git` (Top-Level Module)**: This module serves as the primary public entry point
21
- for creating repository objects. It contains class-level factory methods like
22
- `Git.open`, `Git.clone`, and `Git.init`. It also provides an interface for
23
- accessing global git configuration settings.
24
-
25
- - **`Git::Base`**: This is the main object that users interact with after creating or
26
- opening a repository. It holds the high-level public API for most git operations
27
- (e.g., `g.commit`, `g.add`, `g.status`). It is responsible for managing the
28
- repository's state, such as the paths to the working directory and the `.git`
29
- directory.
30
-
31
- - **`Git::Lib`**: This class is intended to be the low-level wrapper around the `git`
32
- command-line tool. It contains the methods that build the specific command-line
33
- arguments and execute the `git` binary. In practice, it also contains a significant
34
- amount of logic for parsing the output of these commands.
35
-
36
- ## 2. Key Architectural Challenges
37
-
38
- While this structure has been functional, several significant design challenges make
39
- the codebase difficult to maintain, test, and evolve.
40
-
41
- ### A. Unclear Separation of Concerns
42
-
43
- The responsibilities between Git::Base and Git::Lib are "muddy" and overlap
44
- significantly.
45
-
46
- - `Git::Base` sometimes contains logic that feels like it should be lower-level.
47
-
48
- - `Git::Lib`, which should ideally only be concerned with command execution, is
49
- filled with high-level logic for parsing command output into specific Ruby objects
50
- (e.g., parsing log output, diff stats, and branch lists).
51
-
52
- This blending of responsibilities makes it hard to determine where a specific piece
53
- of logic should reside, leading to an inconsistent and confusing internal structure.
54
-
55
- ### B. Circular Dependency
56
-
57
- This is the most critical architectural flaw in the current design.
58
-
59
- - A `Git::Base` instance is created.
60
-
61
- - The first time a command is run, `Git::Base` lazily initializes a `Git::Lib`
62
- instance via its `.lib` accessor method.
63
-
64
- - The `Git::Lib` constructor is passed the `Git::Base` instance (`self`) so that it
65
- can read the repository's path configuration back from the object that is creating
66
- it.
67
-
68
- This creates a tight, circular coupling: `Git::Base` depends on `Git::Lib` to execute
69
- commands, but `Git::Lib` depends on `Git::Base` for its own configuration. This
70
- pattern makes the classes difficult to instantiate or test in isolation and creates a
71
- fragile system where changes in one class can have unexpected side effects in the
72
- other.
73
-
74
- ### C. Undefined Public API Boundary
75
-
76
- The gem lacks a formally defined public interface. Because `Git::Base` exposes its
77
- internal `Git::Lib` instance via the public `g.lib` accessor, many users have come to
78
- rely on `Git::Lib` and its methods as if they were part of the public API.
79
-
80
- This has two negative consequences:
81
-
82
- 1. It prevents the gem's maintainers from refactoring or changing the internal
83
- implementation of `Git::Lib` without causing breaking changes for users.
84
-
85
- 2. It exposes complex, internal methods to users, creating a confusing and
86
- inconsistent user experience.
87
-
88
- ### D. Slow and Brittle Test Suite
89
-
90
- The current testing strategy, built on `TestUnit`, suffers from two major issues:
91
-
92
- - **Over-reliance on Fixtures**: Most tests depend on having a complete, physical git
93
- repository on the filesystem to run against. Managing these fixtures is cumbersome.
94
-
95
- - **Excessive Shelling Out**: Because the logic for command execution and output
96
- parsing are tightly coupled, nearly every test must shell out to the actual `git`
97
- command-line tool.
98
-
99
- This makes the test suite extremely slow, especially on non-UNIX platforms like
100
- Windows where process creation is more expensive. The slow feedback loop discourages
101
- frequent testing and makes development more difficult. The brittleness of
102
- filesystem-dependent tests also leads to flickering or unreliable test runs.