// SPDX-License-Identifier: MIT package cmd import ( "context" "fmt" auth_model "code.gitea.io/gitea/models/auth" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/services/f3/util" "github.com/urfave/cli" "lab.forgefriends.org/friendlyforgeformat/gof3" f3_common "lab.forgefriends.org/friendlyforgeformat/gof3/forges/common" f3_format "lab.forgefriends.org/friendlyforgeformat/gof3/format" ) var CmdF3 = cli.Command{ Name: "f3", Usage: "Friendly Forge Format (F3) format export/import.", Description: "Import or export a repository from or to the Friendly Forge Format (F3) format.", Action: runF3, Flags: []cli.Flag{ cli.StringFlag{ Name: "directory", Value: "./f3", Usage: "Path of the directory where the F3 dump is stored", }, cli.StringFlag{ Name: "user", Value: "", Usage: "The name of the user who owns the repository", }, cli.StringFlag{ Name: "repository", Value: "", Usage: "The name of the repository", }, cli.StringFlag{ Name: "authentication-source", Value: "", Usage: "The name of the authentication source matching the forge of origin", }, cli.BoolFlag{ Name: "no-pull-request", Usage: "Do not dump pull requests", }, cli.BoolFlag{ Name: "import", Usage: "Import from the directory", }, cli.BoolFlag{ Name: "export", Usage: "Export to the directory", }, }, } func runF3(ctx *cli.Context) error { stdCtx, cancel := installSignals() defer cancel() if err := initDB(stdCtx); err != nil { return err } if err := git.InitSimple(stdCtx); err != nil { return err } return RunF3(stdCtx, ctx) } func getAuthenticationSource(ctx context.Context, authenticationSource string) (*auth_model.Source, error) { source, err := auth_model.GetSourceByName(ctx, authenticationSource) if err != nil { if auth_model.IsErrSourceNotExist(err) { return nil, nil } return nil, err } return source, nil } func RunF3(stdCtx context.Context, ctx *cli.Context) error { doer, err := user_model.GetAdminUser(stdCtx) if err != nil { return err } features := gof3.AllFeatures if ctx.Bool("no-pull-request") { features.PullRequests = false } var sourceID int64 sourceName := ctx.String("authentication-source") source, err := getAuthenticationSource(stdCtx, sourceName) if err != nil { return fmt.Errorf("error retrieving the authentication-source %s %v", sourceName, err) } if source != nil { sourceID = source.ID } forgejo := util.ForgejoForgeRoot(features, doer, sourceID) f3 := util.F3ForgeRoot(features, ctx.String("directory")) if ctx.Bool("export") { forgejo.Forge.Users.List(stdCtx) user := forgejo.Forge.Users.GetFromFormat(stdCtx, &f3_format.User{UserName: ctx.String("user")}) if user.IsNil() { return fmt.Errorf("%s is not a known user", ctx.String("user")) } user.Projects.List(stdCtx) project := user.Projects.GetFromFormat(stdCtx, &f3_format.Project{Name: ctx.String("repository")}) if project.IsNil() { return fmt.Errorf("%s/%s is not a known repository", ctx.String("user"), ctx.String("repository")) } options := f3_common.NewMirrorOptionsRecurse(user, project) f3.Forge.Mirror(stdCtx, forgejo.Forge, options) fmt.Println("exported") } else if ctx.Bool("import") { options := f3_common.NewMirrorOptionsRecurse() forgejo.Forge.Mirror(stdCtx, f3.Forge, options) fmt.Println("imported") } else { return fmt.Errorf("either --import or --export must be specified") } return nil }