Skip to content

Commit cffe8fc

Browse files
Igor DrozdovashmckenzieArchish27
authored andcommitted
Merge branch '787-githttp-lint' into 'main'
Lint fixes for githttp package Closes #787 See merge request https://gitlab.com/gitlab-org/gitlab-shell/-/merge_requests/1144 Merged-by: Igor Drozdov <[email protected]> Approved-by: Igor Drozdov <[email protected]> Reviewed-by: Igor Drozdov <[email protected]> Reviewed-by: Ash McKenzie <[email protected]> Co-authored-by: Ash McKenzie <[email protected]> Co-authored-by: Archish <[email protected]>
2 parents b4ed8b5 + b200069 commit cffe8fc

File tree

6 files changed

+118
-121
lines changed

6 files changed

+118
-121
lines changed

internal/command/githttp/pull.go

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
// Package githttp provides functionality to handle Git operations over HTTP(S) and SSH,
2+
// including executing Git commands like git-upload-pack and converting responses to the
3+
// expected format for SSH protocols. It integrates with GitLab's internal components
4+
// for secure access verification and data transfer.
15
package githttp
26

37
import (
4-
"bytes"
58
"context"
6-
"fmt"
79
"io"
810

911
"gitlab.com/gitlab-org/gitlab-shell/v14/internal/command/commandargs"
@@ -17,8 +19,9 @@ import (
1719

1820
const pullService = "git-upload-pack"
1921

20-
var uploadPackHttpPrefix = []byte("001e# service=git-upload-pack\n0000")
22+
var uploadPackHTTPPrefix = []byte("001e# service=git-upload-pack\n0000")
2123

24+
// PullCommand handles the execution of a Git pull operation over HTTP(S) or SSH
2225
type PullCommand struct {
2326
Config *config.Config
2427
ReadWriter *readwriter.ReadWriter
@@ -36,6 +39,12 @@ type PullCommand struct {
3639
// 5. Perform /git-upload-pack request and send this data
3740
// 6. Return the output to the user
3841

42+
// ForInfoRefs returns the necessary Pull specifics for client.InfoRefs()
43+
func (c *PullCommand) ForInfoRefs() (*readwriter.ReadWriter, string, []byte) {
44+
return c.ReadWriter, pullService, uploadPackHTTPPrefix
45+
}
46+
47+
// Execute runs the pull command by determining the appropriate method (HTTP/SSH)
3948
func (c *PullCommand) Execute(ctx context.Context) error {
4049
data := c.Response.Payload.Data
4150
client := &git.Client{URL: data.PrimaryRepo, Headers: data.RequestHeaders}
@@ -48,39 +57,19 @@ func (c *PullCommand) Execute(ctx context.Context) error {
4857
return c.requestSSHUploadPack(ctx, client)
4958
}
5059

51-
if err := c.requestInfoRefs(ctx, client); err != nil {
60+
if err := requestInfoRefs(ctx, client, c); err != nil {
5261
return err
5362
}
5463

5564
return c.requestUploadPack(ctx, client, data.GeoProxyFetchDirectToPrimaryWithOptions)
5665
}
5766

58-
func (c *PullCommand) requestInfoRefs(ctx context.Context, client *git.Client) error {
59-
response, err := client.InfoRefs(ctx, pullService)
60-
if err != nil {
61-
return err
62-
}
63-
defer response.Body.Close()
64-
65-
// Read the first bytes that contain 001e# service=git-upload-pack\n0000 string
66-
// to convert HTTP(S) Git response to the one expected by SSH
67-
p := make([]byte, len(uploadPackHttpPrefix))
68-
_, err = response.Body.Read(p)
69-
if err != nil || !bytes.Equal(p, uploadPackHttpPrefix) {
70-
return fmt.Errorf("Unexpected git-upload-pack response")
71-
}
72-
73-
_, err = io.Copy(c.ReadWriter.Out, response.Body)
74-
75-
return err
76-
}
77-
7867
func (c *PullCommand) requestSSHUploadPack(ctx context.Context, client *git.Client) error {
7968
response, err := client.SSHUploadPack(ctx, io.NopCloser(c.ReadWriter.In))
8069
if err != nil {
8170
return err
8271
}
83-
defer response.Body.Close()
72+
defer response.Body.Close() //nolint:errcheck
8473

8574
_, err = io.Copy(c.ReadWriter.Out, response.Body)
8675

@@ -95,7 +84,7 @@ func (c *PullCommand) requestUploadPack(ctx context.Context, client *git.Client,
9584
if err != nil {
9685
return err
9786
}
98-
defer response.Body.Close()
87+
defer response.Body.Close() //nolint:errcheck
9988

10089
_, err = io.Copy(c.ReadWriter.Out, response.Body)
10190

@@ -108,18 +97,27 @@ func (c *PullCommand) readFromStdin(pw *io.PipeWriter, geoProxyFetchDirectToPrim
10897
for scanner.Scan() {
10998
line := scanner.Bytes()
11099

111-
pw.Write(line)
100+
_, err := pw.Write(line)
101+
if err != nil {
102+
log.WithError(err).Error("failed to write line")
103+
}
112104

113105
if pktline.IsDone(line) {
114106
break
115107
}
116108

117109
if pktline.IsFlush(line) && geoProxyFetchDirectToPrimaryWithOptions {
118-
pw.Write(pktline.PktDone())
110+
_, err := pw.Write(pktline.PktDone())
111+
if err != nil {
112+
log.WithError(err).Error("failed to write packet done line")
113+
}
119114

120115
break
121116
}
122117
}
123118

124-
pw.Close()
119+
err := pw.Close()
120+
if err != nil {
121+
log.WithError(err).Error("failed to close writer")
122+
}
125123
}

internal/command/githttp/pull_test.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"strings"
99
"testing"
1010

11+
"github.com/stretchr/testify/assert"
1112
"github.com/stretchr/testify/require"
1213

1314
"gitlab.com/gitlab-org/gitlab-shell/v14/client/testserver"
@@ -104,7 +105,7 @@ func TestPullExecuteWithFailedInfoRefs(t *testing.T) {
104105
desc: "unexpected response",
105106
statusCode: http.StatusOK,
106107
responseContent: "unexpected response",
107-
expectedErr: "Unexpected git-upload-pack response",
108+
expectedErr: "unexpected git-upload-pack response",
108109
},
109110
}
110111

@@ -114,7 +115,7 @@ func TestPullExecuteWithFailedInfoRefs(t *testing.T) {
114115
{
115116
Path: "/info/refs",
116117
Handler: func(w http.ResponseWriter, r *http.Request) {
117-
require.Equal(t, "git-upload-pack", r.URL.Query().Get("service"))
118+
assert.Equal(t, "git-upload-pack", r.URL.Query().Get("service"))
118119

119120
w.WriteHeader(tc.statusCode)
120121
w.Write([]byte(tc.responseContent))
@@ -167,7 +168,7 @@ func setupPull(t *testing.T, uploadPackStatusCode int) string {
167168
{
168169
Path: "/info/refs",
169170
Handler: func(w http.ResponseWriter, r *http.Request) {
170-
require.Equal(t, "git-upload-pack", r.URL.Query().Get("service"))
171+
assert.Equal(t, "git-upload-pack", r.URL.Query().Get("service"))
171172

172173
w.Write([]byte(infoRefs))
173174
},
@@ -176,10 +177,10 @@ func setupPull(t *testing.T, uploadPackStatusCode int) string {
176177
Path: "/git-upload-pack",
177178
Handler: func(w http.ResponseWriter, r *http.Request) {
178179
body, err := io.ReadAll(r.Body)
179-
require.NoError(t, err)
180+
assert.NoError(t, err)
180181
defer r.Body.Close()
181182

182-
require.True(t, strings.HasSuffix(string(body), "0009done\n"))
183+
assert.True(t, strings.HasSuffix(string(body), "0009done\n"))
183184

184185
w.WriteHeader(uploadPackStatusCode)
185186
},
@@ -195,12 +196,12 @@ func setupSSHPull(t *testing.T, uploadPackStatusCode int) string {
195196
Path: "/ssh-upload-pack",
196197
Handler: func(w http.ResponseWriter, r *http.Request) {
197198
body, err := io.ReadAll(r.Body)
198-
require.NoError(t, err)
199+
assert.NoError(t, err)
199200
defer r.Body.Close()
200201

201-
require.True(t, strings.HasSuffix(string(body), "0009done\n"))
202-
require.Equal(t, "version=2", r.Header.Get("Git-Protocol"))
203-
require.Equal(t, "token", r.Header.Get("Authorization"))
202+
assert.True(t, strings.HasSuffix(string(body), "0009done\n"))
203+
assert.Equal(t, "version=2", r.Header.Get("Git-Protocol"))
204+
assert.Equal(t, "token", r.Header.Get("Authorization"))
204205

205206
w.Write([]byte("upload-pack-response"))
206207
w.WriteHeader(uploadPackStatusCode)

internal/command/githttp/push.go

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package githttp
22

33
import (
4-
"bytes"
54
"context"
6-
"fmt"
75
"io"
86

97
"gitlab.com/gitlab-org/gitlab-shell/v14/internal/command/commandargs"
@@ -15,10 +13,12 @@ import (
1513
"gitlab.com/gitlab-org/labkit/log"
1614
)
1715

18-
const service = "git-receive-pack"
16+
const pushService = "git-receive-pack"
1917

20-
var receivePackHttpPrefix = []byte("001f# service=git-receive-pack\n0000")
18+
var receivePackHTTPPrefix = []byte("001f# service=git-receive-pack\n0000")
2119

20+
// PushCommand handles the execution of a Git push operation,
21+
// including configuration, input/output handling, and access verification.
2222
type PushCommand struct {
2323
Config *config.Config
2424
ReadWriter *readwriter.ReadWriter
@@ -35,6 +35,13 @@ type PushCommand struct {
3535
// 4. Read the send-pack data provided by user via SSH (stdinReader)
3636
// 5. Perform /git-receive-pack request and send this data
3737
// 6. Return the output to the user
38+
39+
// ForInfoRefs returns the necessary Push specifics for client.InfoRefs()
40+
func (c *PushCommand) ForInfoRefs() (*readwriter.ReadWriter, string, []byte) {
41+
return c.ReadWriter, pushService, receivePackHTTPPrefix
42+
}
43+
44+
// Execute runs the push command by determining the appropriate method (HTTP/SSH)
3845
func (c *PushCommand) Execute(ctx context.Context) error {
3946
data := c.Response.Payload.Data
4047
client := &git.Client{URL: data.PrimaryRepo, Headers: data.RequestHeaders}
@@ -47,39 +54,19 @@ func (c *PushCommand) Execute(ctx context.Context) error {
4754
return c.requestSSHReceivePack(ctx, client)
4855
}
4956

50-
if err := c.requestInfoRefs(ctx, client); err != nil {
57+
if err := requestInfoRefs(ctx, client, c); err != nil {
5158
return err
5259
}
5360

5461
return c.requestReceivePack(ctx, client)
5562
}
5663

57-
func (c *PushCommand) requestInfoRefs(ctx context.Context, client *git.Client) error {
58-
response, err := client.InfoRefs(ctx, service)
59-
if err != nil {
60-
return err
61-
}
62-
defer response.Body.Close()
63-
64-
// Read the first bytes that contain 001f# service=git-receive-pack\n0000 string
65-
// to convert HTTP(S) Git response to the one expected by SSH
66-
p := make([]byte, len(receivePackHttpPrefix))
67-
_, err = response.Body.Read(p)
68-
if err != nil || !bytes.Equal(p, receivePackHttpPrefix) {
69-
return fmt.Errorf("Unexpected git-receive-pack response")
70-
}
71-
72-
_, err = io.Copy(c.ReadWriter.Out, response.Body)
73-
74-
return err
75-
}
76-
7764
func (c *PushCommand) requestSSHReceivePack(ctx context.Context, client *git.Client) error {
7865
response, err := client.SSHReceivePack(ctx, io.NopCloser(c.ReadWriter.In))
7966
if err != nil {
8067
return err
8168
}
82-
defer response.Body.Close()
69+
defer response.Body.Close() //nolint:errcheck
8370

8471
_, err = io.Copy(c.ReadWriter.Out, response.Body)
8572

@@ -94,7 +81,7 @@ func (c *PushCommand) requestReceivePack(ctx context.Context, client *git.Client
9481
if err != nil {
9582
return err
9683
}
97-
defer response.Body.Close()
84+
defer response.Body.Close() //nolint:errcheck
9885

9986
_, err = io.Copy(c.ReadWriter.Out, response.Body)
10087

@@ -107,7 +94,10 @@ func (c *PushCommand) readFromStdin(pw *io.PipeWriter) {
10794
scanner := pktline.NewScanner(c.ReadWriter.In)
10895
for scanner.Scan() {
10996
line := scanner.Bytes()
110-
pw.Write(line)
97+
_, err := pw.Write(line)
98+
if err != nil {
99+
log.WithError(err).Error("failed to write line")
100+
}
111101

112102
if pktline.IsFlush(line) {
113103
break
@@ -119,8 +109,14 @@ func (c *PushCommand) readFromStdin(pw *io.PipeWriter) {
119109
}
120110

121111
if needsPackData {
122-
io.Copy(pw, c.ReadWriter.In)
112+
_, err := io.Copy(pw, c.ReadWriter.In)
113+
if err != nil {
114+
log.WithError(err).Error("failed to copy")
115+
}
123116
}
124117

125-
pw.Close()
118+
err := pw.Close()
119+
if err != nil {
120+
log.WithError(err).Error("failed to close writer")
121+
}
126122
}

0 commit comments

Comments
 (0)