summaryrefslogtreecommitdiff
path: root/app/models
diff options
context:
space:
mode:
authorDouwe Maan <douwe@gitlab.com>2015-12-08 13:43:45 +0100
committerDouwe Maan <douwe@gitlab.com>2015-12-08 13:43:45 +0100
commit75486f09c4b8f2df17e2c16bf4d97fceb34dc9ad (patch)
tree9c44f07bf4991a208b969b8bddf0b04e1edb02be /app/models
parente7969d6f6c743ead94b3b430b9184ad21f647337 (diff)
parentf5430e48b42227f1c1874ca27c6907f0f704be28 (diff)
downloadgitlab-ce-75486f09c4b8f2df17e2c16bf4d97fceb34dc9ad.tar.gz
Merge branch 'master' into zj/gitlab-ce-merge-if-green
Diffstat (limited to 'app/models')
-rw-r--r--app/models/application_setting.rb4
-rw-r--r--app/models/broadcast_message.rb8
-rw-r--r--app/models/ci/web_hook.rb3
-rw-r--r--app/models/commit.rb28
-rw-r--r--app/models/global_milestone.rb31
-rw-r--r--app/models/hooks/web_hook.rb39
-rw-r--r--app/models/label.rb4
-rw-r--r--app/models/merge_request.rb2
-rw-r--r--app/models/namespace.rb14
-rw-r--r--app/models/note.rb32
-rw-r--r--app/models/project.rb2
-rw-r--r--app/models/project_services/bamboo_service.rb7
-rw-r--r--app/models/project_services/drone_ci_service.rb29
-rw-r--r--app/models/project_services/external_wiki_service.rb6
-rw-r--r--app/models/project_services/teamcity_service.rb10
-rw-r--r--app/models/repository.rb58
-rw-r--r--app/models/sent_notification.rb2
-rw-r--r--app/models/user.rb6
18 files changed, 179 insertions, 106 deletions
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 5ddcf3d9a0b..1880ad9f33c 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -43,12 +43,12 @@ class ApplicationSetting < ActiveRecord::Base
validates :home_page_url,
allow_blank: true,
- format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" },
+ url: true,
if: :home_page_url_column_exist
validates :after_sign_out_path,
allow_blank: true,
- format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" }
+ url: true
validates :admin_notification_email,
allow_blank: true,
diff --git a/app/models/broadcast_message.rb b/app/models/broadcast_message.rb
index 05f5e979695..ad514706160 100644
--- a/app/models/broadcast_message.rb
+++ b/app/models/broadcast_message.rb
@@ -16,12 +16,12 @@
class BroadcastMessage < ActiveRecord::Base
include Sortable
- validates :message, presence: true
+ validates :message, presence: true
validates :starts_at, presence: true
- validates :ends_at, presence: true
+ validates :ends_at, presence: true
- validates :color, format: { with: /\A\#[0-9A-Fa-f]{3}{1,2}+\Z/ }, allow_blank: true
- validates :font, format: { with: /\A\#[0-9A-Fa-f]{3}{1,2}+\Z/ }, allow_blank: true
+ validates :color, allow_blank: true, color: true
+ validates :font, allow_blank: true, color: true
def self.current
where("ends_at > :now AND starts_at < :now", now: Time.zone.now).last
diff --git a/app/models/ci/web_hook.rb b/app/models/ci/web_hook.rb
index 7ca16a1bde8..0dc15eb6683 100644
--- a/app/models/ci/web_hook.rb
+++ b/app/models/ci/web_hook.rb
@@ -20,8 +20,7 @@ module Ci
# HTTParty timeout
default_timeout 10
- validates :url, presence: true,
- format: { with: URI::regexp(%w(http https)), message: "should be a valid url" }
+ validates :url, presence: true, url: true
def execute(data)
parsed_url = URI.parse(url)
diff --git a/app/models/commit.rb b/app/models/commit.rb
index c0998a45709..8ae5325d16a 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -147,10 +147,10 @@ class Commit
description.present?
end
- def hook_attrs
+ def hook_attrs(with_changed_files: false)
path_with_namespace = project.path_with_namespace
- {
+ data = {
id: id,
message: safe_message,
timestamp: committed_date.xmlschema,
@@ -160,6 +160,12 @@ class Commit
email: author_email
}
}
+
+ if with_changed_files
+ data.merge!(repo_changes)
+ end
+
+ data
end
# Discover issues should be closed when this commit is pushed to a project's
@@ -208,4 +214,22 @@ class Commit
def status
ci_commit.try(:status) || :not_found
end
+
+ private
+
+ def repo_changes
+ changes = { added: [], modified: [], removed: [] }
+
+ diffs.each do |diff|
+ if diff.deleted_file
+ changes[:removed] << diff.old_path
+ elsif diff.renamed_file || diff.new_file
+ changes[:added] << diff.new_path
+ else
+ changes[:modified] << diff.new_path
+ end
+ end
+
+ changes
+ end
end
diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb
index 1321ccd963f..8bfc79d88f8 100644
--- a/app/models/global_milestone.rb
+++ b/app/models/global_milestone.rb
@@ -16,7 +16,15 @@ class GlobalMilestone
end
def safe_title
- @title.parameterize
+ @title.to_slug.to_s
+ end
+
+ def expired?
+ if due_date
+ due_date.past?
+ else
+ false
+ end
end
def projects
@@ -98,4 +106,25 @@ class GlobalMilestone
def complete?
total_items_count == closed_items_count
end
+
+ def due_date
+ return @due_date if defined?(@due_date)
+
+ @due_date =
+ if @milestones.all? { |x| x.due_date == @milestones.first.due_date }
+ @milestones.first.due_date
+ else
+ nil
+ end
+ end
+
+ def expires_at
+ if due_date
+ if due_date.past?
+ "expired at #{due_date.stamp("Aug 21, 2011")}"
+ else
+ "expires at #{due_date.stamp("Aug 21, 2011")}"
+ end
+ end
+ end
end
diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb
index d6c6f415c4a..715ec5908b7 100644
--- a/app/models/hooks/web_hook.rb
+++ b/app/models/hooks/web_hook.rb
@@ -31,37 +31,38 @@ class WebHook < ActiveRecord::Base
# HTTParty timeout
default_timeout Gitlab.config.gitlab.webhook_timeout
- validates :url, presence: true,
- format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" }
+ validates :url, presence: true, url: true
def execute(data, hook_name)
parsed_url = URI.parse(url)
if parsed_url.userinfo.blank?
- WebHook.post(url,
- body: data.to_json,
- headers: {
- "Content-Type" => "application/json",
- "X-Gitlab-Event" => hook_name.singularize.titleize
- },
- verify: enable_ssl_verification)
+ response = WebHook.post(url,
+ body: data.to_json,
+ headers: {
+ "Content-Type" => "application/json",
+ "X-Gitlab-Event" => hook_name.singularize.titleize
+ },
+ verify: enable_ssl_verification)
else
post_url = url.gsub("#{parsed_url.userinfo}@", "")
auth = {
username: URI.decode(parsed_url.user),
password: URI.decode(parsed_url.password),
}
- WebHook.post(post_url,
- body: data.to_json,
- headers: {
- "Content-Type" => "application/json",
- "X-Gitlab-Event" => hook_name.singularize.titleize
- },
- verify: enable_ssl_verification,
- basic_auth: auth)
+ response = WebHook.post(post_url,
+ body: data.to_json,
+ headers: {
+ "Content-Type" => "application/json",
+ "X-Gitlab-Event" => hook_name.singularize.titleize
+ },
+ verify: enable_ssl_verification,
+ basic_auth: auth)
end
- rescue SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, Net::OpenTimeout => e
+
+ [response.code == 200, ActionView::Base.full_sanitizer.sanitize(response.to_s)]
+ rescue SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Net::OpenTimeout => e
logger.error("WebHook Error => #{e}")
- false
+ [false, e.to_s]
end
def async_execute(data, hook_name)
diff --git a/app/models/label.rb b/app/models/label.rb
index bef6063fe88..220da10a6ab 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -27,9 +27,7 @@ class Label < ActiveRecord::Base
has_many :label_links, dependent: :destroy
has_many :issues, through: :label_links, source: :target, source_type: 'Issue'
- validates :color,
- format: { with: /\A#[0-9A-Fa-f]{6}\Z/ },
- allow_blank: false
+ validates :color, color: true, allow_blank: false
validates :project, presence: true, unless: Proc.new { |service| service.template? }
# Don't allow '?', '&', and ',' for label titles
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 4bcbd86a543..60fd2b9a757 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -312,7 +312,7 @@ class MergeRequest < ActiveRecord::Base
work_in_progress: work_in_progress?
}
- unless last_commit.nil?
+ if last_commit
attrs.merge!(last_commit: last_commit.hook_attrs)
end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 20b92e68d61..1c4e101cc10 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -23,19 +23,17 @@ class Namespace < ActiveRecord::Base
validates :owner, presence: true, unless: ->(n) { n.type == "Group" }
validates :name,
- presence: true, uniqueness: true,
length: { within: 0..255 },
- format: { with: Gitlab::Regex.namespace_name_regex,
- message: Gitlab::Regex.namespace_name_regex_message }
+ namespace_name: true,
+ presence: true,
+ uniqueness: true
validates :description, length: { within: 0..255 }
validates :path,
- uniqueness: { case_sensitive: false },
- presence: true,
length: { within: 1..255 },
- exclusion: { in: Gitlab::Blacklist.path },
- format: { with: Gitlab::Regex.namespace_regex,
- message: Gitlab::Regex.namespace_regex_message }
+ namespace: true,
+ presence: true,
+ uniqueness: { case_sensitive: false }
delegate :name, to: :owner, allow_nil: true, prefix: true
diff --git a/app/models/note.rb b/app/models/note.rb
index 1c6345e735c..8d433c57ceb 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -39,9 +39,12 @@ class Note < ActiveRecord::Base
delegate :name, to: :project, prefix: true
delegate :name, :email, to: :author, prefix: true
+ before_validation :set_award!
+
validates :note, :project, presence: true
validates :note, uniqueness: { scope: [:author, :noteable_type, :noteable_id] }, if: ->(n) { n.is_award }
- validates :line_code, format: { with: /\A[a-z0-9]+_\d+_\d+\Z/ }, allow_blank: true
+ validates :note, inclusion: { in: Emoji.emojis_names }, if: ->(n) { n.is_award }
+ validates :line_code, line_code: true, allow_blank: true
# Attachments are deprecated and are handled by Markdown uploader
validates :attachment, file_size: { maximum: :max_attachment_size }
@@ -348,4 +351,31 @@ class Note < ActiveRecord::Base
def editable?
!system?
end
+
+ # Checks if note is an award added as a comment
+ #
+ # If note is an award, this method sets is_award to true
+ # and changes content of the note to award name.
+ #
+ # Method is executed as a before_validation callback.
+ #
+ def set_award!
+ return unless awards_supported? && contains_emoji_only?
+ self.is_award = true
+ self.note = award_emoji_name
+ end
+
+ private
+
+ def awards_supported?
+ noteable.kind_of?(Issue) || noteable.is_a?(MergeRequest)
+ end
+
+ def contains_emoji_only?
+ note =~ /\A#{Gitlab::Markdown::EmojiFilter.emoji_pattern}\s?\Z/
+ end
+
+ def award_emoji_name
+ note.match(Gitlab::Markdown::EmojiFilter.emoji_pattern)[1]
+ end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 6010770a5f2..af034a6692b 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -152,7 +152,7 @@ class Project < ActiveRecord::Base
validates_uniqueness_of :name, scope: :namespace_id
validates_uniqueness_of :path, scope: :namespace_id
validates :import_url,
- format: { with: /\A#{URI.regexp(%w(ssh git http https))}\z/, message: 'should be a valid url' },
+ url: { protocols: %w(ssh git http https) },
if: :external_import?
validates :star_count, numericality: { greater_than_or_equal_to: 0 }
validate :check_limit, on: :create
diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb
index d31b12f539e..0a61ad96a0e 100644
--- a/app/models/project_services/bamboo_service.rb
+++ b/app/models/project_services/bamboo_service.rb
@@ -23,10 +23,7 @@ class BambooService < CiService
prop_accessor :bamboo_url, :build_key, :username, :password
- validates :bamboo_url,
- presence: true,
- format: { with: /\A#{URI.regexp}\z/ },
- if: :activated?
+ validates :bamboo_url, presence: true, url: true, if: :activated?
validates :build_key, presence: true, if: :activated?
validates :username,
presence: true,
@@ -84,7 +81,7 @@ class BambooService < CiService
def supported_events
%w(push)
end
-
+
def build_info(sha)
url = URI.parse("#{bamboo_url}/rest/api/latest/result?label=#{sha}")
diff --git a/app/models/project_services/drone_ci_service.rb b/app/models/project_services/drone_ci_service.rb
index 06c3922593c..08e5ccb3855 100644
--- a/app/models/project_services/drone_ci_service.rb
+++ b/app/models/project_services/drone_ci_service.rb
@@ -19,14 +19,11 @@
#
class DroneCiService < CiService
-
+
prop_accessor :drone_url, :token, :enable_ssl_verification
- validates :drone_url,
- presence: true,
- format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" }, if: :activated?
- validates :token,
- presence: true,
- if: :activated?
+
+ validates :drone_url, presence: true, url: true, if: :activated?
+ validates :token, presence: true, if: :activated?
after_save :compose_service_hook, if: :activated?
@@ -58,16 +55,16 @@ class DroneCiService < CiService
end
def merge_request_status_path(iid, sha = nil, ref = nil)
- url = [drone_url,
- "gitlab/#{project.namespace.path}/#{project.path}/pulls/#{iid}",
+ url = [drone_url,
+ "gitlab/#{project.namespace.path}/#{project.path}/pulls/#{iid}",
"?access_token=#{token}"]
URI.join(*url).to_s
end
def commit_status_path(sha, ref)
- url = [drone_url,
- "gitlab/#{project.namespace.path}/#{project.path}/commits/#{sha}",
+ url = [drone_url,
+ "gitlab/#{project.namespace.path}/#{project.path}/commits/#{sha}",
"?branch=#{URI::encode(ref.to_s)}&access_token=#{token}"]
URI.join(*url).to_s
@@ -114,15 +111,15 @@ class DroneCiService < CiService
end
def merge_request_page(iid, sha, ref)
- url = [drone_url,
+ url = [drone_url,
"gitlab/#{project.namespace.path}/#{project.path}/redirect/pulls/#{iid}"]
URI.join(*url).to_s
end
def commit_page(sha, ref)
- url = [drone_url,
- "gitlab/#{project.namespace.path}/#{project.path}/redirect/commits/#{sha}",
+ url = [drone_url,
+ "gitlab/#{project.namespace.path}/#{project.path}/redirect/commits/#{sha}",
"?branch=#{URI::encode(ref.to_s)}"]
URI.join(*url).to_s
@@ -163,10 +160,10 @@ class DroneCiService < CiService
end
def push_valid?(data)
- opened_merge_requests = project.merge_requests.opened.where(source_project_id: project.id,
+ opened_merge_requests = project.merge_requests.opened.where(source_project_id: project.id,
source_branch: Gitlab::Git.ref_name(data[:ref]))
- opened_merge_requests.empty? && data[:total_commits_count] > 0 &&
+ opened_merge_requests.empty? && data[:total_commits_count] > 0 &&
!Gitlab::Git.blank_ref?(data[:after])
end
diff --git a/app/models/project_services/external_wiki_service.rb b/app/models/project_services/external_wiki_service.rb
index 9c46af7e721..74c57949b4d 100644
--- a/app/models/project_services/external_wiki_service.rb
+++ b/app/models/project_services/external_wiki_service.rb
@@ -22,10 +22,8 @@ class ExternalWikiService < Service
include HTTParty
prop_accessor :external_wiki_url
- validates :external_wiki_url,
- presence: true,
- format: { with: /\A#{URI.regexp}\z/ },
- if: :activated?
+
+ validates :external_wiki_url, presence: true, url: true, if: :activated?
def title
'External Wiki'
diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb
index 0b022461250..29d4236745a 100644
--- a/app/models/project_services/teamcity_service.rb
+++ b/app/models/project_services/teamcity_service.rb
@@ -23,16 +23,16 @@ class TeamcityService < CiService
prop_accessor :teamcity_url, :build_type, :username, :password
- validates :teamcity_url,
- presence: true,
- format: { with: /\A#{URI.regexp}\z/ }, if: :activated?
+ validates :teamcity_url, presence: true, url: true, if: :activated?
validates :build_type, presence: true, if: :activated?
validates :username,
presence: true,
- if: ->(service) { service.password? }, if: :activated?
+ if: ->(service) { service.password? },
+ if: :activated?
validates :password,
presence: true,
- if: ->(service) { service.username? }, if: :activated?
+ if: ->(service) { service.username? },
+ if: :activated?
attr_accessor :response
diff --git a/app/models/repository.rb b/app/models/repository.rb
index d247b0f5012..1d43307e1e7 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -1,7 +1,6 @@
require 'securerandom'
class Repository
- class PreReceiveError < StandardError; end
class CommitError < StandardError; end
include Gitlab::ShellAdapter
@@ -101,17 +100,26 @@ class Repository
end
def find_branch(name)
- branches.find { |branch| branch.name == name }
+ raw_repository.branches.find { |branch| branch.name == name }
end
def find_tag(name)
- tags.find { |tag| tag.name == name }
+ raw_repository.tags.find { |tag| tag.name == name }
end
- def add_branch(branch_name, ref)
- expire_branches_cache
+ def add_branch(user, branch_name, target)
+ oldrev = Gitlab::Git::BLANK_SHA
+ ref = Gitlab::Git::BRANCH_REF_PREFIX + branch_name
+ target = commit(target).try(:id)
+
+ return false unless target
+
+ GitHooksService.new.execute(user, path_to_repo, oldrev, target, ref) do
+ rugged.branches.create(branch_name, target)
+ end
- gitlab_shell.add_branch(path_with_namespace, branch_name, ref)
+ expire_branches_cache
+ find_branch(branch_name)
end
def add_tag(tag_name, ref, message = nil)
@@ -120,10 +128,20 @@ class Repository
gitlab_shell.add_tag(path_with_namespace, tag_name, ref, message)
end
- def rm_branch(branch_name)
+ def rm_branch(user, branch_name)
expire_branches_cache
- gitlab_shell.rm_branch(path_with_namespace, branch_name)
+ branch = find_branch(branch_name)
+ oldrev = branch.try(:target)
+ newrev = Gitlab::Git::BLANK_SHA
+ ref = Gitlab::Git::BRANCH_REF_PREFIX + branch_name
+
+ GitHooksService.new.execute(user, path_to_repo, oldrev, newrev, ref) do
+ rugged.branches.delete(branch_name)
+ end
+
+ expire_branches_cache
+ true
end
def rm_tag(tag_name)
@@ -550,7 +568,6 @@ class Repository
def commit_with_hooks(current_user, branch)
oldrev = Gitlab::Git::BLANK_SHA
ref = Gitlab::Git::BRANCH_REF_PREFIX + branch
- gl_id = Gitlab::ShellEnv.gl_id(current_user)
was_empty = empty?
# Create temporary ref
@@ -569,15 +586,7 @@ class Repository
raise CommitError.new('Failed to create commit')
end
- # Run GitLab pre-receive hook
- pre_receive_hook = Gitlab::Git::Hook.new('pre-receive', path_to_repo)
- pre_receive_hook_status = pre_receive_hook.trigger(gl_id, oldrev, newrev, ref)
-
- # Run GitLab update hook
- update_hook = Gitlab::Git::Hook.new('update', path_to_repo)
- update_hook_status = update_hook.trigger(gl_id, oldrev, newrev, ref)
-
- if pre_receive_hook_status && update_hook_status
+ GitHooksService.new.execute(current_user, path_to_repo, oldrev, newrev, ref) do
if was_empty
# Create branch
rugged.references.create(ref, newrev)
@@ -592,16 +601,11 @@ class Repository
raise CommitError.new('Commit was rejected because branch received new push')
end
end
-
- # Run GitLab post receive hook
- post_receive_hook = Gitlab::Git::Hook.new('post-receive', path_to_repo)
- post_receive_hook.trigger(gl_id, oldrev, newrev, ref)
- else
- # Remove tmp ref and return error to user
- rugged.references.delete(tmp_ref)
-
- raise PreReceiveError.new('Commit was rejected by git hook')
end
+ rescue GitHooksService::PreReceiveError
+ # Remove tmp ref and return error to user
+ rugged.references.delete(tmp_ref)
+ raise
end
private
diff --git a/app/models/sent_notification.rb b/app/models/sent_notification.rb
index d8fe65b06f6..f36eda1531b 100644
--- a/app/models/sent_notification.rb
+++ b/app/models/sent_notification.rb
@@ -21,7 +21,7 @@ class SentNotification < ActiveRecord::Base
validates :reply_key, uniqueness: true
validates :noteable_id, presence: true, unless: :for_commit?
validates :commit_id, presence: true, if: :for_commit?
- validates :line_code, format: { with: /\A[a-z0-9]+_\d+_\d+\Z/ }, allow_blank: true
+ validates :line_code, line_code: true, allow_blank: true
class << self
def reply_key
diff --git a/app/models/user.rb b/app/models/user.rb
index 719b49b16fe..cfed797e725 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -148,11 +148,9 @@ class User < ActiveRecord::Base
validates :bio, length: { maximum: 255 }, allow_blank: true
validates :projects_limit, presence: true, numericality: { greater_than_or_equal_to: 0 }
validates :username,
+ namespace: true,
presence: true,
- uniqueness: { case_sensitive: false },
- exclusion: { in: Gitlab::Blacklist.path },
- format: { with: Gitlab::Regex.namespace_regex,
- message: Gitlab::Regex.namespace_regex_message }
+ uniqueness: { case_sensitive: false }
validates :notification_level, inclusion: { in: Notification.notification_levels }, presence: true
validate :namespace_uniq, if: ->(user) { user.username_changed? }