Skip to content

Conversation

@ferhatelmas
Copy link
Contributor

related to #1731

  • Make encode and decode a function and unexport encoder/decoder to hide state so that
    there is less opportunity to misuse concurrently,
    and drop mutex and recover as a result.
  • Handle non EOF errors in decode trailing check.
  • Add context in object decode for EOF.
  • Drop unused stateFn in encoder/decoder.
  • Accept io.Reader since it's more idiomatic. For decode, internally, we create buffered reader
    if already not buffered but not doing it for
    writing since flushing is required and it's
    generally controlled by caller (file, buffer, etc).

Keeping explicit check for io.EOF because of
convention golang/go#39155

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 refactors the revfile encoder and decoder to improve safety and API design by converting them from reusable objects to pure functions. The changes eliminate potential concurrent misuse by making encoder/decoder types unexported and creating fresh state for each operation, allowing the removal of mutexes and panic recovery.

Key improvements include:

  • Encoder and decoder structs are now unexported with pure functional APIs (Encode/Decode functions)
  • Enhanced error handling for non-EOF errors during trailing data checks in decoder
  • Better EOF context in error messages (e.g., "unexpected EOF at object N")

Reviewed changes

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

Show a summary per file
File Description
plumbing/format/revfile/encoder.go Converted Encoder to unexported encoder type; exposed Encode function; removed mutex, panic recovery, and unused stateFn field; simplified return in writeRevChecksum
plumbing/format/revfile/decoder.go Converted Decoder to unexported decoder type; exposed Decode function accepting io.Reader; improved EOF error handling with context; fixed bug where non-EOF errors during trailing check were not properly handled
plumbing/format/revfile/encoder_test.go Updated tests to use new Encode function API; removed bufio import; adopted error channel pattern for goroutine error handling
plumbing/format/revfile/decoder_test.go Updated tests to use new Decode function API; added errorAfterReader test helper; added test for read errors during EOF check; removed bufio and sync imports; removed "closed chan" test (now documented in API that caller must not close channel)
storage/filesystem/dotgit/writers.go Updated to use new Encode function API directly instead of creating encoder instance

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

You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

Copy link
Member

@pjbgf pjbgf left a comment

Choose a reason for hiding this comment

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

@ferhatelmas thanks for working on this. 🙇 The comments are largely for future reference, no action needed.

)

// errorAfterReader wraps a reader and returns an error after n bytes have been read.
type errorAfterReader struct {
Copy link
Member

Choose a reason for hiding this comment

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

This would certainly be handy in other parts of the code - including other {en,de}coders. But we can extract it on a follow-up PR when it gets used around other tests.

}()
br, ok := r.(*bufio.Reader)
if !ok {
br = bufio.NewReader(r)
Copy link
Member

Choose a reason for hiding this comment

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

I'm not a massive fan of the additional allocation that comes with this trade-off. But considering that on using a io.Reader makes it more flexible, it sounds like a reasonable thing to do.

@pjbgf
Copy link
Member

pjbgf commented Nov 25, 2025

@ferhatelmas this commit also needs to be reworded so that I can go ahead and approve/merge.

related to go-git#1731

* Make encode and decode a function and unexport
encoder/decoder to hide state so that
there is less opportunity to misuse concurrently,
and drop mutex and recover as a result.
* Handle non EOF errors in decode trailing check.
* Add context in object decode for EOF.
* Drop unused stateFn in encoder/decoder.
* Accept io.Reader since it's more idiomatic.
For decode, internally, we create buffered reader
if already not buffered but not doing it for
writing since flushing is required and it's
generally controlled by caller (file, buffer, etc).

Keeping explicit check for io.EOF because of
convention golang/go#39155

Signed-off-by: ferhat elmas <[email protected]>
@ferhatelmas ferhatelmas force-pushed the ferhat/refactor-revfile branch from b8f2943 to a1bf299 Compare November 25, 2025 23:03
@ferhatelmas
Copy link
Contributor Author

Updated this as well.

Aside, shall we update commit message validation to include type of work such as docs, fix, refactor, etc. ?

@pjbgf
Copy link
Member

pjbgf commented Nov 25, 2025

shall we update commit message validation to include type of work such as docs, fix, refactor, etc. ?

Feel free to propose an update to the contributing guidelines then we can loop in other folks on it.

@pjbgf pjbgf merged commit 2d242db into go-git:main Nov 25, 2025
22 of 23 checks passed
@ferhatelmas ferhatelmas deleted the ferhat/refactor-revfile branch November 25, 2025 23:20
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.

2 participants