cerrado @ e775b5356ea3adaeeca2d4be5ef874b36fa183d0

feat: Handle submodule

Submodules tree entries won't have a broken link and will be labeled
properly.
diff --git a/README.md b/README.md
index f6e202a381dc90562512cd33264c39478b7b90da..3f1a12ee7d50c2efec880a6f0597ce4053524268 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,6 @@ ### TODO
 
 - Impove diff display
 - Add log pagination
-- Fix submodule link on tree view
 
 ### Milestone
 - Mail patch / mailing list
diff --git a/templates/gititemtree.qtpl b/templates/gititemtree.qtpl
index 5898506af0e41201754aec08dcb72171efd2a675..2753e24fd356cfec2fd3a412d5d8669266d5da0a 100644
--- a/templates/gititemtree.qtpl
+++ b/templates/gititemtree.qtpl
@@ -1,5 +1,6 @@
 {% import "git.gabrielgio.me/cerrado/pkg/u" %}
 {% import "github.com/go-git/go-git/v5/plumbing/object" %}
+{% import "github.com/go-git/go-git/v5/plumbing/filemode" %}
 
 {% code type GitItemTreePage struct {
     Path []string
@@ -52,10 +53,14 @@           <div class="date"></div>
           <div class="size"></div>
       {% endif %}
       {% for _, e := range g.Tree.Entries %}
-          <div class="mode">{%s Ignore(e.Mode.ToOSFileMode()).String() %}</div>
           {% if e.Mode.IsFile() %}
+          <div class="mode">{%s Ignore(e.Mode.ToOSFileMode()).String() %}</div>
           <div class="name blob"><a href="{%s url(name, Blob, ref, e.Name, g.Path) %}">{%s e.Name %}</a></div>
+          {% elseif e.Mode ==  filemode.Submodule %}
+          <div class="mode">m---------</div>
+          <div class="name tree">{%s e.Name %} (submodule)</div>
           {% else %}
+          <div class="mode">d---------</div>
           <div class="name tree"><a href="{%s url(name, Folder, ref, e.Name, g.Path) %}">{%s e.Name %}</a></div>
           {% endif %}
           <div class="commit"></div>
diff --git a/templates/gititemtree.qtpl.go b/templates/gititemtree.qtpl.go
index f8d1fd2880caeda1c09bed34c6cdf9e8193bbec0..f26b5ca558d08f97e2851d3f4a18c18924ed5f77 100644
--- a/templates/gititemtree.qtpl.go
+++ b/templates/gititemtree.qtpl.go
@@ -10,33 +10,36 @@
 //line gititemtree.qtpl:2
 import "github.com/go-git/go-git/v5/plumbing/object"
 
-//line gititemtree.qtpl:4
+//line gititemtree.qtpl:3
+import "github.com/go-git/go-git/v5/plumbing/filemode"
+
+//line gititemtree.qtpl:5
 import (
 	qtio422016 "io"
 
 	qt422016 "github.com/valyala/quicktemplate"
 )
 
-//line gititemtree.qtpl:4
+//line gititemtree.qtpl:5
 var (
 	_ = qtio422016.Copy
 	_ = qt422016.AcquireByteBuffer
 )
 
-//line gititemtree.qtpl:4
+//line gititemtree.qtpl:5
 type GitItemTreePage struct {
 	Path []string
 	Tree *object.Tree
 }
 
-//line gititemtree.qtpl:10
+//line gititemtree.qtpl:11
 const (
 	Folder = "tree"
 	Blob   = "blob"
 	Root   = ""
 )
 
-//line gititemtree.qtpl:17
+//line gititemtree.qtpl:18
 func url(name, mode, ref, filename string, path []string) string {
 	return u.NewPathing().
 		AddPath(name).
@@ -47,188 +50,200 @@ 		AddPath(filename).
 		Done()
 }
 
-//line gititemtree.qtpl:28
+//line gititemtree.qtpl:29
 func (g *GitItemTreePage) StreamNav(qw422016 *qt422016.Writer, name, ref string) {
-//line gititemtree.qtpl:28
+//line gititemtree.qtpl:29
 	StreamGitItemNav(qw422016, name, ref, Tree)
-//line gititemtree.qtpl:28
+//line gititemtree.qtpl:29
 }
 
-//line gititemtree.qtpl:28
+//line gititemtree.qtpl:29
 func (g *GitItemTreePage) WriteNav(qq422016 qtio422016.Writer, name, ref string) {
-//line gititemtree.qtpl:28
+//line gititemtree.qtpl:29
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line gititemtree.qtpl:28
+//line gititemtree.qtpl:29
 	g.StreamNav(qw422016, name, ref)
-//line gititemtree.qtpl:28
+//line gititemtree.qtpl:29
 	qt422016.ReleaseWriter(qw422016)
-//line gititemtree.qtpl:28
+//line gititemtree.qtpl:29
 }
 
-//line gititemtree.qtpl:28
+//line gititemtree.qtpl:29
 func (g *GitItemTreePage) Nav(name, ref string) string {
-//line gititemtree.qtpl:28
+//line gititemtree.qtpl:29
 	qb422016 := qt422016.AcquireByteBuffer()
-//line gititemtree.qtpl:28
+//line gititemtree.qtpl:29
 	g.WriteNav(qb422016, name, ref)
-//line gititemtree.qtpl:28
+//line gititemtree.qtpl:29
 	qs422016 := string(qb422016.B)
-//line gititemtree.qtpl:28
+//line gititemtree.qtpl:29
 	qt422016.ReleaseByteBuffer(qb422016)
-//line gititemtree.qtpl:28
+//line gititemtree.qtpl:29
 	return qs422016
-//line gititemtree.qtpl:28
+//line gititemtree.qtpl:29
 }
 
-//line gititemtree.qtpl:30
+//line gititemtree.qtpl:31
 func (g *GitItemTreePage) StreamGitContent(qw422016 *qt422016.Writer, name, ref string) {
-//line gititemtree.qtpl:30
+//line gititemtree.qtpl:31
 	qw422016.N().S(`
 <div class="pathing">
     `)
-//line gititemtree.qtpl:33
+//line gititemtree.qtpl:34
 	if len(g.Path) != 0 {
-//line gititemtree.qtpl:33
-		qw422016.N().S(`<a href="`)
 //line gititemtree.qtpl:34
+		qw422016.N().S(`<a href="`)
+//line gititemtree.qtpl:35
 		qw422016.E().S(url(name, Folder, ref, Root, []string{}))
-//line gititemtree.qtpl:34
+//line gititemtree.qtpl:35
 		qw422016.N().S(`">root/</a>`)
-//line gititemtree.qtpl:35
+//line gititemtree.qtpl:36
 		for i, e := range g.Path[:len(g.Path)-1] {
-//line gititemtree.qtpl:35
+//line gititemtree.qtpl:36
 			qw422016.N().S(`<a href="`)
-//line gititemtree.qtpl:36
+//line gititemtree.qtpl:37
 			qw422016.E().S(url(name, Folder, ref, Root, g.Path[:1+i]))
-//line gititemtree.qtpl:36
+//line gititemtree.qtpl:37
 			qw422016.N().S(`">`)
-//line gititemtree.qtpl:36
+//line gititemtree.qtpl:37
 			qw422016.E().S(e)
-//line gititemtree.qtpl:36
+//line gititemtree.qtpl:37
 			qw422016.N().S(`/</a>`)
-//line gititemtree.qtpl:37
+//line gititemtree.qtpl:38
 		}
-//line gititemtree.qtpl:37
-		qw422016.N().S(`<a>`)
 //line gititemtree.qtpl:38
+		qw422016.N().S(`<a>`)
+//line gititemtree.qtpl:39
 		qw422016.E().S(u.LastOrZero(g.Path))
-//line gititemtree.qtpl:38
+//line gititemtree.qtpl:39
 		qw422016.N().S(`</a>`)
-//line gititemtree.qtpl:39
+//line gititemtree.qtpl:40
 	} else {
-//line gititemtree.qtpl:39
+//line gititemtree.qtpl:40
 		qw422016.N().S(`<a>root/</a>`)
-//line gititemtree.qtpl:41
-	}
 //line gititemtree.qtpl:42
+	}
+//line gititemtree.qtpl:43
 	qw422016.N().S(`
 </div>
 <div class="row">
   <div class="col-md-12">
     <div class="tree-list">
       `)
-//line gititemtree.qtpl:47
+//line gititemtree.qtpl:48
 	if len(g.Path) != 0 {
-//line gititemtree.qtpl:47
+//line gititemtree.qtpl:48
 		qw422016.N().S(`
           <div class="mode"><a href="`)
-//line gititemtree.qtpl:48
+//line gititemtree.qtpl:49
 		qw422016.E().S(url(name, Folder, ref, g.Path[len(g.Path)-1], g.Path[:len(g.Path)-1]))
-//line gititemtree.qtpl:48
+//line gititemtree.qtpl:49
 		qw422016.N().S(`">..</a></div>
           <div class="name tree"></div>
           <div class="commit"></div>
           <div class="date"></div>
           <div class="size"></div>
       `)
-//line gititemtree.qtpl:53
+//line gititemtree.qtpl:54
 	}
-//line gititemtree.qtpl:53
+//line gititemtree.qtpl:54
 	qw422016.N().S(`
       `)
-//line gititemtree.qtpl:54
+//line gititemtree.qtpl:55
 	for _, e := range g.Tree.Entries {
-//line gititemtree.qtpl:54
-		qw422016.N().S(`
-          <div class="mode">`)
 //line gititemtree.qtpl:55
-		qw422016.E().S(Ignore(e.Mode.ToOSFileMode()).String())
-//line gititemtree.qtpl:55
-		qw422016.N().S(`</div>
+		qw422016.N().S(`
           `)
 //line gititemtree.qtpl:56
 		if e.Mode.IsFile() {
 //line gititemtree.qtpl:56
 			qw422016.N().S(`
+          <div class="mode">`)
+//line gititemtree.qtpl:57
+			qw422016.E().S(Ignore(e.Mode.ToOSFileMode()).String())
+//line gititemtree.qtpl:57
+			qw422016.N().S(`</div>
           <div class="name blob"><a href="`)
-//line gititemtree.qtpl:57
+//line gititemtree.qtpl:58
 			qw422016.E().S(url(name, Blob, ref, e.Name, g.Path))
-//line gititemtree.qtpl:57
+//line gititemtree.qtpl:58
 			qw422016.N().S(`">`)
-//line gititemtree.qtpl:57
+//line gititemtree.qtpl:58
 			qw422016.E().S(e.Name)
-//line gititemtree.qtpl:57
+//line gititemtree.qtpl:58
 			qw422016.N().S(`</a></div>
           `)
-//line gititemtree.qtpl:58
+//line gititemtree.qtpl:59
+		} else if e.Mode == filemode.Submodule {
+//line gititemtree.qtpl:59
+			qw422016.N().S(`
+          <div class="mode">m---------</div>
+          <div class="name tree">`)
+//line gititemtree.qtpl:61
+			qw422016.E().S(e.Name)
+//line gititemtree.qtpl:61
+			qw422016.N().S(` (submodule)</div>
+          `)
+//line gititemtree.qtpl:62
 		} else {
-//line gititemtree.qtpl:58
+//line gititemtree.qtpl:62
 			qw422016.N().S(`
+          <div class="mode">d---------</div>
           <div class="name tree"><a href="`)
-//line gititemtree.qtpl:59
+//line gititemtree.qtpl:64
 			qw422016.E().S(url(name, Folder, ref, e.Name, g.Path))
-//line gititemtree.qtpl:59
+//line gititemtree.qtpl:64
 			qw422016.N().S(`">`)
-//line gititemtree.qtpl:59
+//line gititemtree.qtpl:64
 			qw422016.E().S(e.Name)
-//line gititemtree.qtpl:59
+//line gititemtree.qtpl:64
 			qw422016.N().S(`</a></div>
           `)
-//line gititemtree.qtpl:60
+//line gititemtree.qtpl:65
 		}
-//line gititemtree.qtpl:60
+//line gititemtree.qtpl:65
 		qw422016.N().S(`
           <div class="commit"></div>
           <div class="date"></div>
           <div class="size">`)
-//line gititemtree.qtpl:63
+//line gititemtree.qtpl:68
 		qw422016.N().DL(Ignore(g.Tree.Size(e.Name)))
-//line gititemtree.qtpl:63
+//line gititemtree.qtpl:68
 		qw422016.N().S(` KiB</div>
       `)
-//line gititemtree.qtpl:64
+//line gititemtree.qtpl:69
 	}
-//line gititemtree.qtpl:64
+//line gititemtree.qtpl:69
 	qw422016.N().S(`
     </div>
   </div>
 </div>
 `)
-//line gititemtree.qtpl:68
+//line gititemtree.qtpl:73
 }
 
-//line gititemtree.qtpl:68
+//line gititemtree.qtpl:73
 func (g *GitItemTreePage) WriteGitContent(qq422016 qtio422016.Writer, name, ref string) {
-//line gititemtree.qtpl:68
+//line gititemtree.qtpl:73
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line gititemtree.qtpl:68
+//line gititemtree.qtpl:73
 	g.StreamGitContent(qw422016, name, ref)
-//line gititemtree.qtpl:68
+//line gititemtree.qtpl:73
 	qt422016.ReleaseWriter(qw422016)
-//line gititemtree.qtpl:68
+//line gititemtree.qtpl:73
 }
 
-//line gititemtree.qtpl:68
+//line gititemtree.qtpl:73
 func (g *GitItemTreePage) GitContent(name, ref string) string {
-//line gititemtree.qtpl:68
+//line gititemtree.qtpl:73
 	qb422016 := qt422016.AcquireByteBuffer()
-//line gititemtree.qtpl:68
+//line gititemtree.qtpl:73
 	g.WriteGitContent(qb422016, name, ref)
-//line gititemtree.qtpl:68
+//line gititemtree.qtpl:73
 	qs422016 := string(qb422016.B)
-//line gititemtree.qtpl:68
+//line gititemtree.qtpl:73
 	qt422016.ReleaseByteBuffer(qb422016)
-//line gititemtree.qtpl:68
+//line gititemtree.qtpl:73
 	return qs422016
-//line gititemtree.qtpl:68
+//line gititemtree.qtpl:73
 }