// SPDX-FileCopyrightText: 2025 Romain Maneschi // // SPDX-License-Identifier: EUPL-1.2 package main import ( "context" "flag" "fmt" "os" "path/filepath" "github.com/go-git/go-git/v6/plumbing" "github.com/goccy/go-yaml" "gitroot.dev/server/background" "gitroot.dev/server/configuration" "gitroot.dev/server/exec" "gitroot.dev/server/logger" "gitroot.dev/server/plugin" "gitroot.dev/server/repository" "gitroot.dev/server/user" ) var version string = "next" // set at build time var commit string // set at build time func main() { log := logger.NewLoggerCtx("root", context.Background()) var rootPath string flag.StringVar(&rootPath, "data", "./data", "path to store data") var rootRemote string flag.StringVar(&rootRemote, "remote", "", "optional repository for root repo, only used at init") var showVersion bool flag.BoolVar(&showVersion, "version", false, "show current version and build time") var initConfig string flag.StringVar(&initConfig, "initConfig", "", "generate a config file to configure GitRoot before the first start") var config string flag.StringVar(&config, "config", "", "use a config file to configure GitRoot before the first start") flag.Parse() conf := configuration.NewConfiguration(rootPath) if config != "" { configContent, err := os.ReadFile(config) if err != nil { log.Error("can't read conf", err, logger.NewLoggerPair("path", config)) os.Exit(1) return } conf.LoadFromFile(configContent) } if showVersion || initConfig != "" { if showVersion { if commit == "" { commit = plumbing.ZeroHash.String() } log.Warn(fmt.Sprintf("Version `%s` for commit `%s`", version, commit)) } if initConfig != "" { confMarshalled, err := yaml.Marshal(conf) if err != nil { log.Error("can't marshal conf", err) os.Exit(1) return } if err := os.WriteFile(initConfig, confMarshalled, 0666); err != nil { log.Error("can't write initConfif file", err, logger.NewLoggerPair("path", initConfig)) os.Exit(1) return } log.Warn(fmt.Sprintf("File %s created, please edit it and launch gitroot with --config=%s to use it", initConfig, initConfig)) } return } needUpdateConf, err := conf.LoadFromOrStoreToRootConf(filepath.Join(rootPath, "gitroot.yml"), version) if err != nil { log.Error("Initialisation of root conf failed", err) os.Exit(1) } userManager, err := user.NewManager(conf) if err != nil { log.Error("Initialisation failed", err) os.Exit(1) } var backgroundManager *background.Manager repoManager := repository.NewManager(conf, userManager) if !repoManager.Exists(conf.ForgeConfigName()) { go func() { if err := repoManager.CreateRootRepoIfNeeded(context.Background(), rootRemote); err != nil { log.Error("Error in CreateRootRepoIfNeeded", err) } }() } else { rootRepo, err := repoManager.OpenForgeRepo(context.Background()) if err != nil { log.Error("Can't open root repo", err) return } c, err := rootRepo.Content(conf.PathFileForgeConfig()) if err != nil { log.Error("Can't read root conf", err) return } if err := conf.LoadFromFile(c); err != nil { log.Error("Can't unmarshal root conf", err) return } if needUpdateConf { log.Debug("will write conf", logger.NewLoggerPair("branch", conf.DefaultBranch)) rootRepoWrite, err := rootRepo.WillWrite(plumbing.NewBranchReferenceName(conf.DefaultBranch)) if err != nil { log.Error("can't open root repository in write mode", err) } confMarshalled, err := conf.Marshall() if err != nil { log.Error("can't marshal conf", err) } err = rootRepoWrite.Write(conf.PathFileForgeConfig(), confMarshalled) if err != nil { log.Error("can't write conf", err) } if _, err := rootRepoWrite.CommitAll("Conf updated", userManager.RootCommiter()); err != nil { log.Error("can't commit new conf", err) } log.Warn("update conf done", logger.NewLoggerPair("branch", conf.DefaultBranch)) } rootRepo.Close() } execManager := exec.NewManager(context.Background(), conf, userManager) pluginManager := plugin.NewManager(conf, repoManager, userManager, execManager) backgroundManager = background.NewManager(context.Background(), conf, repoManager, userManager, pluginManager) pluginManager.SetBackgroundManager(backgroundManager) go func() { if err := NewServerHttp(conf, repoManager).ListenAndServe(); err != nil { log.Error("Http closed", err) } }() if err := NewServerSsh(conf, repoManager, userManager, pluginManager, backgroundManager).ListenAndServe(); err != nil { log.Error("Ssh closed", err) } }