mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-15 00:01:25 -04:00
Compare commits
5 Commits
b48cf03717
...
7cc7db73b9
Author | SHA1 | Date | |
---|---|---|---|
|
7cc7db73b9 | ||
|
22a6e97597 | ||
|
d0c3d0ba26 | ||
|
6cf09ccab4 | ||
|
90237d8abd |
@ -5,6 +5,6 @@ tmp_dir = ".air"
|
|||||||
cmd = "make backend"
|
cmd = "make backend"
|
||||||
bin = "gitea"
|
bin = "gitea"
|
||||||
include_ext = ["go", "tmpl"]
|
include_ext = ["go", "tmpl"]
|
||||||
exclude_dir = ["modules/git/tests", "services/gitdiff/testdata", "modules/avatar/testdata"]
|
exclude_dir = ["modules/git/tests", "services/gitdiff/testdata", "modules/avatar/testdata", "models/fixtures", "models/migrations/fixtures", "modules/migration/file_format_testdata", "modules/avatar/identicon/testdata"]
|
||||||
include_dir = ["cmd", "models", "modules", "options", "routers", "services", "templates"]
|
include_dir = ["cmd", "models", "modules", "options", "routers", "services"]
|
||||||
exclude_regex = ["_test.go$", "_gen.go$"]
|
exclude_regex = ["_test.go$", "_gen.go$"]
|
||||||
|
@ -441,7 +441,7 @@ be reviewed by two maintainers and must pass the automatic tests.
|
|||||||
Code that you contribute should use the standard copyright header:
|
Code that you contribute should use the standard copyright header:
|
||||||
|
|
||||||
```
|
```
|
||||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
// Copyright <year> The Gitea Authors. All rights reserved.
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
```
|
```
|
||||||
|
2
Makefile
2
Makefile
@ -359,7 +359,7 @@ watch-frontend: node-check node_modules
|
|||||||
|
|
||||||
.PHONY: watch-backend
|
.PHONY: watch-backend
|
||||||
watch-backend: go-check
|
watch-backend: go-check
|
||||||
$(GO) run $(AIR_PACKAGE) -c .air.toml
|
GITEA_RUN_MODE=dev $(GO) run $(AIR_PACKAGE) -c .air.toml
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: test-frontend test-backend
|
test: test-frontend test-backend
|
||||||
|
@ -957,6 +957,9 @@ ROUTER = console
|
|||||||
;; Don't allow download source archive files from UI
|
;; Don't allow download source archive files from UI
|
||||||
;DISABLE_DOWNLOAD_SOURCE_ARCHIVES = false
|
;DISABLE_DOWNLOAD_SOURCE_ARCHIVES = false
|
||||||
|
|
||||||
|
;; Allow fork repositories without maximum number limit
|
||||||
|
;ALLOW_FORK_WITHOUT_MAXIMUM_LIMIT = true
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;[repository.editor]
|
;[repository.editor]
|
||||||
|
@ -112,6 +112,7 @@ In addition there is _`StaticRootPath`_ which can be set as a built-in at build
|
|||||||
- `ALLOW_ADOPTION_OF_UNADOPTED_REPOSITORIES`: **false**: Allow non-admin users to adopt unadopted repositories
|
- `ALLOW_ADOPTION_OF_UNADOPTED_REPOSITORIES`: **false**: Allow non-admin users to adopt unadopted repositories
|
||||||
- `ALLOW_DELETION_OF_UNADOPTED_REPOSITORIES`: **false**: Allow non-admin users to delete unadopted repositories
|
- `ALLOW_DELETION_OF_UNADOPTED_REPOSITORIES`: **false**: Allow non-admin users to delete unadopted repositories
|
||||||
- `DISABLE_DOWNLOAD_SOURCE_ARCHIVES`: **false**: Don't allow download source archive files from UI
|
- `DISABLE_DOWNLOAD_SOURCE_ARCHIVES`: **false**: Don't allow download source archive files from UI
|
||||||
|
- `ALLOW_FORK_WITHOUT_MAXIMUM_LIMIT`: **true**: Allow fork repositories without maximum number limit
|
||||||
|
|
||||||
### Repository - Editor (`repository.editor`)
|
### Repository - Editor (`repository.editor`)
|
||||||
|
|
||||||
@ -239,6 +240,10 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
|||||||
- `NOTICE_PAGING_NUM`: **25**: Number of notices that are shown in one page.
|
- `NOTICE_PAGING_NUM`: **25**: Number of notices that are shown in one page.
|
||||||
- `ORG_PAGING_NUM`: **50**: Number of organizations that are shown in one page.
|
- `ORG_PAGING_NUM`: **50**: Number of organizations that are shown in one page.
|
||||||
|
|
||||||
|
### UI - User (`ui.user`)
|
||||||
|
|
||||||
|
- `REPO_PAGING_NUM`: **15**: Number of repos that are shown in one page.
|
||||||
|
|
||||||
### UI - Metadata (`ui.meta`)
|
### UI - Metadata (`ui.meta`)
|
||||||
|
|
||||||
- `AUTHOR`: **Gitea - Git with a cup of tea**: Author meta tag of the homepage.
|
- `AUTHOR`: **Gitea - Git with a cup of tea**: Author meta tag of the homepage.
|
||||||
|
@ -272,7 +272,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.
|
||||||
|
@ -279,6 +279,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)
|
||||||
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext(db.DefaultContext)
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("NewCommitStatus[repo_id: %d, user_id: %d, sha: %s]: %w", opts.Repo.ID, opts.Creator.ID, opts.SHA, err)
|
return fmt.Errorf("NewCommitStatus[repo_id: %d, user_id: %d, sha: %s]: %w", opts.Repo.ID, opts.Creator.ID, opts.SHA, err)
|
||||||
|
@ -275,6 +275,15 @@ func (u *User) CanEditGitHook() bool {
|
|||||||
return !setting.DisableGitHooks && (u.IsAdmin || u.AllowGitHook)
|
return !setting.DisableGitHooks && (u.IsAdmin || u.AllowGitHook)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CanForkRepo returns if user login can fork a repository
|
||||||
|
// It checks especially that the user can create repos, and potentially more
|
||||||
|
func (u *User) CanForkRepo() bool {
|
||||||
|
if setting.Repository.AllowForkWithoutMaximumLimit {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return u.CanCreateRepo()
|
||||||
|
}
|
||||||
|
|
||||||
// CanImportLocal returns true if user can migrate repository by local path.
|
// CanImportLocal returns true if user can migrate repository by local path.
|
||||||
func (u *User) CanImportLocal() bool {
|
func (u *User) CanImportLocal() bool {
|
||||||
if !setting.ImportLocalPaths || u == nil {
|
if !setting.ImportLocalPaths || u == nil {
|
||||||
|
@ -387,7 +387,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 {
|
||||||
|
@ -817,7 +817,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]
|
||||||
}
|
}
|
||||||
@ -853,7 +853,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]
|
||||||
}
|
}
|
||||||
@ -962,7 +962,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
|
||||||
|
|
||||||
@ -972,7 +972,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))))
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,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
|
||||||
|
@ -137,7 +137,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
|
||||||
|
@ -16,7 +16,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").AddDynamicArguments(treeish).RunStdString(&RunOpts{Dir: repo.Path})
|
res, _, err := NewCommand(repo.Ctx, "rev-parse", "--verify").AddDynamicArguments(treeish).RunStdString(&RunOpts{Dir: repo.Path})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -19,7 +19,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").AddDynamicArguments(idStr).RunStdString(&RunOpts{Dir: repo.Path})
|
res, _, err := NewCommand(repo.Ctx, "rev-parse", "--verify").AddDynamicArguments(idStr).RunStdString(&RunOpts{Dir: repo.Path})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -66,7 +66,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
|
||||||
|
@ -17,6 +17,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}$`)
|
||||||
|
|
||||||
@ -50,7 +53,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)
|
||||||
|
@ -48,6 +48,7 @@ var (
|
|||||||
AllowAdoptionOfUnadoptedRepositories bool
|
AllowAdoptionOfUnadoptedRepositories bool
|
||||||
AllowDeleteOfUnadoptedRepositories bool
|
AllowDeleteOfUnadoptedRepositories bool
|
||||||
DisableDownloadSourceArchives bool
|
DisableDownloadSourceArchives bool
|
||||||
|
AllowForkWithoutMaximumLimit bool
|
||||||
|
|
||||||
// Repository editor settings
|
// Repository editor settings
|
||||||
Editor struct {
|
Editor struct {
|
||||||
@ -160,6 +161,7 @@ var (
|
|||||||
DisableMigrations: false,
|
DisableMigrations: false,
|
||||||
DisableStars: false,
|
DisableStars: false,
|
||||||
DefaultBranch: "main",
|
DefaultBranch: "main",
|
||||||
|
AllowForkWithoutMaximumLimit: true,
|
||||||
|
|
||||||
// Repository editor settings
|
// Repository editor settings
|
||||||
Editor: struct {
|
Editor: struct {
|
||||||
|
@ -1043,7 +1043,10 @@ func loadFromConf(allowEmpty bool, extraConfig string) {
|
|||||||
// The following is a purposefully undocumented option. Please do not run Gitea as root. It will only cause future headaches.
|
// The following is a purposefully undocumented option. Please do not run Gitea as root. It will only cause future headaches.
|
||||||
// Please don't use root as a bandaid to "fix" something that is broken, instead the broken thing should instead be fixed properly.
|
// Please don't use root as a bandaid to "fix" something that is broken, instead the broken thing should instead be fixed properly.
|
||||||
unsafeAllowRunAsRoot := Cfg.Section("").Key("I_AM_BEING_UNSAFE_RUNNING_AS_ROOT").MustBool(false)
|
unsafeAllowRunAsRoot := Cfg.Section("").Key("I_AM_BEING_UNSAFE_RUNNING_AS_ROOT").MustBool(false)
|
||||||
|
RunMode = os.Getenv("GITEA_RUN_MODE")
|
||||||
|
if RunMode == "" {
|
||||||
RunMode = Cfg.Section("").Key("RUN_MODE").MustString("prod")
|
RunMode = Cfg.Section("").Key("RUN_MODE").MustString("prod")
|
||||||
|
}
|
||||||
IsProd = strings.EqualFold(RunMode, "prod")
|
IsProd = strings.EqualFold(RunMode, "prod")
|
||||||
// Does not check run user when the install lock is off.
|
// Does not check run user when the install lock is off.
|
||||||
if InstallLock {
|
if InstallLock {
|
||||||
|
@ -141,7 +141,7 @@ func CreateFork(ctx *context.APIContext) {
|
|||||||
Description: repo.Description,
|
Description: repo.Description,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if repo_model.IsErrRepoAlreadyExist(err) {
|
if repo_model.IsErrReachLimitOfRepo(err) || repo_model.IsErrRepoAlreadyExist(err) {
|
||||||
ctx.Error(http.StatusConflict, "ForkRepository", err)
|
ctx.Error(http.StatusConflict, "ForkRepository", err)
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "ForkRepository", err)
|
ctx.Error(http.StatusInternalServerError, "ForkRepository", err)
|
||||||
|
@ -183,6 +183,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)
|
||||||
|
@ -33,6 +33,8 @@ func ResolveRefOrSha(ctx *context.APIContext, ref string) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sha = MustConvertToSHA1(ctx.Context, sha)
|
||||||
|
|
||||||
if ctx.Repo.GitRepo != nil {
|
if ctx.Repo.GitRepo != nil {
|
||||||
err := ctx.Repo.GitRepo.AddLastCommitCache(ctx.Repo.Repository.GetCommitsCountCacheKey(ref, ref != sha), ctx.Repo.Repository.FullName(), sha)
|
err := ctx.Repo.GitRepo.AddLastCommitCache(ctx.Repo.Repository.GetCommitsCountCacheKey(ref, ref != sha), ctx.Repo.Repository.FullName(), sha)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -65,3 +67,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()
|
||||||
|
}
|
||||||
|
@ -283,7 +283,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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,6 +182,15 @@ func getForkRepository(ctx *context.Context) *repo_model.Repository {
|
|||||||
func Fork(ctx *context.Context) {
|
func Fork(ctx *context.Context) {
|
||||||
ctx.Data["Title"] = ctx.Tr("new_fork")
|
ctx.Data["Title"] = ctx.Tr("new_fork")
|
||||||
|
|
||||||
|
if ctx.Doer.CanForkRepo() {
|
||||||
|
ctx.Data["CanForkRepo"] = true
|
||||||
|
} else {
|
||||||
|
maxCreationLimit := ctx.Doer.MaxCreationLimit()
|
||||||
|
msg := ctx.TrN(maxCreationLimit, "repo.form.reach_limit_of_creation_1", "repo.form.reach_limit_of_creation_n", maxCreationLimit)
|
||||||
|
ctx.Data["Flash"] = ctx.Flash
|
||||||
|
ctx.Flash.Error(msg)
|
||||||
|
}
|
||||||
|
|
||||||
getForkRepository(ctx)
|
getForkRepository(ctx)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
@ -254,6 +263,10 @@ func ForkPost(ctx *context.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Data["Err_RepoName"] = true
|
ctx.Data["Err_RepoName"] = true
|
||||||
switch {
|
switch {
|
||||||
|
case repo_model.IsErrReachLimitOfRepo(err):
|
||||||
|
maxCreationLimit := ctxUser.MaxCreationLimit()
|
||||||
|
msg := ctx.TrN(maxCreationLimit, "repo.form.reach_limit_of_creation_1", "repo.form.reach_limit_of_creation_n", maxCreationLimit)
|
||||||
|
ctx.RenderWithErr(msg, tplFork, &form)
|
||||||
case repo_model.IsErrRepoAlreadyExist(err):
|
case repo_model.IsErrRepoAlreadyExist(err):
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplFork, &form)
|
ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplFork, &form)
|
||||||
case db.IsErrNameReserved(err):
|
case db.IsErrNameReserved(err):
|
||||||
|
@ -199,19 +199,19 @@ func getMergeCommit(ctx context.Context, pr *issues_model.PullRequest) (*git.Com
|
|||||||
return nil, fmt.Errorf("ReadFile(%s): %w", headFile, err)
|
return nil, fmt.Errorf("ReadFile(%s): %w", 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").AddDynamicArguments(cmd).
|
mergeCommit, _, err := git.NewCommand(ctx, "rev-list", "--ancestry-path", "--merges", "--reverse").AddDynamicArguments(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: %w", err)
|
return nil, fmt.Errorf("git rev-list --ancestry-path --merges --reverse: %w", 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())
|
||||||
@ -220,9 +220,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]: %w", mergeCommit[:40], err)
|
return nil, fmt.Errorf("GetMergeCommit[%v]: %w", mergeCommit[:git.SHAFullLength], err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return commit, nil
|
return commit, nil
|
||||||
|
@ -839,7 +839,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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +166,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()
|
||||||
|
@ -29,9 +29,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]: %w", sha, err)
|
return fmt.Errorf("GetCommit[%s]: %w", sha, err)
|
||||||
|
} else if len(sha) != git.SHAFullLength {
|
||||||
|
// use complete commit sha
|
||||||
|
sha = commit.ID.String()
|
||||||
}
|
}
|
||||||
gitRepo.Close()
|
gitRepo.Close()
|
||||||
|
|
||||||
|
@ -49,7 +49,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
|
||||||
|
@ -51,6 +51,13 @@ type ForkRepoOptions struct {
|
|||||||
|
|
||||||
// ForkRepository forks a repository
|
// ForkRepository forks a repository
|
||||||
func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts ForkRepoOptions) (*repo_model.Repository, error) {
|
func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts ForkRepoOptions) (*repo_model.Repository, error) {
|
||||||
|
// Fork is prohibited, if user has reached maximum limit of repositories
|
||||||
|
if !owner.CanForkRepo() {
|
||||||
|
return nil, repo_model.ErrReachLimitOfRepo{
|
||||||
|
Limit: owner.MaxRepoCreation,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
forkedRepo, err := repo_model.GetUserFork(ctx, opts.BaseRepo.ID, owner.ID)
|
forkedRepo, err := repo_model.GetUserFork(ctx, opts.BaseRepo.ID, owner.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
@ -29,4 +30,19 @@ func TestForkRepository(t *testing.T) {
|
|||||||
assert.Nil(t, fork)
|
assert.Nil(t, fork)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.True(t, IsErrForkAlreadyExist(err))
|
assert.True(t, IsErrForkAlreadyExist(err))
|
||||||
|
|
||||||
|
// user not reached maximum limit of repositories
|
||||||
|
assert.False(t, repo_model.IsErrReachLimitOfRepo(err))
|
||||||
|
|
||||||
|
// change AllowForkWithoutMaximumLimit to false for the test
|
||||||
|
setting.Repository.AllowForkWithoutMaximumLimit = false
|
||||||
|
// user has reached maximum limit of repositories
|
||||||
|
user.MaxRepoCreation = 0
|
||||||
|
fork2, err := ForkRepository(git.DefaultContext, user, user, ForkRepoOptions{
|
||||||
|
BaseRepo: repo,
|
||||||
|
Name: "test",
|
||||||
|
Description: "test",
|
||||||
|
})
|
||||||
|
assert.Nil(t, fork2)
|
||||||
|
assert.True(t, repo_model.IsErrReachLimitOfRepo(err))
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@
|
|||||||
|
|
||||||
<div class="inline field">
|
<div class="inline field">
|
||||||
<label></label>
|
<label></label>
|
||||||
<button class="ui green button">
|
<button class="ui green button{{if not .CanForkRepo}} disabled{{end}}">
|
||||||
{{.locale.Tr "repo.fork_repo"}}
|
{{.locale.Tr "repo.fork_repo"}}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -68,6 +68,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")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user