From 7cdc5b9e0438c35c83fce739a764cb146d20c004 Mon Sep 17 00:00:00 2001
From: randx <dmitriy.zaporozhets@gmail.com>
Date: Wed, 29 Aug 2012 00:04:06 +0300
Subject: [PATCH] Use similar interface to access gitolite Simplified gitolite
 handle logic Stubn over monkeypatch Stub only specific methods in
 Gitlab:Gitolite Moved grach auth to lib added specs for keys observer removes
 SshKey role

---
 app/models/key.rb                             |  5 +-
 app/models/protected_branch.rb                |  4 +-
 app/models/users_project.rb                   |  6 +--
 app/observers/key_observer.rb                 |  7 ++-
 app/roles/git_host.rb                         |  5 ++
 app/roles/git_merge.rb                        |  2 -
 app/roles/repository.rb                       |  8 ++--
 app/roles/ssh_key.rb                          | 18 -------
 config/environment.rb                         |  2 -
 config/initializers/5_backend.rb              |  5 ++
 features/support/env.rb                       |  8 ++++
 lib/gitlab/{ => backend}/gitolite.rb          | 48 +++++++++++++++++--
 .../gitlab/backend}/grack_auth.rb             |  0
 lib/gitlab/git_host.rb                        | 17 -------
 lib/tasks/gitlab/enable_automerge.rake        |  4 +-
 lib/tasks/gitlab/gitolite_rebuild.rake        |  2 +-
 spec/observers/key_observer_spec.rb           | 34 +++++++++++++
 spec/spec_helper.rb                           |  3 ++
 spec/support/gitolite_stub.rb                 | 35 ++++++++++++++
 spec/support/monkeypatch.rb                   | 30 ------------
 20 files changed, 155 insertions(+), 88 deletions(-)
 create mode 100644 app/roles/git_host.rb
 delete mode 100644 app/roles/git_merge.rb
 delete mode 100644 app/roles/ssh_key.rb
 create mode 100644 config/initializers/5_backend.rb
 rename lib/gitlab/{ => backend}/gitolite.rb (79%)
 rename {config/initializers => lib/gitlab/backend}/grack_auth.rb (100%)
 delete mode 100644 lib/gitlab/git_host.rb
 create mode 100644 spec/observers/key_observer_spec.rb
 create mode 100644 spec/support/gitolite_stub.rb

diff --git a/app/models/key.rb b/app/models/key.rb
index cfcb1f63c26..8b61675a444 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -1,7 +1,6 @@
 require 'digest/md5'
 
 class Key < ActiveRecord::Base
-  include SshKey
   belongs_to :user
   belongs_to :project
 
@@ -50,6 +49,10 @@ class Key < ActiveRecord::Base
       user.projects
     end
   end
+
+  def last_deploy?
+    Key.where(identifier: identifier).count == 0
+  end
 end
 # == Schema Information
 #
diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
index 4da1432c1a9..7c30f7a0b6d 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -1,4 +1,6 @@
 class ProtectedBranch < ActiveRecord::Base
+  include GitHost
+
   belongs_to :project
   validates_presence_of :project_id
   validates_presence_of :name
@@ -7,7 +9,7 @@ class ProtectedBranch < ActiveRecord::Base
   after_destroy :update_repository
 
   def update_repository
-    Gitlab::GitHost.system.update_project(project.path, project)
+    git_host.update_repository(project)
   end
 
   def commit
diff --git a/app/models/users_project.rb b/app/models/users_project.rb
index 36e6d9045b6..7d1729343bb 100644
--- a/app/models/users_project.rb
+++ b/app/models/users_project.rb
@@ -1,4 +1,6 @@
 class UsersProject < ActiveRecord::Base
+  include GitHost
+
   GUEST     = 10
   REPORTER  = 20
   DEVELOPER = 30
@@ -58,9 +60,7 @@ class UsersProject < ActiveRecord::Base
   end
 
   def update_repository
-    Gitlab::GitHost.system.new.configure do |c|
-      c.update_project(project.path, project)
-    end
+    git_host.update_repository(project)
   end
 
   def project_access_human
diff --git a/app/observers/key_observer.rb b/app/observers/key_observer.rb
index fac53a67925..a3f17bdec92 100644
--- a/app/observers/key_observer.rb
+++ b/app/observers/key_observer.rb
@@ -1,9 +1,12 @@
 class KeyObserver < ActiveRecord::Observer
+  include GitHost
+
   def after_save(key)
-    key.update_repository
+    git_host.set_key(key.identifier, key.key, key.projects)
   end
 
   def after_destroy(key)
-    key.repository_delete_key
+    return if key.is_deploy_key && !key.last_deploy?
+    git_host.remove_key(key.identifier, key.projects)
   end
 end
diff --git a/app/roles/git_host.rb b/app/roles/git_host.rb
new file mode 100644
index 00000000000..aa620f77ea4
--- /dev/null
+++ b/app/roles/git_host.rb
@@ -0,0 +1,5 @@
+module GitHost
+  def git_host
+    Gitlab::Gitolite.new
+  end
+end
diff --git a/app/roles/git_merge.rb b/app/roles/git_merge.rb
deleted file mode 100644
index 95e5942fb00..00000000000
--- a/app/roles/git_merge.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-module GitMerge
-end
diff --git a/app/roles/repository.rb b/app/roles/repository.rb
index 17f524991db..5fa950db6d6 100644
--- a/app/roles/repository.rb
+++ b/app/roles/repository.rb
@@ -1,4 +1,6 @@
 module Repository
+  include GitHost
+
   def valid_repo?
     repo
   rescue
@@ -48,7 +50,7 @@ module Repository
   end
 
   def url_to_repo
-    Gitlab::GitHost.url_to_repo(path)
+    git_host.url_to_repo(path)
   end
 
   def path_to_repo
@@ -56,11 +58,11 @@ module Repository
   end
 
   def update_repository
-    Gitlab::GitHost.system.update_project(path, self)
+    git_host.update_repository(self)
   end
 
   def destroy_repository
-    Gitlab::GitHost.system.destroy_project(self)
+    git_host.remove_repository(self)
   end
 
   def repo_exists?
diff --git a/app/roles/ssh_key.rb b/app/roles/ssh_key.rb
deleted file mode 100644
index 5e1d2c23d15..00000000000
--- a/app/roles/ssh_key.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-module SshKey
-  def update_repository
-    Gitlab::GitHost.system.new.configure do |c|
-      c.update_keys(identifier, key)
-      c.update_projects(projects)
-    end
-  end
-
-  def repository_delete_key
-    Gitlab::GitHost.system.new.configure do |c|
-      #delete key file is there is no identically deploy keys
-      if !is_deploy_key || Key.where(identifier: identifier).count() == 0
-        c.delete_key(identifier)
-      end
-      c.update_projects(projects)
-    end
-  end
-end
diff --git a/config/environment.rb b/config/environment.rb
index c880a7adc42..3b186a9d57a 100644
--- a/config/environment.rb
+++ b/config/environment.rb
@@ -3,5 +3,3 @@ require File.expand_path('../application', __FILE__)
 
 # Initialize the rails application
 Gitlab::Application.initialize!
-
-require File.join(Rails.root, "lib", "gitlab", "git_host")
diff --git a/config/initializers/5_backend.rb b/config/initializers/5_backend.rb
new file mode 100644
index 00000000000..85f747ac334
--- /dev/null
+++ b/config/initializers/5_backend.rb
@@ -0,0 +1,5 @@
+# GIT over HTTP
+require Rails.root.join("lib", "gitlab", "backend", "grack_auth")
+
+# GITOLITE backend
+require Rails.root.join("lib", "gitlab", "backend", "gitolite")
diff --git a/features/support/env.rb b/features/support/env.rb
index 80a465b472c..0d9a9ed4281 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -5,10 +5,12 @@ end
 
 require 'cucumber/rails'
 require 'webmock/cucumber'
+
 WebMock.allow_net_connect!
 
 require Rails.root.join 'spec/factories'
 require Rails.root.join 'spec/support/monkeypatch'
+require Rails.root.join 'spec/support/gitolite_stub'
 require Rails.root.join 'spec/support/login_helpers'
 require Rails.root.join 'spec/support/valid_commit'
 
@@ -48,3 +50,9 @@ headless = Headless.new
 headless.start
 
 require 'cucumber/rspec/doubles'
+
+include GitoliteStub
+
+Before do 
+  stub_gitolite!
+end
diff --git a/lib/gitlab/gitolite.rb b/lib/gitlab/backend/gitolite.rb
similarity index 79%
rename from lib/gitlab/gitolite.rb
rename to lib/gitlab/backend/gitolite.rb
index a3f34061471..4d0a0cf02d6 100644
--- a/lib/gitlab/gitolite.rb
+++ b/lib/gitlab/backend/gitolite.rb
@@ -2,24 +2,62 @@ require 'gitolite'
 require 'timeout'
 require 'fileutils'
 
+# TODO: refactor & cleanup 
 module Gitlab
   class Gitolite
     class AccessDenied < StandardError; end
 
-    def self.update_project(path, project)
-      self.new.configure { |git| git.update_project(path, project) }
+    def set_key key_id, key_content, projects
+      self.configure do |c|
+        c.update_keys(key_id, key_content)
+        c.update_project(project.path, projects)
+      end
+    end
+
+    def remove_key key_id, projects
+      self.configure do |c|
+        c.delete_key(key_id)
+        c.update_project(project.path, projects)
+      end
+    end
+
+    def update_repository project
+      self.configure do |c|
+        c.update_project(project.path, project)
+      end
     end
 
-    def self.destroy_project(project)
-      self.new.configure { |git| git.destroy_project(project) }
+    alias_method :create_repository, :update_repository
+
+    def remove_repository project
+      self.configure do |c|
+        c.destroy_project(project)
+      end
     end
 
+    def url_to_repo path
+      Gitlab.config.ssh_path + "#{path}.git"
+    end
+
+    def initialize
+      # create tmp dir
+      @local_dir = File.join(Rails.root, 'tmp',"gitlabhq-gitolite-#{Time.now.to_i}")
+    end
+
+    def enable_automerge
+      self.configure do |git|
+        git.admin_all_repo
+      end
+    end
+
+    private
+
     def pull
       # create tmp dir
       @local_dir = File.join(Rails.root, 'tmp',"gitlabhq-gitolite-#{Time.now.to_i}")
       Dir.mkdir @local_dir
 
-      `git clone #{GitHost.admin_uri} #{@local_dir}/gitolite`
+      `git clone #{self.class.admin_uri} #{@local_dir}/gitolite`
     end
 
     def push
diff --git a/config/initializers/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb
similarity index 100%
rename from config/initializers/grack_auth.rb
rename to lib/gitlab/backend/grack_auth.rb
diff --git a/lib/gitlab/git_host.rb b/lib/gitlab/git_host.rb
deleted file mode 100644
index 76b2c7b19e4..00000000000
--- a/lib/gitlab/git_host.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require File.join(Rails.root, "lib", "gitlab", "gitolite")
-
-module Gitlab
-  class GitHost
-    def self.system
-      Gitlab::Gitolite
-    end
-
-    def self.admin_uri
-      Gitlab.config.git_host.admin_uri
-    end
-
-    def self.url_to_repo(path)
-      Gitlab.config.ssh_path + "#{path}.git"
-    end
-  end
-end
diff --git a/lib/tasks/gitlab/enable_automerge.rake b/lib/tasks/gitlab/enable_automerge.rake
index 07f80586c60..0a1a0fa7350 100644
--- a/lib/tasks/gitlab/enable_automerge.rake
+++ b/lib/tasks/gitlab/enable_automerge.rake
@@ -2,9 +2,7 @@ namespace :gitlab do
   namespace :app do
     desc "GITLAB | Enable auto merge"
     task :enable_automerge => :environment  do
-      Gitlab::GitHost.system.new.configure do |git|
-        git.admin_all_repo
-      end
+      Gitlab::Gitolite.new.enable_automerge
 
       Project.find_each do |project|
         if project.repo_exists? && !project.satellite.exists?
diff --git a/lib/tasks/gitlab/gitolite_rebuild.rake b/lib/tasks/gitlab/gitolite_rebuild.rake
index 5ab176060fb..534aa315631 100644
--- a/lib/tasks/gitlab/gitolite_rebuild.rake
+++ b/lib/tasks/gitlab/gitolite_rebuild.rake
@@ -16,7 +16,7 @@ namespace :gitlab do
     task :update_keys => :environment  do
       puts "Starting Key"
       Key.find_each(:batch_size => 100) do |key|
-        key.update_repository
+        Gitlab::Gitolite.new.set_key(key.identifier, key.key, key.projects)
         print '.'
       end
       puts "Done with keys"
diff --git a/spec/observers/key_observer_spec.rb b/spec/observers/key_observer_spec.rb
new file mode 100644
index 00000000000..7f2a76a320c
--- /dev/null
+++ b/spec/observers/key_observer_spec.rb
@@ -0,0 +1,34 @@
+require 'spec_helper'
+
+describe KeyObserver do
+  before do 
+    @key = double('Key',
+      identifier: 'admin_654654',
+      key: '== a vaild ssh key',
+      projects: [],
+      is_deploy_key: false
+    )
+
+    @gitolite = double('Gitlab::Gitolite',
+      set_key: true,
+      remove_key: true
+    )
+
+    @observer = KeyObserver.instance
+    @observer.stub(:git_host => @gitolite)
+  end
+
+  context :after_save do
+    it do
+      @gitolite.should_receive(:set_key).with(@key.identifier, @key.key, @key.projects)
+      @observer.after_save(@key)
+    end
+  end
+
+  context :after_destroy do 
+    it do
+      @gitolite.should_receive(:remove_key).with(@key.identifier, @key.projects)
+      @observer.after_destroy(@key)
+    end
+  end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 9fb0ad7e249..06909f392bb 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -27,6 +27,7 @@ RSpec.configure do |config|
   config.mock_with :rspec
 
   config.include LoginHelpers, type: :request
+  config.include GitoliteStub
 
   # If you're not using ActiveRecord, or you'd prefer not to run each of your
   # examples within a transaction, remove the following line or assign false
@@ -39,6 +40,8 @@ RSpec.configure do |config|
   end
 
   config.before do
+    stub_gitolite!
+
     # !!! Observers disabled by default in tests
     ActiveRecord::Base.observers.disable(:all)
     # ActiveRecord::Base.observers.enable(:all)
diff --git a/spec/support/gitolite_stub.rb b/spec/support/gitolite_stub.rb
new file mode 100644
index 00000000000..2a907f99bc8
--- /dev/null
+++ b/spec/support/gitolite_stub.rb
@@ -0,0 +1,35 @@
+module GitoliteStub
+  def stub_gitolite!
+    stub_gitlab_gitolite
+    stub_gitolite_admin
+  end
+
+  def stub_gitolite_admin
+    gitolite_repo = mock(
+      clean_permissions: true,
+      add_permission: true
+    )
+
+    gitolite_config = mock(
+      add_repo: true,
+      get_repo: gitolite_repo,
+      has_repo?: true
+    )
+
+    gitolite_admin = double(
+      'Gitolite::GitoliteAdmin', 
+      config: gitolite_config,
+      save: true,
+    )
+
+    Gitolite::GitoliteAdmin.stub(new: gitolite_admin)
+
+  end
+
+  def stub_gitlab_gitolite
+    gitlab_gitolite = Gitlab::Gitolite.new
+    Gitlab::Gitolite.stub(new: gitlab_gitolite)
+    gitlab_gitolite.stub(configure: ->() { yield(self) })
+    gitlab_gitolite.stub(update_keys: true)
+  end
+end
diff --git a/spec/support/monkeypatch.rb b/spec/support/monkeypatch.rb
index 855a31f06de..04bbb6fb680 100644
--- a/spec/support/monkeypatch.rb
+++ b/spec/support/monkeypatch.rb
@@ -1,14 +1,6 @@
 # Stubbing Project <-> git host path
 # create project using Factory only
 class Project
-  def update_repository
-    true
-  end
-
-  def destroy_repository
-    true
-  end
-
   def path_to_repo
     File.join(Rails.root, "tmp", "tests", path)
   end
@@ -18,22 +10,6 @@ class Project
   end
 end
 
-class Key
-  def update_repository
-    true
-  end
-
-  def repository_delete_key
-    true
-  end
-end
-
-class UsersProject
-  def update_repository
-    true
-  end
-end
-
 class FakeSatellite
   def exists?
     true
@@ -43,9 +19,3 @@ class FakeSatellite
     true
   end
 end
-
-class ProtectedBranch
-  def update_repository
-    true
-  end
-end
-- 
GitLab