diff options
author | Runxi Yu <me@runxiyu.org> | 2025-02-20 12:32:43 +0800 |
---|---|---|
committer | Runxi Yu <me@runxiyu.org> | 2025-02-20 12:32:43 +0800 |
commit | 692346f5d864a4eb9965d0201e5c58151570d706 (patch) | |
tree | 32d05e86bd41d46cd482d06ccc3365904837d413 | |
parent | hooks, ssh: Indicate URL of newly-created MRs (diff) | |
download | forge-692346f5d864a4eb9965d0201e5c58151570d706.tar.gz forge-692346f5d864a4eb9965d0201e5c58151570d706.tar.zst forge-692346f5d864a4eb9965d0201e5c58151570d706.zip |
ssh/recv: Check hooksPath before receiving packs
-rw-r--r-- | git_hooks_handle.go | 33 | ||||
-rw-r--r-- | ssh_handle_receive_pack.go | 22 |
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 |