mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2026-05-12 22:10:25 +00:00
fix: make Fetch work with git < 2.41 (#10095)
`git fetch --porcelain` was introduced in 2.41, add a fallback for older git clients. Resolves forgejo/forgejo#10080 Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10095 Reviewed-by: Michael Kriese <michael.kriese@gmx.de> Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org> Co-authored-by: Gusted <postmaster@gusted.xyz> Co-committed-by: Gusted <postmaster@gusted.xyz>
This commit is contained in:
parent
84c931f0ca
commit
8fa32bd3ff
2 changed files with 43 additions and 9 deletions
|
|
@ -6,6 +6,9 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"forgejo.org/modules/log"
|
||||
"forgejo.org/modules/util"
|
||||
)
|
||||
|
||||
var ErrRemoteRefNotFound = errors.New("unable to find remote ref")
|
||||
|
|
@ -25,7 +28,20 @@ func (repo *Repository) Fetch(remoteURL, refspec string) (string, error) {
|
|||
return "", err
|
||||
}
|
||||
|
||||
stdout, stderr, err := NewCommand(repo.Ctx, "fetch", "--porcelain", "--end-of-options").AddDynamicArguments(remoteURL, refspec).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
cmd := NewCommand(repo.Ctx, "fetch")
|
||||
if SupportFetchPorcelain {
|
||||
cmd.AddArguments("--porcelain")
|
||||
} else if !strings.Contains(refspec, ":") {
|
||||
randomString, err := util.CryptoRandomString(8)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
refspec += ":refs/tmp/" + randomString
|
||||
}
|
||||
|
||||
cmd.AddArguments("--end-of-options").AddDynamicArguments(remoteURL, refspec)
|
||||
|
||||
stdout, stderr, err := cmd.RunStdString(&RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
if strings.HasPrefix(stderr, "fatal: couldn't find remote ref ") {
|
||||
return "", ErrRemoteRefNotFound
|
||||
|
|
@ -33,19 +49,35 @@ func (repo *Repository) Fetch(remoteURL, refspec string) (string, error) {
|
|||
return "", err
|
||||
}
|
||||
|
||||
localReference, _, ok := strings.Cut(refspec, ":")
|
||||
_, localReference, ok := strings.Cut(refspec, ":")
|
||||
if !ok {
|
||||
localReference = "FETCH_HEAD"
|
||||
}
|
||||
|
||||
// The porcelain format, per section OUTPUT of git-fetch(1), is expected to be:
|
||||
// <flag><space><old-object-id><space><new-object-id><space><local-reference>\n
|
||||
// flag is one character.
|
||||
if expectedLen := 1 + 1 + objectFormat.FullLength() + 1 + objectFormat.FullLength() + 1 + len(localReference) + 1; len(stdout) != expectedLen {
|
||||
return "", fmt.Errorf("output of git-fetch(1) is unexpected, we expected it to be %d bytes but it is %d bytes. stdout: %s", expectedLen, len(stdout), stdout)
|
||||
// Happy path
|
||||
if SupportFetchPorcelain {
|
||||
// The porcelain format, per section OUTPUT of git-fetch(1), is expected to be:
|
||||
// <flag><space><old-object-id><space><new-object-id><space><local-reference>\n
|
||||
// flag is one character.
|
||||
if expectedLen := 1 + 1 + objectFormat.FullLength() + 1 + objectFormat.FullLength() + 1 + len(localReference) + 1; len(stdout) != expectedLen {
|
||||
return "", fmt.Errorf("output of git-fetch(1) is unexpected, we expected it to be %d bytes but it is %d bytes. stdout: %s", expectedLen, len(stdout), stdout)
|
||||
}
|
||||
|
||||
// Extract the new objectID.
|
||||
newObjectID := stdout[1+1+objectFormat.FullLength()+1 : 1+1+objectFormat.FullLength()+1+objectFormat.FullLength()]
|
||||
return newObjectID, nil
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := repo.RemoveReference(localReference); err != nil {
|
||||
log.Error("Could not remove reference %q from repository %q: %v", localReference, repo.Path, err)
|
||||
}
|
||||
}()
|
||||
|
||||
newObjectID, err := repo.ResolveReference(localReference)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Extract the new objectID.
|
||||
newObjectID := stdout[1+1+objectFormat.FullLength()+1 : 1+1+objectFormat.FullLength()+1+objectFormat.FullLength()]
|
||||
return newObjectID, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ var (
|
|||
|
||||
SupportHashSha256 bool // >= 2.42, SHA-256 repositories no longer an ‘experimental curiosity’
|
||||
InvertedGitFlushEnv bool // 2.43.1
|
||||
SupportFetchPorcelain bool // >= 2.41
|
||||
SupportCheckAttrOnBare bool // >= 2.40
|
||||
SupportGitMergeTree bool // >= 2.38
|
||||
SupportGrepMaxCount bool // >= 2.38
|
||||
|
|
@ -179,6 +180,7 @@ func InitFull(ctx context.Context) (err error) {
|
|||
globalCommandArgs = append(globalCommandArgs, "-c", "credential.helper=")
|
||||
|
||||
SupportHashSha256 = CheckGitVersionAtLeast("2.42") == nil
|
||||
SupportFetchPorcelain = CheckGitVersionAtLeast("2.41") == nil
|
||||
SupportCheckAttrOnBare = CheckGitVersionAtLeast("2.40") == nil
|
||||
if SupportHashSha256 {
|
||||
SupportedObjectFormats = append(SupportedObjectFormats, Sha256ObjectFormat)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue