diff options
-rw-r--r-- | handle_repo_raw.go | 25 | ||||
-rw-r--r-- | handle_repo_tree.go | 20 | ||||
-rw-r--r-- | main.go | 4 | ||||
-rw-r--r-- | ref.go | 46 | ||||
-rw-r--r-- | templates/repo_commit.html.tmpl | 4 | ||||
-rw-r--r-- | templates/repo_index.html.tmpl | 2 | ||||
-rw-r--r-- | templates/repo_tree_file.html.tmpl | 2 | ||||
-rw-r--r-- | url_misc.go | 42 |
8 files changed, 127 insertions, 18 deletions
diff --git a/handle_repo_raw.go b/handle_repo_raw.go index 5693660..d3ffe3e 100644 --- a/handle_repo_raw.go +++ b/handle_repo_raw.go @@ -1,11 +1,11 @@ package main import ( + "errors" "net/http" "path" "strings" - "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" ) @@ -13,19 +13,32 @@ func handle_repo_raw(w http.ResponseWriter, r *http.Request) { data := make(map[string]any) // TODO: Sanitize path values raw_path_spec := r.PathValue("rest") - ref_name, group_name, repo_name, path_spec := r.PathValue("ref"), r.PathValue("group_name"), r.PathValue("repo_name"), strings.TrimSuffix(raw_path_spec, "/") - data["ref"], data["group_name"], data["repo_name"], data["path_spec"] = ref_name, group_name, repo_name, path_spec + group_name, repo_name, path_spec := r.PathValue("group_name"), r.PathValue("repo_name"), strings.TrimSuffix(raw_path_spec, "/") + + ref_type, ref_name, err := get_param_ref_and_type(r) + if err != nil { + if errors.Is(err, err_no_ref_spec) { + ref_type = "head" + } else { + _, _ = w.Write([]byte("Error querying ref type: " + err.Error())) + return + } + } + + data["ref_type"], data["ref"], data["group_name"], data["repo_name"], data["path_spec"] = ref_type, ref_name, group_name, repo_name, path_spec + repo, err := open_git_repo(group_name, repo_name) if err != nil { _, _ = w.Write([]byte("Error opening repo: " + err.Error())) return } - ref, err := repo.Reference(plumbing.NewBranchReferenceName(ref_name), true) + + ref_hash, err := get_ref_hash_from_type_and_name(repo, ref_type, ref_name) if err != nil { - _, _ = w.Write([]byte("Error getting repo reference: " + err.Error())) + _, _ = w.Write([]byte("Error getting ref hash: " + err.Error())) return } - ref_hash := ref.Hash() + commit_object, err := repo.CommitObject(ref_hash) if err != nil { _, _ = w.Write([]byte("Error getting commit object: " + err.Error())) diff --git a/handle_repo_tree.go b/handle_repo_tree.go index 2c1c31e..824f5df 100644 --- a/handle_repo_tree.go +++ b/handle_repo_tree.go @@ -2,6 +2,7 @@ package main import ( "bytes" + "errors" "html/template" "net/http" "path" @@ -10,7 +11,6 @@ import ( chroma_formatters_html "github.com/alecthomas/chroma/v2/formatters/html" chroma_lexers "github.com/alecthomas/chroma/v2/lexers" chroma_styles "github.com/alecthomas/chroma/v2/styles" - "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" ) @@ -18,19 +18,27 @@ func handle_repo_tree(w http.ResponseWriter, r *http.Request) { data := make(map[string]any) // TODO: Sanitize path values raw_path_spec := r.PathValue("rest") - ref_name, group_name, repo_name, path_spec := r.PathValue("ref"), r.PathValue("group_name"), r.PathValue("repo_name"), strings.TrimSuffix(raw_path_spec, "/") - data["ref"], data["group_name"], data["repo_name"], data["path_spec"] = ref_name, group_name, repo_name, path_spec + group_name, repo_name, path_spec := r.PathValue("group_name"), r.PathValue("repo_name"), strings.TrimSuffix(raw_path_spec, "/") + ref_type, ref_name, err := get_param_ref_and_type(r) + if err != nil { + if errors.Is(err, err_no_ref_spec) { + ref_type = "head" + } else { + _, _ = w.Write([]byte("Error querying ref type: " + err.Error())) + return + } + } + data["ref_type"], data["ref"], data["group_name"], data["repo_name"], data["path_spec"] = ref_type, ref_name, group_name, repo_name, path_spec repo, err := open_git_repo(group_name, repo_name) if err != nil { _, _ = w.Write([]byte("Error opening repo: " + err.Error())) return } - ref, err := repo.Reference(plumbing.NewBranchReferenceName(ref_name), true) + ref_hash, err := get_ref_hash_from_type_and_name(repo, ref_type, ref_name) if err != nil { - _, _ = w.Write([]byte("Error getting repo reference: " + err.Error())) + _, _ = w.Write([]byte("Error getting ref hash: " + err.Error())) return } - ref_hash := ref.Hash() commit_object, err := repo.CommitObject(ref_hash) if err != nil { _, _ = w.Write([]byte("Error getting commit object: " + err.Error())) @@ -36,8 +36,8 @@ func main() { http.HandleFunc("/{$}", handle_index) http.HandleFunc("/g/{group_name}/repos/{$}", handle_group_repos) http.HandleFunc("/g/{group_name}/repos/{repo_name}/{$}", handle_repo_index) - http.HandleFunc("/g/{group_name}/repos/{repo_name}/tree/{ref}/{rest...}", handle_repo_tree) - http.HandleFunc("/g/{group_name}/repos/{repo_name}/raw/{ref}/{rest...}", handle_repo_raw) + http.HandleFunc("/g/{group_name}/repos/{repo_name}/tree/{rest...}", handle_repo_tree) + http.HandleFunc("/g/{group_name}/repos/{repo_name}/raw/{rest...}", handle_repo_raw) http.HandleFunc("/g/{group_name}/repos/{repo_name}/log/{ref}/", handle_repo_log) http.HandleFunc("/g/{group_name}/repos/{repo_name}/commit/{commit_id}", handle_repo_commit) @@ -0,0 +1,46 @@ +package main + +import ( + "errors" + + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" + "go.lindenii.runxiyu.org/lindenii-common/misc" +) + +var ( + err_getting_tag_reference = errors.New("Error getting tag reference") + err_getting_branch_reference = errors.New("Error getting branch reference") + err_getting_head = errors.New("Error getting HEAD") +) + +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 "head": + head, err := repo.Head() + if err != nil { + ret_err = misc.Wrap_one_error(err_getting_head, err) + return + } + ref_hash = head.Hash() + case "commit": + ref_hash = plumbing.NewHash(ref_name) + case "branch": + ref, err := repo.Reference(plumbing.NewBranchReferenceName(ref_name), true) + if err != nil { + ret_err = misc.Wrap_one_error(err_getting_branch_reference, err) + return + } + ref_hash = ref.Hash() + case "tag": + ref, err := repo.Reference(plumbing.NewTagReferenceName(ref_name), true) + if err != nil { + ret_err = misc.Wrap_one_error(err_getting_tag_reference, err) + return + } + ref_hash = ref.Hash() + default: + panic("Invalid ref type " + ref_type) + } + return +} diff --git a/templates/repo_commit.html.tmpl b/templates/repo_commit.html.tmpl index a288949..d568887 100644 --- a/templates/repo_commit.html.tmpl +++ b/templates/repo_commit.html.tmpl @@ -53,9 +53,9 @@ <input type="checkbox" id="toggle-{{ .From.Hash }}{{ .To.Hash }}" class="file-toggle toggle-on-toggle"> <label for="toggle-{{ .From.Hash }}{{ .To.Hash }}" class="file-header toggle-on-header"> <span> - --- a/<a href="../../tree/{{ .From.Path }}?commit={{ $parent_commit_object.Hash }}">{{ .From.Path }}</a> {{ .From.Mode }} + --- a/<a href="../tree/{{ .From.Path }}?commit={{ $parent_commit_object.Hash }}">{{ .From.Path }}</a> {{ .From.Mode }} <br /> - +++ b/<a href="../../tree/{{ .To.Path }}?commit={{ $commit_object.Hash }}">{{ .To.Path }}</a> {{ .To.Mode }} + +++ b/<a href="../tree/{{ .To.Path }}?commit={{ $commit_object.Hash }}">{{ .To.Path }}</a> {{ .To.Mode }} </span> </label> <div class="file-content toggle-on-content scroll"> diff --git a/templates/repo_index.html.tmpl b/templates/repo_index.html.tmpl index c3b4759..2f41aac 100644 --- a/templates/repo_index.html.tmpl +++ b/templates/repo_index.html.tmpl @@ -42,7 +42,7 @@ {{- range .files }} <tr> <td class="file-mode">{{ .Mode }}</td> - <td class="file-name"><a href="tree/{{ $ref }}/{{ .Name }}">{{ .Name }}</a>{{ if not .Is_file }}/{{ end }}</td> + <td class="file-name"><a href="tree/{{ .Name }}">{{ .Name }}</a>{{ if not .Is_file }}/{{ end }}</td> <td class="file-size">{{ .Size }}</td> </tr> {{- end }} diff --git a/templates/repo_tree_file.html.tmpl b/templates/repo_tree_file.html.tmpl index 7ddfce1..0401bb0 100644 --- a/templates/repo_tree_file.html.tmpl +++ b/templates/repo_tree_file.html.tmpl @@ -8,7 +8,7 @@ </head> <body class="repo-tree-file"> <p> - /{{ .path_spec }} (<a href="/g/{{ .group_name }}/repos/{{ .repo_name }}/raw/{{ .ref }}/{{ .path_spec }}">raw</a>) + /{{ .path_spec }} (<a href="/g/{{ .group_name }}/repos/{{ .repo_name }}/raw/{{ .path_spec }}?{{ .ref_type }}={{ .ref }}">raw</a>) </p> {{ .file_contents }} <footer> diff --git a/url_misc.go b/url_misc.go new file mode 100644 index 0000000..906e06e --- /dev/null +++ b/url_misc.go @@ -0,0 +1,42 @@ +package main + +import ( + "errors" + "net/http" + "net/url" +) + +var ( + err_duplicate_ref_spec = errors.New("Duplicate ref spec") + err_no_ref_spec = errors.New("No ref spec") +) + +func get_param_ref_and_type(r *http.Request) (ref_type, ref string, err error) { + qr := r.URL.RawQuery + q, err := url.ParseQuery(qr) + if err != nil { + return + } + done := false + for _, _ref_type := range []string{"commit", "branch", "tag"} { + _ref, ok := q[_ref_type] + if ok { + if done { + err = err_duplicate_ref_spec + return + } else { + done = true + if len(_ref) != 1 { + err = err_duplicate_ref_spec + return + } + ref = _ref[0] + ref_type = _ref_type + } + } + } + if !done { + err = err_no_ref_spec + } + return +} |