summaryrefslogtreecommitdiff
path: root/app/models
diff options
context:
space:
mode:
authorDouglas Barbosa Alexandre <dbalexandre@gmail.com>2015-12-08 10:34:51 -0200
committerDouglas Barbosa Alexandre <dbalexandre@gmail.com>2015-12-08 10:34:51 -0200
commitbf0af030b6365936d2ff529e443132d7a508bfc6 (patch)
tree32de5e8e22313ecaba23293b1fb6c2d08186a75a /app/models
parent23c1c70bf0321941ab2b9572a5d0532ed9f58002 (diff)
parentf5430e48b42227f1c1874ca27c6907f0f704be28 (diff)
downloadgitlab-ce-bf0af030b6365936d2ff529e443132d7a508bfc6.tar.gz
Merge branch 'master' into fix-admin-should-be-able-to-add-himself-to-group
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.rb44
-rw-r--r--app/models/commit_range.rb110
-rw-r--r--app/models/concerns/mentionable.rb11
-rw-r--r--app/models/concerns/referable.rb23
-rw-r--r--app/models/global_milestone.rb31
-rw-r--r--app/models/hooks/web_hook.rb39
-rw-r--r--app/models/issue.rb4
-rw-r--r--app/models/label.rb4
-rw-r--r--app/models/merge_request.rb8
-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/snippet.rb4
-rw-r--r--app/models/user.rb6
23 files changed, 310 insertions, 149 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 492f6be1ce3..8ae5325d16a 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -78,11 +78,23 @@ class Commit
}x
end
+ def self.link_reference_pattern
+ super("commit", /(?<commit>\h{6,40})/)
+ end
+
def to_reference(from_project = nil)
if cross_project_reference?(from_project)
- "#{project.to_reference}@#{id}"
+ project.to_reference + self.class.reference_prefix + self.id
else
- id
+ self.id
+ end
+ end
+
+ def reference_link_text(from_project = nil)
+ if cross_project_reference?(from_project)
+ project.to_reference + self.class.reference_prefix + self.short_id
+ else
+ self.short_id
end
end
@@ -135,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,
@@ -148,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
@@ -196,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/commit_range.rb b/app/models/commit_range.rb
index 86fc9eb01a3..14e7971fa06 100644
--- a/app/models/commit_range.rb
+++ b/app/models/commit_range.rb
@@ -2,36 +2,38 @@
#
# Examples:
#
-# range = CommitRange.new('f3f85602...e86e1013')
+# range = CommitRange.new('f3f85602...e86e1013', project)
# range.exclude_start? # => false
# range.reference_title # => "Commits f3f85602 through e86e1013"
# range.to_s # => "f3f85602...e86e1013"
#
-# range = CommitRange.new('f3f856029bc5f966c5a7ee24cf7efefdd20e6019..e86e1013709735be5bb767e2b228930c543f25ae')
+# range = CommitRange.new('f3f856029bc5f966c5a7ee24cf7efefdd20e6019..e86e1013709735be5bb767e2b228930c543f25ae', project)
# range.exclude_start? # => true
# range.reference_title # => "Commits f3f85602^ through e86e1013"
# range.to_param # => {from: "f3f856029bc5f966c5a7ee24cf7efefdd20e6019^", to: "e86e1013709735be5bb767e2b228930c543f25ae"}
# range.to_s # => "f3f85602..e86e1013"
#
-# # Assuming `project` is a Project with a repository containing both commits:
-# range.project = project
+# # Assuming the specified project has a repository containing both commits:
# range.valid_commits? # => true
#
class CommitRange
include ActiveModel::Conversion
include Referable
- attr_reader :sha_from, :notation, :sha_to
+ attr_reader :commit_from, :notation, :commit_to
+ attr_reader :ref_from, :ref_to
# Optional Project model
attr_accessor :project
- # See `exclude_start?`
- attr_reader :exclude_start
-
- # The beginning and ending SHAs can be between 6 and 40 hex characters, and
+ # The beginning and ending refs can be named or SHAs, and
# the range notation can be double- or triple-dot.
- PATTERN = /\h{6,40}\.{2,3}\h{6,40}/
+ REF_PATTERN = /[0-9a-zA-Z][0-9a-zA-Z_.-]*[0-9a-zA-Z\^]/
+ PATTERN = /#{REF_PATTERN}\.{2,3}#{REF_PATTERN}/
+
+ # In text references, the beginning and ending refs can only be SHAs
+ # between 6 and 40 hex characters.
+ STRICT_PATTERN = /\h{6,40}\.{2,3}\h{6,40}/
def self.reference_prefix
'@'
@@ -43,27 +45,40 @@ class CommitRange
def self.reference_pattern
%r{
(?:#{Project.reference_pattern}#{reference_prefix})?
- (?<commit_range>#{PATTERN})
+ (?<commit_range>#{STRICT_PATTERN})
}x
end
+ def self.link_reference_pattern
+ super("compare", /(?<commit_range>#{PATTERN})/)
+ end
+
# Initialize a CommitRange
#
# range_string - The String commit range.
# project - An optional Project model.
#
# Raises ArgumentError if `range_string` does not match `PATTERN`.
- def initialize(range_string, project = nil)
+ def initialize(range_string, project)
+ @project = project
+
range_string.strip!
- unless range_string.match(/\A#{PATTERN}\z/)
+ unless range_string =~ /\A#{PATTERN}\z/
raise ArgumentError, "invalid CommitRange string format: #{range_string}"
end
- @exclude_start = !range_string.include?('...')
- @sha_from, @notation, @sha_to = range_string.split(/(\.{2,3})/, 2)
+ @ref_from, @notation, @ref_to = range_string.split(/(\.{2,3})/, 2)
- @project = project
+ if project.valid_repo?
+ @commit_from = project.commit(@ref_from)
+ @commit_to = project.commit(@ref_to)
+ end
+
+ if valid_commits?
+ @ref_from = Commit.truncate_sha(sha_from) if sha_from.start_with?(@ref_from)
+ @ref_to = Commit.truncate_sha(sha_to) if sha_to.start_with?(@ref_to)
+ end
end
def inspect
@@ -71,15 +86,24 @@ class CommitRange
end
def to_s
- "#{sha_from[0..7]}#{notation}#{sha_to[0..7]}"
+ sha_from + notation + sha_to
end
+ alias_method :id, :to_s
+
def to_reference(from_project = nil)
- # Not using to_s because we want the full SHAs
- reference = sha_from + notation + sha_to
+ if cross_project_reference?(from_project)
+ project.to_reference + self.class.reference_prefix + self.id
+ else
+ self.id
+ end
+ end
+
+ def reference_link_text(from_project = nil)
+ reference = ref_from + notation + ref_to
if cross_project_reference?(from_project)
- reference = project.to_reference + '@' + reference
+ reference = project.to_reference + self.class.reference_prefix + reference
end
reference
@@ -87,46 +111,58 @@ class CommitRange
# Returns a String for use in a link's title attribute
def reference_title
- "Commits #{suffixed_sha_from} through #{sha_to}"
+ "Commits #{sha_start} through #{sha_to}"
end
# Return a Hash of parameters for passing to a URL helper
#
# See `namespace_project_compare_url`
def to_param
- { from: suffixed_sha_from, to: sha_to }
+ { from: sha_start, to: sha_to }
end
def exclude_start?
- exclude_start
+ @notation == '..'
end
# Check if both the starting and ending commit IDs exist in a project's
# repository
- #
- # project - An optional Project to check (default: `project`)
- def valid_commits?(project = project)
- return nil unless project.present?
- return false unless project.valid_repo?
-
- commit_from.present? && commit_to.present?
+ def valid_commits?
+ commit_start.present? && commit_end.present?
end
def persisted?
true
end
- def commit_from
- @commit_from ||= project.repository.commit(suffixed_sha_from)
+ def sha_from
+ return nil unless @commit_from
+
+ @commit_from.id
+ end
+
+ def sha_to
+ return nil unless @commit_to
+
+ @commit_to.id
end
- def commit_to
- @commit_to ||= project.repository.commit(sha_to)
+ def sha_start
+ return nil unless sha_from
+
+ exclude_start? ? sha_from + '^' : sha_from
end
- private
+ def commit_start
+ return nil unless sha_start
- def suffixed_sha_from
- sha_from + (exclude_start? ? '^' : '')
+ if exclude_start?
+ @commit_start ||= project.commit(sha_start)
+ else
+ commit_from
+ end
end
+
+ alias_method :sha_end, :sha_to
+ alias_method :commit_end, :commit_to
end
diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb
index 193c91f1742..634a8d0f274 100644
--- a/app/models/concerns/mentionable.rb
+++ b/app/models/concerns/mentionable.rb
@@ -62,13 +62,18 @@ module Mentionable
return [] if text.blank?
refs = all_references(current_user, text, load_lazy_references: load_lazy_references)
- (refs.issues + refs.merge_requests + refs.commits) - [local_reference]
+ refs = (refs.issues + refs.merge_requests + refs.commits)
+
+ # We're using this method instead of Array diffing because that requires
+ # both of the object's `hash` values to be the same, which may not be the
+ # case for otherwise identical Commit objects.
+ refs.reject { |ref| ref == local_reference }
end
# Create a cross-reference Note for each GFM reference to another Mentionable found in +mentionable_text+.
def create_cross_references!(author = self.author, without = [], text = self.mentionable_text)
refs = referenced_mentionables(author, text)
-
+
# We're using this method instead of Array diffing because that requires
# both of the object's `hash` values to be the same, which may not be the
# case for otherwise identical Commit objects.
@@ -111,7 +116,7 @@ module Mentionable
# Only include changed fields that are mentionable
source.select { |key, val| mentionable.include?(key) }
end
-
+
# Determine whether or not a cross-reference Note has already been created between this Mentionable and
# the specified target.
def cross_reference_exists?(target)
diff --git a/app/models/concerns/referable.rb b/app/models/concerns/referable.rb
index cced66cc1e4..ce064f675ae 100644
--- a/app/models/concerns/referable.rb
+++ b/app/models/concerns/referable.rb
@@ -21,6 +21,10 @@ module Referable
''
end
+ def reference_link_text(from_project = nil)
+ to_reference(from_project)
+ end
+
module ClassMethods
# The character that prefixes the actual reference identifier
#
@@ -44,6 +48,25 @@ module Referable
def reference_pattern
raise NotImplementedError, "#{self} does not implement #{__method__}"
end
+
+ def link_reference_pattern(route, pattern)
+ %r{
+ (?<url>
+ #{Regexp.escape(Gitlab.config.gitlab.url)}
+ \/#{Project.reference_pattern}
+ \/#{Regexp.escape(route)}
+ \/#{pattern}
+ (?<path>
+ (\/[a-z0-9_=-]+)*
+ )?
+ (?<query>
+ \?[a-z0-9_=-]+
+ (&[a-z0-9_=-]+)*
+ )?
+ (?<anchor>\#[a-z0-9_-]+)?
+ )
+ }x
+ end
end
private
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/issue.rb b/app/models/issue.rb
index 72183108033..187b6482b6c 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -69,6 +69,10 @@ class Issue < ActiveRecord::Base
}x
end
+ def self.link_reference_pattern
+ super("issues", /(?<issue>\d+)/)
+ end
+
def to_reference(from_project = nil)
reference = "#{self.class.reference_prefix}#{iid}"
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 1b3d6079d2c..080b7f7fb88 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -151,6 +151,10 @@ class MergeRequest < ActiveRecord::Base
}x
end
+ def self.link_reference_pattern
+ super("merge_requests", /(?<merge_request>\d+)/)
+ end
+
def to_reference(from_project = nil)
reference = "#{self.class.reference_prefix}#{iid}"
@@ -291,7 +295,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
@@ -316,7 +320,7 @@ class MergeRequest < ActiveRecord::Base
issues = commits.flat_map { |c| c.closes_issues(current_user) }
issues.push(*Gitlab::ClosingIssueExtractor.new(project, current_user).
closed_by_message(description))
- issues.uniq.sort_by(&:id)
+ issues.uniq
else
[]
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/snippet.rb b/app/models/snippet.rb
index b0831982aa7..f876be7a4c8 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -65,6 +65,10 @@ class Snippet < ActiveRecord::Base
}x
end
+ def self.link_reference_pattern
+ super("snippets", /(?<snippet>\d+)/)
+ end
+
def to_reference(from_project = nil)
reference = "#{self.class.reference_prefix}#{id}"
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? }