6
6
package repo
7
7
8
8
import (
9
+ "path"
10
+ "time"
11
+
9
12
"code.gitea.io/gitea/models"
13
+ "code.gitea.io/gitea/modules/cache"
10
14
"code.gitea.io/gitea/modules/context"
11
15
"code.gitea.io/gitea/modules/git"
12
16
"code.gitea.io/gitea/modules/httpcache"
@@ -18,8 +22,8 @@ import (
18
22
)
19
23
20
24
// ServeBlobOrLFS download a git.Blob redirecting to LFS if necessary
21
- func ServeBlobOrLFS (ctx * context.Context , blob * git.Blob ) error {
22
- if httpcache .HandleGenericETagCache (ctx .Req , ctx .Resp , `"` + blob .ID .String ()+ `"` ) {
25
+ func ServeBlobOrLFS (ctx * context.Context , blob * git.Blob , lastModified time. Time ) error {
26
+ if httpcache .HandleGenericETagTimeCache (ctx .Req , ctx .Resp , `"` + blob .ID .String ()+ `"` , lastModified ) {
23
27
return nil
24
28
}
25
29
@@ -45,7 +49,7 @@ func ServeBlobOrLFS(ctx *context.Context, blob *git.Blob) error {
45
49
log .Error ("ServeBlobOrLFS: Close: %v" , err )
46
50
}
47
51
closed = true
48
- return common .ServeBlob (ctx , blob )
52
+ return common .ServeBlob (ctx , blob , lastModified )
49
53
}
50
54
if httpcache .HandleGenericETagCache (ctx .Req , ctx .Resp , `"` + pointer .Oid + `"` ) {
51
55
return nil
@@ -76,37 +80,65 @@ func ServeBlobOrLFS(ctx *context.Context, blob *git.Blob) error {
76
80
}
77
81
closed = true
78
82
79
- return common .ServeBlob (ctx , blob )
83
+ return common .ServeBlob (ctx , blob , lastModified )
80
84
}
81
85
82
- // SingleDownload download a file by repos path
83
- func SingleDownload (ctx * context.Context ) {
84
- blob , err := ctx .Repo .Commit .GetBlobByPath (ctx .Repo .TreePath )
86
+ func getBlobForEntry (ctx * context.Context ) (blob * git.Blob , lastModified time.Time ) {
87
+ entry , err := ctx .Repo .Commit .GetTreeEntryByPath (ctx .Repo .TreePath )
85
88
if err != nil {
86
89
if git .IsErrNotExist (err ) {
87
- ctx .NotFound ("GetBlobByPath " , nil )
90
+ ctx .NotFound ("GetTreeEntryByPath " , err )
88
91
} else {
89
- ctx .ServerError ("GetBlobByPath " , err )
92
+ ctx .ServerError ("GetTreeEntryByPath " , err )
90
93
}
91
94
return
92
95
}
93
- if err = common .ServeBlob (ctx , blob ); err != nil {
96
+
97
+ if entry .IsDir () || entry .IsSubModule () {
98
+ ctx .NotFound ("getBlobForEntry" , nil )
99
+ return
100
+ }
101
+
102
+ var c * git.LastCommitCache
103
+ if setting .CacheService .LastCommit .Enabled && ctx .Repo .CommitsCount >= setting .CacheService .LastCommit .CommitsCount {
104
+ c = git .NewLastCommitCache (ctx .Repo .Repository .FullName (), ctx .Repo .GitRepo , setting .LastCommitCacheTTLSeconds , cache .GetCache ())
105
+ }
106
+
107
+ info , _ , err := git .Entries ([]* git.TreeEntry {entry }).GetCommitsInfo (ctx , ctx .Repo .Commit , path .Dir ("/" + ctx .Repo .TreePath )[1 :], c )
108
+ if err != nil {
109
+ ctx .ServerError ("GetCommitsInfo" , err )
110
+ return
111
+ }
112
+
113
+ if len (info ) == 1 {
114
+ // Not Modified
115
+ lastModified = info [0 ].Commit .Committer .When
116
+ }
117
+ blob = entry .Blob ()
118
+
119
+ return
120
+ }
121
+
122
+ // SingleDownload download a file by repos path
123
+ func SingleDownload (ctx * context.Context ) {
124
+ blob , lastModified := getBlobForEntry (ctx )
125
+ if blob == nil {
126
+ return
127
+ }
128
+
129
+ if err := common .ServeBlob (ctx , blob , lastModified ); err != nil {
94
130
ctx .ServerError ("ServeBlob" , err )
95
131
}
96
132
}
97
133
98
134
// SingleDownloadOrLFS download a file by repos path redirecting to LFS if necessary
99
135
func SingleDownloadOrLFS (ctx * context.Context ) {
100
- blob , err := ctx .Repo .Commit .GetBlobByPath (ctx .Repo .TreePath )
101
- if err != nil {
102
- if git .IsErrNotExist (err ) {
103
- ctx .NotFound ("GetBlobByPath" , nil )
104
- } else {
105
- ctx .ServerError ("GetBlobByPath" , err )
106
- }
136
+ blob , lastModified := getBlobForEntry (ctx )
137
+ if blob == nil {
107
138
return
108
139
}
109
- if err = ServeBlobOrLFS (ctx , blob ); err != nil {
140
+
141
+ if err := ServeBlobOrLFS (ctx , blob , lastModified ); err != nil {
110
142
ctx .ServerError ("ServeBlobOrLFS" , err )
111
143
}
112
144
}
@@ -122,7 +154,7 @@ func DownloadByID(ctx *context.Context) {
122
154
}
123
155
return
124
156
}
125
- if err = common .ServeBlob (ctx , blob ); err != nil {
157
+ if err = common .ServeBlob (ctx , blob , time. Time {} ); err != nil {
126
158
ctx .ServerError ("ServeBlob" , err )
127
159
}
128
160
}
@@ -138,7 +170,7 @@ func DownloadByIDOrLFS(ctx *context.Context) {
138
170
}
139
171
return
140
172
}
141
- if err = ServeBlobOrLFS (ctx , blob ); err != nil {
173
+ if err = ServeBlobOrLFS (ctx , blob , time. Time {} ); err != nil {
142
174
ctx .ServerError ("ServeBlob" , err )
143
175
}
144
176
}
0 commit comments