Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions models/user/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,12 @@ func (u *User) CanEditGitHook() bool {
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 {
return u.CanCreateRepo()
}

// CanImportLocal returns true if user can migrate repository by local path.
func (u *User) CanImportLocal() bool {
if !setting.ImportLocalPaths || u == nil {
Expand Down
2 changes: 1 addition & 1 deletion routers/api/v1/repo/fork.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func CreateFork(ctx *context.APIContext) {
Description: repo.Description,
})
if err != nil {
if repo_model.IsErrRepoAlreadyExist(err) {
if repo_model.IsErrReachLimitOfRepo(err) || repo_model.IsErrRepoAlreadyExist(err) {
ctx.Error(http.StatusConflict, "ForkRepository", err)
} else {
ctx.Error(http.StatusInternalServerError, "ForkRepository", err)
Expand Down
11 changes: 11 additions & 0 deletions routers/web/repo/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,13 @@ func getForkRepository(ctx *context.Context) *repo_model.Repository {
func Fork(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("new_fork")

if !ctx.Doer.CanForkRepo() {
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)
if ctx.Written() {
return
Expand Down Expand Up @@ -255,6 +262,10 @@ func ForkPost(ctx *context.Context) {
if err != nil {
ctx.Data["Err_RepoName"] = true
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):
ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplFork, &form)
case db.IsErrNameReserved(err):
Expand Down
7 changes: 7 additions & 0 deletions services/repository/fork.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ type ForkRepoOptions struct {

// ForkRepository forks a repository
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)
if err != nil {
return nil, err
Expand Down
12 changes: 12 additions & 0 deletions services/repository/fork_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,16 @@ func TestForkRepository(t *testing.T) {
assert.Nil(t, fork)
assert.Error(t, err)
assert.True(t, IsErrForkAlreadyExist(err))

// user not reached maximum limit of repositories
assert.False(t, repo_model.IsErrReachLimitOfRepo(err))
// 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))
}
2 changes: 1 addition & 1 deletion templates/repo/pulls/fork.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@

<div class="inline field">
<label></label>
<button class="ui green button">
<button class="ui green button{{if not .CanForkRepo}} disabled{{end}}">
{{.locale.Tr "repo.fork_repo"}}
</button>
<a class="ui button" href="{{.ForkRepo.Link}}">{{.locale.Tr "cancel"}}</a>
Expand Down