1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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
}
|