Skip to content

Commit

Permalink
Move Git hook logic to Opengist (thomiceli#213)
Browse files Browse the repository at this point in the history
  • Loading branch information
thomiceli committed Apr 2, 2024
1 parent dfe70dc commit 7a75c5e
Show file tree
Hide file tree
Showing 16 changed files with 407 additions and 193 deletions.
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ require (
github.com/markbates/goth v1.78.0
github.com/rs/zerolog v1.31.0
github.com/stretchr/testify v1.8.4
github.com/urfave/cli/v2 v2.27.1
github.com/yuin/goldmark v1.6.0
github.com/yuin/goldmark-emoji v1.0.2
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
Expand Down Expand Up @@ -45,6 +46,7 @@ require (
github.com/blevesearch/zapx/v13 v13.3.10 // indirect
github.com/blevesearch/zapx/v14 v14.3.10 // indirect
github.com/blevesearch/zapx/v15 v15.3.13 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dlclark/regexp2 v1.10.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
Expand Down Expand Up @@ -72,8 +74,10 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
go.etcd.io/bbolt v1.3.8 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/oauth2 v0.15.0 // indirect
Expand Down
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -291,6 +293,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A=
github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
Expand All @@ -304,10 +308,14 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho=
github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
Expand Down
12 changes: 6 additions & 6 deletions internal/actions/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ type ActionStatus struct {
}

const (
SyncReposFromFS = iota
SyncReposFromDB = iota
GitGcRepos = iota
SyncGistPreviews = iota
ResetHooks = iota
IndexGists = iota
SyncReposFromFS = iota
SyncReposFromDB
GitGcRepos
SyncGistPreviews
ResetHooks
IndexGists
)

var (
Expand Down
38 changes: 38 additions & 0 deletions internal/cli/hook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package cli

import (
"github.com/thomiceli/opengist/internal/hooks"
"github.com/urfave/cli/v2"
"os"
)

var CmdHook = cli.Command{
Name: "hook",
Usage: "Run Git server hooks, used and should only be called by Opengist itself",
Subcommands: []*cli.Command{
&CmdHookPreReceive,
&CmdHookPostReceive,
},
}

var CmdHookPreReceive = cli.Command{
Name: "pre-receive",
Usage: "Run Git server pre-receive hook for a repository",
Action: func(ctx *cli.Context) error {
if err := hooks.PreReceive(os.Stdin, os.Stdout, os.Stderr); err != nil {
os.Exit(1)
}
return nil
},
}

var CmdHookPostReceive = cli.Command{
Name: "post-receive",
Usage: "Run Git server post-receive hook for a repository",
Action: func(ctx *cli.Context) error {
if err := hooks.PostReceive(os.Stdin, os.Stdout, os.Stderr); err != nil {
os.Exit(1)
}
return nil
},
}
131 changes: 131 additions & 0 deletions internal/cli/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package cli

import (
"fmt"
"github.com/rs/zerolog/log"
"github.com/thomiceli/opengist/internal/config"
"github.com/thomiceli/opengist/internal/db"
"github.com/thomiceli/opengist/internal/git"
"github.com/thomiceli/opengist/internal/index"
"github.com/thomiceli/opengist/internal/memdb"
"github.com/thomiceli/opengist/internal/ssh"
"github.com/thomiceli/opengist/internal/web"
"github.com/urfave/cli/v2"
"os"
"path"
"path/filepath"
)

var CmdVersion = cli.Command{
Name: "version",
Usage: "Print the version of Opengist",
Action: func(c *cli.Context) error {
fmt.Println("Opengist v" + config.OpengistVersion)
return nil
},
}

var CmdStart = cli.Command{
Name: "start",
Usage: "Start Opengist server",
Action: func(ctx *cli.Context) error {
Initialize(ctx)
go web.NewServer(os.Getenv("OG_DEV") == "1").Start()
go ssh.Start()
select {}
},
}

var ConfigFlag = cli.StringFlag{
Name: "config",
Aliases: []string{"c"},
Usage: "Path to a config file in YAML format",
}

func App() error {
app := cli.NewApp()
app.Name = "Opengist"
app.Usage = "A self-hosted pastebin powered by Git."
app.HelpName = "opengist"

app.Commands = []*cli.Command{&CmdVersion, &CmdStart, &CmdHook}
app.DefaultCommand = CmdStart.Name
app.Flags = []cli.Flag{
&ConfigFlag,
}
return app.Run(os.Args)
}

func Initialize(ctx *cli.Context) {
fmt.Println("Opengist v" + config.OpengistVersion)

if err := config.InitConfig(ctx.String("config")); err != nil {
panic(err)
}
if err := os.MkdirAll(filepath.Join(config.GetHomeDir()), 0755); err != nil {
panic(err)
}

config.InitLog()

gitVersion, err := git.GetGitVersion()
if err != nil {
log.Fatal().Err(err).Send()
}

if ok, err := config.CheckGitVersion(gitVersion); err != nil {
log.Fatal().Err(err).Send()
} else if !ok {
log.Warn().Msg("Git version may be too old, as Opengist has not been tested prior git version 2.28 and some features would not work. " +
"Current git version: " + gitVersion)
}

homePath := config.GetHomeDir()
log.Info().Msg("Data directory: " + homePath)

if err := createSymlink(); err != nil {
log.Fatal().Err(err).Send()
}

if err := os.MkdirAll(filepath.Join(homePath, "repos"), 0755); err != nil {
log.Fatal().Err(err).Send()
}
if err := os.MkdirAll(filepath.Join(homePath, "tmp", "repos"), 0755); err != nil {
log.Fatal().Err(err).Send()
}
if err := os.MkdirAll(filepath.Join(homePath, "custom"), 0755); err != nil {
log.Fatal().Err(err).Send()
}
log.Info().Msg("Database file: " + filepath.Join(homePath, config.C.DBFilename))
if err := db.Setup(filepath.Join(homePath, config.C.DBFilename), false); err != nil {
log.Fatal().Err(err).Msg("Failed to initialize database")
}

if err := memdb.Setup(); err != nil {
log.Fatal().Err(err).Msg("Failed to initialize in memory database")
}

if config.C.IndexEnabled {
log.Info().Msg("Index directory: " + filepath.Join(homePath, config.C.IndexDirname))
if err := index.Open(filepath.Join(homePath, config.C.IndexDirname)); err != nil {
log.Fatal().Err(err).Msg("Failed to open index")
}
}
}

func createSymlink() error {
exePath, err := os.Executable()
if err != nil {
return err
}

symlinkPath := path.Join(config.GetHomeDir(), "opengist-bin")

if _, err := os.Lstat(symlinkPath); err == nil {
if err := os.Remove(symlinkPath); err != nil {
return err
}
}

return os.Symlink(exePath, symlinkPath)
}
4 changes: 4 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ func InitConfig(configPath string) error {

C = c

if err = os.Setenv("OG_OPENGIST_HOME_INTERNAL", GetHomeDir()); err != nil {
return err
}

return nil
}

Expand Down
5 changes: 0 additions & 5 deletions internal/db/gist.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"github.com/alecthomas/chroma/v2"
"github.com/alecthomas/chroma/v2/lexers"
"github.com/dustin/go-humanize"
"github.com/labstack/echo/v4"
"github.com/rs/zerolog/log"
"github.com/thomiceli/opengist/internal/index"
"os/exec"
Expand Down Expand Up @@ -330,10 +329,6 @@ func (gist *Gist) InitRepository() error {
return git.InitRepository(gist.User.Username, gist.Uuid)
}

func (gist *Gist) InitRepositoryViaInit(ctx echo.Context) error {
return git.InitRepositoryViaInit(gist.User.Username, gist.Uuid, ctx)
}

func (gist *Gist) DeleteRepository() error {
return git.DeleteRepository(gist.User.Username, gist.Uuid)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/db/sshkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type SSHKey struct {
User User `validate:"-" `
}

func (sshKey *SSHKey) BeforeCreate(tx *gorm.DB) error {
func (sshKey *SSHKey) BeforeCreate(*gorm.DB) error {
pubKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(sshKey.Content))
if err != nil {
return err
Expand Down
75 changes: 9 additions & 66 deletions internal/git/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ var (
)

const truncateLimit = 2 << 18
const BaseHash = "0000000000000000000000000000000000000000"

type RevisionNotFoundError struct{}

Expand Down Expand Up @@ -80,16 +81,6 @@ func InitRepository(user string, gist string) error {
return CreateDotGitFiles(user, gist)
}

func InitRepositoryViaInit(user string, gist string, ctx echo.Context) error {
repositoryPath := RepositoryPath(user, gist)

if err := InitRepository(user, gist); err != nil {
return err
}
repositoryUrl := RepositoryUrl(ctx, user, gist)
return createDotGitHookFile(repositoryPath, "post-receive", fmt.Sprintf(postReceive, repositoryUrl, repositoryUrl))
}

func CountCommits(user string, gist string) (string, error) {
repositoryPath := RepositoryPath(user, gist)

Expand Down Expand Up @@ -424,7 +415,6 @@ func Push(gistTmpId string) error {
if err != nil {
return err
}

return os.RemoveAll(tmpRepositoryPath)
}

Expand Down Expand Up @@ -534,8 +524,12 @@ func CreateDotGitFiles(user string, gist string) error {
}
defer f1.Close()

if err = createDotGitHookFile(repositoryPath, "pre-receive", preReceive); err != nil {
return err
if os.Getenv("OPENGIST_SKIP_GIT_HOOKS") != "1" {
for _, hook := range []string{"pre-receive", "post-receive"} {
if err = createDotGitHookFile(repositoryPath, hook, fmt.Sprintf(hookTemplate, hook)); err != nil {
return err
}
}
}

return nil
Expand Down Expand Up @@ -570,57 +564,6 @@ func removeFilesExceptGit(dir string) error {
})
}

const preReceive = `#!/bin/sh
disallowed_files=""
while read -r old_rev new_rev ref
do
if [ "$old_rev" = "0000000000000000000000000000000000000000" ]; then
# This is the first commit, so we check all the files in that commit
changed_files=$(git ls-tree -r --name-only "$new_rev")
else
# This is not the first commit, so we compare it with its predecessor
changed_files=$(git diff --name-only "$old_rev" "$new_rev")
fi
while IFS= read -r file
do
case $file in
*/*)
disallowed_files="${disallowed_files}${file} "
;;
esac
done <<EOF
$changed_files
EOF
done
if [ -n "$disallowed_files" ]; then
echo ""
echo "Pushing files in folders is not allowed:"
for file in $disallowed_files; do
echo " $file"
done
echo ""
exit 1
fi
`

const postReceive = `#!/bin/sh
while read oldrev newrev refname; do
if ! git rev-parse --verify --quiet HEAD &>/dev/null; then
git symbolic-ref HEAD "$refname"
fi
done
echo ""
echo "Your new repository has been created here: %s"
echo ""
echo "If you want to keep working with your gist, you could set the remote URL via:"
echo "git remote set-url origin %s"
echo ""
rm -f $0
const hookTemplate = `#!/bin/sh
"$OG_OPENGIST_HOME_INTERNAL/opengist-bin" hook %s
`
Loading

0 comments on commit 7a75c5e

Please sign in to comment.