cmd/gitbayd/adminabout.go

v1.32.0
gitbay/cmd/gitbayd/adminabout.go history · blame · raw

98 lines · 3008 bytes

 1package main
 2
 3import (
 4	"fmt"
 5
 6	"github.com/spf13/cobra"
 7
 8	"gitbay.org/gitbay/internal/config"
 9	"gitbay.org/gitbay/internal/control"
10	"gitbay.org/gitbay/internal/gitutil"
11	"gitbay.org/gitbay/internal/store"
12)
13
14// adminMigrateProfileAboutCmd drains profile_about_backfill: each owner's
15// parked about text becomes profile/README.* in <owner>/.gitbay. Idempotent
16// — an owner who already has the file keeps it and loses the row.
17func adminMigrateProfileAboutCmd() *cobra.Command {
18	return &cobra.Command{
19		Use:   "migrate-profile-about",
20		Short: "write parked profile about text into each owner's .gitbay repository",
21		RunE: func(cmd *cobra.Command, args []string) error {
22			cfg, err := config.Load(configPath)
23			if err != nil {
24				return err
25			}
26			st, err := openStore(cfg)
27			if err != nil {
28				return err
29			}
30			defer st.Close()
31			rows, err := st.PendingAboutBackfill()
32			if err != nil {
33				return err
34			}
35			n := 0
36			for _, row := range rows {
37				written, err := writeAbout(cfg, st, row)
38				if err != nil {
39					return fmt.Errorf("%s: %w", row.OwnerName, err)
40				}
41				if err := st.ClearAboutBackfill(row.OwnerKind, row.OwnerID); err != nil {
42					return err
43				}
44				if written {
45					n++
46				}
47			}
48			fmt.Printf("wrote %d profile about file(s)\n", n)
49			return nil
50		},
51	}
52}
53
54// writeAbout creates <owner>/.gitbay if it does not exist and commits the
55// about at the recorded format. It reports whether it wrote anything: an
56// owner who already has the file is left alone.
57func writeAbout(cfg config.Config, st *store.Store, row store.AboutRow) (bool, error) {
58	path := row.OwnerName + "/" + control.ProfileRepoName
59	repo, err := st.RepoByPath(path)
60	if err != nil {
61		// Public, because the about it carries was public where it was.
62		id, cerr := st.CreateRepo(row.OwnerKind, row.OwnerID, control.ProfileRepoName, "public")
63		if cerr != nil {
64			return false, cerr
65		}
66		dir := control.RepoDir(cfg.Server.Root, row.OwnerName, control.ProfileRepoName)
67		if ierr := gitutil.InitBare(dir, "main", control.HooksDir(cfg.Server.Root)); ierr != nil {
68			st.DeleteRepo(id)
69			return false, ierr
70		}
71		if repo, err = st.RepoByPath(path); err != nil {
72			return false, err
73		}
74	}
75	dir := control.RepoDir(cfg.Server.Root, repo.OwnerName, repo.Name)
76	ext := ".md"
77	if row.Format == "org" {
78		ext = ".org"
79	}
80	file := control.AboutBase + ext
81	if _, err := gitutil.ReadBlob(dir, repo.DefaultBranch, file, 1); err == nil {
82		return false, nil // already there
83	}
84	// A commit carries an identity. An owner without a verified address,
85	// and every org, gets the noreply form rather than no commit.
86	email := row.OwnerName + "@users.noreply." + cfg.SiteHost()
87	if row.OwnerKind == "user" {
88		if addr, _ := st.PrimaryVerifiedEmail(row.OwnerID); addr != "" {
89			email = addr
90		}
91	}
92	if _, err := gitutil.CommitFileChange(dir, repo.DefaultBranch, file,
93		[]byte(row.About), row.OwnerName, email,
94		"move profile about out of the database"); err != nil {
95		return false, err
96	}
97	return true, nil
98}