@ -6,7 +6,11 @@
package repo
package repo
import (
import (
"path"
"time"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/httpcache"
"code.gitea.io/gitea/modules/httpcache"
@ -18,8 +22,8 @@ import (
)
)
// ServeBlobOrLFS download a git.Blob redirecting to LFS if necessary
// ServeBlobOrLFS download a git.Blob redirecting to LFS if necessary
func ServeBlobOrLFS ( ctx * context . Context , blob * git . Blob ) error {
func ServeBlobOrLFS ( ctx * context . Context , blob * git . Blob , lastModified time . Time ) error {
if httpcache . HandleGenericETagCache ( ctx . Req , ctx . Resp , ` " ` + blob . ID . String ( ) + ` " ` ) {
if httpcache . HandleGenericETagTime Cache ( ctx . Req , ctx . Resp , ` " ` + blob . ID . String ( ) + ` " ` , lastModified ) {
return nil
return nil
}
}
@ -45,7 +49,7 @@ func ServeBlobOrLFS(ctx *context.Context, blob *git.Blob) error {
log . Error ( "ServeBlobOrLFS: Close: %v" , err )
log . Error ( "ServeBlobOrLFS: Close: %v" , err )
}
}
closed = true
closed = true
return common . ServeBlob ( ctx , blob )
return common . ServeBlob ( ctx , blob , lastModified )
}
}
if httpcache . HandleGenericETagCache ( ctx . Req , ctx . Resp , ` " ` + pointer . Oid + ` " ` ) {
if httpcache . HandleGenericETagCache ( ctx . Req , ctx . Resp , ` " ` + pointer . Oid + ` " ` ) {
return nil
return nil
@ -76,37 +80,65 @@ func ServeBlobOrLFS(ctx *context.Context, blob *git.Blob) error {
}
}
closed = true
closed = true
return common . ServeBlob ( ctx , blob )
return common . ServeBlob ( ctx , blob , lastModified )
}
}
// SingleDownload download a file by repos path
func getBlobForEntry ( ctx * context . Context ) ( blob * git . Blob , lastModified time . Time ) {
func SingleDownload ( ctx * context . Context ) {
entry , err := ctx . Repo . Commit . GetTreeEntryByPath ( ctx . Repo . TreePath )
blob , err := ctx . Repo . Commit . GetBlobByPath ( ctx . Repo . TreePath )
if err != nil {
if err != nil {
if git . IsErrNotExist ( err ) {
if git . IsErrNotExist ( err ) {
ctx . NotFound ( "GetBlobByPath" , nil )
ctx . NotFound ( "GetTreeEntryByPath" , err )
} else {
} else {
ctx . ServerError ( "GetBlobByPath" , err )
ctx . ServerError ( "GetTreeEntryByPath" , err )
}
return
}
if entry . IsDir ( ) || entry . IsSubModule ( ) {
ctx . NotFound ( "getBlobForEntry" , nil )
return
}
var c * git . LastCommitCache
if setting . CacheService . LastCommit . Enabled && ctx . Repo . CommitsCount >= setting . CacheService . LastCommit . CommitsCount {
c = git . NewLastCommitCache ( ctx . Repo . Repository . FullName ( ) , ctx . Repo . GitRepo , setting . LastCommitCacheTTLSeconds , cache . GetCache ( ) )
}
info , _ , err := git . Entries ( [ ] * git . TreeEntry { entry } ) . GetCommitsInfo ( ctx , ctx . Repo . Commit , path . Dir ( "/" + ctx . Repo . TreePath ) [ 1 : ] , c )
if err != nil {
ctx . ServerError ( "GetCommitsInfo" , err )
return
}
}
if len ( info ) == 1 {
// Not Modified
lastModified = info [ 0 ] . Commit . Committer . When
}
blob = entry . Blob ( )
return
}
// SingleDownload download a file by repos path
func SingleDownload ( ctx * context . Context ) {
blob , lastModified := getBlobForEntry ( ctx )
if blob == nil {
return
return
}
}
if err = common . ServeBlob ( ctx , blob ) ; err != nil {
if err := common . ServeBlob ( ctx , blob , lastModified ) ; err != nil {
ctx . ServerError ( "ServeBlob" , err )
ctx . ServerError ( "ServeBlob" , err )
}
}
}
}
// SingleDownloadOrLFS download a file by repos path redirecting to LFS if necessary
// SingleDownloadOrLFS download a file by repos path redirecting to LFS if necessary
func SingleDownloadOrLFS ( ctx * context . Context ) {
func SingleDownloadOrLFS ( ctx * context . Context ) {
blob , err := ctx . Repo . Commit . GetBlobByPath ( ctx . Repo . TreePath )
blob , lastModified := getBlobForEntry ( ctx )
if err != nil {
if blob == nil {
if git . IsErrNotExist ( err ) {
ctx . NotFound ( "GetBlobByPath" , nil )
} else {
ctx . ServerError ( "GetBlobByPath" , err )
}
return
return
}
}
if err = ServeBlobOrLFS ( ctx , blob ) ; err != nil {
if err := ServeBlobOrLFS ( ctx , blob , lastModified ) ; err != nil {
ctx . ServerError ( "ServeBlobOrLFS" , err )
ctx . ServerError ( "ServeBlobOrLFS" , err )
}
}
}
}
@ -122,7 +154,7 @@ func DownloadByID(ctx *context.Context) {
}
}
return
return
}
}
if err = common . ServeBlob ( ctx , blob ) ; err != nil {
if err = common . ServeBlob ( ctx , blob , time . Time { } ) ; err != nil {
ctx . ServerError ( "ServeBlob" , err )
ctx . ServerError ( "ServeBlob" , err )
}
}
}
}
@ -138,7 +170,7 @@ func DownloadByIDOrLFS(ctx *context.Context) {
}
}
return
return
}
}
if err = ServeBlobOrLFS ( ctx , blob ) ; err != nil {
if err = ServeBlobOrLFS ( ctx , blob , time . Time { } ) ; err != nil {
ctx . ServerError ( "ServeBlob" , err )
ctx . ServerError ( "ServeBlob" , err )
}
}
}
}