aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRunxi Yu <me@runxiyu.org>2025-02-20 12:32:43 +0800
committerRunxi Yu <me@runxiyu.org>2025-02-20 12:32:43 +0800
commit692346f5d864a4eb9965d0201e5c58151570d706 (patch)
tree32d05e86bd41d46cd482d06ccc3365904837d413
parenthooks, ssh: Indicate URL of newly-created MRs (diff)
downloadforge-692346f5d864a4eb9965d0201e5c58151570d706.tar.gz
forge-692346f5d864a4eb9965d0201e5c58151570d706.tar.zst
forge-692346f5d864a4eb9965d0201e5c58151570d706.zip
ssh/recv: Check hooksPath before receiving packs
-rw-r--r--git_hooks_handle.go33
-rw-r--r--ssh_handle_receive_pack.go22
2 files changed, 35 insertions, 20 deletions
diff --git a/git_hooks_handle.go b/git_hooks_handle.go
index 3a8a031..59d29c7 100644
--- a/git_hooks_handle.go
+++ b/git_hooks_handle.go
@@ -14,9 +14,8 @@ import (
"strings"
"syscall"
- "github.com/jackc/pgx/v5"
- "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
+ "github.com/jackc/pgx/v5"
"go.lindenii.runxiyu.org/lindenii-common/ansiec"
)
@@ -131,7 +130,7 @@ func hooks_handle_connection(conn net.Conn) {
if strings.HasPrefix(ref_name, "refs/heads/contrib/") {
if all_zero_num_string(old_oid) { // New branch
- fmt.Fprintln(ssh_stderr, ansiec.Blue + "POK" + ansiec.Reset, ref_name)
+ fmt.Fprintln(ssh_stderr, ansiec.Blue+"POK"+ansiec.Reset, ref_name)
var new_mr_id int
err = database.QueryRow(ctx,
"INSERT INTO merge_requests (repo_id, creator, source_ref, status) VALUES ($1, $2, $3, 'open') RETURNING id",
@@ -141,7 +140,7 @@ func hooks_handle_connection(conn net.Conn) {
wf_error(ssh_stderr, "Error creating merge request: %v", err)
return 1
}
- fmt.Fprintln(ssh_stderr, ansiec.Blue + "Created merge request at", generate_http_remote_url(pack_to_hook.group_name, pack_to_hook.repo_name) + "/contrib/" + strconv.FormatUint(uint64(new_mr_id), 10) + "/" + ansiec.Reset)
+ fmt.Fprintln(ssh_stderr, ansiec.Blue+"Created merge request at", generate_http_remote_url(pack_to_hook.group_name, pack_to_hook.repo_name)+"/contrib/"+strconv.FormatUint(uint64(new_mr_id), 10)+"/"+ansiec.Reset)
} else { // Existing contrib branch
var existing_merge_request_user_id int
err = database.QueryRow(ctx,
@@ -158,25 +157,19 @@ func hooks_handle_connection(conn net.Conn) {
}
if existing_merge_request_user_id == 0 {
all_ok = false
- fmt.Fprintln(ssh_stderr, ansiec.Red + "NAK" + ansiec.Reset, ref_name, "(branch belongs to unowned MR)")
+ fmt.Fprintln(ssh_stderr, ansiec.Red+"NAK"+ansiec.Reset, ref_name, "(branch belongs to unowned MR)")
continue
}
if existing_merge_request_user_id != pack_to_hook.user_id {
all_ok = false
- fmt.Fprintln(ssh_stderr, ansiec.Red + "NAK" + ansiec.Reset, ref_name, "(branch belongs another user's MR)")
+ fmt.Fprintln(ssh_stderr, ansiec.Red+"NAK"+ansiec.Reset, ref_name, "(branch belongs another user's MR)")
continue
}
- repo, err := git.PlainOpen(pack_to_hook.repo_path)
- if err != nil {
- wf_error(ssh_stderr, "Daemon failed to open repo: %v", err)
- return 1
- }
-
old_hash := plumbing.NewHash(old_oid)
- old_commit, err := repo.CommitObject(old_hash)
+ old_commit, err := pack_to_hook.repo.CommitObject(old_hash)
if err != nil {
wf_error(ssh_stderr, "Daemon failed to get old commit: %v", err)
return 1
@@ -187,7 +180,7 @@ func hooks_handle_connection(conn net.Conn) {
// objects yet. But it seems to work, and I don't think there's
// any reason for this to only work intermitently.
new_hash := plumbing.NewHash(new_oid)
- new_commit, err := repo.CommitObject(new_hash)
+ new_commit, err := pack_to_hook.repo.CommitObject(new_hash)
if err != nil {
wf_error(ssh_stderr, "Daemon failed to get new commit: %v", err)
return 1
@@ -202,29 +195,29 @@ func hooks_handle_connection(conn net.Conn) {
if !is_ancestor {
// TODO: Create MR snapshot ref instead
all_ok = false
- fmt.Fprintln(ssh_stderr, ansiec.Red + "NAK" + ansiec.Reset, ref_name, "(force pushes are not supported yet)")
+ fmt.Fprintln(ssh_stderr, ansiec.Red+"NAK"+ansiec.Reset, ref_name, "(force pushes are not supported yet)")
continue
}
- fmt.Fprintln(ssh_stderr, ansiec.Blue + "POK" + ansiec.Reset, ref_name)
+ fmt.Fprintln(ssh_stderr, ansiec.Blue+"POK"+ansiec.Reset, ref_name)
}
} else { // Non-contrib branch
all_ok = false
- fmt.Fprintln(ssh_stderr, ansiec.Red + "NAK" + ansiec.Reset, ref_name, "(you cannot push to branches outside of contrib/*)")
+ fmt.Fprintln(ssh_stderr, ansiec.Red+"NAK"+ansiec.Reset, ref_name, "(you cannot push to branches outside of contrib/*)")
}
}
fmt.Fprintln(ssh_stderr)
if all_ok {
- fmt.Fprintln(ssh_stderr, "Overall " + ansiec.Green + "ACK" + ansiec.Reset + " (all checks passed)")
+ fmt.Fprintln(ssh_stderr, "Overall "+ansiec.Green+"ACK"+ansiec.Reset+" (all checks passed)")
return 0
} else {
- fmt.Fprintln(ssh_stderr, "Overall " + ansiec.Red + "NAK" + ansiec.Reset + " (one or more branches failed checks)")
+ fmt.Fprintln(ssh_stderr, "Overall "+ansiec.Red+"NAK"+ansiec.Reset+" (one or more branches failed checks)")
return 1
}
}
default:
- fmt.Fprintln(ssh_stderr, ansiec.Red + "Invalid hook:", args[0] + ansiec.Reset)
+ fmt.Fprintln(ssh_stderr, ansiec.Red+"Invalid hook:", args[0]+ansiec.Reset)
return 1
}
}()
diff --git a/ssh_handle_receive_pack.go b/ssh_handle_receive_pack.go
index af576bc..971d11c 100644
--- a/ssh_handle_receive_pack.go
+++ b/ssh_handle_receive_pack.go
@@ -7,11 +7,13 @@ import (
"os/exec"
glider_ssh "github.com/gliderlabs/ssh"
+ "github.com/go-git/go-git/v5"
"go.lindenii.runxiyu.org/lindenii-common/cmap"
)
type pack_to_hook_t struct {
session glider_ssh.Session
+ repo *git.Repository
pubkey string
direct_access bool
repo_path string
@@ -29,6 +31,25 @@ func ssh_handle_receive_pack(session glider_ssh.Session, pubkey string, repo_ide
if err != nil {
return err
}
+ repo, err := git.PlainOpen(repo_path)
+ if err != nil {
+ return err
+ }
+
+ repo_config, err := repo.Config()
+ if err != nil {
+ return err
+ }
+
+ repo_config_core := repo_config.Raw.Section("core")
+ if repo_config_core == nil {
+ return errors.New("Repository has no core section in config")
+ }
+
+ hooksPath := repo_config_core.OptionAll("hooksPath")
+ if len(hooksPath) != 1 || hooksPath[0] != config.Hooks.Execs {
+ return errors.New("Repository has hooksPath set to an unexpected value")
+ }
if !direct_access {
switch contrib_requirements {
@@ -73,6 +94,7 @@ func ssh_handle_receive_pack(session glider_ssh.Session, pubkey string, repo_ide
repo_id: repo_id,
group_name: group_name,
repo_name: repo_name,
+ repo: repo,
})
defer pack_to_hook_by_cookie.Delete(cookie)
// The Delete won't execute until proc.Wait returns unless something