Skip to content

Commit

Permalink
fix: migrate readme & fix permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
aymanbagabas committed May 2, 2023
1 parent 58ac5a3 commit afc0b57
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 74 deletions.
122 changes: 104 additions & 18 deletions cmd/soft/migrate_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import (
"os"
"path/filepath"
"strings"
"time"

"github.com/charmbracelet/log"
"github.com/charmbracelet/soft-serve/git"
"github.com/charmbracelet/soft-serve/server/backend"
"github.com/charmbracelet/soft-serve/server/backend/sqlite"
"github.com/charmbracelet/soft-serve/server/config"
"github.com/charmbracelet/soft-serve/server/utils"
gitm "github.com/gogs/git-module"
"github.com/spf13/cobra"
"golang.org/x/crypto/ssh"
"gopkg.in/yaml.v3"
Expand All @@ -25,6 +27,9 @@ var (
Short: "Migrate config to new format",
Hidden: true,
RunE: func(cmd *cobra.Command, _ []string) error {
// Disable logging timestamp
log.SetReportTimestamp(false)

keyPath := os.Getenv("SOFT_SERVE_KEY_PATH")
reposPath := os.Getenv("SOFT_SERVE_REPO_PATH")
bindAddr := os.Getenv("SOFT_SERVE_BIND_ADDRESS")
Expand All @@ -46,7 +51,7 @@ var (
// Copy SSH host key
log.Info("Copying SSH host key...")
if keyPath != "" {
if err := os.MkdirAll(filepath.Join(cfg.DataPath, "ssh"), 0700); err != nil {
if err := os.MkdirAll(filepath.Join(cfg.DataPath, "ssh"), os.ModePerm); err != nil {
return fmt.Errorf("failed to create ssh directory: %w", err)
}

Expand Down Expand Up @@ -104,6 +109,9 @@ var (
}
}

readme, readmePath, err := git.LatestFile(r, "README*")
hasReadme := err == nil

// Set server name
cfg.Name = ocfg.Name

Expand All @@ -125,13 +133,17 @@ var (
// Copy repos
if reposPath != "" {
log.Info("Copying repos...")
if err := os.MkdirAll(filepath.Join(cfg.DataPath, "repos"), os.ModePerm); err != nil {
return fmt.Errorf("failed to create repos directory: %w", err)
}

dirs, err := os.ReadDir(reposPath)
if err != nil {
return fmt.Errorf("failed to read repos directory: %w", err)
}

for _, dir := range dirs {
if !dir.IsDir() {
if !dir.IsDir() || dir.Name() == "config" {
continue
}

Expand All @@ -140,12 +152,12 @@ var (
}

log.Infof(" Copying repo %s", dir.Name())
if err := os.MkdirAll(filepath.Join(cfg.DataPath, "repos"), 0700); err != nil {
return fmt.Errorf("failed to create repos directory: %w", err)
src := filepath.Join(reposPath, utils.SanitizeRepo(dir.Name()))
dst := filepath.Join(cfg.DataPath, "repos", utils.SanitizeRepo(dir.Name())) + ".git"
if err := os.MkdirAll(dst, os.ModePerm); err != nil {
return fmt.Errorf("failed to create repo directory: %w", err)
}

src := utils.SanitizeRepo(filepath.Join(reposPath, dir.Name()))
dst := utils.SanitizeRepo(filepath.Join(cfg.DataPath, "repos", dir.Name())) + ".git"
if err := copyDir(src, dst); err != nil {
return fmt.Errorf("failed to copy repo: %w", err)
}
Expand All @@ -154,26 +166,100 @@ var (
fmt.Fprintf(os.Stderr, "failed to create repository: %s\n", err)
}
}

if hasReadme {
log.Infof(" Copying readme from \"config\" to \".soft-serve\"")

// Switch to main branch
bcmd := git.NewCommand("branch", "-M", "main")

rp := filepath.Join(cfg.DataPath, "repos", ".soft-serve.git")
nr, err := git.Init(rp, true)
if err != nil {
return fmt.Errorf("failed to init repo: %w", err)
}

if _, err := nr.SymbolicRef("HEAD", gitm.RefsHeads+"main"); err != nil {
return fmt.Errorf("failed to set HEAD: %w", err)
}

tmpDir, err := os.MkdirTemp("", "soft-serve")
if err != nil {
return fmt.Errorf("failed to create temp dir: %w", err)
}

r, err := git.Init(tmpDir, false)
if err != nil {
return fmt.Errorf("failed to clone repo: %w", err)
}

if _, err := bcmd.RunInDir(tmpDir); err != nil {
return fmt.Errorf("failed to create main branch: %w", err)
}

if err := os.WriteFile(filepath.Join(tmpDir, readmePath), []byte(readme), 0o644); err != nil {
return fmt.Errorf("failed to write readme: %w", err)
}

if err := r.Add(gitm.AddOptions{
All: true,
}); err != nil {
return fmt.Errorf("failed to add readme: %w", err)
}

if err := r.Commit(&gitm.Signature{
Name: "Soft Serve",
Email: "vt100@charm.sh",
When: time.Now(),
}, "Add readme"); err != nil {
return fmt.Errorf("failed to commit readme: %w", err)
}

if err := r.RemoteAdd("origin", "file://"+rp); err != nil {
return fmt.Errorf("failed to add remote: %w", err)
}

if err := r.Push("origin", "main"); err != nil {
return fmt.Errorf("failed to push readme: %w", err)
}

// Create `.soft-serve` repository and add readme
if _, err := sb.CreateRepository(".soft-serve", backend.RepositoryOptions{
ProjectName: "Home",
Description: "Soft Serve home repository",
Hidden: true,
Private: false,
}); err != nil {
fmt.Fprintf(os.Stderr, "failed to create repository: %s\n", err)
}
}
}

// Set repos metadata & collabs
log.Info("Setting repos metadata & collabs...")
for _, repo := range ocfg.Repos {
if err := sb.SetProjectName(repo.Repo, repo.Name); err != nil {
log.Errorf("failed to set repo name to %s: %s", repo.Repo, err)
for _, r := range ocfg.Repos {
repo, name := r.Repo, r.Name
// Special case for config repo
if repo == "config" {
repo = ".soft-serve"
r.Private = false
}

if err := sb.SetProjectName(repo, name); err != nil {
log.Errorf("failed to set repo name to %s: %s", repo, err)
}

if err := sb.SetDescription(repo.Repo, repo.Note); err != nil {
log.Errorf("failed to set repo description to %s: %s", repo.Repo, err)
if err := sb.SetDescription(repo, r.Note); err != nil {
log.Errorf("failed to set repo description to %s: %s", repo, err)
}

if err := sb.SetPrivate(repo.Repo, repo.Private); err != nil {
log.Errorf("failed to set repo private to %s: %s", repo.Repo, err)
if err := sb.SetPrivate(repo, r.Private); err != nil {
log.Errorf("failed to set repo private to %s: %s", repo, err)
}

for _, collab := range repo.Collabs {
if err := sb.AddCollaborator(repo.Repo, collab); err != nil {
log.Errorf("failed to add repo collab to %s: %s", repo.Repo, err)
for _, collab := range r.Collabs {
if err := sb.AddCollaborator(repo, collab); err != nil {
log.Errorf("failed to add repo collab to %s: %s", repo, err)
}
}
}
Expand Down Expand Up @@ -291,11 +377,11 @@ func copyDir(src string, dst string) error {

if fd.IsDir() {
if err = copyDir(srcfp, dstfp); err != nil {
fmt.Println(err)
log.Error("failed to copy directory", "err", err)
}
} else {
if err = copyFile(srcfp, dstfp); err != nil {
fmt.Println(err)
log.Error("failed to copy file", "err", err)
}
}
}
Expand Down
51 changes: 51 additions & 0 deletions git/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package git

import (
"path/filepath"

"github.com/gobwas/glob"
)

// LatestFile returns the contents of the first file at the specified path pattern in the repository and its file path.
func LatestFile(repo *Repository, pattern string) (string, string, error) {
g := glob.MustCompile(pattern)
dir := filepath.Dir(pattern)
head, err := repo.HEAD()
if err != nil {
return "", "", err
}
t, err := repo.TreePath(head, dir)
if err != nil {
return "", "", err
}
ents, err := t.Entries()
if err != nil {
return "", "", err
}
for _, e := range ents {
te := e
fp := filepath.Join(dir, te.Name())
if te.IsTree() {
continue
}
if g.Match(fp) {
if te.IsSymlink() {
bts, err := te.Contents()
if err != nil {
return "", "", err
}
fp = string(bts)
te, err = t.TreeEntry(fp)
if err != nil {
return "", "", err
}
}
bts, err := te.Contents()
if err != nil {
return "", "", err
}
return string(bts), fp, nil
}
}
return "", "", ErrFileNotFound
}
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ require (
)

require (
github.com/aymanbagabas/go-osc52 v1.2.2
github.com/caarlos0/env/v7 v7.1.0
github.com/charmbracelet/keygen v0.4.2
github.com/charmbracelet/log v0.2.1
Expand Down
3 changes: 1 addition & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
github.com/aymanbagabas/go-osc52 v1.2.1 h1:q2sWUyDcozPLcLabEMd+a+7Ea2DitxZVN9hTxab9L4E=
github.com/aymanbagabas/go-osc52 v1.2.1/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
github.com/aymanbagabas/go-osc52 v1.2.2 h1:NT7wkhEhPTcKnBCdPi9djmyy9L3JOL4+3SsfJyqptCo=
github.com/aymanbagabas/go-osc52 v1.2.2/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
Expand Down
12 changes: 6 additions & 6 deletions server/backend/sqlite/sqlite.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (d *SqliteBackend) reposPath() string {
// NewSqliteBackend creates a new SqliteBackend.
func NewSqliteBackend(ctx context.Context, cfg *config.Config) (*SqliteBackend, error) {
dataPath := cfg.DataPath
if err := os.MkdirAll(dataPath, 0755); err != nil {
if err := os.MkdirAll(dataPath, os.ModePerm); err != nil {
return nil, err
}

Expand Down Expand Up @@ -254,7 +254,7 @@ func (d *SqliteBackend) RenameRepository(oldName string, newName string) error {
}

// Make sure the new repository parent directory exists.
if err := os.MkdirAll(filepath.Dir(np), 0755); err != nil {
if err := os.MkdirAll(filepath.Dir(np), os.ModePerm); err != nil {
return err
}

Expand Down Expand Up @@ -639,7 +639,7 @@ func (d *SqliteBackend) InitializeHooks(repo string) error {

repo = utils.SanitizeRepo(repo) + ".git"
hooksPath := filepath.Join(d.reposPath(), repo, "hooks")
if err := os.MkdirAll(hooksPath, 0755); err != nil {
if err := os.MkdirAll(hooksPath, os.ModePerm); err != nil {
return err
}

Expand All @@ -659,13 +659,13 @@ func (d *SqliteBackend) InitializeHooks(repo string) error {
var data bytes.Buffer
var args string
hp := filepath.Join(hooksPath, hook)
if err := os.WriteFile(hp, []byte(hookTpls[i]), 0755); err != nil {
if err := os.WriteFile(hp, []byte(hookTpls[i]), os.ModePerm); err != nil {
return err
}

// Create hook.d directory.
hp += ".d"
if err := os.MkdirAll(hp, 0755); err != nil {
if err := os.MkdirAll(hp, os.ModePerm); err != nil {
return err
}

Expand Down Expand Up @@ -694,7 +694,7 @@ func (d *SqliteBackend) InitializeHooks(repo string) error {
}

hp = filepath.Join(hp, "soft-serve")
err = os.WriteFile(hp, data.Bytes(), 0755) //nolint:gosec
err = os.WriteFile(hp, data.Bytes(), os.ModePerm) //nolint:gosec
if err != nil {
logger.Error("failed to write hook", "err", err)
continue
Expand Down
44 changes: 1 addition & 43 deletions server/backend/utils.go
Original file line number Diff line number Diff line change
@@ -1,59 +1,17 @@
package backend

import (
"path/filepath"

"github.com/charmbracelet/soft-serve/git"
"github.com/gobwas/glob"
)

// LatestFile returns the contents of the latest file at the specified path in
// the repository and its file path.
func LatestFile(r Repository, pattern string) (string, string, error) {
g := glob.MustCompile(pattern)
dir := filepath.Dir(pattern)
repo, err := r.Open()
if err != nil {
return "", "", err
}
head, err := repo.HEAD()
if err != nil {
return "", "", err
}
t, err := repo.TreePath(head, dir)
if err != nil {
return "", "", err
}
ents, err := t.Entries()
if err != nil {
return "", "", err
}
for _, e := range ents {
te := e
fp := filepath.Join(dir, te.Name())
if te.IsTree() {
continue
}
if g.Match(fp) {
if te.IsSymlink() {
bts, err := te.Contents()
if err != nil {
return "", "", err
}
fp = string(bts)
te, err = t.TreeEntry(fp)
if err != nil {
return "", "", err
}
}
bts, err := te.Contents()
if err != nil {
return "", "", err
}
return string(bts), fp, nil
}
}
return "", "", git.ErrFileNotFound
return git.LatestFile(repo, pattern)
}

// Readme returns the repository's README.
Expand Down

0 comments on commit afc0b57

Please sign in to comment.