Template Repositories (#8768)
* Start work on templates Signed-off-by: jolheiser <john.olheiser@gmail.com> * Continue work Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix IsTemplate vs IsGenerated Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tabs vs spaces * Tabs vs Spaces * Add templates to API & start adding tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix integration tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Remove unused User Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move template tests to existing repos Signed-off-by: jolheiser <john.olheiser@gmail.com> * Minor re-check updates and cleanup Signed-off-by: jolheiser <john.olheiser@gmail.com> * make fmt Signed-off-by: jolheiser <john.olheiser@gmail.com> * Test cleanup Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix optionalbool Signed-off-by: jolheiser <john.olheiser@gmail.com> * make fmt Signed-off-by: jolheiser <john.olheiser@gmail.com> * Test fixes and icon change Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add new user and repo for tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tests (finally) Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update meta repo with env variables Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move generation to create page Combine with repo create template Modify API search to prioritize owner for repo Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tests and coverage Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix swagger and JS lint Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix API searching for own private repos Signed-off-by: jolheiser <john.olheiser@gmail.com> * Change wording Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix repo search test. User had a private repo that didn't show up Signed-off-by: jolheiser <john.olheiser@gmail.com> * Another search test fix Signed-off-by: jolheiser <john.olheiser@gmail.com> * Clarify git content Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> * Feedback updates Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add topics WIP Signed-off-by: jolheiser <john.olheiser@gmail.com> * Finish adding topics Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update locale Signed-off-by: jolheiser <john.olheiser@gmail.com>
This commit is contained in:
parent
74bb292fe3
commit
74a6add4d9
58 changed files with 1441 additions and 119 deletions
|
@ -71,6 +71,11 @@ func Search(ctx *context.APIContext) {
|
|||
// description: search only for repos that the user with the given id owns or contributes to
|
||||
// type: integer
|
||||
// format: int64
|
||||
// - name: priority_owner_id
|
||||
// in: query
|
||||
// description: repo owner to prioritize in the results
|
||||
// type: integer
|
||||
// format: int64
|
||||
// - name: starredBy
|
||||
// in: query
|
||||
// description: search only for repos that the user with the given id has starred
|
||||
|
@ -80,6 +85,10 @@ func Search(ctx *context.APIContext) {
|
|||
// in: query
|
||||
// description: include private repositories this user has access to (defaults to true)
|
||||
// type: boolean
|
||||
// - name: template
|
||||
// in: query
|
||||
// description: include template repositories this user has access to (defaults to true)
|
||||
// type: boolean
|
||||
// - name: page
|
||||
// in: query
|
||||
// description: page number of results to return (1-based)
|
||||
|
@ -116,17 +125,23 @@ func Search(ctx *context.APIContext) {
|
|||
opts := &models.SearchRepoOptions{
|
||||
Keyword: strings.Trim(ctx.Query("q"), " "),
|
||||
OwnerID: ctx.QueryInt64("uid"),
|
||||
PriorityOwnerID: ctx.QueryInt64("priority_owner_id"),
|
||||
Page: ctx.QueryInt("page"),
|
||||
PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")),
|
||||
TopicOnly: ctx.QueryBool("topic"),
|
||||
Collaborate: util.OptionalBoolNone,
|
||||
Private: ctx.IsSigned && (ctx.Query("private") == "" || ctx.QueryBool("private")),
|
||||
Template: util.OptionalBoolNone,
|
||||
UserIsAdmin: ctx.IsUserSiteAdmin(),
|
||||
UserID: ctx.Data["SignedUserID"].(int64),
|
||||
StarredByID: ctx.QueryInt64("starredBy"),
|
||||
IncludeDescription: ctx.QueryBool("includeDesc"),
|
||||
}
|
||||
|
||||
if ctx.Query("template") != "" {
|
||||
opts.Template = util.OptionalBoolOf(ctx.QueryBool("template"))
|
||||
}
|
||||
|
||||
if ctx.QueryBool("exclusive") {
|
||||
opts.Collaborate = util.OptionalBoolFalse
|
||||
}
|
||||
|
@ -678,6 +693,10 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err
|
|||
repo.IsPrivate = *opts.Private
|
||||
}
|
||||
|
||||
if opts.Template != nil {
|
||||
repo.IsTemplate = *opts.Template
|
||||
}
|
||||
|
||||
if err := models.UpdateRepository(repo, visibilityChanged); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "UpdateRepository", err)
|
||||
return err
|
||||
|
|
|
@ -51,8 +51,8 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
func getForkRepository(ctx *context.Context) *models.Repository {
|
||||
forkRepo, err := models.GetRepositoryByID(ctx.ParamsInt64(":repoid"))
|
||||
func getRepository(ctx *context.Context, repoID int64) *models.Repository {
|
||||
repo, err := models.GetRepositoryByID(repoID)
|
||||
if err != nil {
|
||||
if models.IsErrRepoNotExist(err) {
|
||||
ctx.NotFound("GetRepositoryByID", nil)
|
||||
|
@ -62,25 +62,33 @@ func getForkRepository(ctx *context.Context) *models.Repository {
|
|||
return nil
|
||||
}
|
||||
|
||||
perm, err := models.GetUserRepoPermission(forkRepo, ctx.User)
|
||||
perm, err := models.GetUserRepoPermission(repo, ctx.User)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetUserRepoPermission", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
if forkRepo.IsEmpty || !perm.CanRead(models.UnitTypeCode) {
|
||||
if log.IsTrace() {
|
||||
if forkRepo.IsEmpty {
|
||||
log.Trace("Empty fork repository %-v", forkRepo)
|
||||
} else {
|
||||
log.Trace("Permission Denied: User %-v cannot read %-v of forkRepo %-v\n"+
|
||||
"User in forkRepo has Permissions: %-+v",
|
||||
ctx.User,
|
||||
models.UnitTypeCode,
|
||||
ctx.Repo,
|
||||
perm)
|
||||
}
|
||||
}
|
||||
if !perm.CanRead(models.UnitTypeCode) {
|
||||
log.Trace("Permission Denied: User %-v cannot read %-v of repo %-v\n"+
|
||||
"User in repo has Permissions: %-+v",
|
||||
ctx.User,
|
||||
models.UnitTypeCode,
|
||||
ctx.Repo,
|
||||
perm)
|
||||
ctx.NotFound("getRepository", nil)
|
||||
return nil
|
||||
}
|
||||
return repo
|
||||
}
|
||||
|
||||
func getForkRepository(ctx *context.Context) *models.Repository {
|
||||
forkRepo := getRepository(ctx, ctx.ParamsInt64(":repoid"))
|
||||
if ctx.Written() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if forkRepo.IsEmpty {
|
||||
log.Trace("Empty repository %-v", forkRepo)
|
||||
ctx.NotFound("getForkRepository", nil)
|
||||
return nil
|
||||
}
|
||||
|
@ -90,7 +98,7 @@ func getForkRepository(ctx *context.Context) *models.Repository {
|
|||
ctx.Data["IsPrivate"] = forkRepo.IsPrivate
|
||||
canForkToUser := forkRepo.OwnerID != ctx.User.ID && !ctx.User.HasForkedRepo(forkRepo.ID)
|
||||
|
||||
if err = forkRepo.GetOwner(); err != nil {
|
||||
if err := forkRepo.GetOwner(); err != nil {
|
||||
ctx.ServerError("GetOwner", err)
|
||||
return nil
|
||||
}
|
||||
|
@ -109,6 +117,7 @@ func getForkRepository(ctx *context.Context) *models.Repository {
|
|||
}
|
||||
|
||||
var traverseParentRepo = forkRepo
|
||||
var err error
|
||||
for {
|
||||
if ctx.User.ID == traverseParentRepo.OwnerID {
|
||||
canForkToUser = false
|
||||
|
|
|
@ -129,6 +129,16 @@ func Create(ctx *context.Context) {
|
|||
}
|
||||
ctx.Data["ContextUser"] = ctxUser
|
||||
|
||||
ctx.Data["repo_template_name"] = ctx.Tr("repo.template_select")
|
||||
templateID := ctx.QueryInt64("template_id")
|
||||
if templateID > 0 {
|
||||
templateRepo, err := models.GetRepositoryByID(templateID)
|
||||
if err == nil && templateRepo.CheckUnitUser(ctxUser.ID, ctxUser.IsAdmin, models.UnitTypeCode) {
|
||||
ctx.Data["repo_template"] = templateID
|
||||
ctx.Data["repo_template_name"] = templateRepo.Name
|
||||
}
|
||||
}
|
||||
|
||||
ctx.HTML(200, tplCreate)
|
||||
}
|
||||
|
||||
|
@ -170,20 +180,53 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) {
|
|||
return
|
||||
}
|
||||
|
||||
repo, err := repo_service.CreateRepository(ctx.User, ctxUser, models.CreateRepoOptions{
|
||||
Name: form.RepoName,
|
||||
Description: form.Description,
|
||||
Gitignores: form.Gitignores,
|
||||
IssueLabels: form.IssueLabels,
|
||||
License: form.License,
|
||||
Readme: form.Readme,
|
||||
IsPrivate: form.Private || setting.Repository.ForcePrivate,
|
||||
AutoInit: form.AutoInit,
|
||||
})
|
||||
if err == nil {
|
||||
log.Trace("Repository created [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name)
|
||||
ctx.Redirect(setting.AppSubURL + "/" + ctxUser.Name + "/" + repo.Name)
|
||||
return
|
||||
var err error
|
||||
if form.RepoTemplate > 0 {
|
||||
opts := models.GenerateRepoOptions{
|
||||
Name: form.RepoName,
|
||||
Description: form.Description,
|
||||
Private: form.Private,
|
||||
GitContent: form.GitContent,
|
||||
Topics: form.Topics,
|
||||
}
|
||||
|
||||
if !opts.IsValid() {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.template.one_item"), tplCreate, form)
|
||||
return
|
||||
}
|
||||
|
||||
templateRepo := getRepository(ctx, form.RepoTemplate)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if !templateRepo.IsTemplate {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.template.invalid"), tplCreate, form)
|
||||
return
|
||||
}
|
||||
|
||||
repo, err := repo_service.GenerateRepository(ctx.User, ctxUser, templateRepo, opts)
|
||||
if err == nil {
|
||||
log.Trace("Repository generated [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name)
|
||||
ctx.Redirect(setting.AppSubURL + "/" + ctxUser.Name + "/" + repo.Name)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
repo, err := repo_service.CreateRepository(ctx.User, ctxUser, models.CreateRepoOptions{
|
||||
Name: form.RepoName,
|
||||
Description: form.Description,
|
||||
Gitignores: form.Gitignores,
|
||||
IssueLabels: form.IssueLabels,
|
||||
License: form.License,
|
||||
Readme: form.Readme,
|
||||
IsPrivate: form.Private || setting.Repository.ForcePrivate,
|
||||
AutoInit: form.AutoInit,
|
||||
})
|
||||
if err == nil {
|
||||
log.Trace("Repository created [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name)
|
||||
ctx.Redirect(setting.AppSubURL + "/" + ctxUser.Name + "/" + repo.Name)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
handleCreateError(ctx, ctxUser, err, "CreatePost", tplCreate, &form)
|
||||
|
|
|
@ -101,6 +101,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
|
|||
repo.LowerName = strings.ToLower(newRepoName)
|
||||
repo.Description = form.Description
|
||||
repo.Website = form.Website
|
||||
repo.IsTemplate = form.Template
|
||||
|
||||
// Visibility of forked repository is forced sync with base repository.
|
||||
if repo.IsFork {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue