mirror of
https://github.com/go-gitea/gitea
synced 2025-07-28 13:18:37 +00:00
Allow renaming/moving binary/LFS files in the UI (#34350)
Adds the ability to rename/move binary files like binary blobs or images and files that are too large in the web ui. This was purposed in #24722, along with the ability edit images via an upload of a new image, which I didn't implement here (could be done in a separate PR). Binary file content:  File too large:  GitHub does the same (I've copied the text from there): 
This commit is contained in:
@@ -145,10 +145,6 @@ func editFile(ctx *context.Context, isNewFile bool) {
|
||||
}
|
||||
|
||||
blob := entry.Blob()
|
||||
if blob.Size() >= setting.UI.MaxDisplayFileSize {
|
||||
ctx.NotFound(err)
|
||||
return
|
||||
}
|
||||
|
||||
buf, dataRc, fInfo, err := getFileReader(ctx, ctx.Repo.Repository.ID, blob)
|
||||
if err != nil {
|
||||
@@ -162,22 +158,37 @@ func editFile(ctx *context.Context, isNewFile bool) {
|
||||
|
||||
defer dataRc.Close()
|
||||
|
||||
ctx.Data["FileSize"] = blob.Size()
|
||||
|
||||
// Only some file types are editable online as text.
|
||||
if !fInfo.st.IsRepresentableAsText() || fInfo.isLFSFile {
|
||||
ctx.NotFound(nil)
|
||||
return
|
||||
if fInfo.isLFSFile {
|
||||
lfsLock, err := git_model.GetTreePathLock(ctx, ctx.Repo.Repository.ID, ctx.Repo.TreePath)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetTreePathLock", err)
|
||||
return
|
||||
}
|
||||
if lfsLock != nil && lfsLock.OwnerID != ctx.Doer.ID {
|
||||
ctx.NotFound(nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
d, _ := io.ReadAll(dataRc)
|
||||
ctx.Data["FileSize"] = fInfo.fileSize
|
||||
|
||||
buf = append(buf, d...)
|
||||
if content, err := charset.ToUTF8(buf, charset.ConvertOpts{KeepBOM: true}); err != nil {
|
||||
log.Error("ToUTF8: %v", err)
|
||||
ctx.Data["FileContent"] = string(buf)
|
||||
// Only some file types are editable online as text.
|
||||
if fInfo.isLFSFile {
|
||||
ctx.Data["NotEditableReason"] = ctx.Tr("repo.editor.cannot_edit_lfs_files")
|
||||
} else if !fInfo.st.IsRepresentableAsText() {
|
||||
ctx.Data["NotEditableReason"] = ctx.Tr("repo.editor.cannot_edit_non_text_files")
|
||||
} else if fInfo.fileSize >= setting.UI.MaxDisplayFileSize {
|
||||
ctx.Data["NotEditableReason"] = ctx.Tr("repo.editor.cannot_edit_too_large_file")
|
||||
} else {
|
||||
ctx.Data["FileContent"] = content
|
||||
d, _ := io.ReadAll(dataRc)
|
||||
|
||||
buf = append(buf, d...)
|
||||
if content, err := charset.ToUTF8(buf, charset.ConvertOpts{KeepBOM: true}); err != nil {
|
||||
log.Error("ToUTF8: %v", err)
|
||||
ctx.Data["FileContent"] = string(buf)
|
||||
} else {
|
||||
ctx.Data["FileContent"] = content
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Append filename from query, or empty string to allow username the new file.
|
||||
@@ -280,6 +291,10 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
|
||||
operation := "update"
|
||||
if isNewFile {
|
||||
operation = "create"
|
||||
} else if !form.Content.Has() && ctx.Repo.TreePath != form.TreePath {
|
||||
// The form content only has data if file is representable as text, is not too large and not in lfs. If it doesn't
|
||||
// have data, the only possible operation is a rename
|
||||
operation = "rename"
|
||||
}
|
||||
|
||||
if _, err := files_service.ChangeRepoFiles(ctx, ctx.Repo.Repository, ctx.Doer, &files_service.ChangeRepoFilesOptions{
|
||||
@@ -292,7 +307,7 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
|
||||
Operation: operation,
|
||||
FromTreePath: ctx.Repo.TreePath,
|
||||
TreePath: form.TreePath,
|
||||
ContentReader: strings.NewReader(strings.ReplaceAll(form.Content, "\r", "")),
|
||||
ContentReader: strings.NewReader(strings.ReplaceAll(form.Content.Value(), "\r", "")),
|
||||
},
|
||||
},
|
||||
Signoff: form.Signoff,
|
||||
|
@@ -99,7 +99,7 @@ func NewDiffPatchPost(ctx *context.Context) {
|
||||
OldBranch: ctx.Repo.BranchName,
|
||||
NewBranch: branchName,
|
||||
Message: message,
|
||||
Content: strings.ReplaceAll(form.Content, "\r", ""),
|
||||
Content: strings.ReplaceAll(form.Content.Value(), "\r", ""),
|
||||
Author: gitCommitter,
|
||||
Committer: gitCommitter,
|
||||
})
|
||||
|
@@ -285,10 +285,10 @@ func prepareToRenderFile(ctx *context.Context, entry *git.TreeEntry) {
|
||||
}
|
||||
}
|
||||
|
||||
prepareToRenderButtons(ctx, fInfo.isLFSFile, isRepresentableAsText, lfsLock)
|
||||
prepareToRenderButtons(ctx, lfsLock)
|
||||
}
|
||||
|
||||
func prepareToRenderButtons(ctx *context.Context, isLFSFile, isRepresentableAsText bool, lfsLock *git_model.LFSLock) {
|
||||
func prepareToRenderButtons(ctx *context.Context, lfsLock *git_model.LFSLock) {
|
||||
// archived or mirror repository, the buttons should not be shown
|
||||
if ctx.Repo.Repository.IsArchived || !ctx.Repo.Repository.CanEnableEditor() {
|
||||
return
|
||||
@@ -301,33 +301,16 @@ func prepareToRenderButtons(ctx *context.Context, isLFSFile, isRepresentableAsTe
|
||||
return
|
||||
}
|
||||
|
||||
if isLFSFile {
|
||||
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_lfs_files")
|
||||
} else if !isRepresentableAsText {
|
||||
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_non_text_files")
|
||||
}
|
||||
|
||||
if !ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, ctx.Repo.BranchName) {
|
||||
if !isLFSFile { // lfs file cannot be edited after fork
|
||||
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.fork_before_edit")
|
||||
}
|
||||
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.fork_before_edit")
|
||||
ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.must_have_write_access")
|
||||
return
|
||||
}
|
||||
|
||||
// it's a lfs file and the user is not the owner of the lock
|
||||
if lfsLock != nil && lfsLock.OwnerID != ctx.Doer.ID {
|
||||
ctx.Data["CanEditFile"] = false
|
||||
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.this_file_locked")
|
||||
ctx.Data["CanDeleteFile"] = false
|
||||
ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.this_file_locked")
|
||||
return
|
||||
}
|
||||
|
||||
if !isLFSFile { // lfs file cannot be edited
|
||||
ctx.Data["CanEditFile"] = true
|
||||
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.edit_this_file")
|
||||
}
|
||||
ctx.Data["CanDeleteFile"] = true
|
||||
ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.delete_this_file")
|
||||
isLFSLocked := lfsLock != nil && lfsLock.OwnerID != ctx.Doer.ID
|
||||
ctx.Data["CanEditFile"] = !isLFSLocked
|
||||
ctx.Data["EditFileTooltip"] = util.Iif(isLFSLocked, ctx.Tr("repo.editor.this_file_locked"), ctx.Tr("repo.editor.edit_this_file"))
|
||||
ctx.Data["CanDeleteFile"] = !isLFSLocked
|
||||
ctx.Data["DeleteFileTooltip"] = util.Iif(isLFSLocked, ctx.Tr("repo.editor.this_file_locked"), ctx.Tr("repo.editor.delete_this_file"))
|
||||
}
|
||||
|
Reference in New Issue
Block a user