mirror of
https://github.com/go-gitea/gitea
synced 2025-12-07 13:28:25 +00:00
Merge branch 'main' into lunny/issue_dev
This commit is contained in:
@@ -117,10 +117,10 @@ func dial(source *Source) (*ldap.Conn, error) {
|
||||
}
|
||||
|
||||
if source.SecurityProtocol == SecurityProtocolLDAPS {
|
||||
return ldap.DialTLS("tcp", net.JoinHostPort(source.Host, strconv.Itoa(source.Port)), tlsConfig)
|
||||
return ldap.DialTLS("tcp", net.JoinHostPort(source.Host, strconv.Itoa(source.Port)), tlsConfig) //nolint:staticcheck
|
||||
}
|
||||
|
||||
conn, err := ldap.Dial("tcp", net.JoinHostPort(source.Host, strconv.Itoa(source.Port)))
|
||||
conn, err := ldap.Dial("tcp", net.JoinHostPort(source.Host, strconv.Itoa(source.Port))) //nolint:staticcheck
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error during Dial: %w", err)
|
||||
}
|
||||
|
||||
+2
-19
@@ -14,7 +14,6 @@ import (
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/httpcache"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
@@ -306,24 +305,8 @@ func RepoRefForAPI(next http.Handler) http.Handler {
|
||||
return
|
||||
}
|
||||
|
||||
if ref := ctx.FormTrim("ref"); len(ref) > 0 {
|
||||
commit, err := ctx.Repo.GitRepo.GetCommit(ref)
|
||||
if err != nil {
|
||||
if git.IsErrNotExist(err) {
|
||||
ctx.NotFound()
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "GetCommit", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
ctx.Repo.Commit = commit
|
||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
||||
ctx.Repo.TreePath = ctx.PathParam("*")
|
||||
next.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
refName := getRefName(ctx.Base, ctx.Repo, RepoRefAny)
|
||||
// NOTICE: the "ref" here for internal usage only (e.g. woodpecker)
|
||||
refName, _ := getRefNameLegacy(ctx.Base, ctx.Repo, ctx.FormTrim("ref"))
|
||||
var err error
|
||||
|
||||
if ctx.Repo.GitRepo.IsBranchExist(refName) {
|
||||
|
||||
@@ -100,6 +100,7 @@ func NewTemplateContextForWeb(ctx *Context) TemplateContext {
|
||||
tmplCtx := NewTemplateContext(ctx)
|
||||
tmplCtx["Locale"] = ctx.Base.Locale
|
||||
tmplCtx["AvatarUtils"] = templates.NewAvatarUtils(ctx)
|
||||
tmplCtx["RenderUtils"] = templates.NewRenderUtils(ctx)
|
||||
tmplCtx["RootData"] = ctx.Data
|
||||
tmplCtx["Consts"] = map[string]any{
|
||||
"RepoUnitTypeCode": unit.TypeCode,
|
||||
@@ -154,7 +155,9 @@ func Contexter() func(next http.Handler) http.Handler {
|
||||
ctx := NewWebContext(base, rnd, session.GetContextSession(req))
|
||||
|
||||
ctx.Data.MergeFrom(middleware.CommonTemplateContextData())
|
||||
ctx.Data["Context"] = ctx // TODO: use "ctx" in template and remove this
|
||||
if setting.IsProd && !setting.IsInTesting {
|
||||
ctx.Data["Context"] = ctx // TODO: use "ctx" in template and remove this
|
||||
}
|
||||
ctx.Data["CurrentURL"] = setting.AppSubURL + req.URL.RequestURI()
|
||||
ctx.Data["Link"] = ctx.Link
|
||||
|
||||
|
||||
+73
-65
@@ -25,6 +25,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/httplib"
|
||||
code_indexer "code.gitea.io/gitea/modules/indexer/code"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/optional"
|
||||
@@ -306,11 +307,9 @@ func RetrieveTemplateRepo(ctx *Context, repo *repo_model.Repository) {
|
||||
}
|
||||
|
||||
// ComposeGoGetImport returns go-get-import meta content.
|
||||
func ComposeGoGetImport(owner, repo string) string {
|
||||
/// setting.AppUrl is guaranteed to be parse as url
|
||||
appURL, _ := url.Parse(setting.AppURL)
|
||||
|
||||
return path.Join(appURL.Host, setting.AppSubURL, url.PathEscape(owner), url.PathEscape(repo))
|
||||
func ComposeGoGetImport(ctx context.Context, owner, repo string) string {
|
||||
curAppURL, _ := url.Parse(httplib.GuessCurrentAppURL(ctx))
|
||||
return path.Join(curAppURL.Host, setting.AppSubURL, url.PathEscape(owner), url.PathEscape(repo))
|
||||
}
|
||||
|
||||
// EarlyResponseForGoGetMeta responses appropriate go-get meta with status 200
|
||||
@@ -332,7 +331,7 @@ func EarlyResponseForGoGetMeta(ctx *Context) {
|
||||
} else {
|
||||
cloneURL = repo_model.ComposeHTTPSCloneURL(username, reponame)
|
||||
}
|
||||
goImportContent := fmt.Sprintf("%s git %s", ComposeGoGetImport(username, reponame), cloneURL)
|
||||
goImportContent := fmt.Sprintf("%s git %s", ComposeGoGetImport(ctx, username, reponame), cloneURL)
|
||||
htmlMeta := fmt.Sprintf(`<meta name="go-import" content="%s">`, html.EscapeString(goImportContent))
|
||||
ctx.PlainText(http.StatusOK, htmlMeta)
|
||||
}
|
||||
@@ -744,7 +743,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
|
||||
}
|
||||
|
||||
if ctx.FormString("go-get") == "1" {
|
||||
ctx.Data["GoGetImport"] = ComposeGoGetImport(owner.Name, repo.Name)
|
||||
ctx.Data["GoGetImport"] = ComposeGoGetImport(ctx, owner.Name, repo.Name)
|
||||
fullURLPrefix := repo.HTMLURL() + "/src/branch/" + util.PathEscapeSegments(ctx.Repo.BranchName)
|
||||
ctx.Data["GoDocDirectory"] = fullURLPrefix + "{/dir}"
|
||||
ctx.Data["GoDocFile"] = fullURLPrefix + "{/dir}/{file}#L{line}"
|
||||
@@ -756,19 +755,11 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
|
||||
type RepoRefType int
|
||||
|
||||
const (
|
||||
// RepoRefLegacy unknown type, make educated guess and redirect.
|
||||
// for backward compatibility with previous URL scheme
|
||||
RepoRefLegacy RepoRefType = iota
|
||||
// RepoRefAny is for usage where educated guess is needed
|
||||
// but redirect can not be made
|
||||
RepoRefAny
|
||||
// RepoRefBranch branch
|
||||
// RepoRefUnknown is for legacy support, makes the code to "guess" the ref type
|
||||
RepoRefUnknown RepoRefType = iota
|
||||
RepoRefBranch
|
||||
// RepoRefTag tag
|
||||
RepoRefTag
|
||||
// RepoRefCommit commit
|
||||
RepoRefCommit
|
||||
// RepoRefBlob blob
|
||||
RepoRefBlob
|
||||
)
|
||||
|
||||
@@ -781,22 +772,6 @@ func RepoRef() func(*Context) context.CancelFunc {
|
||||
return RepoRefByType(RepoRefBranch)
|
||||
}
|
||||
|
||||
// RefTypeIncludesBranches returns true if ref type can be a branch
|
||||
func (rt RepoRefType) RefTypeIncludesBranches() bool {
|
||||
if rt == RepoRefLegacy || rt == RepoRefAny || rt == RepoRefBranch {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// RefTypeIncludesTags returns true if ref type can be a tag
|
||||
func (rt RepoRefType) RefTypeIncludesTags() bool {
|
||||
if rt == RepoRefLegacy || rt == RepoRefAny || rt == RepoRefTag {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func getRefNameFromPath(repo *Repository, path string, isExist func(string) bool) string {
|
||||
refName := ""
|
||||
parts := strings.Split(path, "/")
|
||||
@@ -810,28 +785,50 @@ func getRefNameFromPath(repo *Repository, path string, isExist func(string) bool
|
||||
return ""
|
||||
}
|
||||
|
||||
func isStringLikelyCommitID(objFmt git.ObjectFormat, s string, minLength ...int) bool {
|
||||
minLen := util.OptionalArg(minLength, objFmt.FullLength())
|
||||
if len(s) < minLen || len(s) > objFmt.FullLength() {
|
||||
return false
|
||||
}
|
||||
for _, c := range s {
|
||||
isHex := (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')
|
||||
if !isHex {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func getRefNameLegacy(ctx *Base, repo *Repository, optionalExtraRef ...string) (string, RepoRefType) {
|
||||
extraRef := util.OptionalArg(optionalExtraRef)
|
||||
reqPath := ctx.PathParam("*")
|
||||
reqPath = path.Join(extraRef, reqPath)
|
||||
|
||||
if refName := getRefName(ctx, repo, RepoRefBranch); refName != "" {
|
||||
return refName, RepoRefBranch
|
||||
}
|
||||
if refName := getRefName(ctx, repo, RepoRefTag); refName != "" {
|
||||
return refName, RepoRefTag
|
||||
}
|
||||
|
||||
// For legacy support only full commit sha
|
||||
parts := strings.Split(reqPath, "/")
|
||||
if isStringLikelyCommitID(git.ObjectFormatFromName(repo.Repository.ObjectFormatName), parts[0]) {
|
||||
// FIXME: this logic is different from other types. Ideally, it should also try to GetCommit to check if it exists
|
||||
repo.TreePath = strings.Join(parts[1:], "/")
|
||||
return parts[0], RepoRefCommit
|
||||
}
|
||||
|
||||
if refName := getRefName(ctx, repo, RepoRefBlob); len(refName) > 0 {
|
||||
return refName, RepoRefBlob
|
||||
}
|
||||
repo.TreePath = reqPath
|
||||
return repo.Repository.DefaultBranch, RepoRefBranch
|
||||
}
|
||||
|
||||
func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string {
|
||||
path := ctx.PathParam("*")
|
||||
switch pathType {
|
||||
case RepoRefLegacy, RepoRefAny:
|
||||
if refName := getRefName(ctx, repo, RepoRefBranch); len(refName) > 0 {
|
||||
return refName
|
||||
}
|
||||
if refName := getRefName(ctx, repo, RepoRefTag); len(refName) > 0 {
|
||||
return refName
|
||||
}
|
||||
// For legacy and API support only full commit sha
|
||||
parts := strings.Split(path, "/")
|
||||
|
||||
if len(parts) > 0 && len(parts[0]) == git.ObjectFormatFromName(repo.Repository.ObjectFormatName).FullLength() {
|
||||
repo.TreePath = strings.Join(parts[1:], "/")
|
||||
return parts[0]
|
||||
}
|
||||
if refName := getRefName(ctx, repo, RepoRefBlob); len(refName) > 0 {
|
||||
return refName
|
||||
}
|
||||
repo.TreePath = path
|
||||
return repo.Repository.DefaultBranch
|
||||
case RepoRefBranch:
|
||||
ref := getRefNameFromPath(repo, path, repo.GitRepo.IsBranchExist)
|
||||
if len(ref) == 0 {
|
||||
@@ -866,13 +863,13 @@ func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string {
|
||||
return getRefNameFromPath(repo, path, repo.GitRepo.IsTagExist)
|
||||
case RepoRefCommit:
|
||||
parts := strings.Split(path, "/")
|
||||
|
||||
if len(parts) > 0 && len(parts[0]) >= 7 && len(parts[0]) <= repo.GetObjectFormat().FullLength() {
|
||||
if isStringLikelyCommitID(repo.GetObjectFormat(), parts[0], 7) {
|
||||
// FIXME: this logic is different from other types. Ideally, it should also try to GetCommit to check if it exists
|
||||
repo.TreePath = strings.Join(parts[1:], "/")
|
||||
return parts[0]
|
||||
}
|
||||
|
||||
if len(parts) > 0 && parts[0] == headRefName {
|
||||
if parts[0] == headRefName {
|
||||
// HEAD ref points to last default branch commit
|
||||
commit, err := repo.GitRepo.GetBranchCommit(repo.Repository.DefaultBranch)
|
||||
if err != nil {
|
||||
@@ -888,15 +885,21 @@ func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string {
|
||||
}
|
||||
return path
|
||||
default:
|
||||
log.Error("Unrecognized path type: %v", path)
|
||||
panic(fmt.Sprintf("Unrecognized path type: %v", pathType))
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type RepoRefByTypeOptions struct {
|
||||
IgnoreNotExistErr bool
|
||||
}
|
||||
|
||||
// RepoRefByType handles repository reference name for a specific type
|
||||
// of repository reference
|
||||
func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context) context.CancelFunc {
|
||||
func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func(*Context) context.CancelFunc {
|
||||
opt := util.OptionalArg(opts)
|
||||
return func(ctx *Context) (cancel context.CancelFunc) {
|
||||
refType := detectRefType
|
||||
// Empty repository does not have reference information.
|
||||
if ctx.Repo.Repository.IsEmpty {
|
||||
// assume the user is viewing the (non-existent) default branch
|
||||
@@ -956,7 +959,12 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
}
|
||||
ctx.Repo.IsViewBranch = true
|
||||
} else {
|
||||
refName = getRefName(ctx.Base, ctx.Repo, refType)
|
||||
guessLegacyPath := refType == RepoRefUnknown
|
||||
if guessLegacyPath {
|
||||
refName, refType = getRefNameLegacy(ctx.Base, ctx.Repo)
|
||||
} else {
|
||||
refName = getRefName(ctx.Base, ctx.Repo, refType)
|
||||
}
|
||||
ctx.Repo.RefName = refName
|
||||
isRenamedBranch, has := ctx.Data["IsRenamedBranch"].(bool)
|
||||
if isRenamedBranch && has {
|
||||
@@ -967,7 +975,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
return cancel
|
||||
}
|
||||
|
||||
if refType.RefTypeIncludesBranches() && ctx.Repo.GitRepo.IsBranchExist(refName) {
|
||||
if refType == RepoRefBranch && ctx.Repo.GitRepo.IsBranchExist(refName) {
|
||||
ctx.Repo.IsViewBranch = true
|
||||
ctx.Repo.BranchName = refName
|
||||
|
||||
@@ -977,7 +985,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
return cancel
|
||||
}
|
||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
||||
} else if refType.RefTypeIncludesTags() && ctx.Repo.GitRepo.IsTagExist(refName) {
|
||||
} else if refType == RepoRefTag && ctx.Repo.GitRepo.IsTagExist(refName) {
|
||||
ctx.Repo.IsViewTag = true
|
||||
ctx.Repo.TagName = refName
|
||||
|
||||
@@ -991,7 +999,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
return cancel
|
||||
}
|
||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
||||
} else if len(refName) >= 7 && len(refName) <= ctx.Repo.GetObjectFormat().FullLength() {
|
||||
} else if isStringLikelyCommitID(ctx.Repo.GetObjectFormat(), refName, 7) {
|
||||
ctx.Repo.IsViewCommit = true
|
||||
ctx.Repo.CommitID = refName
|
||||
|
||||
@@ -1002,18 +1010,18 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
}
|
||||
// If short commit ID add canonical link header
|
||||
if len(refName) < ctx.Repo.GetObjectFormat().FullLength() {
|
||||
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))))
|
||||
canonicalURL := util.URLJoin(httplib.GuessCurrentAppURL(ctx), strings.Replace(ctx.Req.URL.RequestURI(), util.PathEscapeSegments(refName), url.PathEscape(ctx.Repo.Commit.ID.String()), 1))
|
||||
ctx.RespHeader().Set("Link", fmt.Sprintf(`<%s>; rel="canonical"`, canonicalURL))
|
||||
}
|
||||
} else {
|
||||
if len(ignoreNotExistErr) > 0 && ignoreNotExistErr[0] {
|
||||
if opt.IgnoreNotExistErr {
|
||||
return cancel
|
||||
}
|
||||
ctx.NotFound("RepoRef invalid repo", fmt.Errorf("branch or tag not exist: %s", refName))
|
||||
return cancel
|
||||
}
|
||||
|
||||
if refType == RepoRefLegacy {
|
||||
if guessLegacyPath {
|
||||
// redirect from old URL scheme to new URL scheme
|
||||
prefix := strings.TrimPrefix(setting.AppSubURL+strings.ToLower(strings.TrimSuffix(ctx.Req.URL.Path, ctx.PathParam("*"))), strings.ToLower(ctx.Repo.RepoLink))
|
||||
redirect := path.Join(
|
||||
|
||||
@@ -185,6 +185,7 @@ func ToBranchProtection(ctx context.Context, bp *git_model.ProtectedBranch, repo
|
||||
RequireSignedCommits: bp.RequireSignedCommits,
|
||||
ProtectedFilePatterns: bp.ProtectedFilePatterns,
|
||||
UnprotectedFilePatterns: bp.UnprotectedFilePatterns,
|
||||
BlockAdminMergeOverride: bp.BlockAdminMergeOverride,
|
||||
Created: bp.CreatedUnix.AsTime(),
|
||||
Updated: bp.UpdatedUnix.AsTime(),
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ func ToAPIMilestone(m *issues_model.Milestone) *api.Milestone {
|
||||
if m.IsClosed {
|
||||
apiMilestone.Closed = m.ClosedDateUnix.AsTimePtr()
|
||||
}
|
||||
if m.DeadlineUnix.Year() < 9999 {
|
||||
if m.DeadlineUnix > 0 {
|
||||
apiMilestone.Deadline = m.DeadlineUnix.AsTimePtr()
|
||||
}
|
||||
return apiMilestone
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func checkDBVersion(ctx context.Context, logger log.Logger, autofix bool) error {
|
||||
logger.Info("Expected database version: %d", migrations.ExpectedVersion())
|
||||
logger.Info("Expected database version: %d", migrations.ExpectedDBVersion())
|
||||
if err := db.InitEngineWithMigration(ctx, migrations.EnsureUpToDate); err != nil {
|
||||
if !autofix {
|
||||
logger.Critical("Error: %v during ensure up to date", err)
|
||||
|
||||
@@ -219,6 +219,7 @@ type ProtectBranchForm struct {
|
||||
RequireSignedCommits bool
|
||||
ProtectedFilePatterns string
|
||||
UnprotectedFilePatterns string
|
||||
BlockAdminMergeOverride bool
|
||||
}
|
||||
|
||||
// Validate validates the fields
|
||||
|
||||
+27
-35
@@ -380,18 +380,11 @@ func (diffFile *DiffFile) GetType() int {
|
||||
}
|
||||
|
||||
// GetTailSection creates a fake DiffLineSection if the last section is not the end of the file
|
||||
func (diffFile *DiffFile) GetTailSection(gitRepo *git.Repository, leftCommitID, rightCommitID string) *DiffSection {
|
||||
func (diffFile *DiffFile) GetTailSection(gitRepo *git.Repository, leftCommit, rightCommit *git.Commit) *DiffSection {
|
||||
if len(diffFile.Sections) == 0 || diffFile.Type != DiffFileChange || diffFile.IsBin || diffFile.IsLFSFile {
|
||||
return nil
|
||||
}
|
||||
leftCommit, err := gitRepo.GetCommit(leftCommitID)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
rightCommit, err := gitRepo.GetCommit(rightCommitID)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
lastSection := diffFile.Sections[len(diffFile.Sections)-1]
|
||||
lastLine := lastSection.Lines[len(lastSection.Lines)-1]
|
||||
leftLineCount := getCommitFileLineCount(leftCommit, diffFile.Name)
|
||||
@@ -536,11 +529,6 @@ parsingLoop:
|
||||
lastFile := createDiffFile(diff, line)
|
||||
diff.End = lastFile.Name
|
||||
diff.IsIncomplete = true
|
||||
_, err := io.Copy(io.Discard, reader)
|
||||
if err != nil {
|
||||
// By the definition of io.Copy this never returns io.EOF
|
||||
return diff, fmt.Errorf("error during io.Copy: %w", err)
|
||||
}
|
||||
break parsingLoop
|
||||
}
|
||||
|
||||
@@ -1101,6 +1089,7 @@ type DiffOptions struct {
|
||||
MaxFiles int
|
||||
WhitespaceBehavior git.TrustedCmdArgs
|
||||
DirectComparison bool
|
||||
FileOnly bool
|
||||
}
|
||||
|
||||
// GetDiff builds a Diff between two commits of a repository.
|
||||
@@ -1109,12 +1098,16 @@ type DiffOptions struct {
|
||||
func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff, error) {
|
||||
repoPath := gitRepo.Path
|
||||
|
||||
var beforeCommit *git.Commit
|
||||
commit, err := gitRepo.GetCommit(opts.AfterCommitID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmdDiff := git.NewCommand(gitRepo.Ctx)
|
||||
cmdCtx, cmdCancel := context.WithCancel(ctx)
|
||||
defer cmdCancel()
|
||||
|
||||
cmdDiff := git.NewCommand(cmdCtx)
|
||||
objectFormat, err := gitRepo.GetObjectFormat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1136,6 +1129,12 @@ func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, fi
|
||||
AddArguments(opts.WhitespaceBehavior...).
|
||||
AddDynamicArguments(actualBeforeCommitID, opts.AfterCommitID)
|
||||
opts.BeforeCommitID = actualBeforeCommitID
|
||||
|
||||
var err error
|
||||
beforeCommit, err = gitRepo.GetCommit(opts.BeforeCommitID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// In git 2.31, git diff learned --skip-to which we can use to shortcut skip to file
|
||||
@@ -1163,14 +1162,16 @@ func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, fi
|
||||
Dir: repoPath,
|
||||
Stdout: writer,
|
||||
Stderr: stderr,
|
||||
}); err != nil {
|
||||
}); err != nil && !git.IsErrCanceledOrKilled(err) {
|
||||
log.Error("error during GetDiff(git diff dir: %s): %v, stderr: %s", repoPath, err, stderr.String())
|
||||
}
|
||||
|
||||
_ = writer.Close()
|
||||
}()
|
||||
|
||||
diff, err := ParsePatch(ctx, opts.MaxLines, opts.MaxLineCharacters, opts.MaxFiles, reader, parsePatchSkipToFile)
|
||||
diff, err := ParsePatch(cmdCtx, opts.MaxLines, opts.MaxLineCharacters, opts.MaxFiles, reader, parsePatchSkipToFile)
|
||||
// Ensure the git process is killed if it didn't exit already
|
||||
cmdCancel()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to ParsePatch: %w", err)
|
||||
}
|
||||
@@ -1205,37 +1206,28 @@ func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, fi
|
||||
}
|
||||
diffFile.IsGenerated = isGenerated.Value()
|
||||
|
||||
tailSection := diffFile.GetTailSection(gitRepo, opts.BeforeCommitID, opts.AfterCommitID)
|
||||
tailSection := diffFile.GetTailSection(gitRepo, beforeCommit, commit)
|
||||
if tailSection != nil {
|
||||
diffFile.Sections = append(diffFile.Sections, tailSection)
|
||||
}
|
||||
}
|
||||
|
||||
separator := "..."
|
||||
if opts.DirectComparison {
|
||||
separator = ".."
|
||||
if opts.FileOnly {
|
||||
return diff, nil
|
||||
}
|
||||
|
||||
diffPaths := []string{opts.BeforeCommitID + separator + opts.AfterCommitID}
|
||||
if len(opts.BeforeCommitID) == 0 || opts.BeforeCommitID == objectFormat.EmptyObjectID().String() {
|
||||
diffPaths = []string{objectFormat.EmptyTree().String(), opts.AfterCommitID}
|
||||
}
|
||||
diff.NumFiles, diff.TotalAddition, diff.TotalDeletion, err = git.GetDiffShortStat(gitRepo.Ctx, repoPath, nil, diffPaths...)
|
||||
if err != nil && strings.Contains(err.Error(), "no merge base") {
|
||||
// git >= 2.28 now returns an error if base and head have become unrelated.
|
||||
// previously it would return the results of git diff --shortstat base head so let's try that...
|
||||
diffPaths = []string{opts.BeforeCommitID, opts.AfterCommitID}
|
||||
diff.NumFiles, diff.TotalAddition, diff.TotalDeletion, err = git.GetDiffShortStat(gitRepo.Ctx, repoPath, nil, diffPaths...)
|
||||
}
|
||||
stats, err := GetPullDiffStats(gitRepo, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
diff.NumFiles, diff.TotalAddition, diff.TotalDeletion = stats.NumFiles, stats.TotalAddition, stats.TotalDeletion
|
||||
|
||||
return diff, nil
|
||||
}
|
||||
|
||||
type PullDiffStats struct {
|
||||
TotalAddition, TotalDeletion int
|
||||
NumFiles, TotalAddition, TotalDeletion int
|
||||
}
|
||||
|
||||
// GetPullDiffStats
|
||||
@@ -1259,12 +1251,12 @@ func GetPullDiffStats(gitRepo *git.Repository, opts *DiffOptions) (*PullDiffStat
|
||||
diffPaths = []string{objectFormat.EmptyTree().String(), opts.AfterCommitID}
|
||||
}
|
||||
|
||||
_, diff.TotalAddition, diff.TotalDeletion, err = git.GetDiffShortStat(gitRepo.Ctx, repoPath, nil, diffPaths...)
|
||||
diff.NumFiles, diff.TotalAddition, diff.TotalDeletion, err = git.GetDiffShortStat(gitRepo.Ctx, repoPath, nil, diffPaths...)
|
||||
if err != nil && strings.Contains(err.Error(), "no merge base") {
|
||||
// git >= 2.28 now returns an error if base and head have become unrelated.
|
||||
// previously it would return the results of git diff --shortstat base head so let's try that...
|
||||
diffPaths = []string{opts.BeforeCommitID, opts.AfterCommitID}
|
||||
_, diff.TotalAddition, diff.TotalDeletion, err = git.GetDiffShortStat(gitRepo.Ctx, repoPath, nil, diffPaths...)
|
||||
diff.NumFiles, diff.TotalAddition, diff.TotalDeletion, err = git.GetDiffShortStat(gitRepo.Ctx, repoPath, nil, diffPaths...)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -52,8 +52,6 @@ func GetTemplateConfig(gitRepo *git.Repository, path string, commit *git.Commit)
|
||||
return GetDefaultTemplateConfig(), nil
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
treeEntry, err := commit.GetTreeEntryByPath(path)
|
||||
if err != nil {
|
||||
return GetDefaultTemplateConfig(), err
|
||||
|
||||
@@ -179,6 +179,11 @@ func BatchHandler(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if setting.LFS.MaxBatchSize != 0 && len(br.Objects) > setting.LFS.MaxBatchSize {
|
||||
writeStatus(ctx, http.StatusRequestEntityTooLarge)
|
||||
return
|
||||
}
|
||||
|
||||
contentStore := lfs_module.NewContentStore()
|
||||
|
||||
var responseObjects []*lfs_module.ObjectResponse
|
||||
@@ -455,7 +460,7 @@ func buildObjectResponse(rc *requestContext, pointer lfs_module.Pointer, downloa
|
||||
var link *lfs_module.Link
|
||||
if setting.LFS.Storage.ServeDirect() {
|
||||
// If we have a signed url (S3, object storage), redirect to this directly.
|
||||
u, err := storage.LFS.URL(pointer.RelativePath(), pointer.Oid)
|
||||
u, err := storage.LFS.URL(pointer.RelativePath(), pointer.Oid, nil)
|
||||
if u != nil && err == nil {
|
||||
// Presigned url does not need the Authorization header
|
||||
// https://github.com/go-gitea/gitea/issues/21525
|
||||
|
||||
@@ -613,14 +613,8 @@ func checkAndUpdateEmptyRepository(ctx context.Context, m *repo_model.Mirror, re
|
||||
}
|
||||
// Update the git repository default branch
|
||||
if err := gitrepo.SetDefaultBranch(ctx, m.Repo, m.Repo.DefaultBranch); err != nil {
|
||||
if !git.IsErrUnsupportedVersion(err) {
|
||||
log.Error("Failed to update default branch of underlying git repository %-v. Error: %v", m.Repo, err)
|
||||
desc := fmt.Sprintf("Failed to update default branch of underlying git repository '%s': %v", m.Repo.RepoPath(), err)
|
||||
if err = system_model.CreateRepositoryNotice(desc); err != nil {
|
||||
log.Error("CreateRepositoryNotice: %v", err)
|
||||
}
|
||||
return false
|
||||
}
|
||||
log.Error("Failed to update default branch of underlying git repository %-v. Error: %v", m.Repo, err)
|
||||
return false
|
||||
}
|
||||
m.Repo.IsEmpty = false
|
||||
// Update the is empty and default_branch columns
|
||||
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
rpm_service "code.gitea.io/gitea/services/packages/rpm"
|
||||
)
|
||||
|
||||
// Task method to execute cleanup rules and cleanup expired package data
|
||||
// CleanupTask executes cleanup rules and cleanup expired package data
|
||||
func CleanupTask(ctx context.Context, olderThan time.Duration) error {
|
||||
if err := ExecuteCleanupRules(ctx); err != nil {
|
||||
return err
|
||||
|
||||
@@ -206,7 +206,11 @@ func buildPackagesIndices(ctx context.Context, ownerID int64, repoVersion *packa
|
||||
w := io.MultiWriter(packagesContent, gzw, xzw)
|
||||
|
||||
addSeparator := false
|
||||
if err := debian_model.SearchPackages(ctx, opts, func(pfd *packages_model.PackageFileDescriptor) {
|
||||
pfds, err := debian_model.SearchPackages(ctx, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, pfd := range pfds {
|
||||
if addSeparator {
|
||||
fmt.Fprintln(w)
|
||||
}
|
||||
@@ -220,10 +224,7 @@ func buildPackagesIndices(ctx context.Context, ownerID int64, repoVersion *packa
|
||||
fmt.Fprintf(w, "SHA1: %s\n", pfd.Blob.HashSHA1)
|
||||
fmt.Fprintf(w, "SHA256: %s\n", pfd.Blob.HashSHA256)
|
||||
fmt.Fprintf(w, "SHA512: %s\n", pfd.Blob.HashSHA512)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gzw.Close()
|
||||
xzw.Close()
|
||||
|
||||
|
||||
@@ -596,12 +596,12 @@ func GetPackageFileStream(ctx context.Context, pf *packages_model.PackageFile) (
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
return GetPackageBlobStream(ctx, pf, pb)
|
||||
return GetPackageBlobStream(ctx, pf, pb, nil)
|
||||
}
|
||||
|
||||
// GetPackageBlobStream returns the content of the specific package blob
|
||||
// If the storage supports direct serving and it's enabled, only the direct serving url is returned.
|
||||
func GetPackageBlobStream(ctx context.Context, pf *packages_model.PackageFile, pb *packages_model.PackageBlob) (io.ReadSeekCloser, *url.URL, *packages_model.PackageFile, error) {
|
||||
func GetPackageBlobStream(ctx context.Context, pf *packages_model.PackageFile, pb *packages_model.PackageBlob, serveDirectReqParams url.Values) (io.ReadSeekCloser, *url.URL, *packages_model.PackageFile, error) {
|
||||
key := packages_module.BlobHash256Key(pb.HashSHA256)
|
||||
|
||||
cs := packages_module.NewContentStore()
|
||||
@@ -611,7 +611,7 @@ func GetPackageBlobStream(ctx context.Context, pf *packages_model.PackageFile, p
|
||||
var err error
|
||||
|
||||
if cs.ShouldServeDirect() {
|
||||
u, err = cs.GetServeDirectURL(key, pf.Name)
|
||||
u, err = cs.GetServeDirectURL(key, pf.Name, serveDirectReqParams)
|
||||
if err != nil && !errors.Is(err, storage.ErrURLNotSupported) {
|
||||
log.Error("Error getting serve direct url: %v", err)
|
||||
}
|
||||
|
||||
+17
-8
@@ -68,7 +68,7 @@ const (
|
||||
)
|
||||
|
||||
// CheckPullMergeable check if the pull mergeable based on all conditions (branch protection, merge options, ...)
|
||||
func CheckPullMergeable(stdCtx context.Context, doer *user_model.User, perm *access_model.Permission, pr *issues_model.PullRequest, mergeCheckType MergeCheckType, adminSkipProtectionCheck bool) error {
|
||||
func CheckPullMergeable(stdCtx context.Context, doer *user_model.User, perm *access_model.Permission, pr *issues_model.PullRequest, mergeCheckType MergeCheckType, adminForceMerge bool) error {
|
||||
return db.WithTx(stdCtx, func(ctx context.Context) error {
|
||||
if pr.HasMerged {
|
||||
return ErrHasMerged
|
||||
@@ -118,13 +118,22 @@ func CheckPullMergeable(stdCtx context.Context, doer *user_model.User, perm *acc
|
||||
err = nil
|
||||
}
|
||||
|
||||
// * if the doer is admin, they could skip the branch protection check
|
||||
if adminSkipProtectionCheck {
|
||||
if isRepoAdmin, errCheckAdmin := access_model.IsUserRepoAdmin(ctx, pr.BaseRepo, doer); errCheckAdmin != nil {
|
||||
log.Error("Unable to check if %-v is a repo admin in %-v: %v", doer, pr.BaseRepo, errCheckAdmin)
|
||||
return errCheckAdmin
|
||||
} else if isRepoAdmin {
|
||||
err = nil // repo admin can skip the check, so clear the error
|
||||
// * if admin tries to "Force Merge", they could sometimes skip the branch protection check
|
||||
if adminForceMerge {
|
||||
isRepoAdmin, errForceMerge := access_model.IsUserRepoAdmin(ctx, pr.BaseRepo, doer)
|
||||
if errForceMerge != nil {
|
||||
return fmt.Errorf("IsUserRepoAdmin failed, repo: %v, doer: %v, err: %w", pr.BaseRepoID, doer.ID, errForceMerge)
|
||||
}
|
||||
|
||||
protectedBranchRule, errForceMerge := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, pr.BaseBranch)
|
||||
if errForceMerge != nil {
|
||||
return fmt.Errorf("GetFirstMatchProtectedBranchRule failed, repo: %v, base branch: %v, err: %w", pr.BaseRepoID, pr.BaseBranch, errForceMerge)
|
||||
}
|
||||
|
||||
// if doer is admin and the "Force Merge" is not blocked, then clear the branch protection check error
|
||||
blockAdminForceMerge := protectedBranchRule != nil && protectedBranchRule.BlockAdminMergeOverride
|
||||
if isRepoAdmin && !blockAdminForceMerge {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -606,12 +606,7 @@ func SetRepoDefaultBranch(ctx context.Context, repo *repo_model.Repository, gitR
|
||||
log.Error("CancelPreviousJobs: %v", err)
|
||||
}
|
||||
|
||||
if err := gitrepo.SetDefaultBranch(ctx, repo, newBranchName); err != nil {
|
||||
if !git.IsErrUnsupportedVersion(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return gitrepo.SetDefaultBranch(ctx, repo, newBranchName)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -339,8 +339,7 @@ func (t *TemporaryUploadRepository) Push(doer *user_model.User, commitHash, bran
|
||||
func (t *TemporaryUploadRepository) DiffIndex() (*gitdiff.Diff, error) {
|
||||
stdoutReader, stdoutWriter, err := os.Pipe()
|
||||
if err != nil {
|
||||
log.Error("Unable to open stdout pipe: %v", err)
|
||||
return nil, fmt.Errorf("Unable to open stdout pipe: %w", err)
|
||||
return nil, fmt.Errorf("unable to open stdout pipe: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = stdoutReader.Close()
|
||||
@@ -348,9 +347,7 @@ func (t *TemporaryUploadRepository) DiffIndex() (*gitdiff.Diff, error) {
|
||||
}()
|
||||
stderr := new(bytes.Buffer)
|
||||
var diff *gitdiff.Diff
|
||||
var finalErr error
|
||||
|
||||
if err := git.NewCommand(t.ctx, "diff-index", "--src-prefix=\\a/", "--dst-prefix=\\b/", "--cached", "-p", "HEAD").
|
||||
err = git.NewCommand(t.ctx, "diff-index", "--src-prefix=\\a/", "--dst-prefix=\\b/", "--cached", "-p", "HEAD").
|
||||
Run(&git.RunOpts{
|
||||
Timeout: 30 * time.Second,
|
||||
Dir: t.basePath,
|
||||
@@ -358,23 +355,20 @@ func (t *TemporaryUploadRepository) DiffIndex() (*gitdiff.Diff, error) {
|
||||
Stderr: stderr,
|
||||
PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error {
|
||||
_ = stdoutWriter.Close()
|
||||
diff, finalErr = gitdiff.ParsePatch(t.ctx, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, stdoutReader, "")
|
||||
if finalErr != nil {
|
||||
log.Error("ParsePatch: %v", finalErr)
|
||||
cancel()
|
||||
}
|
||||
defer cancel()
|
||||
var diffErr error
|
||||
diff, diffErr = gitdiff.ParsePatch(t.ctx, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, stdoutReader, "")
|
||||
_ = stdoutReader.Close()
|
||||
return finalErr
|
||||
if diffErr != nil {
|
||||
// if the diffErr is not nil, it will be returned as the error of "Run()"
|
||||
return fmt.Errorf("ParsePatch: %w", diffErr)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}); err != nil {
|
||||
if finalErr != nil {
|
||||
log.Error("Unable to ParsePatch in temporary repo %s (%s). Error: %v", t.repo.FullName(), t.basePath, finalErr)
|
||||
return nil, finalErr
|
||||
}
|
||||
log.Error("Unable to run diff-index pipeline in temporary repo %s (%s). Error: %v\nStderr: %s",
|
||||
t.repo.FullName(), t.basePath, err, stderr)
|
||||
return nil, fmt.Errorf("Unable to run diff-index pipeline in temporary repo %s. Error: %w\nStderr: %s",
|
||||
t.repo.FullName(), err, stderr)
|
||||
})
|
||||
if err != nil && !git.IsErrCanceledOrKilled(err) {
|
||||
log.Error("Unable to diff-index in temporary repo %s (%s). Error: %v\nStderr: %s", t.repo.FullName(), t.basePath, err, stderr)
|
||||
return nil, fmt.Errorf("unable to run diff-index pipeline in temporary repo: %w", err)
|
||||
}
|
||||
|
||||
diff.NumFiles, diff.TotalAddition, diff.TotalDeletion, err = git.GetDiffShortStat(t.ctx, t.basePath, git.TrustedCmdArgs{"--cached"}, "HEAD")
|
||||
|
||||
@@ -183,9 +183,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
|
||||
repo.IsEmpty = false
|
||||
if repo.DefaultBranch != setting.Repository.DefaultBranch {
|
||||
if err := gitrepo.SetDefaultBranch(ctx, repo, repo.DefaultBranch); err != nil {
|
||||
if !git.IsErrUnsupportedVersion(err) {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Update the is empty and default_branch columns
|
||||
|
||||
@@ -289,6 +289,7 @@ func DeleteInactiveUsers(ctx context.Context, olderThan time.Duration) error {
|
||||
if err = DeleteUser(ctx, u, false); err != nil {
|
||||
// Ignore inactive users that were ever active but then were set inactive by admin
|
||||
if models.IsErrUserOwnRepos(err) || models.IsErrUserHasOrgs(err) || models.IsErrUserOwnPackages(err) {
|
||||
log.Warn("Inactive user %q has repositories, organizations or packages, skipping deletion: %v", u.Name, err)
|
||||
continue
|
||||
}
|
||||
select {
|
||||
|
||||
Reference in New Issue
Block a user