diff --git a/models/repo.go b/models/repo.go index 21d46aa250..610c359747 100644 --- a/models/repo.go +++ b/models/repo.go @@ -407,12 +407,10 @@ var ( // RepoFile represents a file object in git repository. type RepoFile struct { *git.TreeEntry - Path string - Message string - Created time.Time - Size int64 - Repo *git.Repository - LastCommit string + Path string + Size int64 + Repo *git.Repository + Commit *git.Commit } // LookupBlob returns the content of an object. @@ -444,32 +442,28 @@ func GetBranches(userName, reposName string) ([]string, error) { } // GetReposFiles returns a list of file object in given directory of repository. -func GetReposFiles(userName, reposName, branchName, rpath string) ([]*RepoFile, error) { +func GetReposFiles(userName, reposName, branchName, commitId, rpath string) ([]*RepoFile, error) { repo, err := git.OpenRepository(RepoPath(userName, reposName)) if err != nil { return nil, err } - ref, err := repo.LookupReference("refs/heads/" + branchName) - if err != nil { - return nil, err - } - - lastCommit, err := repo.LookupCommit(ref.Oid) + commit, err := GetCommit(userName, reposName, branchName, commitId) if err != nil { return nil, err } var repodirs []*RepoFile var repofiles []*RepoFile - lastCommit.Tree.Walk(func(dirname string, entry *git.TreeEntry) int { + commit.Tree.Walk(func(dirname string, entry *git.TreeEntry) int { if dirname == rpath { + // TODO: size get method shoule be improved size, err := repo.ObjectSize(entry.Id) if err != nil { return 0 } - var cm = lastCommit + var cm = commit for { if cm.ParentCount() == 0 { @@ -524,11 +518,9 @@ func GetReposFiles(userName, reposName, branchName, rpath string) ([]*RepoFile, rp := &RepoFile{ entry, path.Join(dirname, entry.Name), - cm.Message(), - cm.Committer.When, size, repo, - cm.Id().String(), + cm, } if entry.IsFile() { @@ -543,12 +535,23 @@ func GetReposFiles(userName, reposName, branchName, rpath string) ([]*RepoFile, return append(repodirs, repofiles...), nil } -// GetLastestCommit returns the latest commit of given repository. -func GetLastCommit(userName, repoName, branchname string) (*git.Commit, error) { +func GetCommit(userName, repoName, branchname, commitid string) (*git.Commit, error) { repo, err := git.OpenRepository(RepoPath(userName, repoName)) if err != nil { return nil, err } + + if commitid != "" { + oid, err := git.NewOidFromString(commitid) + if err != nil { + return nil, err + } + return repo.LookupCommit(oid) + } + if branchname == "" { + return nil, errors.New("no branch name and no commit id") + } + r, err := repo.LookupReference(fmt.Sprintf("refs/heads/%s", branchname)) if err != nil { return nil, err diff --git a/routers/repo/single.go b/routers/repo/single.go index 64ea508b0e..0cc41b1c8f 100644 --- a/routers/repo/single.go +++ b/routers/repo/single.go @@ -69,7 +69,7 @@ func Single(ctx *middleware.Context, params martini.Params) { // Directory and file list. files, err := models.GetReposFiles(params["username"], params["reponame"], - params["branchname"], treename) + params["branchname"], params["commitid"], treename) if err != nil { log.Error("repo.Single(GetReposFiles): %v", err) ctx.Render.Error(404) @@ -90,9 +90,10 @@ func Single(ctx *middleware.Context, params martini.Params) { } // Get latest commit according username and repo name - commit, err := models.GetLastCommit(params["username"], params["reponame"], params["branchname"]) + commit, err := models.GetCommit(params["username"], params["reponame"], + params["branchname"], params["commitid"]) if err != nil { - log.Error("repo.Single(GetLastestCommit): %v", err) + log.Error("repo.Single(GetCommit): %v", err) ctx.Render.Error(404) return } diff --git a/templates/repo/single.tmpl b/templates/repo/single.tmpl index 3831c2dc41..f167444635 100644 --- a/templates/repo/single.tmpl +++ b/templates/repo/single.tmpl @@ -73,10 +73,10 @@ - {{.Message}} + {{.Commit.Message}} - {{TimeSince .Created}} + {{TimeSince .Commit.Committer.When}} {{end}} diff --git a/web.go b/web.go index 2177d5662f..ca504ea560 100644 --- a/web.go +++ b/web.go @@ -82,6 +82,9 @@ func runWeb(*cli.Context) { middleware.SignInRequire(false), middleware.RepoAssignment(true), repo.Single) m.Get("/:username/:reponame/tree/:branchname", middleware.SignInRequire(false), middleware.RepoAssignment(true), repo.Single) + m.Get("/:username/:reponame/commit/:commitid/**", middleware.SignInRequire(false), middleware.RepoAssignment(true), repo.Single) + m.Get("/:username/:reponame/commit/:commitid", middleware.SignInRequire(false), middleware.RepoAssignment(true), repo.Single) + m.Get("/:username/:reponame", middleware.SignInRequire(false), middleware.RepoAssignment(true), repo.Single) listenAddr := fmt.Sprintf("%s:%s",