Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1354,8 +1354,11 @@ editor.this_file_locked = File is locked
editor.must_be_on_a_branch = You must be on a branch to make or propose changes to this file.
editor.fork_before_edit = You must fork this repository to make or propose changes to this file.
editor.delete_this_file = Delete File
editor.delete_this_directory = Delete Directory
editor.must_have_write_access = You must have write access to make or propose changes to this file.
editor.file_delete_success = File "%s" has been deleted.
editor.directory_delete_success = Directory "%s" has been deleted.
editor.delete_directory = Delete directory '%s'
editor.name_your_file = Name your file…
editor.filename_help = Add a directory by typing its name followed by a slash ('/'). Remove a directory by typing backspace at the beginning of the input field.
editor.or = or
Expand Down
4 changes: 0 additions & 4 deletions routers/api/v1/repo/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -610,10 +610,6 @@ func handleChangeRepoFilesError(ctx *context.APIContext, err error) {
ctx.APIError(http.StatusUnprocessableEntity, err)
return
}
if git.IsErrBranchNotExist(err) || files_service.IsErrRepoFileDoesNotExist(err) || git.IsErrNotExist(err) {
ctx.APIError(http.StatusNotFound, err)
return
}
if errors.Is(err, util.ErrNotExist) {
ctx.APIError(http.StatusNotFound, err)
return
Expand Down
39 changes: 33 additions & 6 deletions routers/web/repo/editor.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,8 @@ func EditFile(ctx *context.Context) {
return
}

prepareHomeTreeSideBarSwitch(ctx)

// on the "New File" page, we should add an empty path field to make end users could input a new name
prepareTreePathFieldsAndPaths(ctx, util.Iif(isNewFile, ctx.Repo.TreePath+"/", ctx.Repo.TreePath))

Expand Down Expand Up @@ -384,25 +386,45 @@ func DeleteFile(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplDeleteFile)
}

// DeleteFilePost response for deleting file
// DeleteFilePost response for deleting file or directory
func DeleteFilePost(ctx *context.Context) {
parsed := prepareEditorCommitSubmittedForm[*forms.DeleteRepoFileForm](ctx)
if ctx.Written() {
return
}

treePath := ctx.Repo.TreePath
_, err := files_service.ChangeRepoFiles(ctx, ctx.Repo.Repository, ctx.Doer, &files_service.ChangeRepoFilesOptions{
if treePath == "" {
ctx.JSONError(ctx.Tr("repo.editor.cannot_delete_root"))
return
}

// Check if the path is a directory
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(treePath)
if err != nil {
ctx.NotFoundOrServerError("GetTreeEntryByPath", git.IsErrNotExist, err)
return
}

var commitMessage string
if entry.IsDir() {
commitMessage = parsed.GetCommitMessage(ctx.Locale.TrString("repo.editor.delete_directory", treePath))
} else {
commitMessage = parsed.GetCommitMessage(ctx.Locale.TrString("repo.editor.delete", treePath))
}

_, err = files_service.ChangeRepoFiles(ctx, ctx.Repo.Repository, ctx.Doer, &files_service.ChangeRepoFilesOptions{
LastCommitID: parsed.form.LastCommit,
OldBranch: parsed.OldBranchName,
NewBranch: parsed.NewBranchName,
Files: []*files_service.ChangeRepoFile{
{
Operation: "delete",
TreePath: treePath,
Operation: "delete",
TreePath: treePath,
DeleteRecursively: true,
},
},
Message: parsed.GetCommitMessage(ctx.Locale.TrString("repo.editor.delete", treePath)),
Message: commitMessage,
Signoff: parsed.form.Signoff,
Author: parsed.GitCommitter,
Committer: parsed.GitCommitter,
Expand All @@ -412,13 +434,18 @@ func DeleteFilePost(ctx *context.Context) {
return
}

ctx.Flash.Success(ctx.Tr("repo.editor.file_delete_success", treePath))
if entry.IsDir() {
ctx.Flash.Success(ctx.Tr("repo.editor.directory_delete_success", treePath))
} else {
ctx.Flash.Success(ctx.Tr("repo.editor.file_delete_success", treePath))
}
redirectTreePath := getClosestParentWithFiles(ctx.Repo.GitRepo, parsed.NewBranchName, treePath)
redirectForCommitChoice(ctx, parsed, redirectTreePath)
}

func UploadFile(ctx *context.Context) {
ctx.Data["PageIsUpload"] = true
prepareHomeTreeSideBarSwitch(ctx)
prepareTreePathFieldsAndPaths(ctx, ctx.Repo.TreePath)
opts := prepareEditorCommitFormOptions(ctx, "_upload")
if ctx.Written() {
Expand Down
1 change: 1 addition & 0 deletions routers/web/repo/editor_apply_patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
)

func NewDiffPatch(ctx *context.Context) {
prepareHomeTreeSideBarSwitch(ctx)
prepareEditorCommitFormOptions(ctx, "_diffpatch")
if ctx.Written() {
return
Expand Down
24 changes: 0 additions & 24 deletions routers/web/repo/find.go

This file was deleted.

1 change: 0 additions & 1 deletion routers/web/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -1188,7 +1188,6 @@ func registerWebRoutes(m *web.Router) {
m.Post("/{username}/{reponame}/markup", optSignIn, context.RepoAssignment, reqUnitsWithMarkdown, web.Bind(structs.MarkupOption{}), misc.Markup)

m.Group("/{username}/{reponame}", func() {
m.Get("/find/*", repo.FindFiles)
m.Group("/tree-list", func() {
m.Get("/branch/*", context.RepoRefByType(git.RefTypeBranch), repo.TreeList)
m.Get("/tag/*", context.RepoRefByType(git.RefTypeTag), repo.TreeList)
Expand Down
11 changes: 11 additions & 0 deletions services/repository/files/temp_repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,17 @@ func (t *TemporaryUploadRepository) LsFiles(ctx context.Context, filenames ...st
return fileList, nil
}

func (t *TemporaryUploadRepository) RemoveRecursivelyFromIndex(ctx context.Context, path string) error {
stdOut := new(bytes.Buffer)
stdErr := new(bytes.Buffer)
return gitcmd.NewCommand("rm", "--cached", "-r").
AddDynamicArguments(path).
WithDir(t.basePath).
WithStdout(stdOut).
WithStderr(stdErr).
Run(ctx)
}

// RemoveFilesFromIndex removes the given files from the index
func (t *TemporaryUploadRepository) RemoveFilesFromIndex(ctx context.Context, filenames ...string) error {
objFmt, err := t.gitRepo.GetObjectFormat()
Expand Down
49 changes: 10 additions & 39 deletions services/repository/files/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ type ChangeRepoFile struct {
FromTreePath string
ContentReader io.ReadSeeker
SHA string
Options *RepoFileOptions

DeleteRecursively bool // when deleting, work as `git rm -r ...`

Options *RepoFileOptions // FIXME: need to refactor, internal usage only
}

// ChangeRepoFilesOptions holds the repository files update options
Expand All @@ -69,26 +72,6 @@ type RepoFileOptions struct {
executable bool
}

// ErrRepoFileDoesNotExist represents a "RepoFileDoesNotExist" kind of error.
type ErrRepoFileDoesNotExist struct {
Path string
Name string
}

// IsErrRepoFileDoesNotExist checks if an error is a ErrRepoDoesNotExist.
func IsErrRepoFileDoesNotExist(err error) bool {
_, ok := err.(ErrRepoFileDoesNotExist)
return ok
}

func (err ErrRepoFileDoesNotExist) Error() string {
return fmt.Sprintf("repository file does not exist [path: %s]", err.Path)
}

func (err ErrRepoFileDoesNotExist) Unwrap() error {
return util.ErrNotExist
}

type LazyReadSeeker interface {
io.ReadSeeker
io.Closer
Expand Down Expand Up @@ -217,24 +200,6 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
}
}

for _, file := range opts.Files {
if file.Operation == "delete" {
// Get the files in the index
filesInIndex, err := t.LsFiles(ctx, file.TreePath)
if err != nil {
return nil, fmt.Errorf("DeleteRepoFile: %w", err)
}

// Find the file we want to delete in the index
inFilelist := slices.Contains(filesInIndex, file.TreePath)
if !inFilelist {
return nil, ErrRepoFileDoesNotExist{
Path: file.TreePath,
}
}
}
}

if hasOldBranch {
// Get the commit of the original branch
commit, err := t.GetBranchCommit(opts.OldBranch)
Expand Down Expand Up @@ -272,6 +237,12 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
addedLfsPointers = append(addedLfsPointers, *addedLfsPointer)
}
case "delete":
if file.DeleteRecursively {
if err = t.RemoveRecursivelyFromIndex(ctx, file.TreePath); err != nil {
return nil, err
}
continue
}
if err = t.RemoveFilesFromIndex(ctx, file.TreePath); err != nil {
return nil, err
}
Expand Down
18 changes: 14 additions & 4 deletions templates/repo/editor/edit.tmpl
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
{{template "base/head" .}}
<div role="main" aria-label="{{.Title}}" class="page-content repository file editor edit">
{{template "repo/header" .}}
<div class="ui container">
<div class="ui container fluid padded">
{{template "base/alert" .}}
<form class="ui edit form form-fetch-action" method="post" action="{{.CommitFormOptions.TargetFormAction}}"
<div class="repo-view-container">
<div class="tw-flex tw-flex-col repo-view-file-tree-container not-mobile {{if not .UserSettingCodeViewShowFileTree}}tw-hidden{{end}}" {{if .IsSigned}}data-user-is-signed-in{{end}}>
{{template "repo/view_file_tree" .}}
</div>
<div class="repo-view-content">
<form class="ui edit form form-fetch-action" method="post" action="{{.CommitFormOptions.TargetFormAction}}"
data-text-empty-confirm-header="{{ctx.Locale.Tr "repo.editor.commit_empty_file_header"}}"
data-text-empty-confirm-content="{{ctx.Locale.Tr "repo.editor.commit_empty_file_text"}}"
>
{{.CsrfTokenHtml}}
{{template "repo/editor/common_top" .}}
<div class="repo-editor-header">
<div class="repo-editor-header tw-flex tw-items-center tw-gap-2">
<button type="button" class="repo-view-file-tree-toggle-show ui compact basic button icon not-mobile {{if .UserSettingCodeViewShowFileTree}}tw-hidden{{end}}" data-global-click="onRepoViewFileTreeToggle" data-toggle-action="show" data-tooltip-content="{{ctx.Locale.Tr "repo.diff.show_file_tree"}}">
{{svg "octicon-sidebar-collapse"}}
</button>
{{template "repo/editor/common_breadcrumb" .}}
</div>
{{if not .NotEditableReason}}
Expand Down Expand Up @@ -47,7 +55,9 @@
</div>
{{end}}
{{template "repo/editor/commit_form" .}}
</form>
</form>
</div>
</div>
</div>
</div>
{{template "base/footer" .}}
62 changes: 32 additions & 30 deletions templates/repo/editor/patch.tmpl
Original file line number Diff line number Diff line change
@@ -1,39 +1,41 @@
{{template "base/head" .}}
<div role="main" aria-label="{{.Title}}" class="page-content repository file editor edit">
{{template "repo/header" .}}
<div class="ui container">
<div class="ui container fluid padded">
{{template "base/alert" .}}
<form class="ui edit form form-fetch-action" method="post" action="{{.CommitFormOptions.TargetFormAction}}"
data-text-empty-confirm-header="{{ctx.Locale.Tr "repo.editor.commit_empty_file_header"}}"
data-text-empty-confirm-content="{{ctx.Locale.Tr "repo.editor.commit_empty_file_text"}}"
>
{{.CsrfTokenHtml}}
{{template "repo/editor/common_top" .}}
<div class="repo-editor-header">
<div class="breadcrumb">
{{ctx.Locale.Tr "repo.editor.patching"}}
<a class="section" href="{{$.RepoLink}}">{{.Repository.FullName}}</a>
<div class="breadcrumb-divider">:</div>
<a class="section" href="{{$.BranchLink}}">{{.BranchName}}</a>
<span>{{ctx.Locale.Tr "repo.editor.or"}} <a href="{{$.BranchLink}}">{{ctx.Locale.Tr "repo.editor.cancel_lower"}}</a></span>
<input type="hidden" name="tree_path" value="__dummy_for_EditRepoFileForm.TreePath(Required)__">
<input id="file-name" type="hidden" value="diff.patch">
</div>
<div class="repo-view-container">
<div class="tw-flex tw-flex-col repo-view-file-tree-container not-mobile {{if not .UserSettingCodeViewShowFileTree}}tw-hidden{{end}}" {{if .IsSigned}}data-user-is-signed-in{{end}}>
{{template "repo/view_file_tree" .}}
</div>
<div class="field">
<div class="ui compact small menu small-menu-items repo-editor-menu">
<a class="active item" data-tab="write">{{svg "octicon-code" 16 "tw-mr-1"}}{{ctx.Locale.Tr "repo.editor.new_patch"}}</a>
</div>
<div class="ui active tab segment tw-rounded tw-p-0" data-tab="write">
<textarea id="edit_area" name="content" class="tw-hidden" data-id="repo-{{.Repository.Name}}-patch"
data-context="{{.RepoLink}}"
data-line-wrap-extensions="{{.LineWrapExtensions}}">
{{.FileContent}}</textarea>
<div class="editor-loading is-loading"></div>
</div>
<div class="repo-view-content">
<form class="ui edit form form-fetch-action" method="post" action="{{.CommitFormOptions.TargetFormAction}}" data-text-empty-confirm-header="{{ctx.Locale.Tr "repo.editor.commit_empty_file_header"}}" data-text-empty-confirm-content="{{ctx.Locale.Tr "repo.editor.commit_empty_file_text"}}">
{{.CsrfTokenHtml}}
{{template "repo/editor/common_top" .}}
<div class="repo-editor-header tw-flex tw-items-center tw-gap-2">
<button type="button" class="repo-view-file-tree-toggle-show ui compact basic button icon not-mobile {{if .UserSettingCodeViewShowFileTree}}tw-hidden{{end}}" data-global-click="onRepoViewFileTreeToggle" data-toggle-action="show" data-tooltip-content="{{ctx.Locale.Tr "repo.diff.show_file_tree"}}">
{{svg "octicon-sidebar-collapse"}}
</button>
<div class="breadcrumb">
{{ctx.Locale.Tr "repo.editor.patching"}}
<a class="section" href="{{$.BranchLink}}">{{.BranchName}}</a>
<span>{{ctx.Locale.Tr "repo.editor.or"}} <a href="{{$.BranchLink}}">{{ctx.Locale.Tr "repo.editor.cancel_lower"}}</a></span>
<input type="hidden" name="tree_path" value="__dummy_for_EditRepoFileForm.TreePath(Required)__">
<input id="file-name" type="hidden" value="diff.patch">
</div>
</div>
<div class="field">
<div class="ui compact small menu small-menu-items repo-editor-menu">
<a class="active item" data-tab="write">{{svg "octicon-code" 16 "tw-mr-1"}}{{ctx.Locale.Tr "repo.editor.new_patch"}}</a>
</div>
<div class="ui active tab segment tw-rounded tw-p-0" data-tab="write">
<textarea id="edit_area" name="content" class="tw-hidden" data-id="repo-{{.Repository.Name}}-patch" data-context="{{.RepoLink}}" data-line-wrap-extensions="{{.LineWrapExtensions}}">{{.FileContent}}</textarea>
<div class="editor-loading is-loading"></div>
</div>
</div>
{{template "repo/editor/commit_form" .}}
</form>
</div>
{{template "repo/editor/commit_form" .}}
</form>
</div>
</div>
</div>
{{template "base/footer" .}}
30 changes: 20 additions & 10 deletions templates/repo/editor/upload.tmpl
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
{{template "base/head" .}}
<div role="main" aria-label="{{.Title}}" class="page-content repository file editor upload">
{{template "repo/header" .}}
<div class="ui container">
<div class="ui container fluid padded">
{{template "base/alert" .}}
<form class="ui comment form form-fetch-action" method="post" action="{{.CommitFormOptions.TargetFormAction}}">
{{.CsrfTokenHtml}}
{{template "repo/editor/common_top" .}}
<div class="repo-editor-header">
{{template "repo/editor/common_breadcrumb" .}}
<div class="repo-view-container">
<div class="tw-flex tw-flex-col repo-view-file-tree-container not-mobile {{if not .UserSettingCodeViewShowFileTree}}tw-hidden{{end}}" {{if .IsSigned}}data-user-is-signed-in{{end}}>
{{template "repo/view_file_tree" .}}
</div>
<div class="field">
{{template "repo/upload" .}}
<div class="repo-view-content">
<form class="ui comment form form-fetch-action" method="post" action="{{.CommitFormOptions.TargetFormAction}}">
{{.CsrfTokenHtml}}
{{template "repo/editor/common_top" .}}
<div class="repo-editor-header tw-flex tw-items-center tw-gap-2">
<button type="button" class="repo-view-file-tree-toggle-show ui compact basic button icon not-mobile {{if .UserSettingCodeViewShowFileTree}}tw-hidden{{end}}" data-global-click="onRepoViewFileTreeToggle" data-toggle-action="show" data-tooltip-content="{{ctx.Locale.Tr "repo.diff.show_file_tree"}}">
{{svg "octicon-sidebar-collapse"}}
</button>
{{template "repo/editor/common_breadcrumb" .}}
</div>
<div class="field">
{{template "repo/upload" .}}
</div>
{{template "repo/editor/commit_form" .}}
</form>
</div>
{{template "repo/editor/commit_form" .}}
</form>
</div>
</div>
</div>
{{template "base/footer" .}}
Loading
Loading