Diff
1diff --git a/server/backend/repo.go b/server/backend/repo.go
2index 2f72164e9e27d50f5d1e063db30d06be4d3f62b0..ddc4c934b3aff06887f8fb2a1e1cbd2a3875fd95 100644
3--- a/server/backend/repo.go
4+++ b/server/backend/repo.go
5@@ -10,6 +10,7 @@ type RepositoryOptions struct {
6 Description string
7 ProjectName string
8 Mirror bool
9+ Hidden bool
10 }
11
12 // RepositoryStore is an interface for managing repositories.
13@@ -46,6 +47,10 @@ type RepositoryMetadata interface {
14 SetPrivate(repo string, private bool) error
15 // IsMirror returns whether the repository is a mirror.
16 IsMirror(repo string) bool
17+ // IsHidden returns whether the repository is hidden.
18+ IsHidden(repo string) bool
19+ // SetHidden sets whether the repository is hidden.
20+ SetHidden(repo string, hidden bool) error
21 }
22
23 // RepositoryAccess is an interface for managing repository access.
24@@ -71,6 +76,8 @@ type Repository interface {
25 IsPrivate() bool
26 // IsMirror returns whether the repository is a mirror.
27 IsMirror() bool
28+ // IsHidden returns whether the repository is hidden.
29+ IsHidden() bool
30 // Open returns the underlying git.Repository.
31 Open() (*git.Repository, error)
32 }
33diff --git a/server/backend/sqlite/repo.go b/server/backend/sqlite/repo.go
34index bdd4384e714d17d6b528147c342b9cda54fccf29..9259f8bea5b063085fd8ea76c30ca3364c41de74 100644
35--- a/server/backend/sqlite/repo.go
36+++ b/server/backend/sqlite/repo.go
37@@ -86,3 +86,17 @@ func (r *Repo) ProjectName() string {
38
39 return name
40 }
41+
42+// IsHidden returns whether the repository is hidden.
43+//
44+// It implements backend.Repository.
45+func (r *Repo) IsHidden() bool {
46+ var hidden bool
47+ if err := wrapTx(r.db, context.Background(), func(tx *sqlx.Tx) error {
48+ return tx.Get(&hidden, "SELECT hidden FROM repo WHERE name = ?", r.name)
49+ }); err != nil {
50+ return false
51+ }
52+
53+ return hidden
54+}
55diff --git a/server/backend/sqlite/sql.go b/server/backend/sqlite/sql.go
56index 8158cac5ae65dda25092946025cb282bb487fc37..719c0707711133ded792eb02d6c1f807311cbbcd 100644
57--- a/server/backend/sqlite/sql.go
58+++ b/server/backend/sqlite/sql.go
59@@ -37,6 +37,7 @@ var (
60 description TEXT NOT NULL,
61 private BOOLEAN NOT NULL,
62 mirror BOOLEAN NOT NULL,
63+ hidden BOOLEAN NOT NULL,
64 created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
65 updated_at DATETIME NOT NULL
66 );`
67diff --git a/server/backend/sqlite/sqlite.go b/server/backend/sqlite/sqlite.go
68index 158993db2e5dd37fd8859e6b6bd657fe8ff8b0bb..2dd6bd39d7d840c6849675daf3d49dceed8e3a05 100644
69--- a/server/backend/sqlite/sqlite.go
70+++ b/server/backend/sqlite/sqlite.go
71@@ -133,9 +133,9 @@ func (d *SqliteBackend) CreateRepository(name string, opts backend.RepositoryOpt
72 }
73
74 if err := wrapTx(d.db, context.Background(), func(tx *sqlx.Tx) error {
75- _, err := tx.Exec(`INSERT INTO repo (name, project_name, description, private, mirror, updated_at)
76+ _, err := tx.Exec(`INSERT INTO repo (name, project_name, description, private, mirror, hidden, updated_at)
77 VALUES (?, ?, ?, ?, ?, CURRENT_TIMESTAMP);`,
78- name, opts.ProjectName, opts.Description, opts.Private, opts.Mirror)
79+ name, opts.ProjectName, opts.Description, opts.Private, opts.Mirror, opts.Hidden)
80 return err
81 }); err != nil {
82 logger.Debug("failed to create repository in database", "err", err)
83@@ -324,6 +324,32 @@ func (d *SqliteBackend) IsPrivate(repo string) bool {
84 return private
85 }
86
87+// IsHidden returns true if the repository is hidden.
88+//
89+// It implements backend.Backend.
90+func (d *SqliteBackend) IsHidden(repo string) bool {
91+ repo = utils.SanitizeRepo(repo)
92+ var hidden bool
93+ if err := wrapTx(d.db, context.Background(), func(tx *sqlx.Tx) error {
94+ return tx.Get(&hidden, "SELECT hidden FROM repo WHERE name = ?", repo)
95+ }); err != nil {
96+ return false
97+ }
98+
99+ return hidden
100+}
101+
102+// SetHidden sets the hidden flag of a repository.
103+//
104+// It implements backend.Backend.
105+func (d *SqliteBackend) SetHidden(repo string, hidden bool) error {
106+ repo = utils.SanitizeRepo(repo)
107+ return wrapDbErr(wrapTx(d.db, context.Background(), func(tx *sqlx.Tx) error {
108+ _, err := tx.Exec("UPDATE repo SET hidden = ?, updated_at = CURRENT_TIMESTAMP WHERE name = ?;", hidden, repo)
109+ return err
110+ }))
111+}
112+
113 // ProjectName returns the project name of a repository.
114 //
115 // It implements backend.Backend.
116diff --git a/server/cmd/hidden.go b/server/cmd/hidden.go
117new file mode 100644
118index 0000000000000000000000000000000000000000..7146579b36262771b56bf618857b8478932c48c9
119--- /dev/null
120+++ b/server/cmd/hidden.go
121@@ -0,0 +1,37 @@
122+package cmd
123+
124+import "github.com/spf13/cobra"
125+
126+func hiddenCommand() *cobra.Command {
127+ cmd := &cobra.Command{
128+ Use: "hidden REPOSITORY [TRUE|FALSE]",
129+ Short: "Hide or unhide a repository",
130+ Args: cobra.MinimumNArgs(1),
131+ RunE: func(cmd *cobra.Command, args []string) error {
132+ cfg, _ := fromContext(cmd)
133+ repo := args[0]
134+ switch len(args) {
135+ case 1:
136+ if err := checkIfReadable(cmd, args); err != nil {
137+ return err
138+ }
139+
140+ hidden := cfg.Backend.IsHidden(repo)
141+ cmd.Println(hidden)
142+ case 2:
143+ if err := checkIfCollab(cmd, args); err != nil {
144+ return err
145+ }
146+
147+ hidden := args[1] == "true"
148+ if err := cfg.Backend.SetHidden(repo, hidden); err != nil {
149+ return err
150+ }
151+ }
152+
153+ return nil
154+ },
155+ }
156+
157+ return cmd
158+}
159diff --git a/server/cmd/repo.go b/server/cmd/repo.go
160index 577ab30304ed4092d0e1a035bda06c713fec42b4..a4c60d680e6444a1104d789b2d345442d4c74265 100644
161--- a/server/cmd/repo.go
162+++ b/server/cmd/repo.go
163@@ -16,6 +16,7 @@ func repoCommand() *cobra.Command {
164 createCommand(),
165 deleteCommand(),
166 descriptionCommand(),
167+ hiddenCommand(),
168 importCommand(),
169 listCommand(),
170 privateCommand(),
171diff --git a/ui/pages/selection/selection.go b/ui/pages/selection/selection.go
172index 97e47ff9708d67612a754dcc9a7735b03f5576a1..4e0056edad21c674e56baf4358a3edc5c177512a 100644
173--- a/ui/pages/selection/selection.go
174+++ b/ui/pages/selection/selection.go
175@@ -198,6 +198,9 @@ func (s *Selection) Init() tea.Cmd {
176 }
177 sortedItems := make(Items, 0)
178 for _, r := range repos {
179+ if r.IsHidden() {
180+ continue
181+ }
182 al := cfg.Backend.AccessLevelByPublicKey(r.Name(), pk)
183 if al >= backend.ReadOnlyAccess {
184 item, err := NewItem(r, cfg)