Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework package structure #15

Merged
merged 7 commits into from
Oct 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
cmd/soft/soft
cmd/soft/.ssh
cmd/soft/.repos
soft
.ssh
.repos
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ The Soft Serve command is called `soft`. You can build and install it with

```bash
git clone ssh://beta.charm.sh/soft-serve
cd soft-serve/cmd/soft
cd soft-serve
go install
```

Expand Down
17 changes: 0 additions & 17 deletions cmd/soft/main.go

This file was deleted.

34 changes: 34 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package config

import (
"log"

"github.com/charmbracelet/soft/stats"
"github.com/meowgorithm/babyenv"
)

// Config is the configuration for the soft-serve.
type Config struct {
Host string `env:"SOFT_SERVE_HOST" default:""`
Port int `env:"SOFT_SERVE_PORT" default:"23231"`
KeyPath string `env:"SOFT_SERVE_KEY_PATH" default:".ssh/soft_serve_server_ed25519"`
RepoPath string `env:"SOFT_SERVE_REPO_PATH" default:".repos"`
InitialAdminKey string `env:"SOFT_SERVE_INITIAL_ADMIN_KEY" default:""`
Stats stats.Stats
}

// DefaultConfig returns a Config with the values populated with the defaults
// or specified environment variables.
func DefaultConfig() *Config {
var scfg Config
err := babyenv.Parse(&scfg)
if err != nil {
log.Fatalln(err)
}
return scfg.WithStats(stats.NewStats())
}

func (cfg *Config) WithStats(s stats.Stats) *Config {
cfg.Stats = s
return cfg
}
29 changes: 15 additions & 14 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
"os"
"path/filepath"

"github.com/charmbracelet/soft/config"
"github.com/charmbracelet/soft/internal/git"
"github.com/charmbracelet/soft/stats"
gg "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/object"
)
Expand All @@ -24,7 +24,7 @@ type Config struct {
Users []User `yaml:"users"`
Repos []Repo `yaml:"repos"`
Source *git.RepoSource
Stats stats.Stats
Cfg *config.Config
}

type User struct {
Expand All @@ -41,19 +41,20 @@ type Repo struct {
Private bool `yaml:"private"`
}

func (cfg *Config) WithStats(s stats.Stats) *Config {
cfg.Stats = s
return cfg
}

func NewConfig(host string, port int, pk string, rs *git.RepoSource) (*Config, error) {
func NewConfig(cfg *config.Config) (*Config, error) {
var anonAccess string
var yamlUsers string
var displayHost string
cfg := &Config{}
cfg.Host = host
cfg.Port = port
cfg.Source = rs
host := cfg.Host
port := cfg.Port
pk := cfg.InitialAdminKey
rs := git.NewRepoSource(cfg.RepoPath)
c := &Config{
Cfg: cfg,
}
c.Host = cfg.Host
c.Port = port
c.Source = rs
if pk == "" {
anonAccess = "read-write"
} else {
Expand All @@ -75,11 +76,11 @@ func NewConfig(host string, port int, pk string, rs *git.RepoSource) (*Config, e
yamlUsers = defaultUserConfig
}
yaml := fmt.Sprintf("%s%s%s", yamlConfig, yamlUsers, exampleUserConfig)
err := cfg.createDefaultConfigRepo(yaml)
err := c.createDefaultConfigRepo(yaml)
if err != nil {
return nil, err
}
return cfg, nil
return c, nil
}

func (cfg *Config) reload() error {
Expand Down
10 changes: 2 additions & 8 deletions internal/config/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,15 @@ import (
)

func (cfg *Config) Push(repo string, pk ssh.PublicKey) {
log.Printf("git push: %s", repo)
err := cfg.reload()
if err != nil {
log.Printf("error reloading after push: %s", err)
}
if cfg.Stats != nil {
cfg.Stats.Push()
}
cfg.Cfg.Stats.Push(repo)
}

func (cfg *Config) Fetch(repo string, pk ssh.PublicKey) {
log.Printf("git fetch: %s", repo)
if cfg.Stats != nil {
cfg.Stats.Fetch()
}
cfg.Cfg.Stats.Fetch(repo)
}

func (cfg *Config) AuthRepo(repo string, pk ssh.PublicKey) gm.AccessLevel {
Expand Down
2 changes: 1 addition & 1 deletion internal/tui/bubbles/commits/bubble.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package commits

import (
"soft-serve/server/git"
"strings"

"github.com/charmbracelet/bubbles/viewport"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/soft/internal/git"
"github.com/dustin/go-humanize"
)

Expand Down
4 changes: 1 addition & 3 deletions internal/tui/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@ func SessionHandler(cfg *config.Config) func(ssh.Session) (tea.Model, []tea.Prog
}
scfg.Width = pty.Window.Width
scfg.Height = pty.Window.Height
if cfg.Stats != nil {
cfg.Stats.Tui()
}
cfg.Cfg.Stats.Tui("view")
return NewBubble(cfg, scfg), []tea.ProgramOption{tea.WithAltScreen()}
}
}
18 changes: 18 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package main

import (
"log"

"github.com/charmbracelet/soft/config"
"github.com/charmbracelet/soft/server"
)

func main() {
cfg := config.DefaultConfig()
s := server.NewServer(cfg)
log.Printf("Starting SSH server on %s:%d\n", cfg.Host, cfg.Port)
err := s.Start()
if err != nil {
log.Fatalln(err)
}
}
73 changes: 0 additions & 73 deletions server.go

This file was deleted.

56 changes: 56 additions & 0 deletions server/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package server

import (
"fmt"
"log"

"github.com/charmbracelet/soft/config"
appCfg "github.com/charmbracelet/soft/internal/config"
"github.com/charmbracelet/soft/internal/tui"

"github.com/charmbracelet/wish"
bm "github.com/charmbracelet/wish/bubbletea"
gm "github.com/charmbracelet/wish/git"
lm "github.com/charmbracelet/wish/logging"
"github.com/gliderlabs/ssh"
)

type Server struct {
SSHServer *ssh.Server
Config *config.Config
}

// NewServer returns a new *ssh.Server configured to serve Soft Serve. The SSH
// server key-pair will be created if none exists. An initial admin SSH public
// key can be provided with authKey. If authKey is provided, access will be
// restricted to that key. If authKey is not provided, the server will be
// publicly writable until configured otherwise by cloning the `config` repo.
func NewServer(cfg *config.Config) *Server {
ac, err := appCfg.NewConfig(cfg)
if err != nil {
log.Fatal(err)
}
mw := []wish.Middleware{
bm.Middleware(tui.SessionHandler(ac)),
gm.Middleware(cfg.RepoPath, ac),
lm.Middleware(),
}
s, err := wish.NewServer(
ssh.PublicKeyAuth(ac.PublicKeyHandler),
ssh.PasswordAuth(ac.PasswordHandler),
wish.WithAddress(fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)),
wish.WithHostKeyPath(cfg.KeyPath),
wish.WithMiddleware(mw...),
)
if err != nil {
log.Fatalln(err)
}
return &Server{
SSHServer: s,
Config: cfg,
}
}

func (srv *Server) Start() error {
return srv.SSHServer.ListenAndServe()
}
26 changes: 23 additions & 3 deletions stats/stats.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
package stats

import "log"

// Stats provides an interface that can be used to collect metrics about the server.
type Stats interface {
Tui()
Push()
Fetch()
Tui(action string)
Push(repo string)
Fetch(repo string)
}

type stats struct{}

func (s *stats) Tui(action string) {
log.Printf("TUI: %s", action)
}

func (s *stats) Push(repo string) {
log.Printf("git push: %s", repo)
}

func (s *stats) Fetch(repo string) {
log.Printf("git fetch: %s", repo)
}

func NewStats() Stats {
return &stats{}
}