forgejo-aneksajo_auto_patch.../data/46/ref_aneksajo_u.diff
2025-01-23 01:26:39 +01:00

192 lines
6.9 KiB
Diff

--- 9.0.3 2024-12-12 08:06:13.000000000 +0100
+++ aneksajo 2024-12-16 08:23:15.000000000 +0100
@@ -34,6 +34,7 @@
unit_model "code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/actions"
+ "code.gitea.io/gitea/modules/annex"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/charset"
"code.gitea.io/gitea/modules/git"
@@ -209,14 +210,59 @@
}
type fileInfo struct {
- isTextFile bool
- isLFSFile bool
- fileSize int64
- lfsMeta *lfs.Pointer
- st typesniffer.SniffedType
+ isTextFile bool
+ isLFSFile bool
+ isAnnexFile bool
+ isAnnexFilePresent bool
+ fileSize int64
+ lfsMeta *lfs.Pointer
+ st typesniffer.SniffedType
}
func getFileReader(ctx gocontext.Context, repoID int64, blob *git.Blob) ([]byte, io.ReadCloser, *fileInfo, error) {
+ isAnnexed, err := annex.IsAnnexed(blob)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ if isAnnexed {
+ // TODO: this code could be merged with the LFS case, especially the redundant type sniffer,
+ // but it is *currently* written this way to make merging with the non-annex upstream easier:
+ // this way, the git-annex patch is (mostly) pure additions.
+
+ annexContent, err := annex.Content(blob)
+ if err != nil {
+ // If annex.Content returns an error it can mean that the blob does not
+ // refer to an annexed file or that it is not present here. Since we already
+ // checked that it is annexed the latter must be the case. So we return the
+ // content of the blob instead and indicate that the file is indeed annexed,
+ // but not present here. The template can then communicate the situation.
+ dataRc, err := blob.DataAsync()
+ if err != nil {
+ return nil, nil, nil, err
+ }
+
+ buf := make([]byte, 1024)
+ n, _ := util.ReadAtMost(dataRc, buf)
+ buf = buf[:n]
+
+ st := typesniffer.DetectContentType(buf)
+ return buf, dataRc, &fileInfo{st.IsText(), false, true, false, blob.Size(), nil, st}, nil
+ }
+
+ stat, err := annexContent.Stat()
+ if err != nil {
+ return nil, nil, nil, err
+ }
+
+ buf := make([]byte, 1024)
+ n, _ := util.ReadAtMost(annexContent, buf)
+ buf = buf[:n]
+
+ st := typesniffer.DetectContentType(buf)
+
+ return buf, annexContent, &fileInfo{st.IsText(), false, true, true, stat.Size(), nil, st}, nil
+ }
+
dataRc, err := blob.DataAsync()
if err != nil {
return nil, nil, nil, err
@@ -231,18 +277,18 @@
// FIXME: what happens when README file is an image?
if !isTextFile || !setting.LFS.StartServer {
- return buf, dataRc, &fileInfo{isTextFile, false, blob.Size(), nil, st}, nil
+ return buf, dataRc, &fileInfo{isTextFile, false, false, false, blob.Size(), nil, st}, nil
}
pointer, _ := lfs.ReadPointerFromBuffer(buf)
if !pointer.IsValid() { // fallback to plain file
- return buf, dataRc, &fileInfo{isTextFile, false, blob.Size(), nil, st}, nil
+ return buf, dataRc, &fileInfo{isTextFile, false, false, false, blob.Size(), nil, st}, nil
}
meta, err := git_model.GetLFSMetaObjectByOid(ctx, repoID, pointer.Oid)
if err != nil { // fallback to plain file
log.Warn("Unable to access LFS pointer %s in repo %d: %v", pointer.Oid, repoID, err)
- return buf, dataRc, &fileInfo{isTextFile, false, blob.Size(), nil, st}, nil
+ return buf, dataRc, &fileInfo{isTextFile, false, false, false, blob.Size(), nil, st}, nil
}
dataRc.Close()
@@ -262,7 +308,7 @@
st = typesniffer.DetectContentType(buf)
- return buf, dataRc, &fileInfo{st.IsText(), true, meta.Size, &meta.Pointer, st}, nil
+ return buf, dataRc, &fileInfo{st.IsText(), true, false, false, meta.Size, &meta.Pointer, st}, nil
}
func renderReadmeFile(ctx *context.Context, subfolder string, readmeFile *git.TreeEntry) {
@@ -325,6 +371,7 @@
},
Metas: ctx.Repo.Repository.ComposeDocumentMetas(ctx),
GitRepo: ctx.Repo.GitRepo,
+ Blob: target.Blob(),
}, rd)
if err != nil {
log.Error("Render failed for %s in %-v: %v Falling back to rendering source", readmeFile.Name(), ctx.Repo.Repository, err)
@@ -447,10 +494,17 @@
isDisplayingSource := ctx.FormString("display") == "source"
isDisplayingRendered := !isDisplayingSource
- if fInfo.isLFSFile {
+ if fInfo.isLFSFile || fInfo.isAnnexFile {
ctx.Data["RawFileLink"] = ctx.Repo.RepoLink + "/media/" + ctx.Repo.BranchNameSubURL() + "/" + util.PathEscapeSegments(ctx.Repo.TreePath)
}
+ if fInfo.isAnnexFile {
+ // pre-git-annex v7, all annexed files were represented in-repo as symlinks;
+ // but we pretend they aren't, since that's a distracting quirk of git-annex
+ // and not a meaningful choice on the user's part
+ ctx.Data["FileIsSymlink"] = false
+ }
+
isRepresentableAsText := fInfo.st.IsRepresentableAsText()
if !isRepresentableAsText {
// If we can't show plain text, always try to render.
@@ -458,6 +512,8 @@
isDisplayingRendered = true
}
ctx.Data["IsLFSFile"] = fInfo.isLFSFile
+ ctx.Data["IsAnnexFile"] = fInfo.isAnnexFile
+ ctx.Data["IsAnnexFilePresent"] = fInfo.isAnnexFilePresent
ctx.Data["FileSize"] = fInfo.fileSize
ctx.Data["IsTextFile"] = fInfo.isTextFile
ctx.Data["IsRepresentableAsText"] = isRepresentableAsText
@@ -492,6 +548,8 @@
// Assume file is not editable first.
if fInfo.isLFSFile {
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_lfs_files")
+ } else if fInfo.isAnnexFile {
+ ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_annex_files")
} else if !isRepresentableAsText {
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_non_text_files")
}
@@ -546,6 +604,7 @@
},
Metas: metas,
GitRepo: ctx.Repo.GitRepo,
+ Blob: entry.Blob(),
}, rd)
if err != nil {
ctx.ServerError("Render", err)
@@ -599,7 +658,7 @@
ctx.Data["FileContent"] = fileContent
ctx.Data["LineEscapeStatus"] = statuses
}
- if !fInfo.isLFSFile {
+ if !fInfo.isLFSFile && !fInfo.isAnnexFile {
if ctx.Repo.CanEnableEditor(ctx, ctx.Doer) {
if lfsLock != nil && lfsLock.OwnerID != ctx.Doer.ID {
ctx.Data["CanEditFile"] = false
@@ -644,6 +703,7 @@
},
Metas: ctx.Repo.Repository.ComposeDocumentMetas(ctx),
GitRepo: ctx.Repo.GitRepo,
+ Blob: entry.Blob(),
}, rd)
if err != nil {
ctx.ServerError("Render", err)
@@ -1153,6 +1213,15 @@
ctx.Data["TreeNames"] = treeNames
ctx.Data["BranchLink"] = branchLink
ctx.Data["CodeIndexerDisabled"] = !setting.Indexer.RepoIndexerEnabled
+ isAnnexFile, okAnnexFile := ctx.Data["IsAnnexFile"]
+ isAnnexFilePresent, okAnnexFilePresent := ctx.Data["IsAnnexFilePresent"]
+ if okAnnexFile && okAnnexFilePresent && isAnnexFile.(bool) && !isAnnexFilePresent.(bool) {
+ // If the file to be viewed is annexed but not present then render it normally
+ // (which will show the plain git blob content, i.e. the symlink or pointer target)
+ // but make the status code a 404.
+ ctx.HTML(http.StatusNotFound, tplRepoHome)
+ return
+ }
ctx.HTML(http.StatusOK, tplRepoHome)
}