1// Copyright 2016 The Gogs Authors. All rights reserved.
2// Copyright 2016 The Gitea Authors. All rights reserved.
3// SPDX-License-Identifier: MIT
4
5package cmd
6
7import (
8 "context"
9 "fmt"
10
11 "forgejo.org/models/db"
12 repo_model "forgejo.org/models/repo"
13 "forgejo.org/modules/git"
14 "forgejo.org/modules/gitrepo"
15 "forgejo.org/modules/log"
16 repo_module "forgejo.org/modules/repository"
17
18 "github.com/urfave/cli/v2"
19)
20
21var (
22 // CmdAdmin represents the available admin sub-command.
23 CmdAdmin = &cli.Command{
24 Name: "admin",
25 Usage: "Perform common administrative operations",
26 Subcommands: []*cli.Command{
27 subcmdUser,
28 subcmdRepoSyncReleases,
29 subcmdRegenerate,
30 subcmdAuth,
31 subcmdSendMail,
32 },
33 }
34
35 subcmdRepoSyncReleases = &cli.Command{
36 Name: "repo-sync-releases",
37 Usage: "Synchronize repository releases with tags",
38 Action: runRepoSyncReleases,
39 }
40
41 subcmdRegenerate = &cli.Command{
42 Name: "regenerate",
43 Usage: "Regenerate specific files",
44 Subcommands: []*cli.Command{
45 microcmdRegenHooks,
46 microcmdRegenKeys,
47 },
48 }
49
50 subcmdAuth = &cli.Command{
51 Name: "auth",
52 Usage: "Modify external auth providers",
53 Subcommands: []*cli.Command{
54 microcmdAuthAddOauth,
55 microcmdAuthUpdateOauth,
56 microcmdAuthAddLdapBindDn,
57 microcmdAuthUpdateLdapBindDn,
58 microcmdAuthAddLdapSimpleAuth,
59 microcmdAuthUpdateLdapSimpleAuth,
60 microcmdAuthAddSMTP,
61 microcmdAuthUpdateSMTP,
62 microcmdAuthList,
63 microcmdAuthDelete,
64 },
65 }
66
67 subcmdSendMail = &cli.Command{
68 Name: "sendmail",
69 Usage: "Send a message to all users",
70 Action: runSendMail,
71 Flags: []cli.Flag{
72 &cli.StringFlag{
73 Name: "title",
74 Usage: `a title of a message`,
75 Value: "",
76 },
77 &cli.StringFlag{
78 Name: "content",
79 Usage: "a content of a message",
80 Value: "",
81 },
82 &cli.BoolFlag{
83 Name: "force",
84 Aliases: []string{"f"},
85 Usage: "A flag to bypass a confirmation step",
86 },
87 },
88 }
89
90 idFlag = &cli.Int64Flag{
91 Name: "id",
92 Usage: "ID of authentication source",
93 }
94)
95
96func runRepoSyncReleases(_ *cli.Context) error {
97 ctx, cancel := installSignals()
98 defer cancel()
99
100 if err := initDB(ctx); err != nil {
101 return err
102 }
103
104 if err := git.InitSimple(ctx); err != nil {
105 return err
106 }
107
108 log.Trace("Synchronizing repository releases (this may take a while)")
109 for page := 1; ; page++ {
110 repos, count, err := repo_model.SearchRepositoryByName(ctx, &repo_model.SearchRepoOptions{
111 ListOptions: db.ListOptions{
112 PageSize: repo_model.RepositoryListDefaultPageSize,
113 Page: page,
114 },
115 Private: true,
116 })
117 if err != nil {
118 return fmt.Errorf("SearchRepositoryByName: %w", err)
119 }
120 if len(repos) == 0 {
121 break
122 }
123 log.Trace("Processing next %d repos of %d", len(repos), count)
124 for _, repo := range repos {
125 log.Trace("Synchronizing repo %s with path %s", repo.FullName(), repo.RepoPath())
126 gitRepo, err := gitrepo.OpenRepository(ctx, repo)
127 if err != nil {
128 log.Warn("OpenRepository: %v", err)
129 continue
130 }
131
132 oldnum, err := getReleaseCount(ctx, repo.ID)
133 if err != nil {
134 log.Warn(" GetReleaseCountByRepoID: %v", err)
135 }
136 log.Trace(" currentNumReleases is %d, running SyncReleasesWithTags", oldnum)
137
138 if err = repo_module.SyncReleasesWithTags(ctx, repo, gitRepo); err != nil {
139 log.Warn(" SyncReleasesWithTags: %v", err)
140 gitRepo.Close()
141 continue
142 }
143
144 count, err = getReleaseCount(ctx, repo.ID)
145 if err != nil {
146 log.Warn(" GetReleaseCountByRepoID: %v", err)
147 gitRepo.Close()
148 continue
149 }
150
151 log.Trace(" repo %s releases synchronized to tags: from %d to %d",
152 repo.FullName(), oldnum, count)
153 gitRepo.Close()
154 }
155 }
156
157 return nil
158}
159
160func getReleaseCount(ctx context.Context, id int64) (int64, error) {
161 return db.Count[repo_model.Release](
162 ctx,
163 repo_model.FindReleasesOptions{
164 RepoID: id,
165 IncludeTags: true,
166 },
167 )
168}