Compare commits

...

7 Commits

Author SHA1 Message Date
John Olheiser
ded9a218f7 fix: omit avatar_url in discord payload when empty (#22393) (#22395)
Backport #22393

Signed-off-by: jolheiser <john.olheiser@gmail.com>
2023-01-10 13:37:15 -06:00
Gusted
03f06d5ac1 Use padded keyid (#22288)
- Followup for #22231 to follow the frontport.
2023-01-02 22:52:05 +01:00
Lunny Xiao
8cd6be1723 Remove ReverseProxy authentication from the API (#22219) (#22252)
backport #22219

Since we changed the /api/v1/ routes to disallow session authentication
we also removed their reliance on CSRF. However, we left the
ReverseProxy authentication here - but this means that POSTs to the API
are no longer protected by CSRF.

Now, ReverseProxy authentication is a kind of session authentication,
and is therefore inconsistent with the removal of session from the API.

This PR proposes that we simply remove the ReverseProxy authentication
from the API and therefore users of the API must explicitly use tokens
or basic authentication.

Replace #22077
Close #22221 
Close #22077 

Signed-off-by: Andrew Thornton <art27@cantab.net>

Signed-off-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: zeripath <art27@cantab.net>
2022-12-30 02:08:16 +02:00
Gusted
f882747209 Fix key signature error page (#22229) (#22231)
- Backport of #22229
- When the GPG key contains an error, such as an invalid signature or an
email address that does not match the user.A page will be shown that
says you must provide a signature for the token.
- This page had two errors: one had the wrong translation key and the
other tried to use an undefined variable
[`.PaddedKeyID`](e81ccc406b/models/asymkey/gpg_key.go (L65-L72)),
which is a function implemented on the `GPGKey` struct, given that we
don't have that, we use
[`KeyID`](e81ccc406b/routers/web/user/setting/keys.go (L102))
which is [the fingerprint of the
publickey](https://pkg.go.dev/golang.org/x/crypto/openpgp/packet#PublicKey.KeyIdString)
and is a valid way for opengpg to refer to a key.

<!--

Please check the following:

1. Make sure you are targeting the `main` branch, pull requests on
release branches are only allowed for bug fixes.
2. Read contributing guidelines:
https://github.com/go-gitea/gitea/blob/main/CONTRIBUTING.md
3. Describe what your pull request does and which issue you're targeting
(if any)

-->
2022-12-28 22:16:18 +02:00
Jason Song
92796dcc8b Use complete SHA to create and query commit status (#22244) (#22258)
Backport #22244.

Fix #13485.

Co-authored-by: delvh <dev.lh@web.de>
Co-authored-by: Lauris BH <lauris@nix.lv>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>

Co-authored-by: delvh <dev.lh@web.de>
Co-authored-by: Lauris BH <lauris@nix.lv>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2022-12-28 11:03:01 +01:00
KN4CK3R
48450939c7 Allow empty assignees on pull request edit (#22150) (#22213)
Backport of #22150

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2022-12-22 13:40:54 +01:00
Lauris BH
7dcf9dd4d8 Fix container layer display overflow (#22208) (#22212)
Backport #22208
2022-12-22 19:27:30 +08:00
26 changed files with 97 additions and 43 deletions

View File

@@ -66,6 +66,11 @@ func doTestRepoCommitWithStatus(t *testing.T, state string, classes ...string) {
reqOne := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/"+path.Base(commitURL)+"/status") reqOne := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/"+path.Base(commitURL)+"/status")
testRepoCommitsWithStatus(t, session.MakeRequest(t, req, http.StatusOK), session.MakeRequest(t, reqOne, http.StatusOK), state) testRepoCommitsWithStatus(t, session.MakeRequest(t, req, http.StatusOK), session.MakeRequest(t, reqOne, http.StatusOK), state)
// By short SHA
req = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/"+path.Base(commitURL)[:10]+"/statuses")
reqOne = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/"+path.Base(commitURL)[:10]+"/status")
testRepoCommitsWithStatus(t, session.MakeRequest(t, req, http.StatusOK), session.MakeRequest(t, reqOne, http.StatusOK), state)
// By Ref // By Ref
req = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/master/statuses") req = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/master/statuses")
reqOne = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/master/status") reqOne = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/master/status")

View File

@@ -287,7 +287,7 @@ func (a *Action) GetRefLink() string {
return a.GetRepoLink() + "/src/branch/" + util.PathEscapeSegments(strings.TrimPrefix(a.RefName, git.BranchPrefix)) return a.GetRepoLink() + "/src/branch/" + util.PathEscapeSegments(strings.TrimPrefix(a.RefName, git.BranchPrefix))
case strings.HasPrefix(a.RefName, git.TagPrefix): case strings.HasPrefix(a.RefName, git.TagPrefix):
return a.GetRepoLink() + "/src/tag/" + util.PathEscapeSegments(strings.TrimPrefix(a.RefName, git.TagPrefix)) return a.GetRepoLink() + "/src/tag/" + util.PathEscapeSegments(strings.TrimPrefix(a.RefName, git.TagPrefix))
case len(a.RefName) == 40 && git.IsValidSHAPattern(a.RefName): case len(a.RefName) == git.SHAFullLength && git.IsValidSHAPattern(a.RefName):
return a.GetRepoLink() + "/src/commit/" + a.RefName return a.GetRepoLink() + "/src/commit/" + a.RefName
default: default:
// FIXME: we will just assume it's a branch - this was the old way - at some point we may want to enforce that there is always a ref here. // FIXME: we will just assume it's a branch - this was the old way - at some point we may want to enforce that there is always a ref here.

View File

@@ -65,11 +65,17 @@ func (key *GPGKey) AfterLoad(session *xorm.Session) {
// PaddedKeyID show KeyID padded to 16 characters // PaddedKeyID show KeyID padded to 16 characters
func (key *GPGKey) PaddedKeyID() string { func (key *GPGKey) PaddedKeyID() string {
if len(key.KeyID) > 15 { return PaddedKeyID(key.KeyID)
return key.KeyID }
// PaddedKeyID show KeyID padded to 16 characters
func PaddedKeyID(keyID string) string {
if len(keyID) > 15 {
return keyID
} }
zeros := "0000000000000000" zeros := "0000000000000000"
return zeros[0:16-len(key.KeyID)] + key.KeyID return zeros[0:16-len(keyID)] + keyID
} }
// ListGPGKeys returns a list of public keys belongs to given user. // ListGPGKeys returns a list of public keys belongs to given user.

View File

@@ -291,6 +291,10 @@ func NewCommitStatus(opts NewCommitStatusOptions) error {
return fmt.Errorf("NewCommitStatus[%s, %s]: no user specified", repoPath, opts.SHA) return fmt.Errorf("NewCommitStatus[%s, %s]: no user specified", repoPath, opts.SHA)
} }
if _, err := git.NewIDFromString(opts.SHA); err != nil {
return fmt.Errorf("NewCommitStatus[%s, %s]: invalid sha: %w", repoPath, opts.SHA, err)
}
// Get the next Status Index // Get the next Status Index
idx, err := GetNextCommitStatusIndex(opts.Repo.ID, opts.SHA) idx, err := GetNextCommitStatusIndex(opts.Repo.ID, opts.SHA)
if err != nil { if err != nil {

View File

@@ -388,7 +388,7 @@ func RepoRefForAPI(next http.Handler) http.Handler {
return return
} }
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String() ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
} else if len(refName) == 40 { } else if len(refName) == git.SHAFullLength {
ctx.Repo.CommitID = refName ctx.Repo.CommitID = refName
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(refName) ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(refName)
if err != nil { if err != nil {

View File

@@ -807,7 +807,7 @@ func getRefName(ctx *Context, pathType RepoRefType) string {
} }
// For legacy and API support only full commit sha // For legacy and API support only full commit sha
parts := strings.Split(path, "/") parts := strings.Split(path, "/")
if len(parts) > 0 && len(parts[0]) == 40 { if len(parts) > 0 && len(parts[0]) == git.SHAFullLength {
ctx.Repo.TreePath = strings.Join(parts[1:], "/") ctx.Repo.TreePath = strings.Join(parts[1:], "/")
return parts[0] return parts[0]
} }
@@ -843,7 +843,7 @@ func getRefName(ctx *Context, pathType RepoRefType) string {
return getRefNameFromPath(ctx, path, ctx.Repo.GitRepo.IsTagExist) return getRefNameFromPath(ctx, path, ctx.Repo.GitRepo.IsTagExist)
case RepoRefCommit: case RepoRefCommit:
parts := strings.Split(path, "/") parts := strings.Split(path, "/")
if len(parts) > 0 && len(parts[0]) >= 7 && len(parts[0]) <= 40 { if len(parts) > 0 && len(parts[0]) >= 7 && len(parts[0]) <= git.SHAFullLength {
ctx.Repo.TreePath = strings.Join(parts[1:], "/") ctx.Repo.TreePath = strings.Join(parts[1:], "/")
return parts[0] return parts[0]
} }
@@ -952,7 +952,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
return return
} }
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String() ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
} else if len(refName) >= 7 && len(refName) <= 40 { } else if len(refName) >= 7 && len(refName) <= git.SHAFullLength {
ctx.Repo.IsViewCommit = true ctx.Repo.IsViewCommit = true
ctx.Repo.CommitID = refName ctx.Repo.CommitID = refName
@@ -962,7 +962,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
return return
} }
// If short commit ID add canonical link header // If short commit ID add canonical link header
if len(refName) < 40 { if len(refName) < git.SHAFullLength {
ctx.RespHeader().Set("Link", fmt.Sprintf("<%s>; rel=\"canonical\"", ctx.RespHeader().Set("Link", fmt.Sprintf("<%s>; rel=\"canonical\"",
util.URLJoin(setting.AppURL, strings.Replace(ctx.Req.URL.RequestURI(), util.PathEscapeSegments(refName), url.PathEscape(ctx.Repo.Commit.ID.String()), 1)))) util.URLJoin(setting.AppURL, strings.Replace(ctx.Req.URL.RequestURI(), util.PathEscapeSegments(refName), url.PathEscape(ctx.Repo.Commit.ID.String()), 1))))
} }

View File

@@ -42,7 +42,7 @@ func (repo *Repository) RemoveReference(name string) error {
// ConvertToSHA1 returns a Hash object from a potential ID string // ConvertToSHA1 returns a Hash object from a potential ID string
func (repo *Repository) ConvertToSHA1(commitID string) (SHA1, error) { func (repo *Repository) ConvertToSHA1(commitID string) (SHA1, error) {
if len(commitID) == 40 { if len(commitID) == SHAFullLength {
sha1, err := NewIDFromString(commitID) sha1, err := NewIDFromString(commitID)
if err == nil { if err == nil {
return sha1, nil return sha1, nil

View File

@@ -138,7 +138,7 @@ func (repo *Repository) getCommitFromBatchReader(rd *bufio.Reader, id SHA1) (*Co
// ConvertToSHA1 returns a Hash object from a potential ID string // ConvertToSHA1 returns a Hash object from a potential ID string
func (repo *Repository) ConvertToSHA1(commitID string) (SHA1, error) { func (repo *Repository) ConvertToSHA1(commitID string) (SHA1, error) {
if len(commitID) == 40 && IsValidSHAPattern(commitID) { if len(commitID) == SHAFullLength && IsValidSHAPattern(commitID) {
sha1, err := NewIDFromString(commitID) sha1, err := NewIDFromString(commitID)
if err == nil { if err == nil {
return sha1, nil return sha1, nil

View File

@@ -17,7 +17,7 @@ import (
// ReadTreeToIndex reads a treeish to the index // ReadTreeToIndex reads a treeish to the index
func (repo *Repository) ReadTreeToIndex(treeish string, indexFilename ...string) error { func (repo *Repository) ReadTreeToIndex(treeish string, indexFilename ...string) error {
if len(treeish) != 40 { if len(treeish) != SHAFullLength {
res, _, err := NewCommand(repo.Ctx, "rev-parse", "--verify", treeish).RunStdString(&RunOpts{Dir: repo.Path}) res, _, err := NewCommand(repo.Ctx, "rev-parse", "--verify", treeish).RunStdString(&RunOpts{Dir: repo.Path})
if err != nil { if err != nil {
return err return err

View File

@@ -20,7 +20,7 @@ func (repo *Repository) getTree(id SHA1) (*Tree, error) {
// GetTree find the tree object in the repository. // GetTree find the tree object in the repository.
func (repo *Repository) GetTree(idStr string) (*Tree, error) { func (repo *Repository) GetTree(idStr string) (*Tree, error) {
if len(idStr) != 40 { if len(idStr) != SHAFullLength {
res, _, err := NewCommand(repo.Ctx, "rev-parse", "--verify", idStr).RunStdString(&RunOpts{Dir: repo.Path}) res, _, err := NewCommand(repo.Ctx, "rev-parse", "--verify", idStr).RunStdString(&RunOpts{Dir: repo.Path})
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -67,7 +67,7 @@ func (repo *Repository) getTree(id SHA1) (*Tree, error) {
// GetTree find the tree object in the repository. // GetTree find the tree object in the repository.
func (repo *Repository) GetTree(idStr string) (*Tree, error) { func (repo *Repository) GetTree(idStr string) (*Tree, error) {
if len(idStr) != 40 { if len(idStr) != SHAFullLength {
res, err := repo.GetRefCommitID(idStr) res, err := repo.GetRefCommitID(idStr)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -18,6 +18,9 @@ const EmptySHA = "0000000000000000000000000000000000000000"
// EmptyTreeSHA is the SHA of an empty tree // EmptyTreeSHA is the SHA of an empty tree
const EmptyTreeSHA = "4b825dc642cb6eb9a060e54bf8d69288fbee4904" const EmptyTreeSHA = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
// SHAFullLength is the full length of a git SHA
const SHAFullLength = 40
// SHAPattern can be used to determine if a string is an valid sha // SHAPattern can be used to determine if a string is an valid sha
var shaPattern = regexp.MustCompile(`^[0-9a-f]{4,40}$`) var shaPattern = regexp.MustCompile(`^[0-9a-f]{4,40}$`)
@@ -51,7 +54,7 @@ func MustIDFromString(s string) SHA1 {
func NewIDFromString(s string) (SHA1, error) { func NewIDFromString(s string) (SHA1, error) {
var id SHA1 var id SHA1
s = strings.TrimSpace(s) s = strings.TrimSpace(s)
if len(s) != 40 { if len(s) != SHAFullLength {
return id, fmt.Errorf("Length must be 40: %s", s) return id, fmt.Errorf("Length must be 40: %s", s)
} }
b, err := hex.DecodeString(s) b, err := hex.DecodeString(s)

View File

@@ -230,13 +230,10 @@ func reqExploreSignIn() func(ctx *context.APIContext) {
} }
} }
func reqBasicOrRevProxyAuth() func(ctx *context.APIContext) { func reqBasicAuth() func(ctx *context.APIContext) {
return func(ctx *context.APIContext) { return func(ctx *context.APIContext) {
if ctx.IsSigned && setting.Service.EnableReverseProxyAuth && ctx.Data["AuthedMethod"].(string) == auth.ReverseProxyMethodName {
return
}
if !ctx.Context.IsBasicAuth { if !ctx.Context.IsBasicAuth {
ctx.Error(http.StatusUnauthorized, "reqBasicOrRevProxyAuth", "auth required") ctx.Error(http.StatusUnauthorized, "reqBasicAuth", "auth required")
return return
} }
ctx.CheckForOTP() ctx.CheckForOTP()
@@ -595,9 +592,6 @@ func buildAuthGroup() *auth.Group {
&auth.HTTPSign{}, &auth.HTTPSign{},
&auth.Basic{}, // FIXME: this should be removed once we don't allow basic auth in API &auth.Basic{}, // FIXME: this should be removed once we don't allow basic auth in API
) )
if setting.Service.EnableReverseProxyAuth {
group.Add(&auth.ReverseProxy{})
}
specialAdd(group) specialAdd(group)
return group return group
@@ -681,7 +675,7 @@ func Routes() *web.Route {
m.Combo("").Get(user.ListAccessTokens). m.Combo("").Get(user.ListAccessTokens).
Post(bind(api.CreateAccessTokenOption{}), user.CreateAccessToken) Post(bind(api.CreateAccessTokenOption{}), user.CreateAccessToken)
m.Combo("/{id}").Delete(user.DeleteAccessToken) m.Combo("/{id}").Delete(user.DeleteAccessToken)
}, reqBasicOrRevProxyAuth()) }, reqBasicAuth())
}, context_service.UserAssignmentAPI()) }, context_service.UserAssignmentAPI())
}) })

View File

@@ -488,6 +488,11 @@ func EditPullRequest(ctx *context.APIContext) {
issue := pr.Issue issue := pr.Issue
issue.Repo = ctx.Repo.Repository issue.Repo = ctx.Repo.Repository
if err := issue.LoadAttributes(ctx); err != nil {
ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
return
}
if !issue.IsPoster(ctx.Doer.ID) && !ctx.Repo.CanWrite(unit.TypePullRequests) { if !issue.IsPoster(ctx.Doer.ID) && !ctx.Repo.CanWrite(unit.TypePullRequests) {
ctx.Status(http.StatusForbidden) ctx.Status(http.StatusForbidden)
return return

View File

@@ -184,6 +184,7 @@ func getCommitStatuses(ctx *context.APIContext, sha string) {
ctx.Error(http.StatusBadRequest, "ref/sha not given", nil) ctx.Error(http.StatusBadRequest, "ref/sha not given", nil)
return return
} }
sha = utils.MustConvertToSHA1(ctx.Context, sha)
repo := ctx.Repo.Repository repo := ctx.Repo.Repository
listOptions := utils.GetListOptions(ctx) listOptions := utils.GetListOptions(ctx)

View File

@@ -30,7 +30,7 @@ func ResolveRefOrSha(ctx *context.APIContext, ref string) string {
return refSHA return refSHA
} }
} }
return ref return MustConvertToSHA1(ctx.Context, ref)
} }
// GetGitRefs return git references based on filter // GetGitRefs return git references based on filter
@@ -55,3 +55,30 @@ func searchRefCommitByType(ctx *context.APIContext, refType, filter string) (str
} }
return "", "", nil return "", "", nil
} }
// ConvertToSHA1 returns a full-length SHA1 from a potential ID string
func ConvertToSHA1(ctx *context.Context, commitID string) (git.SHA1, error) {
if len(commitID) == git.SHAFullLength && git.IsValidSHAPattern(commitID) {
sha1, err := git.NewIDFromString(commitID)
if err == nil {
return sha1, nil
}
}
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, ctx.Repo.Repository.RepoPath())
if err != nil {
return git.SHA1{}, fmt.Errorf("RepositoryFromContextOrOpen: %w", err)
}
defer closer.Close()
return gitRepo.ConvertToSHA1(commitID)
}
// MustConvertToSHA1 returns a full-length SHA1 string from a potential ID string, or returns origin input if it can't convert to SHA1
func MustConvertToSHA1(ctx *context.Context, commitID string) string {
sha, err := ConvertToSHA1(ctx, commitID)
if err != nil {
return commitID
}
return sha.String()
}

View File

@@ -284,7 +284,7 @@ func Diff(ctx *context.Context) {
} }
return return
} }
if len(commitID) != 40 { if len(commitID) != git.SHAFullLength {
commitID = commit.ID.String() commitID = commit.ID.String()
} }

View File

@@ -100,14 +100,18 @@ func KeysPost(ctx *context.Context) {
loadKeysData(ctx) loadKeysData(ctx)
ctx.Data["Err_Content"] = true ctx.Data["Err_Content"] = true
ctx.Data["Err_Signature"] = true ctx.Data["Err_Signature"] = true
ctx.Data["KeyID"] = err.(asymkey_model.ErrGPGInvalidTokenSignature).ID keyID := err.(asymkey_model.ErrGPGInvalidTokenSignature).ID
ctx.Data["KeyID"] = keyID
ctx.Data["PaddedKeyID"] = asymkey_model.PaddedKeyID(keyID)
ctx.RenderWithErr(ctx.Tr("settings.gpg_invalid_token_signature"), tplSettingsKeys, &form) ctx.RenderWithErr(ctx.Tr("settings.gpg_invalid_token_signature"), tplSettingsKeys, &form)
case asymkey_model.IsErrGPGNoEmailFound(err): case asymkey_model.IsErrGPGNoEmailFound(err):
loadKeysData(ctx) loadKeysData(ctx)
ctx.Data["Err_Content"] = true ctx.Data["Err_Content"] = true
ctx.Data["Err_Signature"] = true ctx.Data["Err_Signature"] = true
ctx.Data["KeyID"] = err.(asymkey_model.ErrGPGNoEmailFound).ID keyID := err.(asymkey_model.ErrGPGNoEmailFound).ID
ctx.Data["KeyID"] = keyID
ctx.Data["PaddedKeyID"] = asymkey_model.PaddedKeyID(keyID)
ctx.RenderWithErr(ctx.Tr("settings.gpg_no_key_email_found"), tplSettingsKeys, &form) ctx.RenderWithErr(ctx.Tr("settings.gpg_no_key_email_found"), tplSettingsKeys, &form)
default: default:
ctx.ServerError("AddPublicKey", err) ctx.ServerError("AddPublicKey", err)
@@ -139,7 +143,9 @@ func KeysPost(ctx *context.Context) {
loadKeysData(ctx) loadKeysData(ctx)
ctx.Data["VerifyingID"] = form.KeyID ctx.Data["VerifyingID"] = form.KeyID
ctx.Data["Err_Signature"] = true ctx.Data["Err_Signature"] = true
ctx.Data["KeyID"] = err.(asymkey_model.ErrGPGInvalidTokenSignature).ID keyID := err.(asymkey_model.ErrGPGInvalidTokenSignature).ID
ctx.Data["KeyID"] = keyID
ctx.Data["PaddedKeyID"] = asymkey_model.PaddedKeyID(keyID)
ctx.RenderWithErr(ctx.Tr("settings.gpg_invalid_token_signature"), tplSettingsKeys, &form) ctx.RenderWithErr(ctx.Tr("settings.gpg_invalid_token_signature"), tplSettingsKeys, &form)
default: default:
ctx.ServerError("VerifyGPG", err) ctx.ServerError("VerifyGPG", err)

View File

@@ -200,19 +200,19 @@ func getMergeCommit(ctx context.Context, pr *issues_model.PullRequest) (*git.Com
return nil, fmt.Errorf("ReadFile(%s): %v", headFile, err) return nil, fmt.Errorf("ReadFile(%s): %v", headFile, err)
} }
commitID := string(commitIDBytes) commitID := string(commitIDBytes)
if len(commitID) < 40 { if len(commitID) < git.SHAFullLength {
return nil, fmt.Errorf(`ReadFile(%s): invalid commit-ID "%s"`, headFile, commitID) return nil, fmt.Errorf(`ReadFile(%s): invalid commit-ID "%s"`, headFile, commitID)
} }
cmd := commitID[:40] + ".." + pr.BaseBranch cmd := commitID[:git.SHAFullLength] + ".." + pr.BaseBranch
// Get the commit from BaseBranch where the pull request got merged // Get the commit from BaseBranch where the pull request got merged
mergeCommit, _, err := git.NewCommand(ctx, "rev-list", "--ancestry-path", "--merges", "--reverse", cmd). mergeCommit, _, err := git.NewCommand(ctx, "rev-list", "--ancestry-path", "--merges", "--reverse", cmd).
RunStdString(&git.RunOpts{Dir: "", Env: []string{"GIT_INDEX_FILE=" + indexTmpPath, "GIT_DIR=" + pr.BaseRepo.RepoPath()}}) RunStdString(&git.RunOpts{Dir: "", Env: []string{"GIT_INDEX_FILE=" + indexTmpPath, "GIT_DIR=" + pr.BaseRepo.RepoPath()}})
if err != nil { if err != nil {
return nil, fmt.Errorf("git rev-list --ancestry-path --merges --reverse: %v", err) return nil, fmt.Errorf("git rev-list --ancestry-path --merges --reverse: %v", err)
} else if len(mergeCommit) < 40 { } else if len(mergeCommit) < git.SHAFullLength {
// PR was maybe fast-forwarded, so just use last commit of PR // PR was maybe fast-forwarded, so just use last commit of PR
mergeCommit = commitID[:40] mergeCommit = commitID[:git.SHAFullLength]
} }
gitRepo, err := git.OpenRepository(ctx, pr.BaseRepo.RepoPath()) gitRepo, err := git.OpenRepository(ctx, pr.BaseRepo.RepoPath())
@@ -221,9 +221,9 @@ func getMergeCommit(ctx context.Context, pr *issues_model.PullRequest) (*git.Com
} }
defer gitRepo.Close() defer gitRepo.Close()
commit, err := gitRepo.GetCommit(mergeCommit[:40]) commit, err := gitRepo.GetCommit(mergeCommit[:git.SHAFullLength])
if err != nil { if err != nil {
return nil, fmt.Errorf("GetMergeCommit[%v]: %v", mergeCommit[:40], err) return nil, fmt.Errorf("GetMergeCommit[%v]: %v", mergeCommit[:git.SHAFullLength], err)
} }
return commit, nil return commit, nil

View File

@@ -833,7 +833,7 @@ func MergedManually(pr *issues_model.PullRequest, doer *user_model.User, baseGit
return models.ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: repo_model.MergeStyleManuallyMerged} return models.ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: repo_model.MergeStyleManuallyMerged}
} }
if len(commitID) < 40 { if len(commitID) < git.SHAFullLength {
return fmt.Errorf("Wrong commit ID") return fmt.Errorf("Wrong commit ID")
} }

View File

@@ -167,7 +167,7 @@ func createTemporaryRepo(ctx context.Context, pr *issues_model.PullRequest) (str
var headBranch string var headBranch string
if pr.Flow == issues_model.PullRequestFlowGithub { if pr.Flow == issues_model.PullRequestFlowGithub {
headBranch = git.BranchPrefix + pr.HeadBranch headBranch = git.BranchPrefix + pr.HeadBranch
} else if len(pr.HeadCommitID) == 40 { // for not created pull request } else if len(pr.HeadCommitID) == git.SHAFullLength { // for not created pull request
headBranch = pr.HeadCommitID headBranch = pr.HeadCommitID
} else { } else {
headBranch = pr.GetGitRefName() headBranch = pr.GetGitRefName()

View File

@@ -30,9 +30,12 @@ func CreateCommitStatus(ctx context.Context, repo *repo_model.Repository, creato
} }
defer closer.Close() defer closer.Close()
if _, err := gitRepo.GetCommit(sha); err != nil { if commit, err := gitRepo.GetCommit(sha); err != nil {
gitRepo.Close() gitRepo.Close()
return fmt.Errorf("GetCommit[%s]: %v", sha, err) return fmt.Errorf("GetCommit[%s]: %v", sha, err)
} else if len(sha) != git.SHAFullLength {
// use complete commit sha
sha = commit.ID.String()
} }
gitRepo.Close() gitRepo.Close()

View File

@@ -50,7 +50,7 @@ func GetTreeBySHA(ctx context.Context, repo *repo_model.Repository, gitRepo *git
copy(treeURL[apiURLLen:], "/git/trees/") copy(treeURL[apiURLLen:], "/git/trees/")
// 40 is the size of the sha1 hash in hexadecimal format. // 40 is the size of the sha1 hash in hexadecimal format.
copyPos := len(treeURL) - 40 copyPos := len(treeURL) - git.SHAFullLength
if perPage <= 0 || perPage > setting.API.DefaultGitTreesPerPage { if perPage <= 0 || perPage > setting.API.DefaultGitTreesPerPage {
perPage = setting.API.DefaultGitTreesPerPage perPage = setting.API.DefaultGitTreesPerPage

View File

@@ -54,7 +54,7 @@ type (
Wait bool `json:"wait"` Wait bool `json:"wait"`
Content string `json:"content"` Content string `json:"content"`
Username string `json:"username"` Username string `json:"username"`
AvatarURL string `json:"avatar_url"` AvatarURL string `json:"avatar_url,omitempty"`
TTS bool `json:"tts"` TTS bool `json:"tts"`
Embeds []DiscordEmbed `json:"embeds"` Embeds []DiscordEmbed `json:"embeds"`
} }

View File

@@ -42,7 +42,7 @@
{{end}} {{end}}
{{if .PackageDescriptor.Metadata.ImageLayers}} {{if .PackageDescriptor.Metadata.ImageLayers}}
<h4 class="ui top attached header">{{.i18n.Tr "packages.container.layers"}}</h4> <h4 class="ui top attached header">{{.i18n.Tr "packages.container.layers"}}</h4>
<div class="ui attached segment"> <div class="ui attached segment word-break">
<table class="ui very basic compact table"> <table class="ui very basic compact table">
<tbody> <tbody>
{{range .PackageDescriptor.Metadata.ImageLayers}} {{range .PackageDescriptor.Metadata.ImageLayers}}

View File

@@ -18,11 +18,11 @@
<p>{{.i18n.Tr "settings.gpg_token_required"}}</p> <p>{{.i18n.Tr "settings.gpg_token_required"}}</p>
</div> </div>
<div class="field"> <div class="field">
<label for="token">{{.i18n.Tr "setting.gpg_token"}} <label for="token">{{.i18n.Tr "settings.gpg_token"}}
<input readonly="" value="{{.TokenToSign}}"> <input readonly="" value="{{.TokenToSign}}">
<div class="help"> <div class="help">
<p>{{.i18n.Tr "settings.gpg_token_help"}}</p> <p>{{.i18n.Tr "settings.gpg_token_help"}}</p>
<p><code>{{$.i18n.Tr "settings.gpg_token_code" .TokenToSign .PaddedKeyID}}</code></p> <p><code>{{$.i18n.Tr "settings.gpg_token_code" .TokenToSign .KeyID}}</code></p>
</div> </div>
</div> </div>
<div class="field"> <div class="field">