summaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
authora73x <[email protected]>2024-08-25 13:21:16 +0100
committera73x <[email protected]>2024-08-25 13:50:50 +0100
commitd76ca9ec81086e486a50a4aa03126271a3e520de (patch)
treea2ea33f9263bf3c0e0f8c7e03ee26378bbc67a9f /main.go
parentcc284379187796719bbc6e8e19ff6e0b7e5b4e62 (diff)
now with a go bashscript
and hooks
Diffstat (limited to 'main.go')
-rw-r--r--main.go141
1 files changed, 141 insertions, 0 deletions
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..4902f8b
--- /dev/null
+++ b/main.go
@@ -0,0 +1,141 @@
+package main
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "syscall"
+)
+
+var logger *log.Logger
+var logf *os.File
+
+func main() {
+ var err error
+ logf, err = os.OpenFile("loggy.boi",
+ os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ defer logf.Close()
+
+ logger = log.New(logf, "", log.LstdFlags)
+ sshOriginalCommand := os.Getenv("SSH_ORIGINAL_COMMAND")
+ if sshOriginalCommand == "" {
+ log.Fatal("SSH_ORIGINAL_COMMAND is not set")
+ }
+
+ if err := Run(sshOriginalCommand); err != nil {
+ logger.Fatal(err)
+ }
+}
+
+type Mkdir func([]string) error
+
+func mkdir(path string) error {
+ return os.MkdirAll(path, 0755)
+}
+
+func Run(sshCmd string) error {
+ parts := strings.Split(sshCmd, " ")
+ if len(parts) != 2 {
+ return fmt.Errorf("expected 2 args: %s", sshCmd)
+ }
+
+ command := parts[0]
+ repo := parts[1]
+
+ remmappedRepo := RemapRepoPath(repo, "repos")
+ // creates repos if they don't exist
+ if _, err := os.Stat(remmappedRepo); os.IsNotExist(err) {
+ if err := setupRepo(remmappedRepo); err != nil {
+ return fmt.Errorf("failed to setup repo: %v", err)
+ }
+ }
+
+ bin, err := exec.LookPath(command)
+ if err != nil {
+ return fmt.Errorf("failed to lookup %s:%v", command, err)
+ }
+
+ // Execute the git-shell command
+ return syscall.Exec(bin, []string{command, remmappedRepo}, os.Environ())
+}
+
+func setupRepo(repo string) error {
+ // Create the directory (and any necessary parent directories)
+ if err := mkdir(repo); err != nil {
+ return fmt.Errorf("failed to create directory: %v", err)
+ }
+
+ cmd := exec.Command("git", "init", "--bare", "--initial-branch=main", repo)
+ cmd.Stdout = logf
+ cmd.Stderr = logf
+ if err := cmd.Run(); err != nil {
+ return fmt.Errorf("failed to run initialize git repository: %v", err)
+ }
+
+ if err := writeDescriptionHook(repo); err != nil {
+ logger.Printf("failed to create description hook: %v\n", err)
+ }
+
+ return nil
+}
+
+// 'a73x/cgit.git' => repos/a73x/cgit.git
+func RemapRepoPath(repo string, path string) string {
+ return filepath.Join(path, strings.Trim(repo, "'"))
+}
+
+var descriptionHook = `#!/bin/bash
+
+BRANCH="main"
+FILE=README
+while read oldrev newrev ref
+do
+ # only checking out the master (or whatever branch you would like to deploy)
+ if [ "$ref" = "refs/heads/$BRANCH" ];
+ then
+ changed=$(git ls-tree $REV $FILE)
+ if [ -n $changed ]; then
+ echo "Ref $ref received. updating description"
+ git show HEAD:README | head -n1 > description
+ fi
+ else
+ echo "Ref $ref received. Doing nothing: only the ${BRANCH} branch may be deployed on this server."
+ fi
+done`
+
+func writeDescriptionHook(path string) error {
+ hooksDir := filepath.Join(path, "hooks")
+ scriptPath := filepath.Join(hooksDir, "post-receive")
+ err := os.MkdirAll(hooksDir, 0755)
+ if err != nil {
+ return fmt.Errorf("error creating hooks directory: %v", err)
+ }
+
+ file, err := os.Create(scriptPath)
+ if err != nil {
+ return fmt.Errorf("error creating post-receive file: %v", err)
+ }
+
+ defer file.Close()
+
+ // Write the script to the file
+ _, err = file.WriteString(descriptionHook)
+ if err != nil {
+ return fmt.Errorf("error writing script to file: %v", err)
+ }
+
+ // Set the file permissions to be executable
+ err = os.Chmod(scriptPath, 0755)
+ if err != nil {
+ return fmt.Errorf("error setting file permissions: %v", err)
+ }
+
+ return nil
+}