opengist/internal/git/commands.go

277 lines
5.9 KiB
Go
Raw Normal View History

2023-03-14 15:22:52 +00:00
package git
import (
"io"
"opengist/internal/config"
"os"
"os/exec"
"path"
"path/filepath"
"strings"
)
2023-03-14 22:26:39 +00:00
func RepositoryPath(user string, gist string) string {
return filepath.Join(config.GetHomeDir(), "repos", strings.ToLower(user), gist)
2023-03-14 15:22:52 +00:00
}
2023-03-14 22:26:39 +00:00
func TmpRepositoryPath(gistId string) string {
dirname := TmpRepositoriesPath()
return filepath.Join(dirname, gistId)
2023-03-14 15:22:52 +00:00
}
2023-03-14 22:26:39 +00:00
func TmpRepositoriesPath() string {
return filepath.Join(config.GetHomeDir(), "tmp", "repos")
2023-03-14 15:22:52 +00:00
}
func InitRepository(user string, gist string) error {
2023-03-14 22:26:39 +00:00
repositoryPath := RepositoryPath(user, gist)
2023-03-14 15:22:52 +00:00
cmd := exec.Command(
"git",
"init",
"--bare",
repositoryPath,
)
2023-03-14 22:26:39 +00:00
_, err := cmd.Output()
2023-03-14 15:22:52 +00:00
if err != nil {
return err
}
f1, err := os.OpenFile(filepath.Join(repositoryPath, "git-daemon-export-ok"), os.O_RDONLY|os.O_CREATE, 0644)
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 != nil {
return err
}
preReceiveSrc, err := os.OpenFile(filepath.Join("internal", "resources", "pre-receive"), os.O_RDONLY, os.ModeAppend)
if err != nil {
return err
}
_, err = io.Copy(preReceiveDst, preReceiveSrc)
if err != nil {
return err
}
defer preReceiveDst.Close()
defer preReceiveSrc.Close()
return err
}
func GetNumberOfCommitsOfRepository(user string, gist string) (string, error) {
2023-03-14 22:26:39 +00:00
repositoryPath := RepositoryPath(user, gist)
2023-03-14 15:22:52 +00:00
cmd := exec.Command(
"git",
"rev-list",
"--all",
"--count",
)
cmd.Dir = repositoryPath
stdout, err := cmd.Output()
return strings.TrimSuffix(string(stdout), "\n"), err
}
func GetFilesOfRepository(user string, gist string, revision string) ([]string, error) {
2023-03-14 22:26:39 +00:00
repositoryPath := RepositoryPath(user, gist)
2023-03-14 15:22:52 +00:00
cmd := exec.Command(
"git",
"ls-tree",
revision,
2023-03-14 15:22:52 +00:00
"--name-only",
)
cmd.Dir = repositoryPath
stdout, err := cmd.Output()
if err != nil {
return nil, err
}
slice := strings.Split(string(stdout), "\n")
return slice[:len(slice)-1], nil
}
func GetFileContent(user string, gist string, revision string, filename string, truncate bool) (string, bool, error) {
2023-03-14 22:26:39 +00:00
repositoryPath := RepositoryPath(user, gist)
2023-03-14 15:22:52 +00:00
var maxBytes int64 = -1
if truncate {
maxBytes = 2 << 18
}
2023-03-14 15:22:52 +00:00
cmd := exec.Command(
"git",
"--no-pager",
"show",
revision+":"+filename,
2023-03-14 15:22:52 +00:00
)
cmd.Dir = repositoryPath
stdout, _ := cmd.StdoutPipe()
err := cmd.Start()
if err != nil {
return "", false, err
}
return truncateCommandOutput(stdout, maxBytes)
2023-03-14 15:22:52 +00:00
}
2023-03-18 22:18:20 +00:00
func GetLog(user string, gist string, skip string) ([]*Commit, error) {
2023-03-14 22:26:39 +00:00
repositoryPath := RepositoryPath(user, gist)
2023-03-14 15:22:52 +00:00
cmd := exec.Command(
"git",
"--no-pager",
"log",
"-n",
"11",
"--no-color",
"-p",
"--skip",
skip,
2023-03-18 22:18:20 +00:00
"--format=format:c %H%na %aN%nt %at",
2023-03-14 15:22:52 +00:00
"--shortstat",
"HEAD",
)
cmd.Dir = repositoryPath
2023-03-18 22:18:20 +00:00
stdout, _ := cmd.StdoutPipe()
err := cmd.Start()
if err != nil {
return nil, err
}
2023-03-14 15:22:52 +00:00
2023-03-18 22:18:20 +00:00
return parseLog(stdout), nil
2023-03-14 15:22:52 +00:00
}
func CloneTmp(user string, gist string, gistTmpId string) error {
2023-03-14 22:26:39 +00:00
repositoryPath := RepositoryPath(user, gist)
2023-03-14 15:22:52 +00:00
2023-03-14 22:26:39 +00:00
tmpPath := TmpRepositoriesPath()
2023-03-14 15:22:52 +00:00
tmpRepositoryPath := path.Join(tmpPath, gistTmpId)
2023-03-14 22:26:39 +00:00
err := os.RemoveAll(tmpRepositoryPath)
2023-03-14 15:22:52 +00:00
if err != nil {
return err
}
cmd := exec.Command("git", "clone", repositoryPath, gistTmpId)
cmd.Dir = tmpPath
if err = cmd.Run(); err != nil {
return err
}
cmd = exec.Command("git", "config", "user.name", user)
cmd.Dir = tmpRepositoryPath
if err = cmd.Run(); err != nil {
return err
}
// remove every file (and not the .git directory!)
cmd = exec.Command("find", ".", "-maxdepth", "1", "-type", "f", "-delete")
cmd.Dir = tmpRepositoryPath
return cmd.Run()
}
2023-03-14 22:26:39 +00:00
func ForkClone(userSrc string, gistSrc string, userDst string, gistDst string) error {
repositoryPathSrc := RepositoryPath(userSrc, gistSrc)
repositoryPathDst := RepositoryPath(userDst, gistDst)
cmd := exec.Command("git", "clone", "--bare", repositoryPathSrc, repositoryPathDst)
if err := cmd.Run(); err != nil {
2023-03-14 15:22:52 +00:00
return err
}
2023-03-14 22:26:39 +00:00
cmd = exec.Command("git", "config", "user.name", userDst)
cmd.Dir = repositoryPathDst
return cmd.Run()
}
func SetFileContent(gistTmpId string, filename string, content string) error {
repositoryPath := TmpRepositoryPath(gistTmpId)
2023-03-14 15:22:52 +00:00
return os.WriteFile(filepath.Join(repositoryPath, filename), []byte(content), 0644)
}
func AddAll(gistTmpId string) error {
2023-03-14 22:26:39 +00:00
tmpPath := TmpRepositoryPath(gistTmpId)
2023-03-14 15:22:52 +00:00
// in case of a change where only a file name has its case changed
cmd := exec.Command("git", "rm", "-r", "--cached", "--ignore-unmatch", ".")
cmd.Dir = tmpPath
2023-03-14 22:26:39 +00:00
err := cmd.Run()
2023-03-14 15:22:52 +00:00
if err != nil {
return err
}
cmd = exec.Command("git", "add", "-A")
cmd.Dir = tmpPath
return cmd.Run()
}
2023-03-18 22:18:20 +00:00
func CommitRepository(gistTmpId string) error {
2023-03-14 15:22:52 +00:00
cmd := exec.Command("git", "commit", "--allow-empty", "-m", `"Opengist commit"`)
2023-03-14 22:26:39 +00:00
tmpPath := TmpRepositoryPath(gistTmpId)
2023-03-14 15:22:52 +00:00
cmd.Dir = tmpPath
return cmd.Run()
}
func Push(gistTmpId string) error {
2023-03-14 22:26:39 +00:00
tmpRepositoryPath := TmpRepositoryPath(gistTmpId)
2023-03-14 15:22:52 +00:00
cmd := exec.Command(
"git",
"push",
)
cmd.Dir = tmpRepositoryPath
2023-03-14 22:26:39 +00:00
err := cmd.Run()
2023-03-14 15:22:52 +00:00
if err != nil {
return err
}
return os.RemoveAll(tmpRepositoryPath)
}
func DeleteRepository(user string, gist string) error {
return os.RemoveAll(RepositoryPath(user, gist))
2023-03-14 15:22:52 +00:00
}
func UpdateServerInfo(user string, gist string) error {
2023-03-14 22:26:39 +00:00
repositoryPath := RepositoryPath(user, gist)
2023-03-14 15:22:52 +00:00
cmd := exec.Command("git", "update-server-info")
cmd.Dir = repositoryPath
return cmd.Run()
}
func RPC(user string, gist string, service string) ([]byte, error) {
2023-03-14 22:26:39 +00:00
repositoryPath := RepositoryPath(user, gist)
2023-03-14 15:22:52 +00:00
cmd := exec.Command("git", service, "--stateless-rpc", "--advertise-refs", ".")
cmd.Dir = repositoryPath
stdout, err := cmd.Output()
return stdout, err
}
func GetGitVersion() (string, error) {
cmd := exec.Command("git", "--version")
stdout, err := cmd.Output()
if err != nil {
return "", err
}
versionFields := strings.Fields(string(stdout))
if len(versionFields) < 3 {
return string(stdout), nil
}
return versionFields[2], nil
}