diff --git a/models/repo.go b/models/repo.go index edf800bd7..4b6dedaf9 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 049b10754..a9f4cbf0d 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 87b08a4ad..c10d30a7d 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 e18f79c29..60247898e 100644 --- a/templates/repo/single.tmpl +++ b/templates/repo/single.tmpl @@ -8,104 +8,35 @@ Need to fill in some guide. {{else}}
- {{ $username := .Username}} - {{ $reponame := .Reponame}} - {{ $branchname := .Branchname}} - {{ $treenames := .Treenames}} - {{ $repoLink := .RepositoryLink}} - {{ $n := len $treenames}} - + {{ $n := len .Treenames}} + {{if not .IsFile}}{{end}} - {{$paths := .Paths}} {{ $l := Subtract $n 1}}
- -
-
- {{.LastCommit.Message}} -
-
- {{.LastCommit.Author.Name}} {{TimeSince .LastCommit.Author.When}} -
- - - - - - - - - - - {{if .HasParentPath}} - - - - - - - {{end}} - {{range .Files}} - - - - - - - {{end}} - - -
- {{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 000000000..f74e09de0 --- /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 000000000..b0c31d1e4 --- /dev/null +++ b/templates/repo/single_list.tmpl @@ -0,0 +1,54 @@ +
+
+ {{.LastCommit.Message}} +
+
+ {{.LastCommit.Author.Name}} {{TimeSince .LastCommit.Author.When}} +
+ + + + + + + + + + + {{if .HasParentPath}} + + + + + + + {{end}} + {{range .Files}} + + + + + + + {{end}} + + +
+{{if .ReadmeExist}} + {{template "repo/single_file" .}} +{{end}} \ No newline at end of file diff --git a/web.go b/web.go index f793518a1..ceb193e6f 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)