-
-
Notifications
You must be signed in to change notification settings - Fork 46
fix: handle changes/<change>/patch JSON marshalling error #182
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2,6 +2,7 @@ package gerrit | |||||||||||||||||
|
||||||||||||||||||
import ( | ||||||||||||||||||
"context" | ||||||||||||||||||
"errors" | ||||||||||||||||||
"fmt" | ||||||||||||||||||
"net/url" | ||||||||||||||||||
) | ||||||||||||||||||
|
@@ -140,6 +141,35 @@ type PatchOptions struct { | |||||||||||||||||
Path string `url:"path,omitempty"` | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
// StringPointerWriter is a new type based on *string. | ||||||||||||||||||
// We would like it to implement Writer interface so that we can avoid | ||||||||||||||||||
// unmarshalling of non JSON responses by Client.Do | ||||||||||||||||||
type StringPointerWriter struct { | ||||||||||||||||||
Target *string | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
func NewStringPointerWriter(target *string) (*StringPointerWriter, error) { | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similarly here, this shouldn't be exported. |
||||||||||||||||||
if target == nil { | ||||||||||||||||||
return nil, errors.New("StringPointerWriter: target *string cannot be nil") | ||||||||||||||||||
} | ||||||||||||||||||
return &StringPointerWriter{Target: target}, nil | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
// Write implements the io.Writer interface for *StringPointerWriter. | ||||||||||||||||||
func (spw *StringPointerWriter) Write(p []byte) (n int, err error) { | ||||||||||||||||||
// Check if the StringPointerWriter pointer itself is nil, or if its Target is nil. | ||||||||||||||||||
if spw == nil || spw.Target == nil { | ||||||||||||||||||
return 0, errors.New("StringPointerWriter: receiver or target *string is nil, cannot write") | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
// *(spw.Target) gives us the actual string value. | ||||||||||||||||||
// We append the new data (converted from []byte to string) to it. | ||||||||||||||||||
*(spw.Target) = *(spw.Target) + string(p) | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Appending a string to a string causes a copy and and allocation, so when you have a need to append, it's generally better to stick with []byte which can append without copying and allocating whenever there's enough capacity in the slice. |
||||||||||||||||||
|
||||||||||||||||||
// Return the number of bytes written and no error. | ||||||||||||||||||
return len(p), nil | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
// GetDiff gets the diff of a file from a certain revision. | ||||||||||||||||||
// | ||||||||||||||||||
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#get-diff | ||||||||||||||||||
|
@@ -445,8 +475,17 @@ func (s *ChangesService) GetPatch(ctx context.Context, changeID, revisionID stri | |||||||||||||||||
return nil, nil, err | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
v := new(string) | ||||||||||||||||||
resp, err := s.client.Do(req, v) | ||||||||||||||||||
strVal := "" | ||||||||||||||||||
var v *string = &strVal | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you help clarify what's the motivation to change
|
||||||||||||||||||
|
||||||||||||||||||
// Create an instance of our writer struct since the /patch endpoint | ||||||||||||||||||
// returns a base64 encoded string which cannot be marshalled as JSON. | ||||||||||||||||||
stringWriter, err := NewStringPointerWriter(v) | ||||||||||||||||||
if err != nil { | ||||||||||||||||||
return nil, nil, err | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
resp, err := s.client.Do(req, stringWriter) | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suspect it's better to go with another way to achieve the outcome you want. Consider the similar GetCommitContent method which uses Lines 49 to 56 in 31687dc
As another example, see the approach used by another Gerrit client library here: |
||||||||||||||||||
if err != nil { | ||||||||||||||||||
return nil, resp, err | ||||||||||||||||||
} | ||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an implementation detail of this package, it shouldn't be made exported. Once it's exported, it can't be removed without breaking API compatibility.