1// Copyright 2014 The Gogs Authors. All rights reserved.
2// Copyright 2018 The Gitea Authors. All rights reserved.
3// Use of this source code is governed by a MIT-style
4// license that can be found in the LICENSE file.
5
6package repo
7
8import (
9	"code.gitea.io/gitea/models"
10	"code.gitea.io/gitea/modules/context"
11	"code.gitea.io/gitea/modules/git"
12	"code.gitea.io/gitea/modules/httpcache"
13	"code.gitea.io/gitea/modules/lfs"
14	"code.gitea.io/gitea/modules/log"
15	"code.gitea.io/gitea/modules/setting"
16	"code.gitea.io/gitea/modules/storage"
17	"code.gitea.io/gitea/routers/common"
18)
19
20// ServeBlobOrLFS download a git.Blob redirecting to LFS if necessary
21func ServeBlobOrLFS(ctx *context.Context, blob *git.Blob) error {
22	if httpcache.HandleGenericETagCache(ctx.Req, ctx.Resp, `"`+blob.ID.String()+`"`) {
23		return nil
24	}
25
26	dataRc, err := blob.DataAsync()
27	if err != nil {
28		return err
29	}
30	closed := false
31	defer func() {
32		if closed {
33			return
34		}
35		if err = dataRc.Close(); err != nil {
36			log.Error("ServeBlobOrLFS: Close: %v", err)
37		}
38	}()
39
40	pointer, _ := lfs.ReadPointer(dataRc)
41	if pointer.IsValid() {
42		meta, _ := models.GetLFSMetaObjectByOid(ctx.Repo.Repository.ID, pointer.Oid)
43		if meta == nil {
44			if err = dataRc.Close(); err != nil {
45				log.Error("ServeBlobOrLFS: Close: %v", err)
46			}
47			closed = true
48			return common.ServeBlob(ctx, blob)
49		}
50		if httpcache.HandleGenericETagCache(ctx.Req, ctx.Resp, `"`+pointer.Oid+`"`) {
51			return nil
52		}
53
54		if setting.LFS.ServeDirect {
55			//If we have a signed url (S3, object storage), redirect to this directly.
56			u, err := storage.LFS.URL(pointer.RelativePath(), blob.Name())
57			if u != nil && err == nil {
58				ctx.Redirect(u.String())
59				return nil
60			}
61		}
62
63		lfsDataRc, err := lfs.ReadMetaObject(meta.Pointer)
64		if err != nil {
65			return err
66		}
67		defer func() {
68			if err = lfsDataRc.Close(); err != nil {
69				log.Error("ServeBlobOrLFS: Close: %v", err)
70			}
71		}()
72		return common.ServeData(ctx, ctx.Repo.TreePath, meta.Size, lfsDataRc)
73	}
74	if err = dataRc.Close(); err != nil {
75		log.Error("ServeBlobOrLFS: Close: %v", err)
76	}
77	closed = true
78
79	return common.ServeBlob(ctx, blob)
80}
81
82// SingleDownload download a file by repos path
83func SingleDownload(ctx *context.Context) {
84	blob, err := ctx.Repo.Commit.GetBlobByPath(ctx.Repo.TreePath)
85	if err != nil {
86		if git.IsErrNotExist(err) {
87			ctx.NotFound("GetBlobByPath", nil)
88		} else {
89			ctx.ServerError("GetBlobByPath", err)
90		}
91		return
92	}
93	if err = common.ServeBlob(ctx, blob); err != nil {
94		ctx.ServerError("ServeBlob", err)
95	}
96}
97
98// SingleDownloadOrLFS download a file by repos path redirecting to LFS if necessary
99func 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		}
107		return
108	}
109	if err = ServeBlobOrLFS(ctx, blob); err != nil {
110		ctx.ServerError("ServeBlobOrLFS", err)
111	}
112}
113
114// DownloadByID download a file by sha1 ID
115func DownloadByID(ctx *context.Context) {
116	blob, err := ctx.Repo.GitRepo.GetBlob(ctx.Params("sha"))
117	if err != nil {
118		if git.IsErrNotExist(err) {
119			ctx.NotFound("GetBlob", nil)
120		} else {
121			ctx.ServerError("GetBlob", err)
122		}
123		return
124	}
125	if err = common.ServeBlob(ctx, blob); err != nil {
126		ctx.ServerError("ServeBlob", err)
127	}
128}
129
130// DownloadByIDOrLFS download a file by sha1 ID taking account of LFS
131func DownloadByIDOrLFS(ctx *context.Context) {
132	blob, err := ctx.Repo.GitRepo.GetBlob(ctx.Params("sha"))
133	if err != nil {
134		if git.IsErrNotExist(err) {
135			ctx.NotFound("GetBlob", nil)
136		} else {
137			ctx.ServerError("GetBlob", err)
138		}
139		return
140	}
141	if err = ServeBlobOrLFS(ctx, blob); err != nil {
142		ctx.ServerError("ServeBlob", err)
143	}
144}
145