diff --git a/go.mod b/go.mod index a68dfe1..43c7dbc 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,9 @@ require ( github.com/gorilla/context v1.1.1 // indirect github.com/gorilla/mux v1.6.2 // indirect github.com/gorilla/securecookie v1.1.1 // indirect + github.com/hashicorp/go-immutable-radix v1.3.0 // indirect + github.com/hashicorp/go-memdb v1.3.4 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/labstack/gommon v0.4.0 // indirect diff --git a/go.sum b/go.sum index 75daec6..72f129a 100644 --- a/go.sum +++ b/go.sum @@ -128,8 +128,15 @@ github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+ github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/hashicorp/go-immutable-radix v1.3.0 h1:8exGP7ego3OmkfksihtSouGMZ+hQrhxx+FVELeXpVPE= +github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-memdb v1.3.4 h1:XSL3NR682X/cVk2IeV0d70N4DZ9ljI885xAEU8IoK3c= +github.com/hashicorp/go-memdb v1.3.4/go.mod h1:uBTr1oQbtuMgd1SSGoR8YV27eT3sBHbYiNm53bMpgSg= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= diff --git a/internal/db/gist.go b/internal/db/gist.go index 9aad3da..4ac2787 100644 --- a/internal/db/gist.go +++ b/internal/db/gist.go @@ -1,6 +1,7 @@ package db import ( + "github.com/labstack/echo/v4" "github.com/thomiceli/opengist/internal/git" "gorm.io/gorm" "os/exec" @@ -190,6 +191,11 @@ func (gist *Gist) Update() error { } func (gist *Gist) Delete() error { + err := gist.DeleteRepository() + if err != nil { + return err + } + return db.Delete(&gist).Error } @@ -260,6 +266,10 @@ func (gist *Gist) InitRepository() error { return git.InitRepository(gist.User.Username, gist.Uuid) } +func (gist *Gist) InitRepositoryViaNewPush(ctx echo.Context) error { + return git.InitRepositoryViaNewPush(gist.User.Username, gist.Uuid, ctx) +} + func (gist *Gist) DeleteRepository() error { return git.DeleteRepository(gist.User.Username, gist.Uuid) } diff --git a/internal/git/commands.go b/internal/git/commands.go index 57c9989..f3306bd 100644 --- a/internal/git/commands.go +++ b/internal/git/commands.go @@ -1,7 +1,9 @@ package git import ( + "bytes" "fmt" + "github.com/labstack/echo/v4" "github.com/rs/zerolog/log" "github.com/thomiceli/opengist/internal/config" "os" @@ -16,6 +18,23 @@ func RepositoryPath(user string, gist string) string { return filepath.Join(config.GetHomeDir(), "repos", strings.ToLower(user), gist) } +func RepositoryUrl(ctx echo.Context, user string, gist string) string { + httpProtocol := "http" + if ctx.Request().TLS != nil || ctx.Request().Header.Get("X-Forwarded-Proto") == "https" { + httpProtocol = "https" + } + + var baseHttpUrl string + // if a custom external url is set, use it + if config.C.ExternalUrl != "" { + baseHttpUrl = config.C.ExternalUrl + } else { + baseHttpUrl = httpProtocol + "://" + ctx.Request().Host + } + + return fmt.Sprintf("%s/%s/%s", baseHttpUrl, user, gist) +} + func TmpRepositoryPath(gistId string) string { dirname := TmpRepositoriesPath() return filepath.Join(dirname, gistId) @@ -40,7 +59,17 @@ func InitRepository(user string, gist string) error { return err } - return copyFiles(repositoryPath) + return createDotGitFiles(repositoryPath) +} + +func InitRepositoryViaNewPush(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 GetNumberOfCommitsOfRepository(user string, gist string) (string, error) { @@ -186,7 +215,7 @@ func ForkClone(userSrc string, gistSrc string, userDst string, gistDst string) e return err } - return copyFiles(repositoryPathDst) + return createDotGitFiles(repositoryPathDst) } func SetFileContent(gistTmpId string, filename string, content string) error { @@ -305,6 +334,26 @@ func GcRepos() error { return err } +func HasNoCommits(user string, gist string) (bool, error) { + repositoryPath := RepositoryPath(user, gist) + + cmd := exec.Command("git", "rev-parse", "--all") + cmd.Dir = repositoryPath + + var out bytes.Buffer + cmd.Stdout = &out + + if err := cmd.Run(); err != nil { + return false, err + } + + if out.String() == "" { + return true, nil // No commits exist + } + + return false, nil // Commits exist +} + func GetGitVersion() (string, error) { cmd := exec.Command("git", "--version") stdout, err := cmd.Output() @@ -320,19 +369,27 @@ func GetGitVersion() (string, error) { return versionFields[2], nil } -func copyFiles(repositoryPath string) error { +func createDotGitFiles(repositoryPath string) error { f1, err := os.OpenFile(filepath.Join(repositoryPath, "git-daemon-export-ok"), os.O_RDONLY|os.O_CREATE, 0644) if err != nil { return err } defer f1.Close() - preReceiveDst, err := os.OpenFile(filepath.Join(repositoryPath, "hooks", "pre-receive"), os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0744) + if err = createDotGitHookFile(repositoryPath, "pre-receive", preReceive); err != nil { + return err + } + + return nil +} + +func createDotGitHookFile(repositoryPath string, hook string, content string) error { + preReceiveDst, err := os.OpenFile(filepath.Join(repositoryPath, "hooks", hook), os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0744) if err != nil { return err } - if _, err = preReceiveDst.WriteString(preReceive); err != nil { + if _, err = preReceiveDst.WriteString(content); err != nil { return err } defer preReceiveDst.Close() @@ -346,6 +403,14 @@ 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 @@ -354,15 +419,29 @@ do ;; esac done <