aboutsummaryrefslogtreecommitdiffstats
path: root/plumbing/transport
diff options
context:
space:
mode:
authorAyman Bagabas <ayman.bagabas@gmail.com>2023-11-17 15:29:33 -0500
committerAyman Bagabas <ayman.bagabas@gmail.com>2023-11-23 11:47:24 -0500
commitf46d04a18759071e45b057908050a01e061f1ddd (patch)
treee7d9d7cc1be92cf0d5f0a0136b02abf4829c2b7b /plumbing/transport
parente2c6ae3333a3facd13aa52e1986a2ba2dbc56a9d (diff)
downloadgo-git-f46d04a18759071e45b057908050a01e061f1ddd.tar.gz
plumbing: transport: use git-proto-request and decode error-line errors
Diffstat (limited to 'plumbing/transport')
-rw-r--r--plumbing/transport/git/common.go26
-rw-r--r--plumbing/transport/internal/common/common.go77
-rw-r--r--plumbing/transport/internal/common/common_test.go60
3 files changed, 51 insertions, 112 deletions
diff --git a/plumbing/transport/git/common.go b/plumbing/transport/git/common.go
index 92fc0be..2b878b0 100644
--- a/plumbing/transport/git/common.go
+++ b/plumbing/transport/git/common.go
@@ -2,12 +2,11 @@
package git
import (
- "fmt"
"io"
"net"
"strconv"
- "github.com/go-git/go-git/v5/plumbing/format/pktline"
+ "github.com/go-git/go-git/v5/plumbing/protocol/packp"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/plumbing/transport/internal/common"
"github.com/go-git/go-git/v5/utils/ioutil"
@@ -42,10 +41,18 @@ type command struct {
// Start executes the command sending the required message to the TCP connection
func (c *command) Start() error {
- cmd := endpointToCommand(c.command, c.endpoint)
+ req := packp.GitProtoRequest{
+ RequestCommand: c.command,
+ Pathname: c.endpoint.Path,
+ }
+ host := c.endpoint.Host
+ if c.endpoint.Port != DefaultPort {
+ host = net.JoinHostPort(c.endpoint.Host, strconv.Itoa(c.endpoint.Port))
+ }
+
+ req.Host = host
- e := pktline.NewEncoder(c.conn)
- return e.Encode([]byte(cmd))
+ return req.Encode(c.conn)
}
func (c *command) connect() error {
@@ -90,15 +97,6 @@ func (c *command) StdoutPipe() (io.Reader, error) {
return c.conn, nil
}
-func endpointToCommand(cmd string, ep *transport.Endpoint) string {
- host := ep.Host
- if ep.Port != DefaultPort {
- host = net.JoinHostPort(ep.Host, strconv.Itoa(ep.Port))
- }
-
- return fmt.Sprintf("%s %s%chost=%s%c", cmd, ep.Path, 0, host, 0)
-}
-
// Close closes the TCP connection and connection.
func (c *command) Close() error {
if !c.connected {
diff --git a/plumbing/transport/internal/common/common.go b/plumbing/transport/internal/common/common.go
index da1c2ac..9e1d023 100644
--- a/plumbing/transport/internal/common/common.go
+++ b/plumbing/transport/internal/common/common.go
@@ -203,9 +203,22 @@ func (s *session) AdvertisedReferencesContext(ctx context.Context) (*packp.AdvRe
}
func (s *session) handleAdvRefDecodeError(err error) error {
+ var errLine *pktline.ErrorLine
+ if errors.As(err, &errLine) {
+ if isRepoNotFoundError(errLine.Text) {
+ return transport.ErrRepositoryNotFound
+ }
+
+ return errLine
+ }
+
// If repository is not found, we get empty stdout and server writes an
// error to stderr.
- if err == packp.ErrEmptyInput {
+ if errors.Is(err, packp.ErrEmptyInput) {
+ // TODO:(v6): handle this error in a better way.
+ // Instead of checking the stderr output for a specific error message,
+ // define an ExitError and embed the stderr output and exit (if one
+ // exists) in the error struct. Just like exec.ExitError.
s.finished = true
if err := s.checkNotFoundError(); err != nil {
return err
@@ -399,59 +412,43 @@ func (s *session) checkNotFoundError() error {
return transport.ErrRepositoryNotFound
}
+ // TODO:(v6): return server error just as it is without a prefix
return fmt.Errorf("unknown error: %s", line)
}
}
-var (
- githubRepoNotFoundErr = "ERROR: Repository not found."
- bitbucketRepoNotFoundErr = "conq: repository does not exist."
+const (
+ githubRepoNotFoundErr = "Repository not found."
+ bitbucketRepoNotFoundErr = "repository does not exist."
localRepoNotFoundErr = "does not appear to be a git repository"
- gitProtocolNotFoundErr = "ERR \n Repository not found."
- gitProtocolNoSuchErr = "ERR no such repository"
- gitProtocolAccessDeniedErr = "ERR access denied"
- gogsAccessDeniedErr = "Gogs: Repository does not exist or you do not have access"
- gitlabRepoNotFoundErr = "remote: ERROR: The project you were looking for could not be found"
+ gitProtocolNotFoundErr = "Repository not found."
+ gitProtocolNoSuchErr = "no such repository"
+ gitProtocolAccessDeniedErr = "access denied"
+ gogsAccessDeniedErr = "Repository does not exist or you do not have access"
+ gitlabRepoNotFoundErr = "The project you were looking for could not be found"
)
func isRepoNotFoundError(s string) bool {
- if strings.HasPrefix(s, githubRepoNotFoundErr) {
- return true
- }
-
- if strings.HasPrefix(s, bitbucketRepoNotFoundErr) {
- return true
- }
-
- if strings.HasSuffix(s, localRepoNotFoundErr) {
- return true
- }
-
- if strings.HasPrefix(s, gitProtocolNotFoundErr) {
- return true
- }
-
- if strings.HasPrefix(s, gitProtocolNoSuchErr) {
- return true
- }
-
- if strings.HasPrefix(s, gitProtocolAccessDeniedErr) {
- return true
- }
-
- if strings.HasPrefix(s, gogsAccessDeniedErr) {
- return true
- }
-
- if strings.HasPrefix(s, gitlabRepoNotFoundErr) {
- return true
+ for _, err := range []string{
+ githubRepoNotFoundErr,
+ bitbucketRepoNotFoundErr,
+ localRepoNotFoundErr,
+ gitProtocolNotFoundErr,
+ gitProtocolNoSuchErr,
+ gitProtocolAccessDeniedErr,
+ gogsAccessDeniedErr,
+ gitlabRepoNotFoundErr,
+ } {
+ if strings.Contains(s, err) {
+ return true
+ }
}
return false
}
// uploadPack implements the git-upload-pack protocol.
-func uploadPack(w io.WriteCloser, r io.Reader, req *packp.UploadPackRequest) error {
+func uploadPack(w io.WriteCloser, _ io.Reader, req *packp.UploadPackRequest) error {
// TODO support multi_ack mode
// TODO support multi_ack_detailed mode
// TODO support acks for common objects
diff --git a/plumbing/transport/internal/common/common_test.go b/plumbing/transport/internal/common/common_test.go
index f6f2f67..9344bb6 100644
--- a/plumbing/transport/internal/common/common_test.go
+++ b/plumbing/transport/internal/common/common_test.go
@@ -22,64 +22,8 @@ func (s *CommonSuite) TestIsRepoNotFoundErrorForUnknownSource(c *C) {
c.Assert(isRepoNotFound, Equals, false)
}
-func (s *CommonSuite) TestIsRepoNotFoundErrorForGithub(c *C) {
- msg := fmt.Sprintf("%s : some error stuf", githubRepoNotFoundErr)
-
- isRepoNotFound := isRepoNotFoundError(msg)
-
- c.Assert(isRepoNotFound, Equals, true)
-}
-
-func (s *CommonSuite) TestIsRepoNotFoundErrorForBitBucket(c *C) {
- msg := fmt.Sprintf("%s : some error stuf", bitbucketRepoNotFoundErr)
-
- isRepoNotFound := isRepoNotFoundError(msg)
-
- c.Assert(isRepoNotFound, Equals, true)
-}
-
-func (s *CommonSuite) TestIsRepoNotFoundErrorForLocal(c *C) {
- msg := fmt.Sprintf("some error stuf : %s", localRepoNotFoundErr)
-
- isRepoNotFound := isRepoNotFoundError(msg)
-
- c.Assert(isRepoNotFound, Equals, true)
-}
-
-func (s *CommonSuite) TestIsRepoNotFoundErrorForGitProtocolNotFound(c *C) {
- msg := fmt.Sprintf("%s : some error stuf", gitProtocolNotFoundErr)
-
- isRepoNotFound := isRepoNotFoundError(msg)
-
- c.Assert(isRepoNotFound, Equals, true)
-}
-
-func (s *CommonSuite) TestIsRepoNotFoundErrorForGitProtocolNoSuch(c *C) {
- msg := fmt.Sprintf("%s : some error stuf", gitProtocolNoSuchErr)
-
- isRepoNotFound := isRepoNotFoundError(msg)
-
- c.Assert(isRepoNotFound, Equals, true)
-}
-
-func (s *CommonSuite) TestIsRepoNotFoundErrorForGitProtocolAccessDenied(c *C) {
- msg := fmt.Sprintf("%s : some error stuf", gitProtocolAccessDeniedErr)
-
- isRepoNotFound := isRepoNotFoundError(msg)
-
- c.Assert(isRepoNotFound, Equals, true)
-}
-
-func (s *CommonSuite) TestIsRepoNotFoundErrorForGogsAccessDenied(c *C) {
- msg := fmt.Sprintf("%s : some error stuf", gogsAccessDeniedErr)
-
- isRepoNotFound := isRepoNotFoundError(msg)
-
- c.Assert(isRepoNotFound, Equals, true)
-}
-
-func (s *CommonSuite) TestIsRepoNotFoundErrorForGitlab(c *C) {
- msg := fmt.Sprintf("%s : some error stuf", gitlabRepoNotFoundErr)
+func (s *CommonSuite) TestIsRepoNotFoundError(c *C) {
+ msg := "no such repository : some error stuf"
isRepoNotFound := isRepoNotFoundError(msg)