From dd95e2dbfad7f39060dc70f145d0e1478770e454 Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Tue, 18 Feb 2025 10:23:44 +0800 Subject: *.go: Add some comments for docs --- acl.go | 2 ++ database.go | 5 +++++ git_format_patch.go | 3 +++ git_hooks_deploy.go | 5 +++++ git_hooks_handle.go | 4 ++++ git_init.go | 2 ++ git_misc.go | 6 ++++-- git_ref.go | 2 ++ http_global.go | 1 + http_handle_login.go | 3 +++ http_handle_repo_commit.go | 2 ++ http_template.go | 2 ++ remote_url.go | 2 ++ resources.go | 15 +++++---------- ssh_handle_receive_pack.go | 14 +++++++------- ssh_handle_upload_pack.go | 2 ++ ssh_utils.go | 2 +- 17 files changed, 52 insertions(+), 20 deletions(-) diff --git a/acl.go b/acl.go index 99cd5fb..22c8a4c 100644 --- a/acl.go +++ b/acl.go @@ -4,6 +4,8 @@ import ( "context" ) +// get_path_perm_by_group_repo_key returns the filesystem path and direct +// access permission for a given repo and a provided ssh public key. func get_path_perm_by_group_repo_key(ctx context.Context, group_name, repo_name, ssh_pubkey string) (filesystem_path string, access bool, err error) { err = database.QueryRow(ctx, `SELECT diff --git a/database.go b/database.go index 48d745b..e2591d2 100644 --- a/database.go +++ b/database.go @@ -4,6 +4,8 @@ import ( "context" ) +// query_list is a helper function that executes a query and returns a list of +// results. func query_list[T any](ctx context.Context, query string, args ...any) ([]T, error) { rows, err := database.Query(ctx, query, args...) if err != nil { @@ -27,6 +29,8 @@ func query_list[T any](ctx context.Context, query string, args ...any) ([]T, err return result, nil } +// query_name_desc_list is a helper function that executes a query and returns a +// list of name_desc_t results. func query_name_desc_list(ctx context.Context, query string, args ...any) ([]name_desc_t, error) { rows, err := database.Query(ctx, query, args...) if err != nil { @@ -45,6 +49,7 @@ func query_name_desc_list(ctx context.Context, query string, args ...any) ([]nam return result, rows.Err() } +// name_desc_t holds a name and a description. type name_desc_t struct { Name string Description string diff --git a/git_format_patch.go b/git_format_patch.go index 33b981b..ecb266e 100644 --- a/git_format_patch.go +++ b/git_format_patch.go @@ -10,6 +10,8 @@ import ( "go.lindenii.runxiyu.org/lindenii-common/misc" ) +// get_patch_from_commit formats a commit object as if it was returned by +// git-format-patch. func format_patch_from_commit(commit *object.Commit) (string, error) { _, patch, err := get_patch_from_commit(commit) if err != nil { @@ -23,6 +25,7 @@ func format_patch_from_commit(commit *object.Commit) (string, error) { commit_msg_title, commit_msg_details, _ := strings.Cut(commit.Message, "\n") + // This date is hardcoded in Git. fmt.Fprintf(&buf, "From %s Mon Sep 17 00:00:00 2001\n", commit.Hash) fmt.Fprintf(&buf, "From: %s <%s>\n", author.Name, author.Email) fmt.Fprintf(&buf, "Date: %s\n", date) diff --git a/git_hooks_deploy.go b/git_hooks_deploy.go index eaffb5b..7ac24c2 100644 --- a/git_hooks_deploy.go +++ b/git_hooks_deploy.go @@ -7,6 +7,9 @@ import ( "path/filepath" ) +// deploy_hooks_to_filesystem deploys the git hooks client to the filesystem. +// The git hooks client is expected to be embedded in resources_fs and must be +// pre-compiled during the build process; see the Makefile. func deploy_hooks_to_filesystem() (err error) { err = func() error { src_fd, err := resources_fs.Open("git_hooks_client/git_hooks_client") @@ -32,6 +35,8 @@ func deploy_hooks_to_filesystem() (err error) { return err } + // Go's embed filesystems do not store permissions; but in any case, + // they would need to be 0o755: err = os.Chmod(filepath.Join(config.Hooks.Execs, "git_hooks_client"), 0o755) if err != nil { return err diff --git a/git_hooks_handle.go b/git_hooks_handle.go index f8fb5bd..841c8d7 100644 --- a/git_hooks_handle.go +++ b/git_hooks_handle.go @@ -18,9 +18,13 @@ var ( err_get_ucred = errors.New("Failed getsockopt") ) +// hooks_handle_connection handles a connection from git_hooks_client via the +// unix socket. func hooks_handle_connection(conn net.Conn) { defer conn.Close() + // There aren't reasonable cases where someone would run this as + // another user. ucred, err := get_ucred(conn) if err != nil { conn.Write([]byte{1}) diff --git a/git_init.go b/git_init.go index fdb5e30..10b0382 100644 --- a/git_init.go +++ b/git_init.go @@ -5,6 +5,8 @@ import ( git_format_config "github.com/go-git/go-git/v5/plumbing/format/config" ) +// git_bare_init_with_default_hooks initializes a bare git repository with the +// forge-deployed hooks directory as the hooksPath. func git_bare_init_with_default_hooks(repo_path string) (err error) { repo, err := git.PlainInit(repo_path, true) if err != nil { diff --git a/git_misc.go b/git_misc.go index 29a2824..be75e40 100644 --- a/git_misc.go +++ b/git_misc.go @@ -18,6 +18,7 @@ var ( err_getting_parent_commit_object = errors.New("Error getting parent commit object") ) +// open_git_repo opens a git repository by group and repo name. func open_git_repo(ctx context.Context, group_name, repo_name string) (repo *git.Repository, description string, err error) { var fs_path string err = database.QueryRow(ctx, "SELECT r.filesystem_path, COALESCE(r.description, '') FROM repos r JOIN groups g ON r.group_id = g.id WHERE g.name = $1 AND r.name = $2;", group_name, repo_name).Scan(&fs_path, &description) @@ -28,6 +29,7 @@ func open_git_repo(ctx context.Context, group_name, repo_name string) (repo *git return } +// go-git's tree entries are not friendly for use in HTML templates. type display_git_tree_entry_t struct { Name string Mode string @@ -42,9 +44,9 @@ func build_display_git_tree(tree *object.Tree) []display_git_tree_entry_t { display_git_tree_entry := display_git_tree_entry_t{} os_mode, err := entry.Mode.ToOSFileMode() if err != nil { - display_git_tree_entry.Mode = "x---" + display_git_tree_entry.Mode = "x---------" } else { - display_git_tree_entry.Mode = os_mode.String()[:4] + display_git_tree_entry.Mode = os_mode.String() } display_git_tree_entry.Is_file = entry.Mode.IsFile() display_git_tree_entry.Size, err = tree.Size(entry.Name) diff --git a/git_ref.go b/git_ref.go index 46f08e0..dbf9d7e 100644 --- a/git_ref.go +++ b/git_ref.go @@ -14,6 +14,8 @@ var ( err_getting_head = errors.New("Error getting HEAD") ) +// get_ref_hash_from_type_and_name returns the hash of a reference given its +// type and name as supplied in URL queries. func get_ref_hash_from_type_and_name(repo *git.Repository, ref_type, ref_name string) (ref_hash plumbing.Hash, ret_err error) { switch ref_type { case "": diff --git a/http_global.go b/http_global.go index e007490..ac66069 100644 --- a/http_global.go +++ b/http_global.go @@ -1,5 +1,6 @@ package main +// global_data is passed as "global" when rendering HTML templates. var global_data = map[string]any{ "server_public_key_string": &server_public_key_string, "server_public_key_fingerprint": &server_public_key_fingerprint, diff --git a/http_handle_login.go b/http_handle_login.go index b43e133..f45db80 100644 --- a/http_handle_login.go +++ b/http_handle_login.go @@ -77,6 +77,9 @@ func handle_login(w http.ResponseWriter, r *http.Request, params map[string]any) http.Redirect(w, r, "/", http.StatusSeeOther) } +// random_urlsafe_string generates a random string of the given entropic size +// using the URL-safe base64 encoding. The actual size of the string returned +// will be 4*sz. func random_urlsafe_string(sz int) (string, error) { r := make([]byte, 3*sz) _, err := rand.Read(r) diff --git a/http_handle_repo_commit.go b/http_handle_repo_commit.go index 0eb6bb4..f6b73d5 100644 --- a/http_handle_repo_commit.go +++ b/http_handle_repo_commit.go @@ -11,6 +11,8 @@ import ( "go.lindenii.runxiyu.org/lindenii-common/misc" ) +// The file patch type from go-git isn't really usable in HTML templates +// either. type usable_file_patch struct { From diff.File To diff.File diff --git a/http_template.go b/http_template.go index d135c71..96338a3 100644 --- a/http_template.go +++ b/http_template.go @@ -2,6 +2,8 @@ package main import "net/http" +// render_template abstracts out the annoyances of reporting template rendering +// errors. func render_template(w http.ResponseWriter, template_name string, params map[string]any) { err := templates.ExecuteTemplate(w, template_name, params) if err != nil { diff --git a/remote_url.go b/remote_url.go index f64d6ec..8a192a8 100644 --- a/remote_url.go +++ b/remote_url.go @@ -5,6 +5,8 @@ import ( "strings" ) +// We don't use path.Join because it collapses multiple slashes into one. + func generate_ssh_remote_url(group_name, repo_name string) string { return strings.TrimSuffix(config.SSH.Root, "/") + "/" + url.PathEscape(group_name) + "/:/repos/" + url.PathEscape(repo_name) } diff --git a/resources.go b/resources.go index 4367f8e..2fe7883 100644 --- a/resources.go +++ b/resources.go @@ -7,6 +7,7 @@ import ( "net/http" ) +// We embed all source for easy AGPL compliance. //go:embed .gitignore .gitattributes //go:embed LICENSE README.md //go:embed *.go go.mod go.sum @@ -17,21 +18,15 @@ import ( //go:embed git_hooks_client/*.c //go:embed vendor/* var source_fs embed.FS - -var source_handler http.Handler - -func init() { - source_handler = http.StripPrefix( - "/:/source/", - http.FileServer(http.FS(source_fs)), - ) -} +var source_handler = http.StripPrefix( + "/:/source/", + http.FileServer(http.FS(source_fs)), +) //go:embed templates/* static/* git_hooks_client/git_hooks_client var resources_fs embed.FS var templates *template.Template - func load_templates() (err error) { templates, err = template.New("templates").Funcs(template.FuncMap{ "first_line": first_line, diff --git a/ssh_handle_receive_pack.go b/ssh_handle_receive_pack.go index c680011..72ac3de 100644 --- a/ssh_handle_receive_pack.go +++ b/ssh_handle_receive_pack.go @@ -1,7 +1,6 @@ package main import ( - "crypto/rand" "errors" "fmt" "os" @@ -22,7 +21,12 @@ type pack_to_hook_t struct { var pack_to_hook_by_cookie = cmap.Map[string, pack_to_hook_t]{} +// ssh_handle_receive_pack handles attempts to push to repos. func ssh_handle_receive_pack(session glider_ssh.Session, pubkey string, repo_identifier string) (err error) { + // Here "access" means direct maintainer access. access=false doesn't + // necessarily mean the push is declined. This decision is delegated to + // the pre-receive hook, which is then handled by git_hooks_handle.go + // while being aware of the refs to be updated. repo_path, access, err := get_repo_path_perms_from_ssh_path_pubkey(session.Context(), repo_identifier, pubkey) if err != nil { return err @@ -40,6 +44,8 @@ func ssh_handle_receive_pack(session glider_ssh.Session, pubkey string, repo_ide repo_path: repo_path, }) defer pack_to_hook_by_cookie.Delete(cookie) + // The Delete won't execute until proc.Wait returns unless something + // horribly wrong such as a panic occurs. proc := exec.CommandContext(session.Context(), "git-receive-pack", repo_path) proc.Env = append(os.Environ(), @@ -65,9 +71,3 @@ func ssh_handle_receive_pack(session glider_ssh.Session, pubkey string, repo_ide return err } - -func random_string(sz int) (string, error) { - r := make([]byte, sz) - _, err := rand.Read(r) - return string(r), err -} diff --git a/ssh_handle_upload_pack.go b/ssh_handle_upload_pack.go index ac52e5c..afc9900 100644 --- a/ssh_handle_upload_pack.go +++ b/ssh_handle_upload_pack.go @@ -8,6 +8,8 @@ import ( glider_ssh "github.com/gliderlabs/ssh" ) +// ssh_handle_upload_pack handles clones/fetches. It just uses git-upload-pack +// and has no ACL checks. func ssh_handle_upload_pack(session glider_ssh.Session, pubkey string, repo_identifier string) (err error) { repo_path, _, err := get_repo_path_perms_from_ssh_path_pubkey(session.Context(), repo_identifier, pubkey) if err != nil { diff --git a/ssh_utils.go b/ssh_utils.go index cf96b21..61fdf33 100644 --- a/ssh_utils.go +++ b/ssh_utils.go @@ -9,7 +9,7 @@ import ( var err_ssh_illegal_endpoint = errors.New("Illegal endpoint during SSH access") -func get_repo_path_perms_from_ssh_path_pubkey(ctx context.Context, ssh_path string, ssh_pubkey string) (repo_path string, access bool, err error) { +func get_repo_path_perms_from_ssh_path_pubkey(ctx context.Context, ssh_path string, ssh_pubkey string) (repo_path string, direct_access bool, err error) { segments := strings.Split(strings.TrimPrefix(ssh_path, "/"), "/") for i, segment := range segments { -- cgit v1.2.3