02b44f8de7de217d1b51b46c1f4d2a874eed9481

Author
Ayman Bagabas <ayman.bagabas@gmail.com>
Committer
Ayman Bagabas <ayman.bagabas@gmail.com>
Date

Message

feat(backend,ui): add repo project name

Diff

  1diff --git a/server/backend/file/file.go b/server/backend/file/file.go
  2index 9f855db570573db36b0b313e8ce6addf49d877a6..dfb80526172c31df5976ab7838b0098261765e04 100644
  3--- a/server/backend/file/file.go
  4+++ b/server/backend/file/file.go
  5@@ -49,6 +49,7 @@ const (
  6 	description  = "description"
  7 	exportOk     = "git-daemon-export-ok"
  8 	private      = "private"
  9+	projectName  = "project-name"
 10 	settings     = "settings"
 11 )
 12 
 13@@ -573,6 +574,23 @@ func (fb *FileBackend) SetPrivate(repo string, priv bool) error {
 14 	return nil
 15 }
 16 
 17+// ProjectName returns the project name.
 18+//
 19+// It implements backend.Backend.
 20+func (fb *FileBackend) ProjectName(repo string) string {
 21+	repo = utils.SanitizeRepo(repo) + ".git"
 22+	r := &Repo{path: filepath.Join(fb.reposPath(), repo), root: fb.reposPath()}
 23+	return r.ProjectName()
 24+}
 25+
 26+// SetProjectName sets the project name of the given repo.
 27+//
 28+// It implements backend.Backend.
 29+func (fb *FileBackend) SetProjectName(repo string, name string) error {
 30+	repo = utils.SanitizeRepo(repo) + ".git"
 31+	return os.WriteFile(filepath.Join(fb.reposPath(), repo, projectName), []byte(name), 0600)
 32+}
 33+
 34 // CreateRepository creates a new repository.
 35 //
 36 // Created repositories are always bare.
 37@@ -607,6 +625,11 @@ func (fb *FileBackend) CreateRepository(repo string, private bool) (backend.Repo
 38 		return nil, err
 39 	}
 40 
 41+	if err := fb.SetProjectName(repo, name); err != nil {
 42+		logger.Debug("failed to set project name", "err", err)
 43+		return nil, err
 44+	}
 45+
 46 	r := &Repo{path: rp, root: fb.reposPath()}
 47 	// Add to cache.
 48 	fb.repos[name] = r
 49diff --git a/server/backend/file/repo.go b/server/backend/file/repo.go
 50index 6e760d4295ea089d1951192ca369c1484e70038c..3888201045f5a16b39f85a373b2adfec9a46a452 100644
 51--- a/server/backend/file/repo.go
 52+++ b/server/backend/file/repo.go
 53@@ -27,14 +27,22 @@ func (r *Repo) Name() string {
 54 	return strings.TrimPrefix(name, "/")
 55 }
 56 
 57+// ProjectName returns the repository's project name.
 58+func (r *Repo) ProjectName() string {
 59+	pn, err := readOneLine(filepath.Join(r.path, projectName))
 60+	if err != nil {
 61+		return ""
 62+	}
 63+
 64+	return strings.TrimSpace(pn)
 65+}
 66+
 67 // Description returns the repository's description.
 68 //
 69 // It implements backend.Repository.
 70 func (r *Repo) Description() string {
 71 	desc, err := readAll(filepath.Join(r.path, description))
 72 	if err != nil {
 73-		logger.Debug("failed to read description file", "err", err,
 74-			"path", filepath.Join(r.path, description))
 75 		return ""
 76 	}
 77 
 78diff --git a/server/backend/repo.go b/server/backend/repo.go
 79index 05d2de240656cca7749dcec0afb5bdd5d4bfd8e8..9fcad1c45516d21201e65021877635f82c6320b8 100644
 80--- a/server/backend/repo.go
 81+++ b/server/backend/repo.go
 82@@ -21,6 +21,10 @@ type RepositoryStore interface {
 83 
 84 // RepositoryMetadata is an interface for managing repository metadata.
 85 type RepositoryMetadata interface {
 86+	// ProjectName returns the repository's project name.
 87+	ProjectName(repo string) string
 88+	// SetProjectName sets the repository's project name.
 89+	SetProjectName(repo, name string) error
 90 	// Description returns the repository's description.
 91 	Description(repo string) string
 92 	// SetDescription sets the repository's description.
 93@@ -57,6 +61,8 @@ type RepositoryAccess interface {
 94 type Repository interface {
 95 	// Name returns the repository's name.
 96 	Name() string
 97+	// ProjectName returns the repository's project name.
 98+	ProjectName() string
 99 	// Description returns the repository's description.
100 	Description() string
101 	// IsPrivate returns whether the repository is private.
102diff --git a/server/cmd/cmd.go b/server/cmd/cmd.go
103index 461a9041f126e3526dfb0fed2f5f7bce7cc0d914..f6fcdb13164b478c9488d1f9b46a5104bacd43bf 100644
104--- a/server/cmd/cmd.go
105+++ b/server/cmd/cmd.go
106@@ -64,6 +64,7 @@ func rootCommand() *cobra.Command {
107 		hookCommand(),
108 		listCommand(),
109 		privateCommand(),
110+		projectName(),
111 		renameCommand(),
112 		settingCommand(),
113 		tagCommand(),
114diff --git a/server/cmd/project_name.go b/server/cmd/project_name.go
115new file mode 100644
116index 0000000000000000000000000000000000000000..68ca47c50bd0e06f61b67d4d2b64e330f7ce2e97
117--- /dev/null
118+++ b/server/cmd/project_name.go
119@@ -0,0 +1,40 @@
120+package cmd
121+
122+import (
123+	"strings"
124+
125+	"github.com/spf13/cobra"
126+)
127+
128+func projectName() *cobra.Command {
129+	cmd := &cobra.Command{
130+		Use:     "project-name REPOSITORY [NAME]",
131+		Aliases: []string{"project"},
132+		Short:   "Set or get the project name for a repository",
133+		Args:    cobra.MinimumNArgs(1),
134+		RunE: func(cmd *cobra.Command, args []string) error {
135+			cfg, _ := fromContext(cmd)
136+			rn := strings.TrimSuffix(args[0], ".git")
137+			switch len(args) {
138+			case 1:
139+				if err := checkIfReadable(cmd, args); err != nil {
140+					return err
141+				}
142+
143+				pn := cfg.Backend.ProjectName(rn)
144+				cmd.Println(pn)
145+			default:
146+				if err := checkIfCollab(cmd, args); err != nil {
147+					return err
148+				}
149+				if err := cfg.Backend.SetProjectName(rn, strings.Join(args[1:], " ")); err != nil {
150+					return err
151+				}
152+			}
153+
154+			return nil
155+		},
156+	}
157+
158+	return cmd
159+}
160diff --git a/ui/pages/repo/repo.go b/ui/pages/repo/repo.go
161index 75f3ac38ad302cc3af82ef9633141fe11479ffbb..ff94c890d955ada5b2fd679619d5c0764db72c0a 100644
162--- a/ui/pages/repo/repo.go
163+++ b/ui/pages/repo/repo.go
164@@ -327,7 +327,11 @@ func (r *Repo) headerView() string {
165 		return ""
166 	}
167 	truncate := lipgloss.NewStyle().MaxWidth(r.common.Width)
168-	name := r.common.Styles.Repo.HeaderName.Render(r.selectedRepo.Name())
169+	name := r.selectedRepo.ProjectName()
170+	if name == "" {
171+		name = r.selectedRepo.Name()
172+	}
173+	name = r.common.Styles.Repo.HeaderName.Render(name)
174 	desc := r.selectedRepo.Description()
175 	if desc == "" {
176 		desc = name
177diff --git a/ui/pages/selection/item.go b/ui/pages/selection/item.go
178index 83bf3e6c3cdb17f60d1580de113059ea1c15f078..79c5b634622e9f5d016eb7175d4f11639cf4323e 100644
179--- a/ui/pages/selection/item.go
180+++ b/ui/pages/selection/item.go
181@@ -79,7 +79,12 @@ func (i Item) ID() string {
182 
183 // Title returns the item title. Implements list.DefaultItem.
184 func (i Item) Title() string {
185-	return i.repo.Name()
186+	name := i.repo.ProjectName()
187+	if name == "" {
188+		name = i.repo.Name()
189+	}
190+
191+	return name
192 }
193 
194 // Description returns the item description. Implements list.DefaultItem.