@@ -29,65 +29,24 @@ trait PagesControllerBase extends ControllerBase {
2929 self : AccountService with RepositoryService with PagesService with ReferrerAuthenticator with OwnerAuthenticator =>
3030 import PagesControllerBase ._
3131
32- case class OptionsForm (source : PageSourceType )
33-
3432 val optionsForm = mapping(
3533 " source" -> trim(label(" Pages Source" , text(required, pagesOption)))
3634 )(
37- (source) => OptionsForm (PageSourceType .valueOf(source))
38- )
35+ (source) => OptionsForm (PageSourceType .valueOf(source))
36+ )
3937
4038 val PAGES_BRANCHES = List (" gb-pages" , " gh-pages" )
4139
4240 get(" /:owner/:repository/pages/*" )(referrersOnly { repository =>
4341 val path = params(" splat" )
4442 using(Git .open(Directory .getRepositoryDir(repository.owner, repository.name))) { git =>
45-
46- def resolvePath (objectId : Option [(String , ObjectId )], path : String ) = {
47- objectId match {
48- case Some ((path0, objId)) =>
49- // redirect [owner/repo/pages/path] -> [owner/repo/pages/path/]
50- if (shouldRedirect(path, path0)) {
51- redirect(s " / ${repository.owner}/ ${repository.name}/pages/ $path/ " )
52- } else {
53- JGitUtil .getObjectLoaderFromId(git, objId) { loader =>
54- contentType = Option (servletContext.getMimeType(path0)).getOrElse(" application/octet-stream" )
55- response.setContentLength(loader.getSize.toInt)
56- loader.copyTo(response.getOutputStream)
57- }
58- ()
59- }
60- case None =>
61- NotFound ()
62- }
63- }
64-
65- val source = getPageOptions(repository.owner, repository.name) match {
66- case Some (p) => p.source
67- case None => PageSourceType .GH_PAGES
68- }
69- source match {
43+ getPageSource(repository.owner, repository.name) match {
7044 case PageSourceType .GH_PAGES =>
71- val objectId = PAGES_BRANCHES .collectFirst(resolveBranch(git, _))
72- .map(JGitUtil .getRevCommitFromId(git, _))
73- .flatMap { revCommit =>
74- getPathIndexObjectId(git, path, revCommit)
75- }
76- resolvePath(objectId, path)
45+ renderFromBranch(repository, git, path, PAGES_BRANCHES .collectFirstOpt(resolveBranch(git, _)))
7746 case PageSourceType .MASTER =>
78- val objectId = Option (git.getRepository.resolve(" master" ))
79- .map(JGitUtil .getRevCommitFromId(git, _))
80- .flatMap { revCommit =>
81- getPathIndexObjectId(git, path, revCommit)
82- }
83- resolvePath(objectId, path)
47+ renderFromBranch(repository, git, path, resolveBranch(git, " master" ))
8448 case PageSourceType .MASTER_DOCS =>
85- val objectId = Option (git.getRepository.resolve(" master" ))
86- .map(JGitUtil .getRevCommitFromId(git, _))
87- .flatMap { revCommit =>
88- getPathIndexObjectId(git, s " docs/ $path" , revCommit)
89- }
90- resolvePath(objectId, path)
49+ renderFromBranch(repository, git, joinPath(" docs" , path), resolveBranch(git, " master" ))
9150 case PageSourceType .NONE =>
9251 NotFound ()
9352 }
@@ -99,10 +58,7 @@ trait PagesControllerBase extends ControllerBase {
9958 })
10059
10160 get(" /:owner/:repository/settings/pages" )(ownerOnly { repository =>
102- val source = getPageOptions(repository.owner, repository.name) match {
103- case Some (p) => p.source
104- case None => PageSourceType .GH_PAGES
105- }
61+ val source = getPageSource(repository.owner, repository.name)
10662 html.options(repository, source, flash.get(" info" ))
10763 })
10864
@@ -112,51 +68,83 @@ trait PagesControllerBase extends ControllerBase {
11268 redirect(s " / ${repository.owner}/ ${repository.name}/settings/pages " )
11369 })
11470
71+ def renderPageObject (git : Git , path : String , obj : ObjectId ): Unit = {
72+ JGitUtil .getObjectLoaderFromId(git, obj) { loader =>
73+ contentType = guessContentType(path)
74+ response.setContentLength(loader.getSize.toInt)
75+ loader.copyTo(response.getOutputStream)
76+ }
77+ }
78+
79+ def renderFromBranch (repository : RepositoryService .RepositoryInfo , git : Git , path : String , branchObject : Option [ObjectId ]): Any = {
80+ val pagePair = branchObject
81+ .map(JGitUtil .getRevCommitFromId(git, _))
82+ .flatMap(getPageObjectId(git, path, _))
83+
84+ pagePair match {
85+ case Some ((realPath, _)) if shouldRedirect(path, realPath) =>
86+ redirect(s " / ${repository.owner}/ ${repository.name}/pages/ $path/ " )
87+ case Some ((realPath, pageObject)) =>
88+ renderPageObject(git, realPath, pageObject)
89+ case None =>
90+ NotFound ()
91+ }
92+ }
93+
11594 def resolveBranch (git : Git , name : String ) = Option (git.getRepository.resolve(name))
11695
96+ // redirect [owner/repo/pages/path] -> [owner/repo/pages/path/]
11797 def shouldRedirect (path : String , path0 : String ): Boolean =
11898 ! isRoot(path) && path0 != path && path0.startsWith(path) && ! path.endsWith(" /" )
11999
120- def getPathIndexObjectId (git : Git , path : String , revCommit : RevCommit ): Option [(String , ObjectId )] = {
121- getPathObjectId0(git, path, revCommit)
122- .orElse(getPathObjectId0(git, appendPath(path, " index.html" ), revCommit))
123- .orElse(getPathObjectId0(git, appendPath(path, " index.htm" ), revCommit))
100+ def getPageObjectId (git : Git , path : String , revCommit : RevCommit ): Option [(String , ObjectId )] = {
101+ listProbablePages(path).collectFirstOpt(getPathObjectIdPair(git, _, revCommit))
102+ }
103+
104+ def listProbablePages (path : String ): List [String ] = {
105+ path :: List (" index.html" , " index.htm" ).map(joinPath(path, _))
124106 }
125107
126- def getPathObjectId0 (git : Git , path : String , revCommit : RevCommit ): Option [(String , ObjectId )] = {
108+ def getPathObjectIdPair (git : Git , path : String , revCommit : RevCommit ): Option [(String , ObjectId )] = {
127109 getPathObjectId(git, path, revCommit).map(path -> _)
128110 }
129111
130- def appendPath (base : String , suffix : String ): String = {
131- if (isRoot(base)) suffix
132- else if (base.endsWith( " / " )) base + suffix
133- else base + " /" + suffix
112+ def joinPath (base : String , suffix : String ): String = {
113+ val sfx = suffix.stripPrefix( " / " )
114+ if (isRoot(base )) sfx
115+ else base.stripSuffix( " / " ) + " /" + sfx
134116 }
135117
136118 def isRoot (path : String ): Boolean = path == " "
137119
138- private def pagesOption : Constraint = new Constraint () {
139- override def validate (name : String , value : String , messages : Messages ): Option [String ] =
140- PageSourceType .valueOpt(value) match {
141- case Some (_) => None
142- case None => Some (" Pages source is invalid." )
143- }
120+ def guessContentType (path : String ): String = {
121+ Option (servletContext.getMimeType(path)).getOrElse(" application/octet-stream" )
144122 }
145- }
146123
124+ }
147125
148126object PagesControllerBase {
127+ case class OptionsForm (source : PageSourceType )
128+
149129 implicit class listCollectFirst [A ](private val lst : List [A ]) extends AnyVal {
150130 @ tailrec
151- final def collectFirst [B ](f : A => Option [B ]): Option [B ] = {
131+ final def collectFirstOpt [B ](f : A => Option [B ]): Option [B ] = {
152132 lst match {
153133 case head :: tail =>
154134 f(head) match {
155135 case Some (x) => Some (x)
156- case None => tail.collectFirst (f)
136+ case None => tail.collectFirstOpt (f)
157137 }
158138 case Nil => None
159139 }
160140 }
161141 }
142+
143+ def pagesOption : Constraint = new Constraint () {
144+ override def validate (name : String , value : String , messages : Messages ): Option [String ] =
145+ PageSourceType .valueOpt(value) match {
146+ case Some (_) => None
147+ case None => Some (" Pages source is invalid." )
148+ }
149+ }
162150}
0 commit comments