diff --git a/models/repo.go b/models/repo.go
index edf800bd70..4b6dedaf90 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -81,6 +81,7 @@ var (
var (
ErrRepoAlreadyExist = errors.New("Repository already exist")
ErrRepoNotExist = errors.New("Repository does not exist")
+ ErrRepoFileNotExist = errors.New("Target Repo file does not exist")
)
func init() {
@@ -463,6 +464,51 @@ func GetBranches(userName, reposName string) ([]string, error) {
return brs, nil
}
+func GetTargetFile(userName, reposName, branchName, commitId, rpath string) (*RepoFile, error) {
+ repo, err := git.OpenRepository(RepoPath(userName, reposName))
+ if err != nil {
+ return nil, err
+ }
+
+ commit, err := repo.GetCommit(branchName, commitId)
+ if err != nil {
+ return nil, err
+ }
+
+ parts := strings.Split(path.Clean(rpath), "/")
+
+ var entry *git.TreeEntry
+ tree := commit.Tree
+ for i, part := range parts {
+ if i == len(parts)-1 {
+ entry = tree.EntryByName(part)
+ if entry == nil {
+ return nil, ErrRepoFileNotExist
+ }
+ } else {
+ tree, err = repo.SubTree(tree, part)
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+
+ size, err := repo.ObjectSize(entry.Id)
+ if err != nil {
+ return nil, err
+ }
+
+ repoFile := &RepoFile{
+ entry,
+ rpath,
+ size,
+ repo,
+ commit,
+ }
+
+ return repoFile, nil
+}
+
// GetReposFiles returns a list of file object in given directory of repository.
func GetReposFiles(userName, reposName, branchName, commitId, rpath string) ([]*RepoFile, error) {
repo, err := git.OpenRepository(RepoPath(userName, reposName))
diff --git a/modules/base/markdown.go b/modules/base/markdown.go
index 049b107548..a9f4cbf0d7 100644
--- a/modules/base/markdown.go
+++ b/modules/base/markdown.go
@@ -7,6 +7,8 @@ package base
import (
"bytes"
"path"
+ "path/filepath"
+ "strings"
"github.com/gogits/gfm"
)
@@ -31,6 +33,26 @@ func isLink(link []byte) bool {
return false
}
+func IsMarkdownFile(name string) bool {
+ name = strings.ToLower(name)
+ switch filepath.Ext(name) {
+ case "md", "markdown":
+ return true
+ }
+ return false
+}
+
+func IsReadmeFile(name string) bool {
+ name = strings.ToLower(name)
+ if len(name) < 6 {
+ return false
+ }
+ if name[:6] == "readme" {
+ return true
+ }
+ return false
+}
+
type CustomRender struct {
gfm.Renderer
urlPrefix string
diff --git a/routers/repo/single.go b/routers/repo/single.go
index 87b08a4ad5..c10d30a7d6 100644
--- a/routers/repo/single.go
+++ b/routers/repo/single.go
@@ -5,7 +5,6 @@
package repo
import (
- "fmt"
"strings"
"github.com/codegangsta/martini"
@@ -47,7 +46,7 @@ func Single(ctx *middleware.Context, params martini.Params) {
return
}
- if params["branchname"] == "" {
+ if len(params["branchname"]) == 0 {
params["branchname"] = "master"
}
@@ -56,7 +55,7 @@ func Single(ctx *middleware.Context, params martini.Params) {
if len(treename) > 0 && treename[len(treename)-1] == '/' {
ctx.Redirect("/"+ctx.Repo.Owner.LowerName+"/"+
- ctx.Repo.Repository.Name+"/tree/"+params["branchname"]+"/"+treename[:len(treename)-1], 302)
+ ctx.Repo.Repository.Name+"/src/"+params["branchname"]+"/"+treename[:len(treename)-1], 302)
return
}
@@ -74,14 +73,78 @@ func Single(ctx *middleware.Context, params martini.Params) {
ctx.Data["Branches"] = brs
- // Directory and file list.
- files, err := models.GetReposFiles(params["username"], params["reponame"],
+ repoFile, err := models.GetTargetFile(params["username"], params["reponame"],
params["branchname"], params["commitid"], treename)
- if err != nil {
- log.Error("repo.Single(GetReposFiles): %v", err)
+
+ if err != nil && err != models.ErrRepoFileNotExist {
+ log.Error("repo.Single(GetTargetFile): %v", err)
ctx.Error(404)
return
}
+
+ branchLink := "/" + ctx.Repo.Owner.LowerName + "/" + ctx.Repo.Repository.Name + "/src/" + params["branchname"]
+
+ if repoFile != nil && repoFile.IsFile() {
+ if repoFile.Size > 1024*1024 || repoFile.Filemode != git.FileModeBlob {
+ ctx.Data["FileIsLarge"] = true
+ } else if blob, err := repoFile.LookupBlob(); err != nil {
+ log.Error("repo.Single(repoFile.LookupBlob): %v", err)
+ ctx.Error(404)
+ } else {
+ ctx.Data["IsFile"] = true
+ ctx.Data["FileName"] = repoFile.Name
+
+ readmeExist := base.IsMarkdownFile(repoFile.Name) || base.IsReadmeFile(repoFile.Name)
+ ctx.Data["ReadmeExist"] = readmeExist
+ if readmeExist {
+ ctx.Data["FileContent"] = string(base.RenderMarkdown(blob.Contents(), ""))
+ } else {
+ ctx.Data["FileContent"] = string(blob.Contents())
+ }
+ }
+
+ } else {
+ // Directory and file list.
+ files, err := models.GetReposFiles(params["username"], params["reponame"],
+ params["branchname"], params["commitid"], treename)
+ if err != nil {
+ log.Error("repo.Single(GetReposFiles): %v", err)
+ ctx.Error(404)
+ return
+ }
+
+ ctx.Data["Files"] = files
+
+ var readmeFile *models.RepoFile
+
+ for _, f := range files {
+ if !f.IsFile() || !base.IsReadmeFile(f.Name) {
+ continue
+ } else {
+ readmeFile = f
+ break
+ }
+ }
+
+ if readmeFile != nil {
+ ctx.Data["ReadmeExist"] = true
+ // if file large than 1M not show it
+ if readmeFile.Size > 1024*1024 || readmeFile.Filemode != git.FileModeBlob {
+ ctx.Data["FileIsLarge"] = true
+ } else if blob, err := readmeFile.LookupBlob(); err != nil {
+ log.Error("repo.Single(readmeFile.LookupBlob): %v", err)
+ ctx.Error(404)
+ return
+ } else {
+ // current repo branch link
+ urlPrefix := "http://" + base.Domain + branchLink
+
+ ctx.Data["FileName"] = readmeFile.Name
+ ctx.Data["FileContent"] = string(base.RenderMarkdown(blob.Contents(), urlPrefix))
+ }
+ }
+ }
+
ctx.Data["Username"] = params["username"]
ctx.Data["Reponame"] = params["reponame"]
ctx.Data["Branchname"] = params["branchname"]
@@ -111,39 +174,10 @@ func Single(ctx *middleware.Context, params martini.Params) {
}
ctx.Data["LastCommit"] = commit
- var readmeFile *models.RepoFile
-
- for _, f := range files {
- if !f.IsFile() || len(f.Name) < 6 {
- continue
- } else if strings.ToLower(f.Name[:6]) == "readme" {
- readmeFile = f
- break
- }
- }
-
- if readmeFile != nil {
- ctx.Data["ReadmeExist"] = true
- // if file large than 1M not show it
- if readmeFile.Size > 1024*1024 || readmeFile.Filemode != git.FileModeBlob {
- ctx.Data["FileIsLarge"] = true
- } else if blob, err := readmeFile.LookupBlob(); err != nil {
- ctx.Data["ReadmeExist"] = false
- } else {
- // current repo branch link
- urlPrefix := "http://" + base.Domain + "/" + ctx.Repo.Owner.LowerName + "/" +
- ctx.Repo.Repository.Name + "/tree/" + params["branchname"]
-
- ctx.Data["ReadmeContent"] = string(base.RenderMarkdown(blob.Contents(), urlPrefix))
- }
- }
-
- log.Trace("repo.Single: Paths: %s", strings.Join(Paths, ", "))
-
ctx.Data["Paths"] = Paths
ctx.Data["Treenames"] = treenames
ctx.Data["IsRepoToolbarSource"] = true
- ctx.Data["Files"] = files
+ ctx.Data["BranchLink"] = branchLink
ctx.HTML(200, "repo/single", ctx.Data)
}
diff --git a/templates/repo/single.tmpl b/templates/repo/single.tmpl
index e18f79c293..60247898e2 100644
--- a/templates/repo/single.tmpl
+++ b/templates/repo/single.tmpl
@@ -8,104 +8,35 @@
Need to fill in some guide.
{{else}}
-
-
- {{if .ReadmeExist}}
-
-
- README.md
-
- {{if .FileIsLarge}}
-
- {{else}}
-
- {{.ReadmeContent|str2html}}
-
- {{end}}
-
+ {{if .IsFile}}
+ {{template "repo/single_file" .}}
+ {{else}}
+ {{template "repo/single_list" .}}
{{end}}
{{end}}
diff --git a/templates/repo/single_file.tmpl b/templates/repo/single_file.tmpl
new file mode 100644
index 0000000000..f74e09de09
--- /dev/null
+++ b/templates/repo/single_file.tmpl
@@ -0,0 +1,20 @@
+
+
+ {{.FileName}}
+
+ {{if .FileIsLarge}}
+
+ {{else}}
+ {{if .ReadmeExist}}
+
+ {{.FileContent|str2html}}
+
+ {{else}}
+
+
{{.FileContent|str2html}}
+
+ {{end}}
+ {{end}}
+
\ No newline at end of file
diff --git a/templates/repo/single_list.tmpl b/templates/repo/single_list.tmpl
new file mode 100644
index 0000000000..b0c31d1e44
--- /dev/null
+++ b/templates/repo/single_list.tmpl
@@ -0,0 +1,54 @@
+
+{{if .ReadmeExist}}
+ {{template "repo/single_file" .}}
+{{end}}
\ No newline at end of file
diff --git a/web.go b/web.go
index f793518a18..ceb193e6fd 100644
--- a/web.go
+++ b/web.go
@@ -107,9 +107,9 @@ func runWeb(*cli.Context) {
m.Get("/:username/:reponame/pulls", ignSignIn, middleware.RepoAssignment(true), repo.Pulls)
m.Get("/:username/:reponame/branches", ignSignIn, middleware.RepoAssignment(true), repo.Branches)
m.Get("/:username/:reponame/action/:action", reqSignIn, middleware.RepoAssignment(true), repo.Action)
- m.Get("/:username/:reponame/tree/:branchname/**",
+ m.Get("/:username/:reponame/src/:branchname/**",
ignSignIn, middleware.RepoAssignment(true), repo.Single)
- m.Get("/:username/:reponame/tree/:branchname",
+ m.Get("/:username/:reponame/src/:branchname",
ignSignIn, middleware.RepoAssignment(true), repo.Single)
m.Get("/:username/:reponame/commit/:commitid/**", ignSignIn, middleware.RepoAssignment(true), repo.Single)
m.Get("/:username/:reponame/commit/:commitid", ignSignIn, middleware.RepoAssignment(true), repo.Single)