// Copyright Earl Warren // Copyright Loïc Dachary // SPDX-License-Identifier: MIT package f3 import ( "context" "fmt" "slices" "code.forgejo.org/f3/gof3/v3/f3" "code.forgejo.org/f3/gof3/v3/id" "code.forgejo.org/f3/gof3/v3/kind" "code.forgejo.org/f3/gof3/v3/path" "code.forgejo.org/f3/gof3/v3/tree/generic" "code.forgejo.org/f3/gof3/v3/util" ) type ForgeDriverInterface interface { SetNative(native any) GetNativeID() string GetHelper() any } func ConvertToAny[T any](s ...T) []any { a := make([]any, 0, len(s)) for _, e := range s { a = append(a, e) } return a } func ConvertNativeChild(ctx context.Context, tree generic.TreeInterface, parent generic.NodeInterface, kind kind.Kind, nativeChild any) generic.NodeInterface { child := tree.Factory(ctx, kind) child.SetParent(parent) childDriver := child.GetDriver().(ForgeDriverInterface) childDriver.SetNative(nativeChild) child.SetID(id.NewNodeID(childDriver.GetNativeID())) return child } func ConvertListed(ctx context.Context, node generic.NodeInterface, nativeChildren ...any) generic.ChildrenSlice { children := generic.NewChildrenSlice(len(nativeChildren)) tree := node.GetTree() f3Tree := tree.(TreeInterface) kind := f3Tree.GetChildrenKind(node.GetKind()) for _, nativeChild := range nativeChildren { children = append(children, ConvertNativeChild(ctx, tree, node, kind, nativeChild)) } return children } func GetFirstNodeKind(node generic.NodeInterface, kind ...kind.Kind) generic.NodeInterface { if slices.Contains(kind, node.GetKind()) { return node } parent := node.GetParent() if parent == generic.NilNode { return generic.NilNode } return GetFirstNodeKind(parent, kind...) } func GetFirstFormat[T f3.Interface](node generic.NodeInterface) T { f := node.NewFormat() switch f.(type) { case T: return node.ToFormat().(T) } parent := node.GetParent() if parent == generic.NilNode { panic(fmt.Errorf("no parent of the desired type")) } return GetFirstFormat[T](parent) } func GetProject(node generic.NodeInterface) generic.NodeInterface { return GetFirstNodeKind(node, KindProject) } func GetProjectID(node generic.NodeInterface) int64 { return util.ParseInt(GetProject(node).GetID().String()) } func GetProjectName(node generic.NodeInterface) string { return GetProject(node).ToFormat().(*f3.Project).Name } func GetOwner(node generic.NodeInterface) generic.NodeInterface { return GetFirstNodeKind(node, KindUser, KindOrganization) } func GetOwnerID(node generic.NodeInterface) int64 { return GetOwner(node).GetID().Int64() } func GetReactionable(node generic.NodeInterface) generic.NodeInterface { return GetFirstNodeKind(node, KindComment, KindIssue, KindPullRequest) } func GetReactionableID(node generic.NodeInterface) int64 { return GetReactionable(node).GetID().Int64() } func GetCommentable(node generic.NodeInterface) generic.NodeInterface { return GetFirstNodeKind(node, KindIssue, KindPullRequest) } func GetCommentableID(node generic.NodeInterface) int64 { return GetCommentable(node).GetID().Int64() } func GetComment(node generic.NodeInterface) generic.NodeInterface { return GetFirstNodeKind(node, KindComment, KindReviewComment) } func GetCommentID(node generic.NodeInterface) int64 { return GetComment(node).GetID().Int64() } func GetRelease(node generic.NodeInterface) generic.NodeInterface { return GetFirstNodeKind(node, KindRelease) } func GetReleaseID(node generic.NodeInterface) int64 { return GetRelease(node).GetID().Int64() } func GetPullRequest(node generic.NodeInterface) generic.NodeInterface { return GetFirstNodeKind(node, KindPullRequest) } func GetPullRequestID(node generic.NodeInterface) int64 { return GetPullRequest(node).GetID().Int64() } func GetReview(node generic.NodeInterface) generic.NodeInterface { return GetFirstNodeKind(node, KindReview) } func GetReviewID(node generic.NodeInterface) int64 { return GetReview(node).GetID().Int64() } func GetReviewComment(node generic.NodeInterface) generic.NodeInterface { return GetFirstNodeKind(node, KindReviewComment) } func GetReviewCommentID(node generic.NodeInterface) int64 { return GetReviewComment(node).GetID().Int64() } func GetOwnerName(node generic.NodeInterface) string { owner := GetOwner(node) if owner == generic.NilNode { panic(fmt.Errorf("no user or organization parent for %s", node)) } switch f := owner.ToFormat().(type) { case *f3.User: return f.UserName case *f3.Organization: return f.Name default: panic(fmt.Errorf("unexpected type %T", owner.ToFormat())) } } func GetUsernameFromID(ctx context.Context, tree TreeInterface, id int64) string { var name string getName := func(ctx context.Context, parent, p path.Path, node generic.NodeInterface) { name = node.ToFormat().(*f3.User).UserName } p := NewUserPath(id) if !tree.ApplyAndGet(ctx, p, generic.NewApplyOptions(getName)) { panic(fmt.Errorf("%s not found", p)) } return name }