Commit b0f300063e499f398c6e563b1b3960fbb104d16a

Authored by Dmitriy Zaporozhets
2 parents 8841eec4 bd20ec1a

Merge branch 'feature/delete_file' of /home/git/repositories/gitlab/gitlabhq

app/contexts/files/delete_context.rb 0 → 100644
@@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
  1 +module Files
  2 + class DeleteContext < BaseContext
  3 + def execute
  4 + allowed = if project.protected_branch?(ref)
  5 + can?(current_user, :push_code_to_protected_branches, project)
  6 + else
  7 + can?(current_user, :push_code, project)
  8 + end
  9 +
  10 + unless allowed
  11 + return error("You are not allowed to push into this branch")
  12 + end
  13 +
  14 + unless repository.branch_names.include?(ref)
  15 + return error("You can only create files if you are on top of a branch")
  16 + end
  17 +
  18 + blob = repository.blob_at(ref, path)
  19 +
  20 + unless blob
  21 + return error("You can only edit text files")
  22 + end
  23 +
  24 + delete_file_action = Gitlab::Satellite::DeleteFileAction.new(current_user, project, ref, path)
  25 +
  26 + deleted_successfully = delete_file_action.commit!(
  27 + nil,
  28 + params[:commit_message]
  29 + )
  30 +
  31 + if deleted_successfully
  32 + success
  33 + else
  34 + error("Your changes could not be commited, because the file has been changed")
  35 + end
  36 + end
  37 + end
  38 +end
app/controllers/projects/blob_controller.rb
@@ -7,9 +7,30 @@ class Projects::BlobController &lt; Projects::ApplicationController @@ -7,9 +7,30 @@ class Projects::BlobController &lt; Projects::ApplicationController
7 before_filter :authorize_code_access! 7 before_filter :authorize_code_access!
8 before_filter :require_non_empty_project 8 before_filter :require_non_empty_project
9 9
  10 + before_filter :blob
  11 +
10 def show 12 def show
11 - @blob = @repository.blob_at(@commit.id, @path) 13 + end
  14 +
  15 + def destroy
  16 + result = Files::DeleteContext.new(@project, current_user, params, @ref, @path).execute
  17 +
  18 + if result[:status] == :success
  19 + flash[:notice] = "Your changes have been successfully commited"
  20 + redirect_to project_tree_path(@project, @ref)
  21 + else
  22 + flash[:alert] = result[:error]
  23 + render :show
  24 + end
  25 + end
  26 +
  27 + private
  28 +
  29 + def blob
  30 + @blob ||= @repository.blob_at(@commit.id, @path)
  31 +
  32 + return not_found! unless @blob
12 33
13 - not_found! unless @blob 34 + @blob
14 end 35 end
15 end 36 end
app/views/projects/blob/_actions.html.haml
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 - if allowed_tree_edit? 4 - if allowed_tree_edit?
5 = link_to "edit", project_edit_tree_path(@project, @id), class: "btn btn-small" 5 = link_to "edit", project_edit_tree_path(@project, @id), class: "btn btn-small"
6 - else 6 - else
7 - %span.btn.btn-small.disabled Edit 7 + %span.btn.btn-small.disabled edit
8 = link_to "raw", project_raw_path(@project, @id), class: "btn btn-small", target: "_blank" 8 = link_to "raw", project_raw_path(@project, @id), class: "btn btn-small", target: "_blank"
9 -# only show normal/blame view links for text files 9 -# only show normal/blame view links for text files
10 - if @blob.text? 10 - if @blob.text?
@@ -13,3 +13,7 @@ @@ -13,3 +13,7 @@
13 - else 13 - else
14 = link_to "blame", project_blame_path(@project, @id), class: "btn btn-small" unless @blob.empty? 14 = link_to "blame", project_blame_path(@project, @id), class: "btn btn-small" unless @blob.empty?
15 = link_to "history", project_commits_path(@project, @id), class: "btn btn-small" 15 = link_to "history", project_commits_path(@project, @id), class: "btn btn-small"
  16 +
  17 + - if allowed_tree_edit?
  18 + = link_to '#modal-remove-blob', class: "remove-blob btn btn-small btn-remove", "data-toggle" => "modal" do
  19 + remove
app/views/projects/blob/_remove.html.haml 0 → 100644
@@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
  1 +%div#modal-remove-blob.modal.hide
  2 + .modal-header
  3 + %a.close{href: "#", "data-dismiss" => "modal"} ×
  4 + %h3.page-title Remove #{@blob.name}
  5 + %p.light
  6 + From branch
  7 + %strong= @ref
  8 +
  9 + .modal-body
  10 + = form_tag project_blob_path(@project, @id), method: :delete do
  11 + .control-group.commit_message-group
  12 + = label_tag 'commit_message', class: "control-label" do
  13 + Commit message
  14 + .controls
  15 + = text_area_tag 'commit_message', params[:commit_message], placeholder: "Removed this file because...", required: true, rows: 3
  16 + .control-group
  17 + .controls
  18 + = submit_tag 'Remove file', class: 'btn btn-remove'
  19 + = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal"
app/views/projects/blob/show.html.haml
@@ -2,3 +2,6 @@ @@ -2,3 +2,6 @@
2 = render 'shared/ref_switcher', destination: 'blob', path: @path 2 = render 'shared/ref_switcher', destination: 'blob', path: @path
3 %div#tree-holder.tree-holder 3 %div#tree-holder.tree-holder
4 = render 'blob', blob: @blob 4 = render 'blob', blob: @blob
  5 +
  6 +- if allowed_tree_edit?
  7 + = render 'projects/blob/remove'
config/routes.rb
@@ -173,7 +173,7 @@ Gitlab::Application.routes.draw do @@ -173,7 +173,7 @@ Gitlab::Application.routes.draw do
173 end 173 end
174 174
175 scope module: :projects do 175 scope module: :projects do
176 - resources :blob, only: [:show], constraints: {id: /.+/} 176 + resources :blob, only: [:show, :destroy], constraints: {id: /.+/}
177 resources :raw, only: [:show], constraints: {id: /.+/} 177 resources :raw, only: [:show], constraints: {id: /.+/}
178 resources :tree, only: [:show], constraints: {id: /.+/, format: /(html|js)/ } 178 resources :tree, only: [:show], constraints: {id: /.+/, format: /(html|js)/ }
179 resources :edit_tree, only: [:show, :update], constraints: {id: /.+/}, path: 'edit' 179 resources :edit_tree, only: [:show, :update], constraints: {id: /.+/}, path: 'edit'
lib/gitlab/satellite/files/delete_file_action.rb 0 → 100644
@@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
  1 +require_relative 'file_action'
  2 +
  3 +module Gitlab
  4 + module Satellite
  5 + class DeleteFileAction < FileAction
  6 + # Deletes file and creates a new commit for it
  7 + #
  8 + # Returns false if committing the change fails
  9 + # Returns false if pushing from the satellite to bare repo failed or was rejected
  10 + # Returns true otherwise
  11 + def commit!(content, commit_message)
  12 + in_locked_and_timed_satellite do |repo|
  13 + prepare_satellite!(repo)
  14 +
  15 + # create target branch in satellite at the corresponding commit from bare repo
  16 + repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}")
  17 +
  18 + # update the file in the satellite's working dir
  19 + file_path_in_satellite = File.join(repo.working_dir, file_path)
  20 + File.delete(file_path_in_satellite)
  21 +
  22 + # add removed file
  23 + repo.remove(file_path_in_satellite)
  24 +
  25 + # commit the changes
  26 + # will raise CommandFailed when commit fails
  27 + repo.git.commit(raise: true, timeout: true, a: true, m: commit_message)
  28 +
  29 +
  30 + # push commit back to bare repo
  31 + # will raise CommandFailed when push fails
  32 + repo.git.push({raise: true, timeout: true}, :origin, ref)
  33 +
  34 + # everything worked
  35 + true
  36 + end
  37 + rescue Grit::Git::CommandFailed => ex
  38 + Gitlab::GitLogger.error(ex.message)
  39 + false
  40 + end
  41 + end
  42 + end
  43 +end
lib/gitlab/satellite/files/edit_file_action.rb
@@ -8,13 +8,13 @@ module Gitlab @@ -8,13 +8,13 @@ module Gitlab
8 # 8 #
9 # Returns false if the ref has been updated while editing the file 9 # Returns false if the ref has been updated while editing the file
10 # Returns false if committing the change fails 10 # Returns false if committing the change fails
11 - # Returns false if pushing from the satellite to Gitolite failed or was rejected 11 + # Returns false if pushing from the satellite to bare repo failed or was rejected
12 # Returns true otherwise 12 # Returns true otherwise
13 def commit!(content, commit_message) 13 def commit!(content, commit_message)
14 in_locked_and_timed_satellite do |repo| 14 in_locked_and_timed_satellite do |repo|
15 prepare_satellite!(repo) 15 prepare_satellite!(repo)
16 16
17 - # create target branch in satellite at the corresponding commit from Gitolite 17 + # create target branch in satellite at the corresponding commit from bare repo
18 repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}") 18 repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}")
19 19
20 # update the file in the satellite's working dir 20 # update the file in the satellite's working dir
@@ -26,7 +26,7 @@ module Gitlab @@ -26,7 +26,7 @@ module Gitlab
26 repo.git.commit(raise: true, timeout: true, a: true, m: commit_message) 26 repo.git.commit(raise: true, timeout: true, a: true, m: commit_message)
27 27
28 28
29 - # push commit back to Gitolite 29 + # push commit back to bare repo
30 # will raise CommandFailed when push fails 30 # will raise CommandFailed when push fails
31 repo.git.push({raise: true, timeout: true}, :origin, ref) 31 repo.git.push({raise: true, timeout: true}, :origin, ref)
32 32
lib/gitlab/satellite/files/new_file_action.rb
@@ -7,13 +7,13 @@ module Gitlab @@ -7,13 +7,13 @@ module Gitlab
7 # 7 #
8 # Returns false if the ref has been updated while editing the file 8 # Returns false if the ref has been updated while editing the file
9 # Returns false if committing the change fails 9 # Returns false if committing the change fails
10 - # Returns false if pushing from the satellite to Gitolite failed or was rejected 10 + # Returns false if pushing from the satellite to bare repo failed or was rejected
11 # Returns true otherwise 11 # Returns true otherwise
12 def commit!(content, commit_message) 12 def commit!(content, commit_message)
13 in_locked_and_timed_satellite do |repo| 13 in_locked_and_timed_satellite do |repo|
14 prepare_satellite!(repo) 14 prepare_satellite!(repo)
15 15
16 - # create target branch in satellite at the corresponding commit from Gitolite 16 + # create target branch in satellite at the corresponding commit from bare repo
17 repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}") 17 repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}")
18 18
19 # update the file in the satellite's working dir 19 # update the file in the satellite's working dir
@@ -28,7 +28,7 @@ module Gitlab @@ -28,7 +28,7 @@ module Gitlab
28 repo.git.commit(raise: true, timeout: true, a: true, m: commit_message) 28 repo.git.commit(raise: true, timeout: true, a: true, m: commit_message)
29 29
30 30
31 - # push commit back to Gitolite 31 + # push commit back to bare repo
32 # will raise CommandFailed when push fails 32 # will raise CommandFailed when push fails
33 repo.git.push({raise: true, timeout: true}, :origin, ref) 33 repo.git.push({raise: true, timeout: true}, :origin, ref)
34 34
lib/gitlab/satellite/merge_action.rb
@@ -28,7 +28,7 @@ module Gitlab @@ -28,7 +28,7 @@ module Gitlab
28 in_locked_and_timed_satellite do |merge_repo| 28 in_locked_and_timed_satellite do |merge_repo|
29 prepare_satellite!(merge_repo) 29 prepare_satellite!(merge_repo)
30 if merge_in_satellite!(merge_repo) 30 if merge_in_satellite!(merge_repo)
31 - # push merge back to Gitolite 31 + # push merge back to bare repo
32 # will raise CommandFailed when push fails 32 # will raise CommandFailed when push fails
33 merge_repo.git.push(default_options, :origin, merge_request.target_branch) 33 merge_repo.git.push(default_options, :origin, merge_request.target_branch)
34 # remove source branch 34 # remove source branch
lib/gitlab/satellite/satellite.rb
@@ -123,7 +123,7 @@ module Gitlab @@ -123,7 +123,7 @@ module Gitlab
123 remotes.each { |name| repo.git.remote(default_options,'rm', name)} 123 remotes.each { |name| repo.git.remote(default_options,'rm', name)}
124 end 124 end
125 125
126 - # Updates the satellite from Gitolite 126 + # Updates the satellite from bare repo
127 # 127 #
128 # Note: this will only update remote branches (i.e. origin/*) 128 # Note: this will only update remote branches (i.e. origin/*)
129 def update_from_source! 129 def update_from_source!