Compare commits

..

No commits in common. "9030c27f0037e453c2825ac75b818a798a7d4e26" and "b32eb0a759ea862860bb984fc193fa3b1c30d2a8" have entirely different histories.

9 changed files with 48 additions and 60 deletions

View File

@ -10,7 +10,7 @@ Minimal git server
ugit allows cloning via HTTPS/SSH, but can only be pushed to via SSH. ugit allows cloning via HTTPS/SSH, but can only be pushed to via SSH.
There are no plans to directly support issues or PR workflows, although webhooks are planned and auxillary software may be created to facilitate these things. There are no plans to directly support issues or PR workflows, although webhooks are planned and auxillary software may be created to facilitate these things.
For now, if you wish to collaborate, please send me patches at [ugit@jolheiser.com](mailto:git@jolheiser.com). For now, if you wish to collaborate, please send me patches at [john+ugit@jolheiser.com](mailto:john+ugit@jolheiser.com).
Currently all HTML is allowed in markdown, ugit is intended to be run by/for a trusted user. Currently all HTML is allowed in markdown, ugit is intended to be run by/for a trusted user.

View File

@ -1,7 +1,7 @@
package html package html
type BaseContext struct { type BaseContext struct {
Title string Title string
Description string Description string
} }
@ -23,3 +23,4 @@ templ base(bc BaseContext) {
</body> </body>
</html> </html>
} }

View File

@ -3,11 +3,6 @@
color: rgb(var(--ctp-text)); color: rgb(var(--ctp-text));
} }
.markdown code,
.markdown pre {
background-color: rgb(var(--ctp-base));
}
.markdown a { .markdown a {
color: rgb(var(--ctp-blue)); color: rgb(var(--ctp-blue));
text-decoration-line: underline; text-decoration-line: underline;

View File

@ -3,10 +3,10 @@ package html
import "fmt" import "fmt"
type RepoHeaderComponentContext struct { type RepoHeaderComponentContext struct {
Name string Name string
Ref string Ref string
Description string Description string
CloneURL string CloneURL string
} }
templ repoHeaderComponent(rhcc RepoHeaderComponentContext) { templ repoHeaderComponent(rhcc RepoHeaderComponentContext) {
@ -21,9 +21,10 @@ templ repoHeaderComponent(rhcc RepoHeaderComponentContext) {
{ " - " } { " - " }
<a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/log/%s", rhcc.Name, rhcc.Ref)) }>log</a> <a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/log/%s", rhcc.Name, rhcc.Ref)) }>log</a>
{ " - " } { " - " }
<form class="inline-block" action={ templ.SafeURL(fmt.Sprintf("/%s/search", rhcc.Name)) } method="get"><input class="rounded p-1 bg-mantle focus:border-lavender focus:outline-none focus:ring-0" id="search" type="text" name="q" placeholder="search"/></form> <a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/search", rhcc.Name)) }>search</a>
{ " - " } { " - " }
<pre class="text-text inline select-all bg-base dark:bg-base/50 p-1 rounded">{ fmt.Sprintf("%s/%s.git", rhcc.CloneURL, rhcc.Name) }</pre> <pre class="text-text inline select-all bg-base dark:bg-base/50 p-1 rounded">{ fmt.Sprintf("%s/%s.git", rhcc.CloneURL, rhcc.Name) }</pre>
</div> </div>
<div class="text-text/80 mb-1">{ rhcc.Description }</div> <div class="text-text/80 mb-1">{ rhcc.Description }</div>
} }

View File

@ -4,7 +4,7 @@ import "fmt"
import "go.jolheiser.com/ugit/internal/git" import "go.jolheiser.com/ugit/internal/git"
type SearchContext struct { type SearchContext struct {
BaseContext BaseContext
RepoHeaderComponentContext RepoHeaderComponentContext
Results []git.GrepResult Results []git.GrepResult
} }
@ -33,12 +33,10 @@ func (s SearchContext) DedupeResults() [][]git.GrepResult {
templ RepoSearch(sc SearchContext) { templ RepoSearch(sc SearchContext) {
@base(sc.BaseContext) { @base(sc.BaseContext) {
@repoHeaderComponent(sc.RepoHeaderComponentContext) @repoHeaderComponent(sc.RepoHeaderComponentContext)
<form method="get"><label class="text-text">Search <input class="rounded p-1 mt-2 bg-mantle focus:border-lavender focus:outline-none focus:ring-0" id="search" type="text" name="q" placeholder="search"/></label></form>
for _, results := range sc.DedupeResults() { for _, results := range sc.DedupeResults() {
@repoSearchResult(sc.RepoHeaderComponentContext.Name, sc.RepoHeaderComponentContext.Ref, results) @repoSearchResult(sc.RepoHeaderComponentContext.Name, sc.RepoHeaderComponentContext.Ref, results)
} }
if len(sc.DedupeResults()) == 0 {
<p class="text-text mt-5 text-lg">No results</p>
}
} }
<script> <script>
const search = new URLSearchParams(window.location.search).get("q"); const search = new URLSearchParams(window.location.search).get("q");
@ -48,18 +46,15 @@ templ RepoSearch(sc SearchContext) {
templ repoSearchResult(repo, ref string, results []git.GrepResult) { templ repoSearchResult(repo, ref string, results []git.GrepResult) {
<div class="text-text mt-5"><a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s#L%d", repo, ref, results[0].File, results[0].Line)) }>{ results[0].File }</a></div> <div class="text-text mt-5"><a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s#L%d", repo, ref, results[0].File, results[0].Line)) }>{ results[0].File }</a></div>
<div class="code"> <div class="code">@templ.Raw(results[0].Content)</div>
@templ.Raw(results[0].Content)
</div>
if len(results) > 1 { if len(results) > 1 {
<details class="text-text cursor-pointer"> <details class="text-text cursor-pointer">
<summary>{ fmt.Sprintf("%d ", len(results[1:])) }more</summary> <summary>{ fmt.Sprintf("%d ", len(results[1:])) }more</summary>
for _, result := range results[1:] { for _, result := range results[1:] {
<div class="text-text mt-5 ml-5"><a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s#L%d", repo, ref, result.File, result.Line)) }>{ results[0].File }</a></div> <div class="text-text mt-5 ml-5"><a class="underline decoration-text/50 decoration-dashed hover:decoration-solid" href={ templ.SafeURL(fmt.Sprintf("/%s/tree/%s/%s#L%d", repo, ref, result.File, result.Line)) }>{ results[0].File }</a></div>
<div class="code ml-5"> <div class="code ml-5">@templ.Raw(result.Content)</div>
@templ.Raw(result.Content)
</div>
} }
</details> </details>
} }
} }

View File

@ -63,7 +63,16 @@ func RepoSearch(sc SearchContext) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <form method=\"get\"><label class=\"text-text\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Var3 := `Search `
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<input class=\"rounded p-1 mt-2 bg-mantle focus:border-lavender focus:outline-none focus:ring-0\" id=\"search\" type=\"text\" name=\"q\" placeholder=\"search\"></label></form>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -73,25 +82,6 @@ func RepoSearch(sc SearchContext) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if len(sc.DedupeResults()) == 0 {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<p class=\"text-text mt-5 text-lg\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Var3 := `No results`
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
if !templ_7745c5c3_IsBuffer { if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
} }
@ -153,7 +143,7 @@ func repoSearchResult(repo, ref string, results []git.GrepResult) templ.Componen
var templ_7745c5c3_Var7 string var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(results[0].File) templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(results[0].File)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 49, Col: 230} return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 47, Col: 230}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -179,7 +169,7 @@ func repoSearchResult(repo, ref string, results []git.GrepResult) templ.Componen
var templ_7745c5c3_Var8 string var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d ", len(results[1:]))) templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d ", len(results[1:])))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 55, Col: 50} return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 51, Col: 50}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -211,7 +201,7 @@ func repoSearchResult(repo, ref string, results []git.GrepResult) templ.Componen
var templ_7745c5c3_Var11 string var templ_7745c5c3_Var11 string
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(results[0].File) templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(results[0].File)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 57, Col: 230} return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo_search.templ`, Line: 53, Col: 230}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {

View File

@ -166,7 +166,7 @@ func repoHeaderComponent(rhcc RepoHeaderComponentContext) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<form class=\"inline-block\" action=\"") _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <a class=\"underline decoration-text/50 decoration-dashed hover:decoration-solid\" href=\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -175,16 +175,25 @@ func repoHeaderComponent(rhcc RepoHeaderComponentContext) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" method=\"get\"><input class=\"rounded p-1 bg-mantle focus:border-lavender focus:outline-none focus:ring-0\" id=\"search\" type=\"text\" name=\"q\" placeholder=\"search\"></form>") _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var15 string templ_7745c5c3_Var15 := `search`
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(" - ") _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var15)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var16 string
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(" - ")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 24, Col: 9} return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 24, Col: 9}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -192,12 +201,12 @@ func repoHeaderComponent(rhcc RepoHeaderComponentContext) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var16 string var templ_7745c5c3_Var17 string
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%s/%s.git", rhcc.CloneURL, rhcc.Name)) templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%s/%s.git", rhcc.CloneURL, rhcc.Name))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 25, Col: 131} return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 25, Col: 131}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -205,12 +214,12 @@ func repoHeaderComponent(rhcc RepoHeaderComponentContext) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var17 string var templ_7745c5c3_Var18 string
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(rhcc.Description) templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(rhcc.Description)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 27, Col: 50} return templ.Error{Err: templ_7745c5c3_Err, FileName: `repo.templ`, Line: 27, Col: 50}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }

File diff suppressed because one or more lines are too long

View File

@ -71,9 +71,6 @@ func (rh repoHandler) repoTree(ref, path string) http.HandlerFunc {
func (rh repoHandler) repoFile(w http.ResponseWriter, r *http.Request, repo *git.Repo, ref, path string) error { func (rh repoHandler) repoFile(w http.ResponseWriter, r *http.Request, repo *git.Repo, ref, path string) error {
content, err := repo.FileContent(ref, path) content, err := repo.FileContent(ref, path)
if err != nil { if err != nil {
if errors.Is(err, object.ErrFileNotFound) {
return httperr.Status(err, http.StatusNotFound)
}
return httperr.Error(err) return httperr.Error(err)
} }