Skip to content

git: Add strict checks for supported extensions#1850

Merged
pjbgf merged 4 commits intomainfrom
fail-safe
Feb 17, 2026
Merged

git: Add strict checks for supported extensions#1850
pjbgf merged 4 commits intomainfrom
fail-safe

Conversation

@pjbgf
Copy link
Member

@pjbgf pjbgf commented Feb 16, 2026

The upstream Git enforces fail-safe heuristics to ensure that older git versions
will avoid handling repositories using extensions they are unaware of.

The logic is largely based on the value of core.repositoryformatversion. As per
official Git docs:

This version specifies the rules for operating on the on-disk repository data.
An implementation of git which does not understand a particular version
advertised by an on-disk repository MUST NOT operate on that repository;
doing so risks not only producing wrong results, but actually losing data.

Now go-git will ensure that:

  • The git.Open logic will verify and enforces the extension support rules.
  • go-git will keep track of built-in extensions that it supports.
  • Any extension that is Storer-specific (e.g. objectformat, reftables),
    will be confirmed by the specific Storer via new x/storage.ExtensionChecker
    interface. Failing to do so, it will be assumed that the extension is
    unsupported and the git.Open operation will return an error.

This is a breaking change and it will force go-git to not be able to open
repositories that it in fact doesn't really support. Conversaly, the error
messages will be more useful (e.g. unknown extension vs object not found).

Upstream refs:

Copilot AI review requested due to automatic review settings February 16, 2026 16:56
@pjbgf pjbgf requested a review from aymanbagabas February 16, 2026 16:56
Comment on lines +267 to +269
err = verifyExtensions(s, cfg)
if err != nil {
return nil, err
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aymanbagabas following-up from the previous discussion on ObjectFormatGetter, this PR removes the need for that interface from a data corruption perspective.

As a separate change, I'll look into dropping the Getter/Setter.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing! This looks much better!

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds strict repository extension validation during git.Open, aligning go-git behavior with upstream Git’s fail-safe rules to avoid operating on repositories that declare unsupported/unknown extensions.

Changes:

  • Introduces x/storage.ExtensionChecker so storers can explicitly confirm support for storage-specific Git extensions.
  • Adds extension verification logic (verifyExtensions) and integrates it into Open.
  • Implements and tests SupportsExtension for memory and filesystem storers; adds repo-level tests for extension verification.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
x/storage/storer.go Adds the ExtensionChecker interface for storage-specific extension support checks.
repository_extensions.go Implements extension discovery + strict validation logic used during Open.
repository_extensions_test.go Adds tests covering extension validation behavior across repo format versions.
repository.go Calls verifyExtensions during Open (replacing prior objectformat-only heuristic).
storage/memory/storage.go Implements SupportsExtension for in-memory storage (objectformat).
storage/memory/storage_test.go Adds tests ensuring memory storage implements/behaves per ExtensionChecker.
storage/filesystem/storage.go Implements SupportsExtension for filesystem storage (objectformat).
storage/filesystem/storage_test.go Adds tests ensuring filesystem storage implements/behaves per ExtensionChecker.
repository_test.go Adjusts server cleanup to ignore srv.Close() errors in one test.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Git extensions may be Storer-specific, like reftables or objectformat. By implementing
this interface, the Storers will be able to tell the core go-git precisely what extensions
they support.

Signed-off-by: Paulo Gomes <[email protected]>
@pjbgf pjbgf force-pushed the fail-safe branch 2 times, most recently from 2769d8f to 8b473d6 Compare February 16, 2026 22:28
pjbgf added a commit to pjbgf/go-git that referenced this pull request Feb 16, 2026
The SHA256 implementation introduced a temporary ObjectFormatGetter interface
that had two key goals:
- Provide a way to access the ObjectFormat from a storer.Storer, without
  changing the existing API.
- Be able to distinguish between storer.Storer implementations that support
  the objectformat extension.

The PR go-git#1850 ensures that the storer.Storer being used supports the required
objectformat. With that, this interface can be replaced by config.ConfigStorer,
making the config the single source of truth for the objectformat.

Signed-off-by: Paulo Gomes <[email protected]>
pjbgf added a commit to pjbgf/go-git that referenced this pull request Feb 16, 2026
The SHA256 implementation introduced a temporary ObjectFormatGetter interface
that had two key goals:
- Provide a way to access the ObjectFormat from a storer.Storer, without
  changing the existing API.
- Be able to distinguish between storer.Storer implementations that support
  the objectformat extension.

The PR go-git#1850 ensures that the storer.Storer being used supports the required
objectformat. With that, this interface can be replaced by config.ConfigStorer,
making the config the single source of truth for the objectformat.

Signed-off-by: Paulo Gomes <[email protected]>
The upstream Git enforces fail-safe heuristics to ensure that older git versions
will avoid handling repositories using extensions they are unaware of.

The logic is largely based on the value of core.repositoryformatversion. As per
official Git docs:
> This version specifies the rules for operating on the on-disk repository data.
> An implementation of git which does not understand a particular version
> advertised by an on-disk repository MUST NOT operate on that repository;
> doing so risks not only producing wrong results, but actually losing data.

Now go-git will ensure that:
- The git.Open logic will verify and enforces the extension support rules.
- go-git will keep track of built-in extensions that it supports.
- Any extension that is Storer-specific (e.g. objectformat, reftables),
  will be confirmed by the specific Storer via new x/storage.ExtensionChecker
  interface. Failing to do so, it will be assumed that the extension is
  unsupported and the Open operation will return an error.

This is a breaking change and it will force go-git to not be able to open
repositories that it in fact doesn't really support. Conversaly, the error
messages will be more useful (e.g. unknown extension vs object not found).

Upstream refs:
- https://git-scm.com/docs/git-config#Documentation/git-config.txt-extensions
- https://git-scm.com/docs/gitrepository-layout#_git_repository_format_versions

Signed-off-by: Paulo Gomes <[email protected]>
@pjbgf pjbgf merged commit 39044ba into main Feb 17, 2026
24 of 26 checks passed
@pjbgf pjbgf deleted the fail-safe branch February 17, 2026 21:55
pjbgf added a commit to pjbgf/go-git that referenced this pull request Feb 26, 2026
The SHA256 implementation introduced a temporary ObjectFormatGetter interface
that had two key goals:
- Provide a way to access the ObjectFormat from a storer.Storer, without
  changing the existing API.
- Be able to distinguish between storer.Storer implementations that support
  the objectformat extension.

The PR go-git#1850 ensures that the storer.Storer being used supports the required
objectformat. With that, this interface can be replaced by config.ConfigStorer,
making the config the single source of truth for the objectformat.

Signed-off-by: Paulo Gomes <[email protected]>
pjbgf added a commit to pjbgf/go-git that referenced this pull request Feb 26, 2026
The SHA256 implementation introduced a temporary ObjectFormatGetter interface
that had two key goals:
- Provide a way to access the ObjectFormat from a storer.Storer, without
  changing the existing API.
- Be able to distinguish between storer.Storer implementations that support
  the objectformat extension.

The PR go-git#1850 ensures that the storer.Storer being used supports the required
objectformat. With that, this interface can be replaced by config.ConfigStorer,
making the config the single source of truth for the objectformat.

Signed-off-by: Paulo Gomes <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants