diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index dbd99a65d8e..54e7037cd80 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -1145,11 +1145,6 @@ LEVEL = Info ;; The default Git object format of new repositories. Available values: sha1, sha256. ;DEFAULT_OBJECT_FORMAT = sha1 ;; -;; Allow adoption of unadopted repositories -;ALLOW_ADOPTION_OF_UNADOPTED_REPOSITORIES = false -;; -;; Allow deletion of unadopted repositories -;ALLOW_DELETION_OF_UNADOPTED_REPOSITORIES = false ;; Don't allow download source archive files from UI ;DISABLE_DOWNLOAD_SOURCE_ARCHIVES = false diff --git a/models/git/branch.go b/models/git/branch.go index 2418c45aa19..7f9a2be6458 100644 --- a/models/git/branch.go +++ b/models/git/branch.go @@ -217,11 +217,6 @@ func GetDeletedBranchByID(ctx context.Context, repoID, branchID int64) (*Branch, return &branch, nil } -func DeleteRepoBranches(ctx context.Context, repoID int64) error { - _, err := db.GetEngine(ctx).Where("repo_id=?", repoID).Delete(new(Branch)) - return err -} - func DeleteBranches(ctx context.Context, repoID, doerID int64, branchIDs []int64) error { return db.WithTx(ctx, func(ctx context.Context) error { branches := make([]*Branch, 0, len(branchIDs)) diff --git a/models/repo/release.go b/models/repo/release.go index 9930b850609..fbda6977571 100644 --- a/models/repo/release.go +++ b/models/repo/release.go @@ -578,8 +578,3 @@ func FindTagsByCommitIDs(ctx context.Context, repoID int64, commitIDs ...string) } return res, nil } - -func DeleteRepoReleases(ctx context.Context, repoID int64) error { - _, err := db.GetEngine(ctx).Where("repo_id = ?", repoID).Delete(new(Release)) - return err -} diff --git a/models/repo/repo_list.go b/models/repo/repo_list.go index 2515012551f..04d50ddb8ee 100644 --- a/models/repo/repo_list.go +++ b/models/repo/repo_list.go @@ -204,8 +204,6 @@ type SearchRepoOptions struct { // True -> include just has milestones // False -> include just has no milestone HasMilestones optional.Option[bool] - // LowerNames represents valid lower names to restrict to - LowerNames []string // When specified true, apply some filters over the conditions: // - Don't show forks, when opts.Fork is OptionalBoolNone. // - Do not display repositories that don't have a description, an icon and topics. @@ -824,10 +822,6 @@ func GetUserRepositories(ctx context.Context, opts SearchRepoOptions) (Repositor cond = cond.And(builder.Eq{"is_private": false}) } - if len(opts.LowerNames) > 0 { - cond = cond.And(builder.In("lower_name", opts.LowerNames)) - } - sess := db.GetEngine(ctx) count, err := sess.Where(cond).Count(new(Repository)) diff --git a/modules/git/gitrepo/dbrepo.go b/modules/git/gitrepo/dbrepo.go index 85486fb1bbb..49aaf4952d6 100644 --- a/modules/git/gitrepo/dbrepo.go +++ b/modules/git/gitrepo/dbrepo.go @@ -18,7 +18,7 @@ func RepoWikiGitRepoRelativePath(ownerName, repoName string) string { } // CodeRepoByName returns an unmanaged repository facade for the code repository of the given owner and repository name. -// Usually it is used for migration fixes or repository adoption/creation/rename/transfer. +// Usually it is used for migration fixes or repository creation/rename/transfer. func CodeRepoByName(ownerName, repoName string) RepositoryFacade { return RepositoryUnmanaged(RepoCodeGitRepoRelativePath(ownerName, repoName)) } diff --git a/modules/git/gitrepo/gitrepo.go b/modules/git/gitrepo/gitrepo.go index bdd55459c57..8e2f5378bf4 100644 --- a/modules/git/gitrepo/gitrepo.go +++ b/modules/git/gitrepo/gitrepo.go @@ -80,7 +80,7 @@ func (r *repositoryUnmanaged) GitRepoLocation() string { // RepositoryUnmanaged returns a RepositoryFacade for a repository that might not be managed by Gitea. // If the path is not absolute, then it is relative to setting.RepoRootPath // This function is mainly for maintaining the owner's repo when the repo is not managed yet. -// e.g.: init, clone, transfer, rename, adopt, etc., and temp repo creation and modification. +// e.g.: init, clone, transfer, rename, etc., and temp repo creation and modification. func RepositoryUnmanaged(s string) RepositoryFacade { return &repositoryUnmanaged{loc: filepath.Clean(s)} } diff --git a/modules/setting/repository.go b/modules/setting/repository.go index aecd1fec3e9..c41d3e30a53 100644 --- a/modules/setting/repository.go +++ b/modules/setting/repository.go @@ -59,8 +59,6 @@ var ( DisableStars bool `ini:"DISABLE_STARS"` DefaultBranch string DefaultObjectFormat string - AllowAdoptionOfUnadoptedRepositories bool - AllowDeleteOfUnadoptedRepositories bool DisableDownloadSourceArchives bool AllowForkWithoutMaximumLimit bool AllowForkIntoSameOwner bool diff --git a/options/locale/locale_en-US.json b/options/locale/locale_en-US.json index 1b22c13cf10..1cea2ce1960 100644 --- a/options/locale/locale_en-US.json +++ b/options/locale/locale_en-US.json @@ -547,9 +547,6 @@ "form.repo_name_been_taken": "The repository name is already used.", "form.repository_force_private": "Force Private is enabled: private repositories cannot be made public.", "form.repository_files_already_exist": "Files already exist for this repository. Contact the system administrator.", - "form.repository_files_already_exist.adopt": "Files already exist for this repository and can only be adopted.", - "form.repository_files_already_exist.delete": "Files already exist for this repository. You must delete them.", - "form.repository_files_already_exist.adopt_or_delete": "Files already exist for this repository. Either adopt them or delete them.", "form.org_name_been_taken": "The organization name is already taken.", "form.team_name_been_taken": "The team name is already taken.", "form.team_no_units_error": "Allow access to at least one repository section.", @@ -1014,15 +1011,6 @@ "repo.reactions": "Reactions", "repo.unit_disabled": "The site administrator has disabled this repository section.", "repo.language_other": "Other", - "repo.adopt_search": "Enter username to search for unadopted repositories… (leave blank to find all)", - "repo.adopt_preexisting_label": "Adopt Files", - "repo.adopt_preexisting": "Adopt pre-existing files", - "repo.adopt_preexisting_content": "Create repository from %s", - "repo.adopt_preexisting_success": "Adopted files and created repository from %s", - "repo.delete_preexisting_label": "Delete", - "repo.delete_preexisting": "Delete pre-existing files", - "repo.delete_preexisting_content": "Delete files in %s", - "repo.delete_preexisting_success": "Deleted unadopted files in %s", "repo.blame_prior": "View blame prior to this change", "repo.blame.ignore_revs": "Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.", "repo.blame.ignore_revs.failed": "Failed to ignore revisions in .git-blame-ignore-revs.", @@ -3148,8 +3136,6 @@ "admin.orgs.members": "Members", "admin.orgs.new_orga": "New Organization", "admin.repos.repo_manage_panel": "Repository Management", - "admin.repos.unadopted": "Unadopted Repositories", - "admin.repos.unadopted.no_more": "No more unadopted repositories found", "admin.repos.owner": "Owner", "admin.repos.name": "Name", "admin.repos.private": "Private", diff --git a/routers/api/v1/admin/adopt.go b/routers/api/v1/admin/adopt.go deleted file mode 100644 index fec4f3eebd2..00000000000 --- a/routers/api/v1/admin/adopt.go +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2020 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package admin - -import ( - "net/http" - - repo_model "gitea.dev/models/repo" - user_model "gitea.dev/models/user" - "gitea.dev/modules/git" - "gitea.dev/modules/git/gitrepo" - "gitea.dev/routers/api/v1/utils" - "gitea.dev/services/context" - repo_service "gitea.dev/services/repository" -) - -// ListUnadoptedRepositories lists the unadopted repositories that match the provided names -func ListUnadoptedRepositories(ctx *context.APIContext) { - // swagger:operation GET /admin/unadopted admin adminUnadoptedList - // --- - // summary: List unadopted repositories - // produces: - // - application/json - // parameters: - // - name: page - // in: query - // description: page number of results to return (1-based) - // type: integer - // - name: limit - // in: query - // description: page size of results - // type: integer - // - name: query - // in: query - // description: glob pattern of repositories to search for, in the form owner or owner/repo - // type: string - // responses: - // "200": - // "$ref": "#/responses/StringSlice" - // default: - // "$ref": "#/responses/error" - - listOptions := utils.GetListOptions(ctx) - if listOptions.Page == 0 { - listOptions.Page = 1 - } - repoNames, count, err := repo_service.ListUnadoptedRepositories(ctx, ctx.FormString("query"), &listOptions) - if err != nil { - ctx.APIErrorInternal(err) - return - } - - ctx.SetTotalCountHeader(count) - - ctx.JSON(http.StatusOK, repoNames) -} - -// AdoptRepository will adopt an unadopted repository -func AdoptRepository(ctx *context.APIContext) { - // swagger:operation POST /admin/unadopted/{owner}/{repo} admin adminAdoptRepository - // --- - // summary: Adopt unadopted files as a repository - // produces: - // - application/json - // parameters: - // - name: owner - // in: path - // description: owner of the repo - // type: string - // required: true - // - name: repo - // in: path - // description: name of the repo - // type: string - // required: true - // responses: - // "204": - // "$ref": "#/responses/empty" - // default: - // "$ref": "#/responses/error" - ownerName := ctx.PathParam("username") - repoName := ctx.PathParam("reponame") - - ctxUser, err := user_model.GetUserByName(ctx, ownerName) - if err != nil { - if user_model.IsErrUserNotExist(err) { - ctx.APIErrorNotFound() - return - } - ctx.APIErrorInternal(err) - return - } - - // check not a repo - has, err := repo_model.IsRepositoryModelExist(ctx, ctxUser, repoName) - if err != nil { - ctx.APIErrorInternal(err) - return - } - exist, err := git.IsRepositoryExist(ctx, gitrepo.CodeRepoByName(ctxUser.Name, repoName)) - if err != nil { - ctx.APIErrorInternal(err) - return - } - if has || !exist { - ctx.APIErrorNotFound() - return - } - if _, err := repo_service.AdoptRepository(ctx, ctx.Doer, ctxUser, repo_service.CreateRepoOptions{ - Name: repoName, - IsPrivate: true, - }); err != nil { - ctx.APIErrorInternal(err) - return - } - - ctx.Status(http.StatusNoContent) -} - -// DeleteUnadoptedRepository will delete an unadopted repository -func DeleteUnadoptedRepository(ctx *context.APIContext) { - // swagger:operation DELETE /admin/unadopted/{owner}/{repo} admin adminDeleteUnadoptedRepository - // --- - // summary: Delete unadopted files - // produces: - // - application/json - // parameters: - // - name: owner - // in: path - // description: owner of the repo - // type: string - // required: true - // - name: repo - // in: path - // description: name of the repo - // type: string - // required: true - // responses: - // "204": - // "$ref": "#/responses/empty" - // default: - // "$ref": "#/responses/error" - ownerName := ctx.PathParam("username") - repoName := ctx.PathParam("reponame") - - ctxUser, err := user_model.GetUserByName(ctx, ownerName) - if err != nil { - if user_model.IsErrUserNotExist(err) { - ctx.APIErrorNotFound() - return - } - ctx.APIErrorInternal(err) - return - } - - // check not a repo - has, err := repo_model.IsRepositoryModelExist(ctx, ctxUser, repoName) - if err != nil { - ctx.APIErrorInternal(err) - return - } - exist, err := git.IsRepositoryExist(ctx, gitrepo.CodeRepoByName(ctxUser.Name, repoName)) - if err != nil { - ctx.APIErrorInternal(err) - return - } - if has || !exist { - ctx.APIErrorNotFound() - return - } - - if err := repo_service.DeleteUnadoptedRepository(ctx, ctx.Doer, ctxUser, repoName); err != nil { - ctx.APIErrorInternal(err) - return - } - - ctx.Status(http.StatusNoContent) -} diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 0d72a390e28..87ed07f25b7 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1854,11 +1854,6 @@ func Routes() *web.Router { m.Get("", admin.GetAllEmails) m.Get("/search", admin.SearchEmail) }) - m.Group("/unadopted", func() { - m.Get("", admin.ListUnadoptedRepositories) - m.Post("/{username}/{reponame}", admin.AdoptRepository) - m.Delete("/{username}/{reponame}", admin.DeleteUnadoptedRepository) - }) m.Group("/hooks", func() { m.Combo("").Get(admin.ListHooks). Post(bind(api.CreateHookOption{}), admin.CreateHook) diff --git a/routers/api/v1/repo/migrate.go b/routers/api/v1/repo/migrate.go index cd895c1443c..f8cbcdadae1 100644 --- a/routers/api/v1/repo/migrate.go +++ b/routers/api/v1/repo/migrate.go @@ -222,7 +222,7 @@ func handleMigrateError(ctx *context.APIContext, repoOwner *user_model.User, err case repo_model.IsErrRepoAlreadyExist(err): ctx.APIError(http.StatusConflict, "The repository with the same name already exists.") case repo_model.IsErrRepoFilesAlreadyExist(err): - ctx.APIError(http.StatusConflict, "Files already exist for this repository. Adopt them or delete them.") + ctx.APIError(http.StatusConflict, "Files already exist for this repository.") case migrations.IsRateLimitError(err): ctx.APIError(http.StatusUnprocessableEntity, "Remote visit addressed rate limitation.") case migrations.IsTwoFactorAuthError(err): diff --git a/routers/api/v1/swagger/misc.go b/routers/api/v1/swagger/misc.go index e999d89ec3d..5a4a2b30172 100644 --- a/routers/api/v1/swagger/misc.go +++ b/routers/api/v1/swagger/misc.go @@ -42,13 +42,6 @@ type swaggerResponseLicenseTemplateInfo struct { Body api.LicenseTemplateInfo `json:"body"` } -// StringSlice -// swagger:response StringSlice -type swaggerResponseStringSlice struct { - // in:body - Body []string `json:"body"` -} - // LabelTemplateList // swagger:response LabelTemplateList type swaggerResponseLabelTemplateList struct { diff --git a/routers/web/admin/repos.go b/routers/web/admin/repos.go index 16c9bebaca3..766666d5da2 100644 --- a/routers/web/admin/repos.go +++ b/routers/web/admin/repos.go @@ -4,15 +4,7 @@ package admin import ( - "net/http" - "net/url" - "strings" - - "gitea.dev/models/db" repo_model "gitea.dev/models/repo" - user_model "gitea.dev/models/user" - "gitea.dev/modules/git" - "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/log" "gitea.dev/modules/setting" "gitea.dev/modules/templates" @@ -22,8 +14,7 @@ import ( ) const ( - tplRepos templates.TplName = "admin/repo/list" - tplUnadoptedRepos templates.TplName = "admin/repo/unadopted" + tplRepos templates.TplName = "admin/repo/list" ) // Repos show all the repositories @@ -56,101 +47,3 @@ func DeleteRepo(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("repo.settings.deletion_success")) ctx.JSONRedirect("") } - -// UnadoptedRepos lists the unadopted repositories -func UnadoptedRepos(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("admin.repositories") - ctx.Data["PageIsAdminRepositories"] = true - - opts := db.ListOptions{ - PageSize: setting.UI.Admin.UserPagingNum, - Page: ctx.FormInt("page"), - } - - if opts.Page <= 0 { - opts.Page = 1 - } - - ctx.Data["CurrentPage"] = opts.Page - - doSearch := ctx.FormBool("search") - - ctx.Data["search"] = doSearch - q := ctx.FormString("q") - - if !doSearch { - pager := context.NewPagerBuilder(ctx).TotalCount(0).PerPageLimit(opts.PageSize).CurPage(opts.Page).Build() - ctx.Data["Page"] = pager - ctx.HTML(http.StatusOK, tplUnadoptedRepos) - return - } - - ctx.Data["Keyword"] = q - repoNames, count, err := repo_service.ListUnadoptedRepositories(ctx, q, &opts) - if err != nil { - ctx.ServerError("ListUnadoptedRepositories", err) - return - } - ctx.Data["Dirs"] = repoNames - pager := context.NewPagerBuilder(ctx).TotalCount(count).PerPageLimit(opts.PageSize).CurPage(opts.Page).Build() - ctx.Data["Page"] = pager - ctx.HTML(http.StatusOK, tplUnadoptedRepos) -} - -// AdoptOrDeleteRepository adopts or deletes a repository -func AdoptOrDeleteRepository(ctx *context.Context) { - dir := ctx.FormString("id") - action := ctx.FormString("action") - page := ctx.FormString("page") - q := ctx.FormString("q") - - dirSplit := strings.SplitN(dir, "/", 2) - if len(dirSplit) != 2 { - ctx.Redirect(setting.AppSubURL + "/-/admin/repos") - return - } - - ctxUser, err := user_model.GetUserByName(ctx, dirSplit[0]) - if err != nil { - if user_model.IsErrUserNotExist(err) { - log.Debug("User does not exist: %s", dirSplit[0]) - ctx.Redirect(setting.AppSubURL + "/-/admin/repos") - return - } - ctx.ServerError("GetUserByName", err) - return - } - - repoName := dirSplit[1] - - // check not a repo - has, err := repo_model.IsRepositoryModelExist(ctx, ctxUser, repoName) - if err != nil { - ctx.ServerError("IsRepositoryExist", err) - return - } - exist, err := git.IsRepositoryExist(ctx, gitrepo.CodeRepoByName(ctxUser.Name, repoName)) - if err != nil { - ctx.ServerError("IsDir", err) - return - } - if has || !exist { - // Fallthrough to failure mode - } else if action == "adopt" { - if _, err := repo_service.AdoptRepository(ctx, ctx.Doer, ctxUser, repo_service.CreateRepoOptions{ - Name: dirSplit[1], - IsPrivate: true, - }); err != nil { - ctx.ServerError("repository.AdoptRepository", err) - return - } - ctx.Flash.Success(ctx.Tr("repo.adopt_preexisting_success", dir)) - } else if action == "delete" { - if err := repo_service.DeleteUnadoptedRepository(ctx, ctx.Doer, ctxUser, dirSplit[1]); err != nil { - ctx.ServerError("repository.AdoptRepository", err) - return - } - ctx.Flash.Success(ctx.Tr("repo.delete_preexisting_success", dir)) - } - ctx.Redirect(setting.AppSubURL + "/-/admin/repos/unadopted?search=true&q=" + url.QueryEscape(q) + "&page=" + url.QueryEscape(page)) -} diff --git a/routers/web/repo/fork.go b/routers/web/repo/fork.go index d2b8559722a..21bc93024cb 100644 --- a/routers/web/repo/fork.go +++ b/routers/web/repo/fork.go @@ -17,7 +17,6 @@ import ( "gitea.dev/modules/log" "gitea.dev/modules/optional" "gitea.dev/modules/repository" - "gitea.dev/modules/setting" "gitea.dev/modules/structs" "gitea.dev/modules/templates" "gitea.dev/modules/web" @@ -212,16 +211,7 @@ func ForkRepoTo(ctx *context.Context, owner *user_model.User, forkOpts repo_serv case repo_model.IsErrRepoAlreadyExist(err): ctx.JSONError(ctx.Tr("repo.settings.new_owner_has_same_repo")) case repo_model.IsErrRepoFilesAlreadyExist(err): - switch { - case ctx.IsUserSiteAdmin() || (setting.Repository.AllowAdoptionOfUnadoptedRepositories && setting.Repository.AllowDeleteOfUnadoptedRepositories): - ctx.JSONError(ctx.Tr("form.repository_files_already_exist.adopt_or_delete")) - case setting.Repository.AllowAdoptionOfUnadoptedRepositories: - ctx.JSONError(ctx.Tr("form.repository_files_already_exist.adopt")) - case setting.Repository.AllowDeleteOfUnadoptedRepositories: - ctx.JSONError(ctx.Tr("form.repository_files_already_exist.delete")) - default: - ctx.JSONError(ctx.Tr("form.repository_files_already_exist")) - } + ctx.JSONError(ctx.Tr("form.repository_files_already_exist")) case errors.As(err, &errNameReserved): ctx.JSONError(ctx.Tr("repo.form.name_reserved", errNameReserved.Name)) case errors.As(err, &errNamePatternNotAllowed): diff --git a/routers/web/repo/migrate.go b/routers/web/repo/migrate.go index bdddb3c6f8c..eef2528afee 100644 --- a/routers/web/repo/migrate.go +++ b/routers/web/repo/migrate.go @@ -81,16 +81,7 @@ func handleMigrateError(ctx *context.Context, owner *user_model.User, err error) case repo_model.IsErrRepoAlreadyExist(err): ctx.JSONErrorWithField(ctx.Tr("form.repo_name_been_taken"), "repo_name") case repo_model.IsErrRepoFilesAlreadyExist(err): - switch { - case ctx.IsUserSiteAdmin() || (setting.Repository.AllowAdoptionOfUnadoptedRepositories && setting.Repository.AllowDeleteOfUnadoptedRepositories): - ctx.JSONErrorWithField(ctx.Tr("form.repository_files_already_exist.adopt_or_delete"), "repo_name") - case setting.Repository.AllowAdoptionOfUnadoptedRepositories: - ctx.JSONErrorWithField(ctx.Tr("form.repository_files_already_exist.adopt"), "repo_name") - case setting.Repository.AllowDeleteOfUnadoptedRepositories: - ctx.JSONErrorWithField(ctx.Tr("form.repository_files_already_exist.delete"), "repo_name") - default: - ctx.JSONErrorWithField(ctx.Tr("form.repository_files_already_exist"), "repo_name") - } + ctx.JSONErrorWithField(ctx.Tr("form.repository_files_already_exist"), "repo_name") case errors.As(err, &errNameReserved): ctx.JSONErrorWithField(ctx.Tr("repo.form.name_reserved", errNameReserved.Name), "repo_name") case errors.As(err, &errNamePatternNotAllowed): diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go index 82b6d53d45a..90c489b494e 100644 --- a/routers/web/repo/repo.go +++ b/routers/web/repo/repo.go @@ -177,16 +177,7 @@ func handleCreateError(ctx *context.Context, owner *user_model.User, err error, ctx.RenderWithErrDeprecated(ctx.Tr("form.repo_name_been_taken"), tpl, form) case repo_model.IsErrRepoFilesAlreadyExist(err): ctx.Data["Err_RepoName"] = true - switch { - case ctx.IsUserSiteAdmin() || (setting.Repository.AllowAdoptionOfUnadoptedRepositories && setting.Repository.AllowDeleteOfUnadoptedRepositories): - ctx.RenderWithErrDeprecated(ctx.Tr("form.repository_files_already_exist.adopt_or_delete"), tpl, form) - case setting.Repository.AllowAdoptionOfUnadoptedRepositories: - ctx.RenderWithErrDeprecated(ctx.Tr("form.repository_files_already_exist.adopt"), tpl, form) - case setting.Repository.AllowDeleteOfUnadoptedRepositories: - ctx.RenderWithErrDeprecated(ctx.Tr("form.repository_files_already_exist.delete"), tpl, form) - default: - ctx.RenderWithErrDeprecated(ctx.Tr("form.repository_files_already_exist"), tpl, form) - } + ctx.RenderWithErrDeprecated(ctx.Tr("form.repository_files_already_exist"), tpl, form) case errors.As(err, &errNameReserved): ctx.Data["Err_RepoName"] = true ctx.RenderWithErrDeprecated(ctx.Tr("repo.form.name_reserved", errNameReserved.Name), tpl, form) diff --git a/routers/web/repo/setting/setting.go b/routers/web/repo/setting/setting.go index 7ead84220b0..b3975d0ab36 100644 --- a/routers/web/repo/setting/setting.go +++ b/routers/web/repo/setting/setting.go @@ -237,16 +237,7 @@ func handleSettingsPostUpdate(ctx *context.Context) { ctx.RenderWithErrDeprecated(ctx.Tr("repo.form.name_reserved", errNameReserved.Name), tplSettingsOptions, &form) case repo_model.IsErrRepoFilesAlreadyExist(err): ctx.Data["Err_RepoName"] = true - switch { - case ctx.IsUserSiteAdmin() || (setting.Repository.AllowAdoptionOfUnadoptedRepositories && setting.Repository.AllowDeleteOfUnadoptedRepositories): - ctx.RenderWithErrDeprecated(ctx.Tr("form.repository_files_already_exist.adopt_or_delete"), tplSettingsOptions, form) - case setting.Repository.AllowAdoptionOfUnadoptedRepositories: - ctx.RenderWithErrDeprecated(ctx.Tr("form.repository_files_already_exist.adopt"), tplSettingsOptions, form) - case setting.Repository.AllowDeleteOfUnadoptedRepositories: - ctx.RenderWithErrDeprecated(ctx.Tr("form.repository_files_already_exist.delete"), tplSettingsOptions, form) - default: - ctx.RenderWithErrDeprecated(ctx.Tr("form.repository_files_already_exist"), tplSettingsOptions, form) - } + ctx.RenderWithErrDeprecated(ctx.Tr("form.repository_files_already_exist"), tplSettingsOptions, form) case errors.As(err, &errNamePatternNotAllowed): ctx.RenderWithErrDeprecated(ctx.Tr("repo.form.name_pattern_not_allowed", errNamePatternNotAllowed.Pattern), tplSettingsOptions, &form) default: diff --git a/routers/web/user/setting/adopt.go b/routers/web/user/setting/adopt.go deleted file mode 100644 index be6057fde71..00000000000 --- a/routers/web/user/setting/adopt.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2020 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package setting - -import ( - repo_model "gitea.dev/models/repo" - "gitea.dev/modules/git" - "gitea.dev/modules/git/gitrepo" - "gitea.dev/modules/setting" - "gitea.dev/services/context" - repo_service "gitea.dev/services/repository" -) - -// AdoptOrDeleteRepository adopts or deletes a repository -func AdoptOrDeleteRepository(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("settings.adopt") - ctx.Data["PageIsSettingsRepos"] = true - allowAdopt := ctx.IsUserSiteAdmin() || setting.Repository.AllowAdoptionOfUnadoptedRepositories - ctx.Data["allowAdopt"] = allowAdopt - allowDelete := ctx.IsUserSiteAdmin() || setting.Repository.AllowDeleteOfUnadoptedRepositories - ctx.Data["allowDelete"] = allowDelete - - dir := ctx.FormString("id") - action := ctx.FormString("action") - - ctxUser := ctx.Doer - - // check not a repo - has, err := repo_model.IsRepositoryModelExist(ctx, ctxUser, dir) - if err != nil { - ctx.ServerError("IsRepositoryExist", err) - return - } - - exist, err := git.IsRepositoryExist(ctx, gitrepo.CodeRepoByName(ctxUser.Name, dir)) - if err != nil { - ctx.ServerError("IsDir", err) - return - } - if has || !exist { - // Fallthrough to failure mode - } else if action == "adopt" && allowAdopt { - if _, err := repo_service.AdoptRepository(ctx, ctxUser, ctxUser, repo_service.CreateRepoOptions{ - Name: dir, - IsPrivate: true, - }); err != nil { - ctx.ServerError("repository.AdoptRepository", err) - return - } - ctx.Flash.Success(ctx.Tr("repo.adopt_preexisting_success", dir)) - } else if action == "delete" && allowDelete { - if err := repo_service.DeleteUnadoptedRepository(ctx, ctxUser, ctxUser, dir); err != nil { - ctx.ServerError("repository.AdoptRepository", err) - return - } - ctx.Flash.Success(ctx.Tr("repo.delete_preexisting_success", dir)) - } - - ctx.Redirect(setting.AppSubURL + "/user/settings/repos") -} diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go index cba181eb7c7..512e6238e23 100644 --- a/routers/web/user/setting/profile.go +++ b/routers/web/user/setting/profile.go @@ -10,15 +10,11 @@ import ( "io" "math/big" "net/http" - "os" - "path/filepath" - "strings" "gitea.dev/models/db" "gitea.dev/models/organization" repo_model "gitea.dev/models/repo" user_model "gitea.dev/models/user" - "gitea.dev/modules/git/gitrepo" "gitea.dev/modules/log" "gitea.dev/modules/optional" "gitea.dev/modules/setting" @@ -207,9 +203,6 @@ func Organization(ctx *context.Context) { func Repos(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("settings.repos") ctx.Data["PageIsSettingsRepos"] = true - ctx.Data["allowAdopt"] = ctx.IsUserSiteAdmin() || setting.Repository.AllowAdoptionOfUnadoptedRepositories - ctx.Data["allowDelete"] = ctx.IsUserSiteAdmin() || setting.Repository.AllowDeleteOfUnadoptedRepositories - opts := db.ListOptions{ PageSize: setting.UI.Admin.UserPagingNum, Page: ctx.FormInt("page"), @@ -218,91 +211,21 @@ func Repos(ctx *context.Context) { if opts.Page <= 0 { opts.Page = 1 } - start := int64((opts.Page - 1) * opts.PageSize) - end := start + int64(opts.PageSize) - - adoptOrDelete := ctx.IsUserSiteAdmin() || (setting.Repository.AllowAdoptionOfUnadoptedRepositories && setting.Repository.AllowDeleteOfUnadoptedRepositories) - - ctxUser := ctx.Doer - var count int64 - - if adoptOrDelete { - repoNames := make([]string, 0, setting.UI.Admin.UserPagingNum) - repos := map[string]*repo_model.Repository{} - // We're going to iterate by pagesize. - root := gitrepo.UserLocalPath(ctxUser.Name) - if err := filepath.WalkDir(root, func(path string, d os.DirEntry, err error) error { - if err != nil { - if os.IsNotExist(err) { - return nil - } - return err - } - if !d.IsDir() || path == root { - return nil - } - name := d.Name() - if !strings.HasSuffix(name, ".git") { - return filepath.SkipDir - } - name = name[:len(name)-4] - if repo_model.IsUsableRepoName(name) != nil || strings.ToLower(name) != name { - return filepath.SkipDir - } - if count >= start && count < end { - repoNames = append(repoNames, name) - } - count++ - return filepath.SkipDir - }); err != nil { - ctx.ServerError("filepath.WalkDir", err) - return - } - - userRepos, _, err := repo_model.GetUserRepositories(ctx, repo_model.SearchRepoOptions{ - OwnerID: ctxUser.ID, - Private: true, - ListOptions: db.ListOptions{ - Page: 1, - PageSize: setting.UI.Admin.UserPagingNum, - }, - LowerNames: repoNames, - }) - if err != nil { - ctx.ServerError("GetUserRepositories", err) - return - } - for _, repo := range userRepos { - if repo.IsFork { - if err := repo.GetBaseRepo(ctx); err != nil { - ctx.ServerError("GetBaseRepo", err) - return - } - } - repos[repo.LowerName] = repo - } - ctx.Data["Dirs"] = repoNames - ctx.Data["ReposMap"] = repos - } else { - repos, reposCount, err := repo_model.GetUserRepositories(ctx, repo_model.SearchRepoOptions{OwnerID: ctxUser.ID, Private: true, ListOptions: opts}) - if err != nil { - ctx.ServerError("GetUserRepositories", err) - return - } - count = reposCount - - for i := range repos { - if repos[i].IsFork { - if err := repos[i].GetBaseRepo(ctx); err != nil { - ctx.ServerError("GetBaseRepo", err) - return - } - } - } - - ctx.Data["Repos"] = repos + repos, count, err := repo_model.GetUserRepositories(ctx, repo_model.SearchRepoOptions{OwnerID: ctx.Doer.ID, Private: true, ListOptions: opts}) + if err != nil { + ctx.ServerError("GetUserRepositories", err) + return } - ctx.Data["ContextUser"] = ctxUser + for i := range repos { + if repos[i].IsFork { + if err := repos[i].GetBaseRepo(ctx); err != nil { + ctx.ServerError("GetBaseRepo", err) + return + } + } + } + + ctx.Data["Repos"] = repos pager := context.NewPagerBuilder(ctx).TotalCount(count).PerPageLimit(opts.PageSize).CurPage(opts.Page).Build() ctx.Data["Page"] = pager ctx.HTML(http.StatusOK, tplSettingsRepositories) diff --git a/routers/web/web.go b/routers/web/web.go index 58a9c0e84c6..f72116f66a4 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -702,7 +702,6 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { m.Get("/organization", user_setting.Organization) m.Get("/repos", user_setting.Repos) - m.Post("/repos/unadopted", user_setting.AdoptOrDeleteRepository) m.Group("/hooks", func() { m.Get("", user_setting.Webhooks) @@ -818,7 +817,6 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { m.Group("/repos", func() { m.Get("", admin.Repos) - m.Combo("/unadopted").Get(admin.UnadoptedRepos).Post(admin.AdoptOrDeleteRepository) m.Post("/delete", admin.DeleteRepo) }) diff --git a/services/indexer/notify.go b/services/indexer/notify.go index 3bd68ebcda5..392f1a5fb59 100644 --- a/services/indexer/notify.go +++ b/services/indexer/notify.go @@ -29,10 +29,6 @@ func NewNotifier() notify_service.Notifier { return &indexerNotifier{} } -func (r *indexerNotifier) AdoptRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { - r.MigrateRepository(ctx, doer, u, repo) -} - func (r *indexerNotifier) CreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User, ) { diff --git a/services/notify/notifier.go b/services/notify/notifier.go index 308c5fcafa9..ddb8cd6b351 100644 --- a/services/notify/notifier.go +++ b/services/notify/notifier.go @@ -21,7 +21,6 @@ import ( type Notifier interface { Run() - AdoptRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) CreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) MigrateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) DeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository) diff --git a/services/notify/notify.go b/services/notify/notify.go index cc858de2ee3..c79551f966e 100644 --- a/services/notify/notify.go +++ b/services/notify/notify.go @@ -364,15 +364,6 @@ func CreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_ } } -// AdoptRepository notifies the adoption of a repository to notifiers -func AdoptRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { - defer recoverPanic() - - for _, notifier := range notifiers { - notifier.AdoptRepository(ctx, doer, u, repo) - } -} - // MigrateRepository notifies create repository to notifiers func MigrateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { defer recoverPanic() diff --git a/services/notify/null.go b/services/notify/null.go index 2efc6e15ce7..7704202ef0b 100644 --- a/services/notify/null.go +++ b/services/notify/null.go @@ -154,10 +154,6 @@ func (*NullNotifier) IssueChangeProjectColumn(ctx context.Context, doer *user_mo func (*NullNotifier) CreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { } -// AdoptRepository places a place holder function -func (*NullNotifier) AdoptRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) { -} - // DeleteRepository places a place holder function func (*NullNotifier) DeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository) { } diff --git a/services/repository/adopt.go b/services/repository/adopt.go deleted file mode 100644 index f7865719f15..00000000000 --- a/services/repository/adopt.go +++ /dev/null @@ -1,377 +0,0 @@ -// Copyright 2020 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package repository - -import ( - "context" - "fmt" - "os" - "path" - "path/filepath" - "strings" - - "gitea.dev/models/db" - git_model "gitea.dev/models/git" - repo_model "gitea.dev/models/repo" - user_model "gitea.dev/models/user" - "gitea.dev/modules/container" - "gitea.dev/modules/git" - "gitea.dev/modules/git/gitrepo" - "gitea.dev/modules/glob" - "gitea.dev/modules/graceful" - "gitea.dev/modules/log" - "gitea.dev/modules/optional" - repo_module "gitea.dev/modules/repository" - "gitea.dev/modules/setting" - notify_service "gitea.dev/services/notify" -) - -func deleteFailedAdoptRepository(repoID int64) error { - return db.WithTx(graceful.GetManager().ShutdownContext(), func(ctx context.Context) error { - if err := deleteDBRepository(ctx, repoID); err != nil { - return fmt.Errorf("deleteDBRepository: %w", err) - } - if err := git_model.DeleteRepoBranches(ctx, repoID); err != nil { - return fmt.Errorf("deleteRepoBranches: %w", err) - } - return repo_model.DeleteRepoReleases(ctx, repoID) - }) -} - -// AdoptRepository adopts pre-existing repository files for the user/organization. -func AdoptRepository(ctx context.Context, doer, owner *user_model.User, opts CreateRepoOptions) (*repo_model.Repository, error) { - if !doer.CanCreateRepoIn(owner) { - return nil, repo_model.ErrReachLimitOfRepo{ - Limit: owner.MaxRepoCreation, - } - } - - repo := &repo_model.Repository{ - OwnerID: owner.ID, - Owner: owner, - OwnerName: owner.Name, - Name: opts.Name, - LowerName: strings.ToLower(opts.Name), - Description: opts.Description, - OriginalURL: opts.OriginalURL, - OriginalServiceType: opts.GitServiceType, - IsPrivate: opts.IsPrivate, - IsFsckEnabled: !opts.IsMirror, - CloseIssuesViaCommitInAnyBranch: setting.Repository.DefaultCloseIssuesViaCommitsInAnyBranch, - Status: repo_model.RepositoryBeingMigrated, - IsEmpty: !opts.AutoInit, - } - - // 1 - create the repository database operations first - err := db.WithTx(ctx, func(ctx context.Context) error { - return createRepositoryInDB(ctx, doer, owner, repo, false) - }) - if err != nil { - return nil, err - } - - // last - clean up if something goes wrong - // WARNING: Don't override all later err with local variables - defer func() { - if err != nil { - // we can not use `ctx` because it may be canceled or timed out - if errDel := deleteFailedAdoptRepository(repo.ID); errDel != nil { - log.Error("Failed to delete repository %s that could not be adopted: %v", repo.FullName(), errDel) - } - } - }() - - // Re-fetch the repository from database before updating it (else it would - // override changes that were done earlier with sql) - if repo, err = repo_model.GetRepositoryByID(ctx, repo.ID); err != nil { - return nil, fmt.Errorf("getRepositoryByID: %w", err) - } - - // 2 - adopt the repository from disk - if err = adoptRepository(ctx, repo, opts.DefaultBranch); err != nil { - return nil, fmt.Errorf("adoptRepository: %w", err) - } - - // 3 - Update the git repository - if err = updateGitRepoAfterCreate(ctx, repo); err != nil { - return nil, fmt.Errorf("updateGitRepoAfterCreate: %w", err) - } - - // 4 - update repository status - repo.Status = repo_model.RepositoryReady - if err = repo_model.UpdateRepositoryColsWithAutoTime(ctx, repo, "status"); err != nil { - return nil, fmt.Errorf("UpdateRepositoryCols: %w", err) - } - - notify_service.AdoptRepository(ctx, doer, owner, repo) - - return repo, nil -} - -func adoptRepository(ctx context.Context, repo *repo_model.Repository, defaultBranch string) (err error) { - isExist, err := git.IsRepositoryExist(ctx, repo) - if err != nil { - log.Error("Unable to check if %s exists. Error: %v", repo.FullName(), err) - return err - } - if !isExist { - return fmt.Errorf("adoptRepository: path does not already exist: %s", repo.FullName()) - } - - if err := git.CreateDelegateHooks(ctx, repo); err != nil { - return fmt.Errorf("createDelegateHooks: %w", err) - } - - repo.IsEmpty = false - - if len(defaultBranch) > 0 { - repo.DefaultBranch = defaultBranch - - if err = git.SetDefaultBranch(ctx, repo, repo.DefaultBranch); err != nil { - return fmt.Errorf("setDefaultBranch: %w", err) - } - } else { - repo.DefaultBranch, err = git.GetDefaultBranch(ctx, repo) - if err != nil { - repo.DefaultBranch = setting.Repository.DefaultBranch - if err = git.SetDefaultBranch(ctx, repo, repo.DefaultBranch); err != nil { - return fmt.Errorf("setDefaultBranch: %w", err) - } - } - } - - // Don't bother looking this repo in the context it won't be there - gitRepo, err := git.OpenRepository(ctx, repo) - if err != nil { - return fmt.Errorf("openRepository: %w", err) - } - defer gitRepo.Close() - - if _, _, err = repo_module.SyncRepoBranchesWithRepo(ctx, repo, gitRepo, 0); err != nil { - return fmt.Errorf("SyncRepoBranchesWithRepo: %w", err) - } - - if _, err = repo_module.SyncReleasesWithTags(ctx, repo, gitRepo); err != nil { - return fmt.Errorf("SyncReleasesWithTags: %w", err) - } - - branches, _ := git_model.FindBranchNames(ctx, git_model.FindBranchOptions{ - RepoID: repo.ID, - ListOptions: db.ListOptionsAll, - IsDeletedBranch: optional.Some(false), - }) - - found := false - hasDefault := false - hasMaster := false - hasMain := false - for _, branch := range branches { - if branch == repo.DefaultBranch { - found = true - break - } else if branch == setting.Repository.DefaultBranch { - hasDefault = true - } else if branch == "master" { - hasMaster = true - } else if branch == "main" { - hasMain = true - } - } - if !found { - if hasDefault { - repo.DefaultBranch = setting.Repository.DefaultBranch - } else if hasMaster { - repo.DefaultBranch = "master" - } else if hasMain { - repo.DefaultBranch = "main" - } else if len(branches) > 0 { - repo.DefaultBranch = branches[0] - } else { - repo.IsEmpty = true - repo.DefaultBranch = setting.Repository.DefaultBranch - } - - if err = git.SetDefaultBranch(ctx, repo, repo.DefaultBranch); err != nil { - return fmt.Errorf("setDefaultBranch: %w", err) - } - } - - if err = repo_model.UpdateRepositoryColsNoAutoTime(ctx, repo, "is_empty", "default_branch"); err != nil { - return fmt.Errorf("UpdateRepositoryCols: %w", err) - } - - if err = repo_module.UpdateRepoSize(ctx, repo); err != nil { - log.Error("Failed to update size for repository: %v", err) - } - - return nil -} - -// DeleteUnadoptedRepository deletes unadopted repository files from the filesystem -func DeleteUnadoptedRepository(ctx context.Context, doer, u *user_model.User, repoName string) error { - if err := repo_model.IsUsableRepoName(repoName); err != nil { - return err - } - - codeRepo := gitrepo.CodeRepoByName(u.Name, repoName) - exist, err := git.IsRepositoryExist(ctx, codeRepo) - if err != nil { - log.Error("Unable to check if repo %s/%s exists. Error: %v", u.Name, repoName, err) - return err - } - if !exist { - return repo_model.ErrRepoNotExist{ - OwnerName: u.Name, - Name: repoName, - } - } - - if exist, err := repo_model.IsRepositoryModelExist(ctx, u, repoName); err != nil { - return err - } else if exist { - return repo_model.ErrRepoAlreadyExist{ - Uname: u.Name, - Name: repoName, - } - } - - return git.DeleteRepository(ctx, codeRepo) -} - -type unadoptedRepositories struct { - repositories []string - count int64 - start, end int64 -} - -func (unadopted *unadoptedRepositories) add(repository string) { - if unadopted.count >= unadopted.start && unadopted.count < unadopted.end { - unadopted.repositories = append(unadopted.repositories, repository) - } - unadopted.count++ -} - -func checkUnadoptedRepositories(ctx context.Context, userName string, repoNamesToCheck []string, unadopted *unadoptedRepositories) error { - if len(repoNamesToCheck) == 0 { - return nil - } - ctxUser, err := user_model.GetUserByName(ctx, userName) - if err != nil { - if user_model.IsErrUserNotExist(err) { - log.Debug("Missing user: %s", userName) - return nil - } - return err - } - repos, _, err := repo_model.GetUserRepositories(ctx, repo_model.SearchRepoOptions{ - OwnerID: ctxUser.ID, - Private: true, - ListOptions: db.ListOptions{ - Page: 1, - PageSize: len(repoNamesToCheck), - }, LowerNames: repoNamesToCheck, - }) - if err != nil { - return err - } - if len(repos) == len(repoNamesToCheck) { - return nil - } - repoNames := make(container.Set[string], len(repos)) - for _, repo := range repos { - repoNames.Add(repo.LowerName) - } - for _, repoName := range repoNamesToCheck { - if !repoNames.Contains(repoName) { - unadopted.add(path.Join(userName, repoName)) // These are not used as filepaths - but as reponames - therefore use path.Join not filepath.Join - } - } - return nil -} - -// ListUnadoptedRepositories lists all the unadopted repositories that match the provided query -func ListUnadoptedRepositories(ctx context.Context, query string, opts *db.ListOptions) ([]string, int64, error) { - opts.SetDefaultValues() - globUser, _ := glob.Compile("*") - globRepo, _ := glob.Compile("*") - - qsplit := strings.SplitN(query, "/", 2) - if len(qsplit) > 0 && len(query) > 0 { - var err error - globUser, err = glob.Compile(qsplit[0]) - if err != nil { - log.Info("Invalid glob expression '%s' (skipped): %v", qsplit[0], err) - } - if len(qsplit) > 1 { - globRepo, err = glob.Compile(qsplit[1]) - if err != nil { - log.Info("Invalid glob expression '%s' (skipped): %v", qsplit[1], err) - } - } - } - var repoNamesToCheck []string - - start := int64((opts.Page - 1) * opts.PageSize) - unadopted := &unadoptedRepositories{ - repositories: make([]string, 0, opts.PageSize), - start: start, - end: start + int64(opts.PageSize), - count: 0, - } - - var userName string - - // We're going to iterate by pagesize. - root := filepath.Clean(setting.RepoRootPath) - if err := filepath.WalkDir(root, func(path string, d os.DirEntry, err error) error { - if err != nil { - return err - } - if !d.IsDir() || path == root { - return nil - } - - name := d.Name() - - if !strings.ContainsRune(path[len(root)+1:], filepath.Separator) { - // Got a new user - if err = checkUnadoptedRepositories(ctx, userName, repoNamesToCheck, unadopted); err != nil { - return err - } - repoNamesToCheck = repoNamesToCheck[:0] - - if !globUser.Match(name) { - return filepath.SkipDir - } - - userName = name - return nil - } - - if !strings.HasSuffix(name, ".git") { - return filepath.SkipDir - } - name = name[:len(name)-4] - if repo_model.IsUsableRepoName(name) != nil || strings.ToLower(name) != name || !globRepo.Match(name) { - return filepath.SkipDir - } - - repoNamesToCheck = append(repoNamesToCheck, name) - if len(repoNamesToCheck) >= setting.Database.IterateBufferSize { - if err = checkUnadoptedRepositories(ctx, userName, repoNamesToCheck, unadopted); err != nil { - return err - } - repoNamesToCheck = repoNamesToCheck[:0] - } - return filepath.SkipDir - }); err != nil { - return nil, 0, err - } - - if err := checkUnadoptedRepositories(ctx, userName, repoNamesToCheck, unadopted); err != nil { - return nil, 0, err - } - - return unadopted.repositories, unadopted.count, nil -} diff --git a/services/repository/adopt_test.go b/services/repository/adopt_test.go deleted file mode 100644 index 4c01f063d41..00000000000 --- a/services/repository/adopt_test.go +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2021 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package repository - -import ( - "os" - "path" - "path/filepath" - "testing" - - "gitea.dev/models/db" - repo_model "gitea.dev/models/repo" - "gitea.dev/models/unittest" - user_model "gitea.dev/models/user" - "gitea.dev/modules/git" - "gitea.dev/modules/git/gitrepo" - "gitea.dev/modules/setting" - - "github.com/stretchr/testify/assert" -) - -func TestCheckUnadoptedRepositories_Add(t *testing.T) { - const start = 10 - const end = 20 - unadopted := &unadoptedRepositories{ - start: start, - end: end, - count: 0, - } - - const total = 30 - for range total { - unadopted.add("something") - } - - assert.EqualValues(t, total, unadopted.count) - assert.Len(t, unadopted.repositories, end-start) -} - -func TestCheckUnadoptedRepositories(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - // - // Non existent user - // - unadopted := &unadoptedRepositories{start: 0, end: 100} - err := checkUnadoptedRepositories(t.Context(), "notauser", []string{"repo"}, unadopted) - assert.NoError(t, err) - assert.Empty(t, unadopted.repositories) - // - // Unadopted repository is returned - // Existing (adopted) repository is not returned - // - userName := "user2" - repoName := "repo2" - unadoptedRepoName := "unadopted" - unadopted = &unadoptedRepositories{start: 0, end: 100} - err = checkUnadoptedRepositories(t.Context(), userName, []string{repoName, unadoptedRepoName}, unadopted) - assert.NoError(t, err) - assert.Equal(t, []string{path.Join(userName, unadoptedRepoName)}, unadopted.repositories) - // - // Existing (adopted) repository is not returned - // - unadopted = &unadoptedRepositories{start: 0, end: 100} - err = checkUnadoptedRepositories(t.Context(), userName, []string{repoName}, unadopted) - assert.NoError(t, err) - assert.Empty(t, unadopted.repositories) - assert.Zero(t, unadopted.count) -} - -func TestListUnadoptedRepositories_ListOptions(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - username := "user2" - unadoptedList := []string{path.Join(username, "unadopted1"), path.Join(username, "unadopted2")} - for _, unadopted := range unadoptedList { - _ = os.Mkdir(filepath.Join(setting.RepoRootPath, unadopted+".git"), 0o755) - } - - for i, unadopted := range unadoptedList { - opts := db.ListOptions{Page: i + 1, PageSize: 1} - repoNames, count, err := ListUnadoptedRepositories(t.Context(), "", &opts) - assert.NoError(t, err) - assert.EqualValues(t, 2, count) - assert.Equal(t, unadopted, repoNames[0]) - } -} - -func TestAdoptRepository(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - - testRepoName := "test-adopt" - user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - destDir := filepath.Join(setting.RepoRootPath, user2.Name, testRepoName+".git") - - t.Run("Success", func(t *testing.T) { - // a successful adopt - assert.NoError(t, unittest.SyncDirs(filepath.Join(setting.RepoRootPath, user2.Name, "repo1.git"), destDir)) - - adoptedRepo, err := AdoptRepository(t.Context(), user2, user2, CreateRepoOptions{Name: testRepoName}) - assert.NoError(t, err) - repoTestAdopt := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: testRepoName}) - assert.Equal(t, "sha1", repoTestAdopt.ObjectFormatName) - - // just delete the adopted repo's db records - err = deleteFailedAdoptRepository(adoptedRepo.ID) - assert.NoError(t, err) - }) - - t.Run("Failure", func(t *testing.T) { - unittest.AssertNotExistsBean(t, &repo_model.Repository{OwnerName: user2.Name, Name: testRepoName}) - // a failed adopt because some mock data - // remove the hooks directory and create a file so that we cannot create the hooks successfully - _ = os.RemoveAll(filepath.Join(destDir, "hooks", "update.d")) - assert.NoError(t, os.WriteFile(filepath.Join(destDir, "hooks", "update.d"), []byte("dummy-content"), os.ModePerm)) - - adoptedRepo, err := AdoptRepository(t.Context(), user2, user2, CreateRepoOptions{Name: testRepoName}) - assert.Error(t, err) - assert.Nil(t, adoptedRepo) - - unittest.AssertNotExistsBean(t, &repo_model.Repository{OwnerName: user2.Name, Name: testRepoName}) - - exist, err := git.IsRepositoryExist(t.Context(), gitrepo.CodeRepoByName(user2.Name, testRepoName)) - assert.NoError(t, err) - assert.True(t, exist) // the repository should be still in the disk - }) -} diff --git a/services/repository/create.go b/services/repository/create.go index 754ee3cf6c2..cace37dd037 100644 --- a/services/repository/create.go +++ b/services/repository/create.go @@ -278,7 +278,7 @@ func CreateRepositoryDirectly(ctx context.Context, doer, owner *user_model.User, return nil, err } if isExist { - log.Error("Files already exist in %s and we are not going to adopt or delete.", repo.FullName()) + log.Error("Files already exist in %s", repo.FullName()) // Don't return directly, we need err in defer to cleanupRepository err = repo_model.ErrRepoFilesAlreadyExist{ Uname: repo.OwnerName, diff --git a/services/repository/fork.go b/services/repository/fork.go index 462f811fb4b..b4eace9d355 100644 --- a/services/repository/fork.go +++ b/services/repository/fork.go @@ -137,7 +137,7 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork return nil, err } if isExist { - log.Error("Files already exist in %s and we are not going to adopt or delete.", repo.FullName()) + log.Error("Files already exist in %s", repo.FullName()) // Don't return directly, we need err in defer to cleanupRepository err = repo_model.ErrRepoFilesAlreadyExist{ Uname: repo.OwnerName, diff --git a/templates/admin/repo/list.tmpl b/templates/admin/repo/list.tmpl index 2e3adb2e8a2..c64d73800a2 100644 --- a/templates/admin/repo/list.tmpl +++ b/templates/admin/repo/list.tmpl @@ -2,9 +2,6 @@

{{ctx.Locale.Tr "admin.repos.repo_manage_panel"}} ({{ctx.Locale.Tr "admin.total" .Total}}) -

{{template "shared/repo/search" .}} diff --git a/templates/admin/repo/unadopted.tmpl b/templates/admin/repo/unadopted.tmpl deleted file mode 100644 index b6e85c7432a..00000000000 --- a/templates/admin/repo/unadopted.tmpl +++ /dev/null @@ -1,73 +0,0 @@ -{{template "admin/layout_head" (dict "pageClass" "admin")}} -
-

- {{ctx.Locale.Tr "admin.repos.unadopted"}} - -

-
-
-
- - - {{template "shared/search/button"}} -
-
-
- {{if .search}} -
- {{if .Dirs}} -
- {{range $dirI, $dir := .Dirs}} -
- {{svg "octicon-file-directory-fill"}} {{$dir}} -
- - -
- {{ctx.Locale.Tr "repo.adopt_preexisting"}} -
-
-

{{ctx.Locale.Tr "repo.adopt_preexisting_content" $dir}}

-
-
- - - - - {{template "base/modal_actions_confirm"}} -
-
- - -
- {{ctx.Locale.Tr "repo.delete_preexisting"}} -
-
-

{{ctx.Locale.Tr "repo.delete_preexisting_content" $dir}}

-
-
- - - - - {{template "base/modal_actions_confirm"}} -
-
-
-
- {{end}} -
- {{template "base/paginate" .}} - {{else}} -
- {{ctx.Locale.Tr "admin.repos.unadopted.no_more"}} -
- {{template "base/paginate" .}} - {{end}} -
- {{end}} -
- -{{template "admin/layout_footer" .}} diff --git a/templates/swagger/v1-openapi3.generated.json b/templates/swagger/v1-openapi3.generated.json index e1b924341e7..c019b8713e3 100644 --- a/templates/swagger/v1-openapi3.generated.json +++ b/templates/swagger/v1-openapi3.generated.json @@ -1375,19 +1375,6 @@ }, "description": "StopWatchList" }, - "StringSlice": { - "content": { - "application/json": { - "schema": { - "items": { - "type": "string" - }, - "type": "array" - } - } - }, - "description": "StringSlice" - }, "Tag": { "content": { "application/json": { @@ -12064,121 +12051,6 @@ ] } }, - "/admin/unadopted": { - "get": { - "operationId": "adminUnadoptedList", - "parameters": [ - { - "description": "page number of results to return (1-based)", - "in": "query", - "name": "page", - "schema": { - "type": "integer" - } - }, - { - "description": "page size of results", - "in": "query", - "name": "limit", - "schema": { - "type": "integer" - } - }, - { - "description": "glob pattern of repositories to search for, in the form owner or owner/repo", - "in": "query", - "name": "query", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "$ref": "#/components/responses/StringSlice" - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "summary": "List unadopted repositories", - "tags": [ - "admin" - ] - } - }, - "/admin/unadopted/{owner}/{repo}": { - "delete": { - "operationId": "adminDeleteUnadoptedRepository", - "parameters": [ - { - "description": "owner of the repo", - "in": "path", - "name": "owner", - "required": true, - "schema": { - "type": "string" - } - }, - { - "description": "name of the repo", - "in": "path", - "name": "repo", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "$ref": "#/components/responses/empty" - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "summary": "Delete unadopted files", - "tags": [ - "admin" - ] - }, - "post": { - "operationId": "adminAdoptRepository", - "parameters": [ - { - "description": "owner of the repo", - "in": "path", - "name": "owner", - "required": true, - "schema": { - "type": "string" - } - }, - { - "description": "name of the repo", - "in": "path", - "name": "repo", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "$ref": "#/components/responses/empty" - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "summary": "Adopt unadopted files as a repository", - "tags": [ - "admin" - ] - } - }, "/admin/users": { "get": { "operationId": "adminSearchUsers", diff --git a/templates/swagger/v1-swagger.generated.json b/templates/swagger/v1-swagger.generated.json index 28be28ba989..3ffab56e1a4 100644 --- a/templates/swagger/v1-swagger.generated.json +++ b/templates/swagger/v1-swagger.generated.json @@ -676,116 +676,6 @@ } } }, - "/admin/unadopted": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "List unadopted repositories", - "operationId": "adminUnadoptedList", - "parameters": [ - { - "type": "integer", - "description": "page number of results to return (1-based)", - "name": "page", - "in": "query" - }, - { - "type": "integer", - "description": "page size of results", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "glob pattern of repositories to search for, in the form owner or owner/repo", - "name": "query", - "in": "query" - } - ], - "responses": { - "200": { - "$ref": "#/responses/StringSlice" - }, - "default": { - "$ref": "#/responses/error" - } - } - } - }, - "/admin/unadopted/{owner}/{repo}": { - "post": { - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "Adopt unadopted files as a repository", - "operationId": "adminAdoptRepository", - "parameters": [ - { - "type": "string", - "description": "owner of the repo", - "name": "owner", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "name of the repo", - "name": "repo", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "$ref": "#/responses/empty" - }, - "default": { - "$ref": "#/responses/error" - } - } - }, - "delete": { - "produces": [ - "application/json" - ], - "tags": [ - "admin" - ], - "summary": "Delete unadopted files", - "operationId": "adminDeleteUnadoptedRepository", - "parameters": [ - { - "type": "string", - "description": "owner of the repo", - "name": "owner", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "name of the repo", - "name": "repo", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "$ref": "#/responses/empty" - }, - "default": { - "$ref": "#/responses/error" - } - } - } - }, "/admin/users": { "get": { "produces": [ @@ -34666,15 +34556,6 @@ } } }, - "StringSlice": { - "description": "StringSlice", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - }, "Tag": { "description": "Tag", "schema": { diff --git a/templates/user/settings/repos.tmpl b/templates/user/settings/repos.tmpl index 290e47bce13..44eef70d392 100644 --- a/templates/user/settings/repos.tmpl +++ b/templates/user/settings/repos.tmpl @@ -4,112 +4,37 @@ {{ctx.Locale.Tr "settings.repos"}}
- {{if or .allowAdopt .allowDelete}} - {{if .Dirs}} -
- {{range $dirI, $dir := .Dirs}} - {{$repo := index $.ReposMap $dir}} -
{{/* if not repo, then there are "adapt" buttons, so the padding shouldn't be that default large*/}} -
- {{if $repo}} - {{if $repo.IsPrivate}} - {{svg "octicon-lock"}} - {{else if $repo.IsFork}} - {{svg "octicon-repo-forked"}} - {{else if $repo.IsMirror}} - {{svg "octicon-mirror"}} - {{else if $repo.IsTemplate}} - {{svg "octicon-repo-template"}} - {{else}} - {{svg "octicon-repo"}} - {{end}} - {{$repo.OwnerName}}/{{$repo.Name}} - {{FormatByteSize $repo.Size}} - {{if $repo.IsFork}} - {{ctx.Locale.Tr "repo.forked_from"}} - {{$repo.BaseRepo.OwnerName}}/{{$repo.BaseRepo.Name}} - {{end}} - {{else}} - {{svg "octicon-file-directory-fill"}} - {{$.ContextUser.Name}}/{{$dir}} -
- {{if $.allowAdopt}} - - -
- {{ctx.Locale.Tr "repo.adopt_preexisting"}} -
-
-

{{ctx.Locale.Tr "repo.adopt_preexisting_content" $dir}}

-
-
- - - {{template "base/modal_actions_confirm" $}} -
-
- {{end}} - {{if $.allowDelete}} - - -
- {{ctx.Locale.Tr "repo.delete_preexisting"}} -
-
-

{{ctx.Locale.Tr "repo.delete_preexisting_content" $dir}}

-
-
- - - {{template "base/modal_actions_confirm" $}} -
-
- {{end}} -
- {{end}} -
+ {{if .Repos}} +
+ {{range .Repos}} +
+
+ {{if .IsPrivate}} + {{svg "octicon-lock" 16 "tw-text-gold"}} + {{else if .IsFork}} + {{svg "octicon-repo-forked"}} + {{else if .IsMirror}} + {{svg "octicon-mirror"}} + {{else if .IsTemplate}} + {{svg "octicon-repo-template"}} + {{else}} + {{svg "octicon-repo"}} + {{end}} + {{.OwnerName}}/{{.Name}} + {{FormatByteSize .Size}} + {{if .IsFork}} + {{ctx.Locale.Tr "repo.forked_from"}} + {{.BaseRepo.OwnerName}}/{{.BaseRepo.Name}} + {{end}}
- {{end}} -
- {{template "base/paginate" .}} - {{else}} -
- {{ctx.Locale.Tr "settings.repos_none"}} -
- {{end}} +
+ {{end}} +
+ {{template "base/paginate" .}} {{else}} - {{if .Repos}} -
- {{range .Repos}} -
-
- {{if .IsPrivate}} - {{svg "octicon-lock" 16 "tw-text-gold"}} - {{else if .IsFork}} - {{svg "octicon-repo-forked"}} - {{else if .IsMirror}} - {{svg "octicon-mirror"}} - {{else if .IsTemplate}} - {{svg "octicon-repo-template"}} - {{else}} - {{svg "octicon-repo"}} - {{end}} - {{.OwnerName}}/{{.Name}} - {{FormatByteSize .Size}} - {{if .IsFork}} - {{ctx.Locale.Tr "repo.forked_from"}} - {{.BaseRepo.OwnerName}}/{{.BaseRepo.Name}} - {{end}} -
-
- {{end}} -
- {{template "base/paginate" .}} - {{else}} -
- {{ctx.Locale.Tr "settings.repos_none"}} -
- {{end}} +
+ {{ctx.Locale.Tr "settings.repos_none"}} +
{{end}}