forgejo/services/f3/driver/project.go
Earl Warren e99d3f7055
feat(F3): CLI: f3 mirror to convert to/from Forgejo
feat(F3): driver stub

feat(F3): util.Logger

feat(F3): driver compliance tests

feat(F3): driver/users implementation

feat(F3): driver/user implementation

feat(F3): driver/{projects,project} implementation

feat(F3): driver/{labels,label} implementation

feat(F3): driver/{milestones,milestone} implementation

feat(F3): driver/{repositories,repository} implementation

feat(F3): driver/{organizations,organization} implementation

feat(F3): driver/{releases,release} implementation

feat(F3): driver/{issues,issue} implementation

feat(F3): driver/{comments,comment} implementation

feat(F3): driver/{assets,asset} implementation

feat(F3): driver/{pullrequests,pullrequest} implementation

feat(F3): driver/{reviews,review} implementation

feat(F3): driver/{topics,topic} implementation

feat(F3): driver/{reactions,reaction} implementation

feat(F3): driver/{reviewComments,reviewComment} implementation

feat(F3): CLI: f3 mirror

chore(F3): move to code.forgejo.org

feat(f3): upgrade to gof3 3.1.0

repositories in pull requests are represented with a reference instead
of an owner/project pair of names
2024-06-14 12:52:12 +02:00

189 lines
5.1 KiB
Go

// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package driver
import (
"context"
"fmt"
"strings"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
repo_service "code.gitea.io/gitea/services/repository"
"code.forgejo.org/f3/gof3/v3/f3"
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
"code.forgejo.org/f3/gof3/v3/tree/generic"
f3_util "code.forgejo.org/f3/gof3/v3/util"
)
var _ f3_tree.ForgeDriverInterface = &project{}
type project struct {
common
forgejoProject *repo_model.Repository
forked *f3.Reference
}
func (o *project) SetNative(project any) {
o.forgejoProject = project.(*repo_model.Repository)
}
func (o *project) GetNativeID() string {
return fmt.Sprintf("%d", o.forgejoProject.ID)
}
func (o *project) NewFormat() f3.Interface {
node := o.GetNode()
return node.GetTree().(f3_tree.TreeInterface).NewFormat(node.GetKind())
}
func (o *project) setForkedReference(ctx context.Context) {
if !o.forgejoProject.IsFork {
return
}
if err := o.forgejoProject.GetBaseRepo(ctx); err != nil {
panic(fmt.Errorf("GetBaseRepo %v %w", o.forgejoProject, err))
}
forkParent := o.forgejoProject.BaseRepo
if err := forkParent.LoadOwner(ctx); err != nil {
panic(fmt.Errorf("LoadOwner %v %w", forkParent, err))
}
owners := "users"
if forkParent.Owner.IsOrganization() {
owners = "organizations"
}
o.forked = f3_tree.NewProjectReference(owners, fmt.Sprintf("%d", forkParent.Owner.ID), fmt.Sprintf("%d", forkParent.ID))
}
func (o *project) ToFormat() f3.Interface {
if o.forgejoProject == nil {
return o.NewFormat()
}
return &f3.Project{
Common: f3.NewCommon(fmt.Sprintf("%d", o.forgejoProject.ID)),
Name: o.forgejoProject.Name,
IsPrivate: o.forgejoProject.IsPrivate,
IsMirror: o.forgejoProject.IsMirror,
Description: o.forgejoProject.Description,
DefaultBranch: o.forgejoProject.DefaultBranch,
Forked: o.forked,
}
}
func (o *project) FromFormat(content f3.Interface) {
project := content.(*f3.Project)
o.forgejoProject = &repo_model.Repository{
ID: f3_util.ParseInt(project.GetID()),
Name: project.Name,
IsPrivate: project.IsPrivate,
IsMirror: project.IsMirror,
Description: project.Description,
DefaultBranch: project.DefaultBranch,
}
if project.Forked != nil {
o.forgejoProject.IsFork = true
o.forgejoProject.ForkID = project.Forked.GetIDAsInt()
}
o.forked = project.Forked
}
func (o *project) Get(ctx context.Context) bool {
node := o.GetNode()
o.Trace("%s", node.GetID())
id := f3_util.ParseInt(string(node.GetID()))
u, err := repo_model.GetRepositoryByID(ctx, id)
if repo_model.IsErrRepoNotExist(err) {
return false
}
if err != nil {
panic(fmt.Errorf("project %v %w", id, err))
}
o.forgejoProject = u
o.setForkedReference(ctx)
return true
}
func (o *project) Patch(ctx context.Context) {
o.Trace("%d", o.forgejoProject.ID)
o.forgejoProject.LowerName = strings.ToLower(o.forgejoProject.Name)
if err := repo_model.UpdateRepositoryCols(ctx, o.forgejoProject,
"description",
"name",
"lower_name",
); err != nil {
panic(fmt.Errorf("UpdateRepositoryCols: %v %v", o.forgejoProject, err))
}
}
func (o *project) Put(ctx context.Context) generic.NodeID {
node := o.GetNode()
o.Trace("%s", node.GetID())
ownerID := f3_tree.GetOwnerID(o.GetNode())
owner, err := user_model.GetUserByID(ctx, ownerID)
if err != nil {
panic(fmt.Errorf("GetUserByID %v %w", ownerID, err))
}
doer, err := user_model.GetAdminUser(ctx)
if err != nil {
panic(fmt.Errorf("GetAdminUser %w", err))
}
if o.forked == nil {
repo, err := repo_service.CreateRepositoryDirectly(ctx, doer, owner, repo_service.CreateRepoOptions{
Name: o.forgejoProject.Name,
Description: o.forgejoProject.Description,
IsPrivate: o.forgejoProject.IsPrivate,
DefaultBranch: o.forgejoProject.DefaultBranch,
})
if err != nil {
panic(err)
}
o.forgejoProject = repo
o.Trace("project created %d", o.forgejoProject.ID)
} else {
if err = o.forgejoProject.GetBaseRepo(ctx); err != nil {
panic(fmt.Errorf("GetBaseRepo %v %w", o.forgejoProject, err))
}
if err = o.forgejoProject.BaseRepo.LoadOwner(ctx); err != nil {
panic(fmt.Errorf("LoadOwner %v %w", o.forgejoProject.BaseRepo, err))
}
repo, err := repo_service.ForkRepository(ctx, doer, owner, repo_service.ForkRepoOptions{
BaseRepo: o.forgejoProject.BaseRepo,
Name: o.forgejoProject.Name,
Description: o.forgejoProject.Description,
})
if err != nil {
panic(err)
}
o.forgejoProject = repo
o.Trace("project created %d", o.forgejoProject.ID)
}
return generic.NodeID(fmt.Sprintf("%d", o.forgejoProject.ID))
}
func (o *project) Delete(ctx context.Context) {
node := o.GetNode()
o.Trace("%s", node.GetID())
doer, err := user_model.GetAdminUser(ctx)
if err != nil {
panic(fmt.Errorf("GetAdminUser %w", err))
}
if err := repo_service.DeleteRepository(ctx, doer, o.forgejoProject, true); err != nil {
panic(err)
}
}
func newProject() generic.NodeDriverInterface {
return &project{}
}