mirror of
https://github.com/go-gitea/gitea.git
synced 2026-05-17 21:00:38 +02:00
update repository storage layout as per https://github.com/go-gitea/gitea/issues/1872#issuecomment-3194681583
This commit is contained in:
parent
296131c63c
commit
e602134b3e
@ -228,13 +228,21 @@ func init() {
|
|||||||
db.RegisterModel(new(Repository))
|
db.RegisterModel(new(Repository))
|
||||||
}
|
}
|
||||||
|
|
||||||
func RelativePath(ownerName, repoName string) string {
|
func RelativePathBaseName(ownerName, repoName string, groupID int64) string {
|
||||||
return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".git"
|
var groupSegment string
|
||||||
|
if groupID > 0 {
|
||||||
|
groupSegment = strconv.FormatInt(groupID, 10) + "/"
|
||||||
|
}
|
||||||
|
return strings.ToLower(ownerName) + "/" + groupSegment + strings.ToLower(repoName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RelativePath(ownerName, repoName string, groupID int64) string {
|
||||||
|
return RelativePathBaseName(ownerName, repoName, groupID) + ".git"
|
||||||
}
|
}
|
||||||
|
|
||||||
// RelativePath should be an unix style path like username/reponame.git
|
// RelativePath should be an unix style path like username/reponame.git
|
||||||
func (repo *Repository) RelativePath() string {
|
func (repo *Repository) RelativePath() string {
|
||||||
return RelativePath(repo.OwnerName, repo.Name)
|
return RelativePath(repo.OwnerName, repo.Name, repo.GroupID)
|
||||||
}
|
}
|
||||||
|
|
||||||
type StorageRepo string
|
type StorageRepo string
|
||||||
@ -583,13 +591,19 @@ func (repo *Repository) IsGenerated() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RepoPath returns repository path by given user and repository name.
|
// RepoPath returns repository path by given user and repository name.
|
||||||
func RepoPath(userName, repoName string) string { //revive:disable-line:exported
|
func RepoPath(userName, repoName string, groupID int64) string { //revive:disable-line:exported
|
||||||
return filepath.Join(setting.RepoRootPath, filepath.Clean(strings.ToLower(userName)), filepath.Clean(strings.ToLower(repoName)+".git"))
|
var joinArgs []string
|
||||||
|
joinArgs = append(joinArgs, user_model.UserPath(userName))
|
||||||
|
if groupID > 0 {
|
||||||
|
joinArgs = append(joinArgs, strconv.FormatInt(groupID, 10))
|
||||||
|
}
|
||||||
|
joinArgs = append(joinArgs, strings.ToLower(repoName)+".git")
|
||||||
|
return filepath.Join(joinArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RepoPath returns the repository path
|
// RepoPath returns the repository path
|
||||||
func (repo *Repository) RepoPath() string {
|
func (repo *Repository) RepoPath() string {
|
||||||
return RepoPath(repo.OwnerName, repo.Name)
|
return RepoPath(repo.OwnerName, repo.Name, repo.GroupID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link returns the repository relative url
|
// Link returns the repository relative url
|
||||||
@ -659,13 +673,25 @@ type CloneLink struct {
|
|||||||
Tea string
|
Tea string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getGroupSegment(gid int64) string {
|
||||||
|
var groupSegment string
|
||||||
|
if gid > 0 {
|
||||||
|
groupSegment = fmt.Sprintf("%d", gid)
|
||||||
|
}
|
||||||
|
return groupSegment
|
||||||
|
}
|
||||||
|
|
||||||
|
func groupSegmentWithTrailingSlash(gid int64) string {
|
||||||
|
return getGroupSegment(gid) + "/"
|
||||||
|
}
|
||||||
|
|
||||||
// ComposeHTTPSCloneURL returns HTTPS clone URL based on the given owner and repository name.
|
// ComposeHTTPSCloneURL returns HTTPS clone URL based on the given owner and repository name.
|
||||||
func ComposeHTTPSCloneURL(ctx context.Context, owner, repo string) string {
|
func ComposeHTTPSCloneURL(ctx context.Context, owner, repo string, groupID int64) string {
|
||||||
return fmt.Sprintf("%s%s/%s.git", httplib.GuessCurrentAppURL(ctx), url.PathEscape(owner), url.PathEscape(repo))
|
return fmt.Sprintf("%s%s/%s%s.git", httplib.GuessCurrentAppURL(ctx), url.PathEscape(owner), groupSegmentWithTrailingSlash(groupID), url.PathEscape(repo))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ComposeSSHCloneURL returns SSH clone URL based on the given owner and repository name.
|
// ComposeSSHCloneURL returns SSH clone URL based on the given owner and repository name.
|
||||||
func ComposeSSHCloneURL(doer *user_model.User, ownerName, repoName string) string {
|
func ComposeSSHCloneURL(doer *user_model.User, ownerName, repoName string, groupID int64) string {
|
||||||
sshUser := setting.SSH.User
|
sshUser := setting.SSH.User
|
||||||
sshDomain := setting.SSH.Domain
|
sshDomain := setting.SSH.Domain
|
||||||
|
|
||||||
@ -684,7 +710,7 @@ func ComposeSSHCloneURL(doer *user_model.User, ownerName, repoName string) strin
|
|||||||
// non-standard port, it must use full URI
|
// non-standard port, it must use full URI
|
||||||
if setting.SSH.Port != 22 {
|
if setting.SSH.Port != 22 {
|
||||||
sshHost := net.JoinHostPort(sshDomain, strconv.Itoa(setting.SSH.Port))
|
sshHost := net.JoinHostPort(sshDomain, strconv.Itoa(setting.SSH.Port))
|
||||||
return fmt.Sprintf("ssh://%s@%s/%s/%s.git", sshUser, sshHost, url.PathEscape(ownerName), url.PathEscape(repoName))
|
return fmt.Sprintf("ssh://%s@%s/%s%s/%s.git", sshUser, sshHost, url.PathEscape(ownerName), groupSegmentWithTrailingSlash(groupID), url.PathEscape(repoName))
|
||||||
}
|
}
|
||||||
|
|
||||||
// for standard port, it can use a shorter URI (without the port)
|
// for standard port, it can use a shorter URI (without the port)
|
||||||
@ -699,25 +725,25 @@ func ComposeSSHCloneURL(doer *user_model.User, ownerName, repoName string) strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ComposeTeaCloneCommand returns Tea CLI clone command based on the given owner and repository name.
|
// ComposeTeaCloneCommand returns Tea CLI clone command based on the given owner and repository name.
|
||||||
func ComposeTeaCloneCommand(ctx context.Context, owner, repo string) string {
|
func ComposeTeaCloneCommand(ctx context.Context, owner, repo string, groupID int64) string {
|
||||||
return fmt.Sprintf("tea clone %s/%s", url.PathEscape(owner), url.PathEscape(repo))
|
return fmt.Sprintf("tea clone %s/%s%s", url.PathEscape(owner), url.PathEscape(repo), groupSegmentWithTrailingSlash(groupID))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Repository) cloneLink(ctx context.Context, doer *user_model.User, repoPathName string) *CloneLink {
|
func (repo *Repository) cloneLink(ctx context.Context, doer *user_model.User, repoPathName string, groupID int64) *CloneLink {
|
||||||
return &CloneLink{
|
return &CloneLink{
|
||||||
SSH: ComposeSSHCloneURL(doer, repo.OwnerName, repoPathName),
|
SSH: ComposeSSHCloneURL(doer, repo.OwnerName, repoPathName, groupID),
|
||||||
HTTPS: ComposeHTTPSCloneURL(ctx, repo.OwnerName, repoPathName),
|
HTTPS: ComposeHTTPSCloneURL(ctx, repo.OwnerName, repoPathName, groupID),
|
||||||
Tea: ComposeTeaCloneCommand(ctx, repo.OwnerName, repoPathName),
|
Tea: ComposeTeaCloneCommand(ctx, repo.OwnerName, repoPathName, groupID),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CloneLink returns clone URLs of repository.
|
// CloneLink returns clone URLs of repository.
|
||||||
func (repo *Repository) CloneLink(ctx context.Context, doer *user_model.User) (cl *CloneLink) {
|
func (repo *Repository) CloneLink(ctx context.Context, doer *user_model.User) (cl *CloneLink) {
|
||||||
return repo.cloneLink(ctx, doer, repo.Name)
|
return repo.cloneLink(ctx, doer, repo.Name, repo.GroupID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Repository) CloneLinkGeneral(ctx context.Context) (cl *CloneLink) {
|
func (repo *Repository) CloneLinkGeneral(ctx context.Context) (cl *CloneLink) {
|
||||||
return repo.cloneLink(ctx, nil /* no doer, use a general git user */, repo.Name)
|
return repo.cloneLink(ctx, nil /* no doer, use a general git user */, repo.Name, repo.GroupID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOriginalURLHostname returns the hostname of a URL or the URL
|
// GetOriginalURLHostname returns the hostname of a URL or the URL
|
||||||
@ -855,10 +881,11 @@ func GetRepositoriesMapByIDs(ctx context.Context, ids []int64) (map[int64]*Repos
|
|||||||
return repos, db.GetEngine(ctx).In("id", ids).Find(&repos)
|
return repos, db.GetEngine(ctx).In("id", ids).Find(&repos)
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsRepositoryModelExist(ctx context.Context, u *user_model.User, repoName string) (bool, error) {
|
func IsRepositoryModelExist(ctx context.Context, u *user_model.User, repoName string, groupID int64) (bool, error) {
|
||||||
return db.GetEngine(ctx).Get(&Repository{
|
return db.GetEngine(ctx).Get(&Repository{
|
||||||
OwnerID: u.ID,
|
OwnerID: u.ID,
|
||||||
LowerName: strings.ToLower(repoName),
|
LowerName: strings.ToLower(repoName),
|
||||||
|
GroupID: groupID,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -254,7 +254,7 @@ func CreatePendingRepositoryTransfer(ctx context.Context, doer, newOwner *user_m
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if new owner has repository with same name.
|
// Check if new owner has repository with same name.
|
||||||
if has, err := IsRepositoryModelExist(ctx, newOwner, repo.Name); err != nil {
|
if has, err := IsRepositoryModelExist(ctx, newOwner, repo.Name, repo.GroupID); err != nil {
|
||||||
return fmt.Errorf("IsRepositoryExist: %w", err)
|
return fmt.Errorf("IsRepositoryExist: %w", err)
|
||||||
} else if has {
|
} else if has {
|
||||||
return ErrRepoAlreadyExist{
|
return ErrRepoAlreadyExist{
|
||||||
|
|||||||
@ -5,12 +5,10 @@
|
|||||||
package repo
|
package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrWikiAlreadyExist represents a "WikiAlreadyExist" kind of error.
|
// ErrWikiAlreadyExist represents a "WikiAlreadyExist" kind of error.
|
||||||
@ -72,15 +70,13 @@ func (err ErrWikiInvalidFileName) Unwrap() error {
|
|||||||
|
|
||||||
// WikiCloneLink returns clone URLs of repository wiki.
|
// WikiCloneLink returns clone URLs of repository wiki.
|
||||||
func (repo *Repository) WikiCloneLink(ctx context.Context, doer *user_model.User) *CloneLink {
|
func (repo *Repository) WikiCloneLink(ctx context.Context, doer *user_model.User) *CloneLink {
|
||||||
return repo.cloneLink(ctx, doer, repo.Name+".wiki")
|
return repo.cloneLink(ctx, doer, repo.Name+".wiki", repo.GroupID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RelativeWikiPath(ownerName, repoName string) string {
|
func RelativeWikiPath(ownerName, repoName string, groupID int64) string {
|
||||||
return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".wiki.git"
|
return RelativePathBaseName(ownerName, repoName, groupID) + ".wiki.git"
|
||||||
}
|
}
|
||||||
|
|
||||||
// WikiStorageRepo returns the storage repo for the wiki
|
|
||||||
// The wiki repository should have the same object format as the code repository
|
|
||||||
func (repo *Repository) WikiStorageRepo() StorageRepo {
|
func (repo *Repository) WikiStorageRepo() StorageRepo {
|
||||||
return StorageRepo(RelativeWikiPath(repo.OwnerName, repo.Name))
|
return StorageRepo(RelativeWikiPath(repo.OwnerName, repo.Name, repo.GroupID))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,6 +55,47 @@ func ListUnadoptedRepositories(ctx *context.APIContext) {
|
|||||||
ctx.JSON(http.StatusOK, repoNames)
|
ctx.JSON(http.StatusOK, repoNames)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func commonAdoptRepository(ctx *context.APIContext) {
|
||||||
|
ownerName := ctx.PathParam("username")
|
||||||
|
repoName := ctx.PathParam("reponame")
|
||||||
|
groupID := ctx.PathParamInt64("group_id")
|
||||||
|
|
||||||
|
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, groupID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.APIErrorInternal(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.StorageRepo(repo_model.RelativePath(ctxUser.Name, repoName, groupID)))
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
// AdoptRepository will adopt an unadopted repository
|
// AdoptRepository will adopt an unadopted repository
|
||||||
func AdoptRepository(ctx *context.APIContext) {
|
func AdoptRepository(ctx *context.APIContext) {
|
||||||
// swagger:operation POST /admin/unadopted/{owner}/{repo} admin adminAdoptRepository
|
// swagger:operation POST /admin/unadopted/{owner}/{repo} admin adminAdoptRepository
|
||||||
@ -80,8 +121,40 @@ func AdoptRepository(ctx *context.APIContext) {
|
|||||||
// "$ref": "#/responses/notFound"
|
// "$ref": "#/responses/notFound"
|
||||||
// "403":
|
// "403":
|
||||||
// "$ref": "#/responses/forbidden"
|
// "$ref": "#/responses/forbidden"
|
||||||
|
commonAdoptRepository(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func AdoptGroupRepository(ctx *context.APIContext) {
|
||||||
|
// swagger:operation POST /admin/unadopted/{owner}/{group_id}/{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"
|
||||||
|
// "404":
|
||||||
|
// "$ref": "#/responses/notFound"
|
||||||
|
// "403":
|
||||||
|
// "$ref": "#/responses/forbidden"
|
||||||
|
commonAdoptRepository(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func commonDeleteUnadoptedRepo(ctx *context.APIContext) {
|
||||||
ownerName := ctx.PathParam("username")
|
ownerName := ctx.PathParam("username")
|
||||||
repoName := ctx.PathParam("reponame")
|
repoName := ctx.PathParam("reponame")
|
||||||
|
groupID := ctx.PathParamInt64("group_id")
|
||||||
|
|
||||||
ctxUser, err := user_model.GetUserByName(ctx, ownerName)
|
ctxUser, err := user_model.GetUserByName(ctx, ownerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -94,12 +167,12 @@ func AdoptRepository(ctx *context.APIContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check not a repo
|
// check not a repo
|
||||||
has, err := repo_model.IsRepositoryModelExist(ctx, ctxUser, repoName)
|
has, err := repo_model.IsRepositoryModelExist(ctx, ctxUser, repoName, groupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.APIErrorInternal(err)
|
ctx.APIErrorInternal(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.StorageRepo(repo_model.RelativePath(ctxUser.Name, repoName)))
|
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.StorageRepo(repo_model.RelativePath(ctxUser.Name, repoName, groupID)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.APIErrorInternal(err)
|
ctx.APIErrorInternal(err)
|
||||||
return
|
return
|
||||||
@ -108,10 +181,8 @@ func AdoptRepository(ctx *context.APIContext) {
|
|||||||
ctx.APIErrorNotFound()
|
ctx.APIErrorNotFound()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, err := repo_service.AdoptRepository(ctx, ctx.Doer, ctxUser, repo_service.CreateRepoOptions{
|
|
||||||
Name: repoName,
|
if err := repo_service.DeleteUnadoptedRepository(ctx, ctx.Doer, ctxUser, repoName, groupID); err != nil {
|
||||||
IsPrivate: true,
|
|
||||||
}); err != nil {
|
|
||||||
ctx.APIErrorInternal(err)
|
ctx.APIErrorInternal(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -142,39 +213,30 @@ func DeleteUnadoptedRepository(ctx *context.APIContext) {
|
|||||||
// "$ref": "#/responses/empty"
|
// "$ref": "#/responses/empty"
|
||||||
// "403":
|
// "403":
|
||||||
// "$ref": "#/responses/forbidden"
|
// "$ref": "#/responses/forbidden"
|
||||||
ownerName := ctx.PathParam("username")
|
commonDeleteUnadoptedRepo(ctx)
|
||||||
repoName := ctx.PathParam("reponame")
|
}
|
||||||
|
|
||||||
ctxUser, err := user_model.GetUserByName(ctx, ownerName)
|
func DeleteUnadoptedRepositoryInGroup(ctx *context.APIContext) {
|
||||||
if err != nil {
|
// swagger:operation DELETE /admin/unadopted/{owner}/{group_id}/{repo} admin adminDeleteUnadoptedRepository
|
||||||
if user_model.IsErrUserNotExist(err) {
|
// ---
|
||||||
ctx.APIErrorNotFound()
|
// summary: Delete unadopted files
|
||||||
return
|
// produces:
|
||||||
}
|
// - application/json
|
||||||
ctx.APIErrorInternal(err)
|
// parameters:
|
||||||
return
|
// - name: owner
|
||||||
}
|
// in: path
|
||||||
|
// description: owner of the repo
|
||||||
// check not a repo
|
// type: string
|
||||||
has, err := repo_model.IsRepositoryModelExist(ctx, ctxUser, repoName)
|
// required: true
|
||||||
if err != nil {
|
// - name: repo
|
||||||
ctx.APIErrorInternal(err)
|
// in: path
|
||||||
return
|
// description: name of the repo
|
||||||
}
|
// type: string
|
||||||
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.StorageRepo(repo_model.RelativePath(ctxUser.Name, repoName)))
|
// required: true
|
||||||
if err != nil {
|
// responses:
|
||||||
ctx.APIErrorInternal(err)
|
// "204":
|
||||||
return
|
// "$ref": "#/responses/empty"
|
||||||
}
|
// "403":
|
||||||
if has || !exist {
|
// "$ref": "#/responses/forbidden"
|
||||||
ctx.APIErrorNotFound()
|
commonDeleteUnadoptedRepo(ctx)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := repo_service.DeleteUnadoptedRepository(ctx, ctx.Doer, ctxUser, repoName); err != nil {
|
|
||||||
ctx.APIErrorInternal(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.Status(http.StatusNoContent)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -66,6 +66,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
actions_model "code.gitea.io/gitea/models/actions"
|
actions_model "code.gitea.io/gitea/models/actions"
|
||||||
@ -140,7 +141,16 @@ func repoAssignment() func(ctx *context.APIContext) {
|
|||||||
return func(ctx *context.APIContext) {
|
return func(ctx *context.APIContext) {
|
||||||
userName := ctx.PathParam("username")
|
userName := ctx.PathParam("username")
|
||||||
repoName := ctx.PathParam("reponame")
|
repoName := ctx.PathParam("reponame")
|
||||||
|
var gid int64
|
||||||
|
group := ctx.PathParam("group_id")
|
||||||
|
if group != "" {
|
||||||
|
gid, _ = strconv.ParseInt(group, 10, 64)
|
||||||
|
if gid == 0 {
|
||||||
|
ctx.Redirect(strings.Replace(ctx.Req.URL.RequestURI(), "/0/", "/", 1))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
group += "/"
|
||||||
|
}
|
||||||
var (
|
var (
|
||||||
owner *user_model.User
|
owner *user_model.User
|
||||||
err error
|
err error
|
||||||
@ -186,6 +196,10 @@ func repoAssignment() func(ctx *context.APIContext) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if repo.GroupID != gid {
|
||||||
|
ctx.APIErrorNotFound()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
repo.Owner = owner
|
repo.Owner = owner
|
||||||
ctx.Repo.Repository = repo
|
ctx.Repo.Repository = repo
|
||||||
@ -1777,8 +1791,13 @@ func Routes() *web.Router {
|
|||||||
})
|
})
|
||||||
m.Group("/unadopted", func() {
|
m.Group("/unadopted", func() {
|
||||||
m.Get("", admin.ListUnadoptedRepositories)
|
m.Get("", admin.ListUnadoptedRepositories)
|
||||||
m.Post("/{username}/{reponame}", admin.AdoptRepository)
|
m.Group("/{username}", func() {
|
||||||
m.Delete("/{username}/{reponame}", admin.DeleteUnadoptedRepository)
|
m.Post("/{reponame}", admin.AdoptRepository)
|
||||||
|
m.Delete("/{reponame}", admin.DeleteUnadoptedRepository)
|
||||||
|
m.Post("/{group_id}/{reponame}", admin.AdoptGroupRepository)
|
||||||
|
m.Delete("/{group_id}/{reponame}", admin.DeleteUnadoptedRepositoryInGroup)
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
m.Group("/hooks", func() {
|
m.Group("/hooks", func() {
|
||||||
m.Combo("").Get(admin.ListHooks).
|
m.Combo("").Get(admin.ListHooks).
|
||||||
|
|||||||
@ -6,6 +6,7 @@ package admin
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
@ -127,14 +128,18 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repoName := dirSplit[1]
|
repoName := dirSplit[1]
|
||||||
|
var groupID int64
|
||||||
|
if len(dirSplit) >= 3 {
|
||||||
|
groupID, _ = strconv.ParseInt(dirSplit[2], 10, 64)
|
||||||
|
}
|
||||||
|
|
||||||
// check not a repo
|
// check not a repo
|
||||||
has, err := repo_model.IsRepositoryModelExist(ctx, ctxUser, repoName)
|
has, err := repo_model.IsRepositoryModelExist(ctx, ctxUser, repoName, groupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("IsRepositoryExist", err)
|
ctx.ServerError("IsRepositoryExist", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.StorageRepo(repo_model.RelativePath(ctxUser.Name, repoName)))
|
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.StorageRepo(repo_model.RelativePath(ctxUser.Name, repoName, groupID)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("IsDir", err)
|
ctx.ServerError("IsDir", err)
|
||||||
return
|
return
|
||||||
@ -151,7 +156,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
ctx.Flash.Success(ctx.Tr("repo.adopt_preexisting_success", dir))
|
ctx.Flash.Success(ctx.Tr("repo.adopt_preexisting_success", dir))
|
||||||
} else if action == "delete" {
|
} else if action == "delete" {
|
||||||
if err := repo_service.DeleteUnadoptedRepository(ctx, ctx.Doer, ctxUser, dirSplit[1]); err != nil {
|
if err := repo_service.DeleteUnadoptedRepository(ctx, ctx.Doer, ctxUser, dirSplit[1], groupID); err != nil {
|
||||||
ctx.ServerError("repository.AdoptRepository", err)
|
ctx.ServerError("repository.AdoptRepository", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func addOwnerRepoGitHTTPRouters(m *web.Router, middlewares ...any) {
|
func addOwnerRepoGitHTTPRouters(m *web.Router, middlewares ...any) {
|
||||||
m.Group("/{username}/{reponame}", func() {
|
m.Group("/{username}/{group_id}?/{reponame}", func() {
|
||||||
m.Methods("POST,OPTIONS", "/git-upload-pack", repo.ServiceUploadPack)
|
m.Methods("POST,OPTIONS", "/git-upload-pack", repo.ServiceUploadPack)
|
||||||
m.Methods("POST,OPTIONS", "/git-receive-pack", repo.ServiceReceivePack)
|
m.Methods("POST,OPTIONS", "/git-receive-pack", repo.ServiceReceivePack)
|
||||||
m.Methods("POST,OPTIONS", "/git-upload-archive", repo.ServiceUploadArchive)
|
m.Methods("POST,OPTIONS", "/git-upload-archive", repo.ServiceUploadArchive)
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
@ -22,14 +23,17 @@ func goGet(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
parts := strings.SplitN(ctx.Req.URL.EscapedPath(), "/", 4)
|
parts := strings.SplitN(ctx.Req.URL.EscapedPath(), "/", 5)
|
||||||
|
|
||||||
if len(parts) < 3 {
|
if len(parts) < 3 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var group string
|
||||||
ownerName := parts[1]
|
ownerName := parts[1]
|
||||||
repoName := parts[2]
|
repoName := parts[2]
|
||||||
|
if len(parts) > 3 {
|
||||||
|
group = parts[3]
|
||||||
|
}
|
||||||
|
|
||||||
// Quick responses appropriate go-get meta with status 200
|
// Quick responses appropriate go-get meta with status 200
|
||||||
// regardless of if user have access to the repository,
|
// regardless of if user have access to the repository,
|
||||||
@ -56,7 +60,11 @@ func goGet(ctx *context.Context) {
|
|||||||
if err == nil && len(repo.DefaultBranch) > 0 {
|
if err == nil && len(repo.DefaultBranch) > 0 {
|
||||||
branchName = repo.DefaultBranch
|
branchName = repo.DefaultBranch
|
||||||
}
|
}
|
||||||
prefix := setting.AppURL + path.Join(url.PathEscape(ownerName), url.PathEscape(repoName), "src", "branch", util.PathEscapeSegments(branchName))
|
prefix := setting.AppURL + url.PathEscape(ownerName)
|
||||||
|
if group != "" {
|
||||||
|
prefix = path.Join(prefix, group)
|
||||||
|
}
|
||||||
|
prefix = path.Join(prefix, url.PathEscape(repoName), "src", "branch", util.PathEscapeSegments(branchName))
|
||||||
|
|
||||||
appURL, _ := url.Parse(setting.AppURL)
|
appURL, _ := url.Parse(setting.AppURL)
|
||||||
|
|
||||||
@ -68,10 +76,11 @@ func goGet(ctx *context.Context) {
|
|||||||
goGetImport := context.ComposeGoGetImport(ctx, ownerName, trimmedRepoName)
|
goGetImport := context.ComposeGoGetImport(ctx, ownerName, trimmedRepoName)
|
||||||
|
|
||||||
var cloneURL string
|
var cloneURL string
|
||||||
|
gid, _ := strconv.ParseInt(group, 10, 64)
|
||||||
if setting.Repository.GoGetCloneURLProtocol == "ssh" {
|
if setting.Repository.GoGetCloneURLProtocol == "ssh" {
|
||||||
cloneURL = repo_model.ComposeSSHCloneURL(ctx.Doer, ownerName, repoName)
|
cloneURL = repo_model.ComposeSSHCloneURL(ctx.Doer, ownerName, repoName, gid)
|
||||||
} else {
|
} else {
|
||||||
cloneURL = repo_model.ComposeHTTPSCloneURL(ctx, ownerName, repoName)
|
cloneURL = repo_model.ComposeHTTPSCloneURL(ctx, ownerName, repoName, gid)
|
||||||
}
|
}
|
||||||
goImportContent := fmt.Sprintf("%s git %s", goGetImport, cloneURL /*CloneLink*/)
|
goImportContent := fmt.Sprintf("%s git %s", goGetImport, cloneURL /*CloneLink*/)
|
||||||
goSourceContent := fmt.Sprintf("%s _ %s %s", goGetImport, prefix+"{/dir}" /*GoDocDirectory*/, prefix+"{/dir}/{file}#L{line}" /*GoDocFile*/)
|
goSourceContent := fmt.Sprintf("%s _ %s %s", goGetImport, prefix+"{/dir}" /*GoDocDirectory*/, prefix+"{/dir}/{file}#L{line}" /*GoDocFile*/)
|
||||||
|
|||||||
@ -4,6 +4,9 @@
|
|||||||
package setting
|
package setting
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/modules/gitrepo"
|
"code.gitea.io/gitea/modules/gitrepo"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
@ -21,18 +24,24 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
|
|||||||
ctx.Data["allowDelete"] = allowDelete
|
ctx.Data["allowDelete"] = allowDelete
|
||||||
|
|
||||||
dir := ctx.FormString("id")
|
dir := ctx.FormString("id")
|
||||||
|
var gid int64
|
||||||
|
if len(strings.Split(dir, "/")) > 1 {
|
||||||
|
split := strings.Split(dir, "/")
|
||||||
|
dir = split[0]
|
||||||
|
gid, _ = strconv.ParseInt(split[1], 10, 64)
|
||||||
|
}
|
||||||
action := ctx.FormString("action")
|
action := ctx.FormString("action")
|
||||||
|
|
||||||
ctxUser := ctx.Doer
|
ctxUser := ctx.Doer
|
||||||
|
|
||||||
// check not a repo
|
// check not a repo
|
||||||
has, err := repo_model.IsRepositoryModelExist(ctx, ctxUser, dir)
|
has, err := repo_model.IsRepositoryModelExist(ctx, ctxUser, dir, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("IsRepositoryExist", err)
|
ctx.ServerError("IsRepositoryExist", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.StorageRepo(repo_model.RelativePath(ctxUser.Name, dir)))
|
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.StorageRepo(repo_model.RelativePath(ctxUser.Name, dir, gid)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("IsDir", err)
|
ctx.ServerError("IsDir", err)
|
||||||
return
|
return
|
||||||
@ -49,7 +58,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
ctx.Flash.Success(ctx.Tr("repo.adopt_preexisting_success", dir))
|
ctx.Flash.Success(ctx.Tr("repo.adopt_preexisting_success", dir))
|
||||||
} else if action == "delete" && allowDelete {
|
} else if action == "delete" && allowDelete {
|
||||||
if err := repo_service.DeleteUnadoptedRepository(ctx, ctxUser, ctxUser, dir); err != nil {
|
if err := repo_service.DeleteUnadoptedRepository(ctx, ctxUser, ctxUser, dir, gid); err != nil {
|
||||||
ctx.ServerError("repository.AdoptRepository", err)
|
ctx.ServerError("repository.AdoptRepository", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
auth_model "code.gitea.io/gitea/models/auth"
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
@ -369,6 +370,7 @@ func ComposeGoGetImport(ctx context.Context, owner, repo string) string {
|
|||||||
func EarlyResponseForGoGetMeta(ctx *Context) {
|
func EarlyResponseForGoGetMeta(ctx *Context) {
|
||||||
username := ctx.PathParam("username")
|
username := ctx.PathParam("username")
|
||||||
reponame := strings.TrimSuffix(ctx.PathParam("reponame"), ".git")
|
reponame := strings.TrimSuffix(ctx.PathParam("reponame"), ".git")
|
||||||
|
groupID := ctx.PathParamInt64("group_id")
|
||||||
if username == "" || reponame == "" {
|
if username == "" || reponame == "" {
|
||||||
ctx.PlainText(http.StatusBadRequest, "invalid repository path")
|
ctx.PlainText(http.StatusBadRequest, "invalid repository path")
|
||||||
return
|
return
|
||||||
@ -376,9 +378,9 @@ func EarlyResponseForGoGetMeta(ctx *Context) {
|
|||||||
|
|
||||||
var cloneURL string
|
var cloneURL string
|
||||||
if setting.Repository.GoGetCloneURLProtocol == "ssh" {
|
if setting.Repository.GoGetCloneURLProtocol == "ssh" {
|
||||||
cloneURL = repo_model.ComposeSSHCloneURL(ctx.Doer, username, reponame)
|
cloneURL = repo_model.ComposeSSHCloneURL(ctx.Doer, username, reponame, groupID)
|
||||||
} else {
|
} else {
|
||||||
cloneURL = repo_model.ComposeHTTPSCloneURL(ctx, username, reponame)
|
cloneURL = repo_model.ComposeHTTPSCloneURL(ctx, username, reponame, groupID)
|
||||||
}
|
}
|
||||||
goImportContent := fmt.Sprintf("%s git %s", ComposeGoGetImport(ctx, username, reponame), cloneURL)
|
goImportContent := fmt.Sprintf("%s git %s", ComposeGoGetImport(ctx, username, reponame), cloneURL)
|
||||||
htmlMeta := fmt.Sprintf(`<meta name="go-import" content="%s">`, html.EscapeString(goImportContent))
|
htmlMeta := fmt.Sprintf(`<meta name="go-import" content="%s">`, html.EscapeString(goImportContent))
|
||||||
@ -481,6 +483,20 @@ func repoAssignmentPrepareData(ctx *Context) *repoAssignmentPrepareDataStruct {
|
|||||||
// HINT: here it doesn't handle ".wiki" extension, it is handled in repoAssignmentAutoRedirectWiki, need to be refactored in the future
|
// HINT: here it doesn't handle ".wiki" extension, it is handled in repoAssignmentAutoRedirectWiki, need to be refactored in the future
|
||||||
userName := ctx.PathParam("username")
|
userName := ctx.PathParam("username")
|
||||||
repoName := ctx.PathParam("reponame")
|
repoName := ctx.PathParam("reponame")
|
||||||
|
group := ctx.PathParam("group_id")
|
||||||
|
var gid int64
|
||||||
|
if group != "" {
|
||||||
|
gid, _ = strconv.ParseInt(group, 10, 64)
|
||||||
|
if gid == 0 {
|
||||||
|
q := ctx.Req.URL.RawQuery
|
||||||
|
if q != "" {
|
||||||
|
q = "?" + q
|
||||||
|
}
|
||||||
|
ctx.Redirect(strings.Replace(ctx.Link, "/0/", "/", 1) + q)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
group += "/"
|
||||||
|
}
|
||||||
repoName = strings.TrimSuffix(repoName, ".git")
|
repoName = strings.TrimSuffix(repoName, ".git")
|
||||||
if setting.Other.EnableFeed {
|
if setting.Other.EnableFeed {
|
||||||
ctx.Data["EnableFeed"] = true
|
ctx.Data["EnableFeed"] = true
|
||||||
@ -535,7 +551,7 @@ func repoAssignmentAutoRedirectWiki(ctx *Context, data *repoAssignmentPrepareDat
|
|||||||
redirectRepoName += originalRepoName[len(redirectRepoName)+5:]
|
redirectRepoName += originalRepoName[len(redirectRepoName)+5:]
|
||||||
redirectPath := strings.Replace(
|
redirectPath := strings.Replace(
|
||||||
ctx.Req.URL.EscapedPath(),
|
ctx.Req.URL.EscapedPath(),
|
||||||
url.PathEscape(userName)+"/"+url.PathEscape(originalRepoName),
|
url.PathEscape(userName)+"/"+group+url.PathEscape(originalRepoName),
|
||||||
url.PathEscape(userName)+"/"+url.PathEscape(redirectRepoName)+"/wiki",
|
url.PathEscape(userName)+"/"+url.PathEscape(redirectRepoName)+"/wiki",
|
||||||
1,
|
1,
|
||||||
)
|
)
|
||||||
@ -570,6 +586,9 @@ func repoAssignmentPrepareRepo(ctx *Context, data *repoAssignmentPrepareDataStru
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if repo.GroupID != gid {
|
||||||
|
ctx.NotFound(nil)
|
||||||
|
}
|
||||||
repo.Owner = ctx.Repo.Owner
|
repo.Owner = ctx.Repo.Owner
|
||||||
data.repo = repo
|
data.repo = repo
|
||||||
}
|
}
|
||||||
|
|||||||
@ -208,12 +208,12 @@ func adoptRepository(ctx context.Context, repo *repo_model.Repository, defaultBr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeleteUnadoptedRepository deletes unadopted repository files from the filesystem
|
// DeleteUnadoptedRepository deletes unadopted repository files from the filesystem
|
||||||
func DeleteUnadoptedRepository(ctx context.Context, doer, u *user_model.User, repoName string) error {
|
func DeleteUnadoptedRepository(ctx context.Context, doer, u *user_model.User, repoName string, groupID int64) error {
|
||||||
if err := repo_model.IsUsableRepoName(repoName); err != nil {
|
if err := repo_model.IsUsableRepoName(repoName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
relativePath := repo_model.RelativePath(u.Name, repoName)
|
relativePath := repo_model.RelativePath(u.Name, repoName, groupID)
|
||||||
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.StorageRepo(relativePath))
|
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.StorageRepo(relativePath))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Unable to check if %s exists. Error: %v", relativePath, err)
|
log.Error("Unable to check if %s exists. Error: %v", relativePath, err)
|
||||||
@ -226,7 +226,7 @@ func DeleteUnadoptedRepository(ctx context.Context, doer, u *user_model.User, re
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if exist, err := repo_model.IsRepositoryModelExist(ctx, u, repoName); err != nil {
|
if exist, err := repo_model.IsRepositoryModelExist(ctx, u, repoName, groupID); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if exist {
|
} else if exist {
|
||||||
return repo_model.ErrRepoAlreadyExist{
|
return repo_model.ErrRepoAlreadyExist{
|
||||||
|
|||||||
@ -369,7 +369,7 @@ func createRepositoryInDB(ctx context.Context, doer, u *user_model.User, repo *r
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
has, err := repo_model.IsRepositoryModelExist(ctx, u, repo.Name)
|
has, err := repo_model.IsRepositoryModelExist(ctx, u, repo.Name, repo.GroupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("IsRepositoryExist: %w", err)
|
return fmt.Errorf("IsRepositoryExist: %w", err)
|
||||||
} else if has {
|
} else if has {
|
||||||
|
|||||||
@ -91,12 +91,12 @@ func AcceptTransferOwnership(ctx context.Context, repo *repo_model.Repository, d
|
|||||||
}
|
}
|
||||||
|
|
||||||
// isRepositoryModelOrDirExist returns true if the repository with given name under user has already existed.
|
// isRepositoryModelOrDirExist returns true if the repository with given name under user has already existed.
|
||||||
func isRepositoryModelOrDirExist(ctx context.Context, u *user_model.User, repoName string) (bool, error) {
|
func isRepositoryModelOrDirExist(ctx context.Context, u *user_model.User, repoName string, groupID int64) (bool, error) {
|
||||||
has, err := repo_model.IsRepositoryModelExist(ctx, u, repoName)
|
has, err := repo_model.IsRepositoryModelExist(ctx, u, repoName, groupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
repo := repo_model.StorageRepo(repo_model.RelativePath(u.Name, repoName))
|
repo := repo_model.StorageRepo(repo_model.RelativePath(u.Name, repoName, groupID))
|
||||||
isExist, err := gitrepo.IsRepositoryExist(ctx, repo)
|
isExist, err := gitrepo.IsRepositoryExist(ctx, repo)
|
||||||
return has || isExist, err
|
return has || isExist, err
|
||||||
}
|
}
|
||||||
@ -118,7 +118,7 @@ func transferOwnership(ctx context.Context, doer *user_model.User, newOwnerName
|
|||||||
}
|
}
|
||||||
|
|
||||||
if repoRenamed {
|
if repoRenamed {
|
||||||
oldRelativePath, newRelativePath := repo_model.RelativePath(newOwnerName, repo.Name), repo_model.RelativePath(oldOwnerName, repo.Name)
|
oldRelativePath, newRelativePath := repo_model.RelativePath(newOwnerName, repo.Name, 0), repo_model.RelativePath(oldOwnerName, repo.Name, repo.GroupID)
|
||||||
if err := gitrepo.RenameRepository(ctx, repo_model.StorageRepo(oldRelativePath), repo_model.StorageRepo(newRelativePath)); err != nil {
|
if err := gitrepo.RenameRepository(ctx, repo_model.StorageRepo(oldRelativePath), repo_model.StorageRepo(newRelativePath)); err != nil {
|
||||||
log.Critical("Unable to move repository %s/%s directory from %s back to correct place %s: %v", oldOwnerName, repo.Name,
|
log.Critical("Unable to move repository %s/%s directory from %s back to correct place %s: %v", oldOwnerName, repo.Name,
|
||||||
oldRelativePath, newRelativePath, err)
|
oldRelativePath, newRelativePath, err)
|
||||||
@ -126,7 +126,7 @@ func transferOwnership(ctx context.Context, doer *user_model.User, newOwnerName
|
|||||||
}
|
}
|
||||||
|
|
||||||
if wikiRenamed {
|
if wikiRenamed {
|
||||||
oldRelativePath, newRelativePath := repo_model.RelativeWikiPath(newOwnerName, repo.Name), repo_model.RelativeWikiPath(oldOwnerName, repo.Name)
|
oldRelativePath, newRelativePath := repo_model.RelativeWikiPath(newOwnerName, repo.Name, 0), repo_model.RelativeWikiPath(oldOwnerName, repo.Name, repo.GroupID)
|
||||||
if err := gitrepo.RenameRepository(ctx, repo_model.StorageRepo(oldRelativePath), repo_model.StorageRepo(newRelativePath)); err != nil {
|
if err := gitrepo.RenameRepository(ctx, repo_model.StorageRepo(oldRelativePath), repo_model.StorageRepo(newRelativePath)); err != nil {
|
||||||
log.Critical("Unable to move wiki for repository %s/%s directory from %s back to correct place %s: %v", oldOwnerName, repo.Name,
|
log.Critical("Unable to move wiki for repository %s/%s directory from %s back to correct place %s: %v", oldOwnerName, repo.Name,
|
||||||
oldRelativePath, newRelativePath, err)
|
oldRelativePath, newRelativePath, err)
|
||||||
@ -154,7 +154,7 @@ func transferOwnership(ctx context.Context, doer *user_model.User, newOwnerName
|
|||||||
newOwnerName = newOwner.Name // ensure capitalisation matches
|
newOwnerName = newOwner.Name // ensure capitalisation matches
|
||||||
|
|
||||||
// Check if new owner has repository with same name.
|
// Check if new owner has repository with same name.
|
||||||
if has, err := isRepositoryModelOrDirExist(ctx, newOwner, repo.Name); err != nil {
|
if has, err := isRepositoryModelOrDirExist(ctx, newOwner, repo.Name, 0); err != nil {
|
||||||
return fmt.Errorf("IsRepositoryExist: %w", err)
|
return fmt.Errorf("IsRepositoryExist: %w", err)
|
||||||
} else if has {
|
} else if has {
|
||||||
return repo_model.ErrRepoAlreadyExist{
|
return repo_model.ErrRepoAlreadyExist{
|
||||||
@ -304,19 +304,19 @@ func transferOwnership(ctx context.Context, doer *user_model.User, newOwnerName
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rename remote repository to new path and delete local copy.
|
// Rename remote repository to new path and delete local copy.
|
||||||
oldRelativePath, newRelativePath := repo_model.RelativePath(oldOwner.Name, repo.Name), repo_model.RelativePath(newOwner.Name, repo.Name)
|
oldRelativePath, newRelativePath := repo_model.RelativePath(oldOwner.Name, repo.Name, repo.GroupID), repo_model.RelativePath(newOwner.Name, repo.Name, repo.GroupID)
|
||||||
if err := gitrepo.RenameRepository(ctx, repo_model.StorageRepo(oldRelativePath), repo_model.StorageRepo(newRelativePath)); err != nil {
|
if err := gitrepo.RenameRepository(ctx, repo_model.StorageRepo(oldRelativePath), repo_model.StorageRepo(newRelativePath)); err != nil {
|
||||||
return fmt.Errorf("rename repository directory: %w", err)
|
return fmt.Errorf("rename repository directory: %w", err)
|
||||||
}
|
}
|
||||||
repoRenamed = true
|
repoRenamed = true
|
||||||
|
|
||||||
// Rename remote wiki repository to new path and delete local copy.
|
// Rename remote wiki repository to new path and delete local copy.
|
||||||
wikiStorageRepo := repo_model.StorageRepo(repo_model.RelativeWikiPath(oldOwner.Name, repo.Name))
|
wikiStorageRepo := repo_model.StorageRepo(repo_model.RelativeWikiPath(oldOwner.Name, repo.Name, repo.GroupID))
|
||||||
if isExist, err := gitrepo.IsRepositoryExist(ctx, wikiStorageRepo); err != nil {
|
if isExist, err := gitrepo.IsRepositoryExist(ctx, wikiStorageRepo); err != nil {
|
||||||
log.Error("Unable to check if %s exists. Error: %v", wikiStorageRepo.RelativePath(), err)
|
log.Error("Unable to check if %s exists. Error: %v", wikiStorageRepo.RelativePath(), err)
|
||||||
return err
|
return err
|
||||||
} else if isExist {
|
} else if isExist {
|
||||||
if err := gitrepo.RenameRepository(ctx, wikiStorageRepo, repo_model.StorageRepo(repo_model.RelativeWikiPath(newOwner.Name, repo.Name))); err != nil {
|
if err := gitrepo.RenameRepository(ctx, wikiStorageRepo, repo_model.StorageRepo(repo_model.RelativeWikiPath(newOwner.Name, repo.Name, repo.GroupID))); err != nil {
|
||||||
return fmt.Errorf("rename repository wiki: %w", err)
|
return fmt.Errorf("rename repository wiki: %w", err)
|
||||||
}
|
}
|
||||||
wikiRenamed = true
|
wikiRenamed = true
|
||||||
@ -365,7 +365,7 @@ func changeRepositoryName(ctx context.Context, repo *repo_model.Repository, newR
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
has, err := isRepositoryModelOrDirExist(ctx, repo.Owner, newRepoName)
|
has, err := isRepositoryModelOrDirExist(ctx, repo.Owner, newRepoName, repo.GroupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("IsRepositoryExist: %w", err)
|
return fmt.Errorf("IsRepositoryExist: %w", err)
|
||||||
} else if has {
|
} else if has {
|
||||||
@ -376,13 +376,13 @@ func changeRepositoryName(ctx context.Context, repo *repo_model.Repository, newR
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err = gitrepo.RenameRepository(ctx, repo,
|
if err = gitrepo.RenameRepository(ctx, repo,
|
||||||
repo_model.StorageRepo(repo_model.RelativePath(repo.OwnerName, newRepoName))); err != nil {
|
repo_model.StorageRepo(repo_model.RelativePath(repo.OwnerName, newRepoName, 0))); err != nil {
|
||||||
return fmt.Errorf("rename repository directory: %w", err)
|
return fmt.Errorf("rename repository directory: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if HasWiki(ctx, repo) {
|
if HasWiki(ctx, repo) {
|
||||||
if err = gitrepo.RenameRepository(ctx, repo.WikiStorageRepo(), repo_model.StorageRepo(
|
if err = gitrepo.RenameRepository(ctx, repo.WikiStorageRepo(), repo_model.StorageRepo(
|
||||||
repo_model.RelativeWikiPath(repo.OwnerName, newRepoName))); err != nil {
|
repo_model.RelativeWikiPath(repo.OwnerName, newRepoName, repo.GroupID))); err != nil {
|
||||||
return fmt.Errorf("rename repository wiki: %w", err)
|
return fmt.Errorf("rename repository wiki: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user