Commit c4299bb45a97314fd51962b91346c65ba564d388
1 parent
01033631
Exists in
master
and in
4 other branches
Move directory logic out of model. Use Gitlab:Shell class to interact with file system
Showing
3 changed files
with
80 additions
and
33 deletions
Show diff stats
app/models/namespace.rb
| ... | ... | @@ -13,6 +13,8 @@ |
| 13 | 13 | # |
| 14 | 14 | |
| 15 | 15 | class Namespace < ActiveRecord::Base |
| 16 | + include Gitlab::ShellAdapter | |
| 17 | + | |
| 16 | 18 | attr_accessible :name, :description, :path |
| 17 | 19 | |
| 18 | 20 | has_many :projects, dependent: :destroy |
| ... | ... | @@ -31,7 +33,7 @@ class Namespace < ActiveRecord::Base |
| 31 | 33 | delegate :name, to: :owner, allow_nil: true, prefix: true |
| 32 | 34 | |
| 33 | 35 | after_create :ensure_dir_exist |
| 34 | - after_update :move_dir | |
| 36 | + after_update :move_dir, if: :path_changed? | |
| 35 | 37 | after_destroy :rm_dir |
| 36 | 38 | |
| 37 | 39 | scope :root, -> { where('type IS NULL') } |
| ... | ... | @@ -53,48 +55,34 @@ class Namespace < ActiveRecord::Base |
| 53 | 55 | end |
| 54 | 56 | |
| 55 | 57 | def ensure_dir_exist |
| 56 | - unless dir_exists? | |
| 57 | - FileUtils.mkdir( namespace_full_path, mode: 0770 ) | |
| 58 | - end | |
| 59 | - end | |
| 60 | - | |
| 61 | - def dir_exists? | |
| 62 | - File.exists?(namespace_full_path) | |
| 58 | + gitlab_shell.add_namespace(path) | |
| 63 | 59 | end |
| 64 | 60 | |
| 65 | - def namespace_full_path | |
| 66 | - @namespace_full_path ||= File.join(Gitlab.config.gitlab_shell.repos_path, path) | |
| 61 | + def rm_dir | |
| 62 | + gitlab_shell.rm_namespace(path) | |
| 67 | 63 | end |
| 68 | 64 | |
| 69 | 65 | def move_dir |
| 70 | - if path_changed? | |
| 71 | - old_path = File.join(Gitlab.config.gitlab_shell.repos_path, path_was) | |
| 72 | - new_path = File.join(Gitlab.config.gitlab_shell.repos_path, path) | |
| 73 | - if File.exists?(new_path) | |
| 74 | - raise "Already exists" | |
| 75 | - end | |
| 76 | - | |
| 77 | - | |
| 66 | + if gitlab_shell.mv_namespace(path_was, path) | |
| 67 | + # If repositories moved successfully we need to remove old satellites | |
| 68 | + # and send update instructions to users. | |
| 69 | + # However we cannot allow rollback since we moved namespace dir | |
| 70 | + # So we basically we mute exceptions in next actions | |
| 78 | 71 | begin |
| 79 | - # Remove satellite when moving repo | |
| 80 | - if path_was.present? | |
| 81 | - satellites_path = File.join(Gitlab.config.satellites.path, path_was) | |
| 82 | - FileUtils.rm_r( satellites_path, force: true ) | |
| 83 | - end | |
| 84 | - | |
| 85 | - FileUtils.mv( old_path, new_path ) | |
| 72 | + gitlab_shell.rm_satellites(path_was) | |
| 86 | 73 | send_update_instructions |
| 87 | - rescue Exception => e | |
| 88 | - raise "Namespace move error #{old_path} #{new_path}" | |
| 74 | + rescue | |
| 75 | + # Returning false does not rolback after_* transaction but gives | |
| 76 | + # us information about failing some of tasks | |
| 77 | + false | |
| 89 | 78 | end |
| 79 | + else | |
| 80 | + # if we cannot move namespace directory we should rollback | |
| 81 | + # db changes in order to prevent out of sync between db and fs | |
| 82 | + raise Exception.new('namespace directory cannot be moved') | |
| 90 | 83 | end |
| 91 | 84 | end |
| 92 | 85 | |
| 93 | - def rm_dir | |
| 94 | - dir_path = File.join(Gitlab.config.gitlab_shell.repos_path, path) | |
| 95 | - FileUtils.rm_r( dir_path, force: true ) | |
| 96 | - end | |
| 97 | - | |
| 98 | 86 | def send_update_instructions |
| 99 | 87 | projects.each(&:send_move_instructions) |
| 100 | 88 | end | ... | ... |
lib/gitlab/backend/shell.rb
| ... | ... | @@ -65,13 +65,72 @@ module Gitlab |
| 65 | 65 | system("#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-keys rm-key #{key_id} \"#{key_content}\"") |
| 66 | 66 | end |
| 67 | 67 | |
| 68 | + # Add empty directory for storing repositories | |
| 69 | + # | |
| 70 | + # Ex. | |
| 71 | + # add_namespace("gitlab") | |
| 72 | + # | |
| 73 | + def add_namespace(name) | |
| 74 | + FileUtils.mkdir(full_path(name), mode: 0770) unless exists?(name) | |
| 75 | + end | |
| 76 | + | |
| 77 | + # Remove directory from repositories storage | |
| 78 | + # Every repository inside this directory will be removed too | |
| 79 | + # | |
| 80 | + # Ex. | |
| 81 | + # rm_namespace("gitlab") | |
| 82 | + # | |
| 83 | + def rm_namespace(name) | |
| 84 | + FileUtils.rm_r(full_path(name), force: true) | |
| 85 | + end | |
| 86 | + | |
| 87 | + # Move namespace directory inside repositories storage | |
| 88 | + # | |
| 89 | + # Ex. | |
| 90 | + # mv_namespace("gitlab", "gitlabhq") | |
| 91 | + # | |
| 92 | + def mv_namespace(old_name, new_name) | |
| 93 | + return false if exists?(new_name) || !exists?(old_name) | |
| 94 | + | |
| 95 | + FileUtils.mv(full_path(old_name), full_path(new_name)) | |
| 96 | + end | |
| 97 | + | |
| 98 | + # Remove GitLab Satellites for provided path (namespace or repo dir) | |
| 99 | + # | |
| 100 | + # Ex. | |
| 101 | + # rm_satellites("gitlab") | |
| 102 | + # | |
| 103 | + # rm_satellites("gitlab/gitlab-ci.git") | |
| 104 | + # | |
| 105 | + def rm_satellites(path) | |
| 106 | + raise ArgumentError.new("Path can't be blank") if path.blank? | |
| 107 | + | |
| 108 | + satellites_path = File.join(Gitlab.config.satellites.path, path) | |
| 109 | + FileUtils.rm_r(satellites_path, force: true) | |
| 110 | + end | |
| 111 | + | |
| 68 | 112 | def url_to_repo path |
| 69 | 113 | Gitlab.config.gitlab_shell.ssh_path_prefix + "#{path}.git" |
| 70 | 114 | end |
| 71 | 115 | |
| 116 | + protected | |
| 117 | + | |
| 72 | 118 | def gitlab_shell_user_home |
| 73 | 119 | File.expand_path("~#{Gitlab.config.gitlab_shell.ssh_user}") |
| 74 | 120 | end |
| 75 | 121 | |
| 122 | + def repos_path | |
| 123 | + Gitlab.config.gitlab_shell.repos_path | |
| 124 | + end | |
| 125 | + | |
| 126 | + def full_path(dir_name) | |
| 127 | + raise ArgumentError.new("Directory name can't be blank") if dir_name.blank? | |
| 128 | + | |
| 129 | + File.join(repos_path, dir_name) | |
| 130 | + end | |
| 131 | + | |
| 132 | + def exists?(dir_name) | |
| 133 | + File.exists?(full_path(dir_name)) | |
| 134 | + end | |
| 76 | 135 | end |
| 77 | 136 | end | ... | ... |
spec/models/namespace_spec.rb
| ... | ... | @@ -60,7 +60,7 @@ describe Namespace do |
| 60 | 60 | end |
| 61 | 61 | |
| 62 | 62 | it "should raise error when dirtory exists" do |
| 63 | - expect { @namespace.move_dir }.to raise_error("Already exists") | |
| 63 | + expect { @namespace.move_dir }.to raise_error("namespace directory cannot be moved") | |
| 64 | 64 | end |
| 65 | 65 | |
| 66 | 66 | it "should move dir if path changed" do | ... | ... |