summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2012-02-15 22:02:33 +0200
committerDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2012-02-15 22:02:33 +0200
commit37224dc9c1ee80ba9030b616e2bc87bd96919e09 (patch)
tree5291abadd8748ea47685c326df4b137d0d6a2194
parent3a9e5a9357b6b0cac2acdefa203136c9b572e102 (diff)
downloadgitlab-ce-37224dc9c1ee80ba9030b616e2bc87bd96919e09.tar.gz
ProtectedBranches model, Master permission for repo\n Allow push to protected branch for masters only
-rw-r--r--app/controllers/protected_branches_controller.rb23
-rw-r--r--app/models/project.rb41
-rw-r--r--app/models/protected_branch.rb29
-rw-r--r--app/models/repository.rb4
-rw-r--r--app/views/protected_branches/index.html.haml39
-rw-r--r--app/views/repositories/_branches_head.html.haml9
-rw-r--r--app/views/repositories/_head.html.haml2
-rw-r--r--app/views/repositories/branches.html.haml2
-rw-r--r--config/routes.rb1
-rw-r--r--db/migrate/20120215182305_create_protected_branches.rb10
-rw-r--r--db/schema.rb21
-rw-r--r--lib/gitlabhq/gitolite.rb62
-rw-r--r--spec/models/project_spec.rb23
-rw-r--r--spec/models/protected_branch_spec.rb16
14 files changed, 229 insertions, 53 deletions
diff --git a/app/controllers/protected_branches_controller.rb b/app/controllers/protected_branches_controller.rb
new file mode 100644
index 00000000000..c91bd903645
--- /dev/null
+++ b/app/controllers/protected_branches_controller.rb
@@ -0,0 +1,23 @@
+class ProtectedBranchesController < ApplicationController
+ before_filter :project
+
+ # Authorize
+ before_filter :add_project_abilities
+ before_filter :authorize_read_project!
+ before_filter :require_non_empty_project
+
+ layout "project"
+
+ def index
+ @branches = @project.protected_branches.all
+ @protected_branch = @project.protected_branches.new
+ end
+
+ def create
+ @project.protected_branches.create(params[:protected_branch])
+ redirect_to project_protected_branches_path(@project)
+ end
+
+ def destroy
+ end
+end
diff --git a/app/models/project.rb b/app/models/project.rb
index 49311daaea7..ac70eedb009 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -16,6 +16,7 @@ class Project < ActiveRecord::Base
has_many :snippets, :dependent => :destroy
has_many :deploy_keys, :dependent => :destroy, :foreign_key => "project_id", :class_name => "Key"
has_many :web_hooks, :dependent => :destroy
+ has_many :protected_branches, :dependent => :destroy
acts_as_taggable
@@ -138,6 +139,15 @@ class Project < ActiveRecord::Base
data
end
+ def open_branches
+ if protected_branches.empty?
+ self.repo.heads
+ else
+ pnames = protected_branches.map(&:name)
+ self.repo.heads.reject { |h| pnames.include?(h.name) }
+ end.sort_by(&:name)
+ end
+
def team_member_by_name_or_email(email = nil, name = nil)
user = users.where("email like ? or name like ?", email, name).first
users_projects.find_by_user_id(user.id) if user
@@ -210,6 +220,12 @@ class Project < ActiveRecord::Base
keys.map(&:identifier)
end
+ def repository_masters
+ keys = Key.joins({:user => :users_projects}).
+ where("users_projects.project_id = ? AND users_projects.repo_access = ?", id, Repository::REPO_MASTER)
+ keys.map(&:identifier)
+ end
+
def readers
@readers ||= users_projects.includes(:user).where(:project_access => [PROJECT_R, PROJECT_RW, PROJECT_RWA]).map(&:user)
end
@@ -235,7 +251,7 @@ class Project < ActiveRecord::Base
end
def allow_pull_for?(user)
- !users_projects.where(:user_id => user.id, :repo_access => [Repository::REPO_R, Repository::REPO_RW]).empty?
+ !users_projects.where(:user_id => user.id, :repo_access => [Repository::REPO_R, Repository::REPO_RW, Repository::REPO_MASTER]).empty?
end
def root_ref
@@ -340,15 +356,18 @@ end
#
# Table name: projects
#
-# id :integer not null, primary key
-# name :string(255)
-# path :string(255)
-# description :text
-# created_at :datetime
-# updated_at :datetime
-# private_flag :boolean default(TRUE), not null
-# code :string(255)
-# owner_id :integer
-# default_branch :string(255) default("master"), not null
+# id :integer not null, primary key
+# name :string(255)
+# path :string(255)
+# description :text
+# created_at :datetime
+# updated_at :datetime
+# private_flag :boolean default(TRUE), not null
+# code :string(255)
+# owner_id :integer
+# default_branch :string(255) default("master"), not null
+# issues_enabled :boolean default(TRUE), not null
+# wall_enabled :boolean default(TRUE), not null
+# merge_requests_enabled :boolean default(TRUE), not null
#
diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
new file mode 100644
index 00000000000..9c2d391d0c1
--- /dev/null
+++ b/app/models/protected_branch.rb
@@ -0,0 +1,29 @@
+class ProtectedBranch < ActiveRecord::Base
+ belongs_to :project
+ validates_presence_of :project_id
+ validates_presence_of :name
+
+ after_save :update_repository
+ after_destroy :update_repository
+
+ def update_repository
+ Gitlabhq::GitHost.system.new.configure do |c|
+ c.update_project(project.path, project)
+ end
+ end
+
+ def commit
+ project.commit(self.name)
+ end
+end
+# == Schema Information
+#
+# Table name: protected_branches
+#
+# id :integer not null, primary key
+# project_id :integer not null
+# name :string(255) not null
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 8f9f9746257..3d9ad262390 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -4,6 +4,7 @@ class Repository
REPO_N = 0
REPO_R = 1
REPO_RW = 2
+ REPO_MASTER = 3
attr_accessor :project
@@ -15,7 +16,8 @@ class Repository
{
"Denied" => REPO_N,
"Pull" => REPO_R,
- "Pull & Push" => REPO_RW
+ "Pull & Push" => REPO_RW,
+ "Master" => REPO_MASTER
}
end
diff --git a/app/views/protected_branches/index.html.haml b/app/views/protected_branches/index.html.haml
new file mode 100644
index 00000000000..055d9369091
--- /dev/null
+++ b/app/views/protected_branches/index.html.haml
@@ -0,0 +1,39 @@
+= render "repositories/branches_head"
+
+= form_for [@project, @protected_branch] do |f|
+ -if @protected_branch.errors.any?
+ .alert-message.block-message.error
+ %ul
+ - @protected_branch.errors.full_messages.each do |msg|
+ %li= msg
+
+ .clearfix
+ = f.label :name
+ .input= f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , { :include_blank => "Select branch" }, { :style => "width:300px" })
+ .actions
+ = f.submit 'Add', :class => "primary btn"
+
+
+- unless @branches.empty?
+ %table
+ %thead
+ %tr
+ %th Name
+ %th Last commit
+ %tbody
+ - @branches.each do |branch|
+ %tr
+ %td
+ = link_to project_commits_path(@project, :ref => branch.name) do
+ %strong= branch.name
+ - if branch.name == @project.root_ref
+ %span.label default
+ %td
+ = link_to project_commits_path(@project, branch.commit.id) do
+ = truncate branch.commit.id.to_s, :length => 10
+ = time_ago_in_words(branch.commit.committed_date)
+ ago
+
+
+:javascript
+ $('select#protected_branch_name').chosen();
diff --git a/app/views/repositories/_branches_head.html.haml b/app/views/repositories/_branches_head.html.haml
new file mode 100644
index 00000000000..d98dedc23eb
--- /dev/null
+++ b/app/views/repositories/_branches_head.html.haml
@@ -0,0 +1,9 @@
+= render "repositories/head"
+%ul.pills
+ %li{:class => ("active" if current_page?(branches_project_repository_path(@project)))}
+ = link_to branches_project_repository_path(@project) do
+ All
+ %li{:class => ("active" if current_page?(project_protected_branches_path(@project)))}
+ = link_to project_protected_branches_path(@project) do
+ Protected
+
diff --git a/app/views/repositories/_head.html.haml b/app/views/repositories/_head.html.haml
index 37360d48a62..2d43d008e2a 100644
--- a/app/views/repositories/_head.html.haml
+++ b/app/views/repositories/_head.html.haml
@@ -3,7 +3,7 @@
= link_to project_repository_path(@project) do
%span
Activities
- %li{:class => "#{'active' if current_page?(branches_project_repository_path(@project)) }"}
+ %li{:class => "#{'active' if current_page?(branches_project_repository_path(@project)) || current_page?(project_protected_branches_path(@project)) }"}
= link_to branches_project_repository_path(@project) do
%span
Branches
diff --git a/app/views/repositories/branches.html.haml b/app/views/repositories/branches.html.haml
index d817ab5147f..91a97207791 100644
--- a/app/views/repositories/branches.html.haml
+++ b/app/views/repositories/branches.html.haml
@@ -1,4 +1,4 @@
-= render "head"
+= render "repositories/branches_head"
- unless @branches.empty?
%table
%thead
diff --git a/config/routes.rb b/config/routes.rb
index 81bf93c7f23..e7a96fb4afb 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -62,6 +62,7 @@ Gitlab::Application.routes.draw do
end
resources :deploy_keys
+ resources :protected_branches, :only => [:index, :create, :destroy]
resources :refs, :only => [], :path => "/" do
collection do
diff --git a/db/migrate/20120215182305_create_protected_branches.rb b/db/migrate/20120215182305_create_protected_branches.rb
new file mode 100644
index 00000000000..841d08c33d5
--- /dev/null
+++ b/db/migrate/20120215182305_create_protected_branches.rb
@@ -0,0 +1,10 @@
+class CreateProtectedBranches < ActiveRecord::Migration
+ def change
+ create_table :protected_branches do |t|
+ t.integer :project_id, :null => false
+ t.string :name, :null => false
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index bb9f638764a..f7006c4c9c2 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,19 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20120206170141) do
+ActiveRecord::Schema.define(:version => 20120215182305) do
+
+ create_table "features", :force => true do |t|
+ t.string "name"
+ t.string "branch_name"
+ t.integer "assignee_id"
+ t.integer "author_id"
+ t.integer "project_id"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.string "version"
+ t.integer "status", :default => 0, :null => false
+ end
create_table "issues", :force => true do |t|
t.string "title"
@@ -82,6 +94,13 @@ ActiveRecord::Schema.define(:version => 20120206170141) do
t.boolean "merge_requests_enabled", :default => true, :null => false
end
+ create_table "protected_branches", :force => true do |t|
+ t.integer "project_id", :null => false
+ t.string "name", :null => false
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
create_table "snippets", :force => true do |t|
t.string "title"
t.text "content"
diff --git a/lib/gitlabhq/gitolite.rb b/lib/gitlabhq/gitolite.rb
index e6eb8e5144b..4f911113ea0 100644
--- a/lib/gitlabhq/gitolite.rb
+++ b/lib/gitlabhq/gitolite.rb
@@ -64,21 +64,9 @@ module Gitlabhq
def update_project(repo_name, project)
ga_repo = ::Gitolite::GitoliteAdmin.new(File.join(@local_dir,'gitolite'))
conf = ga_repo.config
-
- repo = if conf.has_repo?(repo_name)
- conf.get_repo(repo_name)
- else
- ::Gitolite::Config::Repo.new(repo_name)
- end
-
- name_readers = project.repository_readers
- name_writers = project.repository_writers
-
- repo.clean_permissions
- repo.add_permission("R", "", name_readers) unless name_readers.blank?
- repo.add_permission("RW+", "", name_writers) unless name_writers.blank?
+ repo = update_project_config(project, conf)
conf.add_repo(repo, true)
-
+
ga_repo.save
end
@@ -89,25 +77,43 @@ module Gitlabhq
conf = ga_repo.config
projects.each do |project|
- repo_name = project.path
-
- repo = if conf.has_repo?(repo_name)
- conf.get_repo(repo_name)
- else
- ::Gitolite::Config::Repo.new(repo_name)
- end
-
- name_readers = project.repository_readers
- name_writers = project.repository_writers
-
- repo.clean_permissions
- repo.add_permission("R", "", name_readers) unless name_readers.blank?
- repo.add_permission("RW+", "", name_writers) unless name_writers.blank?
+ repo = update_project_config(project, conf)
conf.add_repo(repo, true)
end
ga_repo.save
end
+ def update_project_config(project, conf)
+ repo_name = project.path
+
+ repo = if conf.has_repo?(repo_name)
+ conf.get_repo(repo_name)
+ else
+ ::Gitolite::Config::Repo.new(repo_name)
+ end
+
+ name_readers = project.repository_readers
+ name_writers = project.repository_writers
+ name_masters = project.repository_masters
+
+ pr_br = project.protected_branches.map(&:name).join(" ")
+
+ repo.clean_permissions
+
+ # Deny access to protected branches for writers
+ unless name_writers.blank? || pr_br.blank?
+ repo.add_permission("-", pr_br, name_writers)
+ end
+
+ # Add read permissions
+ repo.add_permission("R", "", name_readers) unless name_readers.blank?
+
+ # Add write permissions
+ repo.add_permission("RW+", "", name_writers) unless name_writers.blank?
+ repo.add_permission("RW+", "", name_masters) unless name_masters.blank?
+
+ repo
+ end
end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 68bc82de898..437b139752a 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -290,15 +290,18 @@ end
#
# Table name: projects
#
-# id :integer not null, primary key
-# name :string(255)
-# path :string(255)
-# description :text
-# created_at :datetime
-# updated_at :datetime
-# private_flag :boolean default(TRUE), not null
-# code :string(255)
-# owner_id :integer
-# default_branch :string(255) default("master"), not null
+# id :integer not null, primary key
+# name :string(255)
+# path :string(255)
+# description :text
+# created_at :datetime
+# updated_at :datetime
+# private_flag :boolean default(TRUE), not null
+# code :string(255)
+# owner_id :integer
+# default_branch :string(255) default("master"), not null
+# issues_enabled :boolean default(TRUE), not null
+# wall_enabled :boolean default(TRUE), not null
+# merge_requests_enabled :boolean default(TRUE), not null
#
diff --git a/spec/models/protected_branch_spec.rb b/spec/models/protected_branch_spec.rb
new file mode 100644
index 00000000000..a0b0032a558
--- /dev/null
+++ b/spec/models/protected_branch_spec.rb
@@ -0,0 +1,16 @@
+# == Schema Information
+#
+# Table name: protected_branches
+#
+# id :integer not null, primary key
+# project_id :integer not null
+# name :string(255) not null
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
+require 'spec_helper'
+
+describe ProtectedBranch do
+ pending "add some examples to (or delete) #{__FILE__}"
+end