Merge branch 'master' into discussions
Conflicts: app/assets/stylesheets/main.scss app/models/project.rb app/views/notes/_common_form.html.haml app/views/notes/_per_line_form.html.haml lib/gitlab/markdown.rb spec/models/note_spec.rb
This commit is contained in:
commit
db2c15369c
276 changed files with 4466 additions and 2603 deletions
|
@ -17,9 +17,7 @@ class Ability
|
|||
|
||||
# Rules based on role in project
|
||||
if project.master_access_for?(user)
|
||||
# TODO: replace with master rules.
|
||||
# Only allow project administration for namespace owners
|
||||
rules << project_admin_rules
|
||||
rules << project_master_rules
|
||||
|
||||
elsif project.dev_access_for?(user)
|
||||
rules << project_dev_rules
|
||||
|
@ -93,13 +91,16 @@ class Ability
|
|||
:admin_merge_request,
|
||||
:admin_note,
|
||||
:accept_mr,
|
||||
:admin_wiki
|
||||
:admin_wiki,
|
||||
:admin_project
|
||||
]
|
||||
end
|
||||
|
||||
def project_admin_rules
|
||||
project_master_rules + [
|
||||
:admin_project
|
||||
:change_namespace,
|
||||
:rename_project,
|
||||
:remove_project
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -87,14 +87,10 @@ class Commit
|
|||
last = project.commit(from.try(:strip))
|
||||
|
||||
if first && last
|
||||
commits = [first, last].sort_by(&:created_at)
|
||||
younger = commits.first
|
||||
older = commits.last
|
||||
|
||||
result[:same] = (younger.id == older.id)
|
||||
result[:commits] = project.repo.commits_between(younger.id, older.id).map {|c| Commit.new(c)}
|
||||
result[:diffs] = project.repo.diff(younger.id, older.id) rescue []
|
||||
result[:commit] = Commit.new(older)
|
||||
result[:same] = (first.id == last.id)
|
||||
result[:commits] = project.repo.commits_between(last.id, first.id).map {|c| Commit.new(c)}
|
||||
result[:diffs] = project.repo.diff(last.id, first.id) rescue []
|
||||
result[:commit] = Commit.new(first)
|
||||
end
|
||||
|
||||
result
|
||||
|
@ -163,6 +159,8 @@ class Commit
|
|||
while !lines.first.start_with?("diff --git") do
|
||||
lines.shift
|
||||
end
|
||||
lines.pop if lines.last =~ /^[\d.]+$/ # Git version
|
||||
lines.pop if lines.last == "-- " # end of diff
|
||||
lines.join("\n")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#
|
||||
|
||||
class Event < ActiveRecord::Base
|
||||
include NoteEvent
|
||||
include PushEvent
|
||||
|
||||
attr_accessible :project, :action, :data, :author_id, :project_id,
|
||||
|
@ -58,12 +59,14 @@ class Event < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
# Next events currently enabled for system
|
||||
# - push
|
||||
# - new issue
|
||||
# - merge request
|
||||
def allowed?
|
||||
push? || issue? || merge_request? || membership_changed?
|
||||
def proper?
|
||||
if push?
|
||||
true
|
||||
elsif membership_changed?
|
||||
true
|
||||
else
|
||||
(issue? || merge_request? || note? || milestone?) && target
|
||||
end
|
||||
end
|
||||
|
||||
def project_name
|
||||
|
@ -94,6 +97,14 @@ class Event < ActiveRecord::Base
|
|||
action == self.class::Reopened
|
||||
end
|
||||
|
||||
def milestone?
|
||||
target_type == "Milestone"
|
||||
end
|
||||
|
||||
def note?
|
||||
target_type == "Note"
|
||||
end
|
||||
|
||||
def issue?
|
||||
target_type == "Issue"
|
||||
end
|
||||
|
|
|
@ -36,4 +36,22 @@ class GitlabCiService < Service
|
|||
def commit_badge_path sha
|
||||
project_url + "/status?sha=#{sha}"
|
||||
end
|
||||
|
||||
def commit_status_path sha
|
||||
project_url + "/builds/#{sha}/status.json?token=#{token}"
|
||||
end
|
||||
|
||||
def commit_status sha
|
||||
response = HTTParty.get(commit_status_path(sha))
|
||||
|
||||
if response.code == 200 and response["status"]
|
||||
response["status"]
|
||||
else
|
||||
:error
|
||||
end
|
||||
end
|
||||
|
||||
def build_page sha
|
||||
project_url + "/builds/#{sha}"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -204,7 +204,7 @@ class MergeRequest < ActiveRecord::Base
|
|||
|
||||
def mr_and_commit_notes
|
||||
commit_ids = commits.map(&:id)
|
||||
Note.where("(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND noteable_id IN (:commit_ids))", mr_id: id, commit_ids: commit_ids)
|
||||
Note.where("(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND commit_id IN (:commit_ids))", mr_id: id, commit_ids: commit_ids)
|
||||
end
|
||||
|
||||
# Returns the raw diff for this merge request
|
||||
|
@ -220,4 +220,8 @@ class MergeRequest < ActiveRecord::Base
|
|||
def to_patch
|
||||
project.repo.git.format_patch({timeout: 30, raise: true, stdout: true}, "#{target_branch}..#{source_branch}")
|
||||
end
|
||||
|
||||
def last_commit_short_sha
|
||||
@last_commit_short_sha ||= last_commit.sha[0..10]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,18 +13,26 @@
|
|||
#
|
||||
|
||||
class Milestone < ActiveRecord::Base
|
||||
attr_accessible :title, :description, :due_date, :closed
|
||||
attr_accessible :title, :description, :due_date, :closed, :author_id_of_changes
|
||||
attr_accessor :author_id_of_changes
|
||||
|
||||
belongs_to :project
|
||||
has_many :issues
|
||||
has_many :merge_requests
|
||||
|
||||
scope :active, where(closed: false)
|
||||
scope :closed, where(closed: true)
|
||||
|
||||
validates :title, presence: true
|
||||
validates :project, presence: true
|
||||
validates :closed, inclusion: { in: [true, false] }
|
||||
|
||||
def self.active
|
||||
where("due_date > ? OR due_date IS NULL", Date.today)
|
||||
def expired?
|
||||
if due_date
|
||||
due_date < Date.today
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def participants
|
||||
|
@ -52,4 +60,20 @@ class Milestone < ActiveRecord::Base
|
|||
def expires_at
|
||||
"expires at #{due_date.stamp("Aug 21, 2011")}" if due_date
|
||||
end
|
||||
|
||||
def can_be_closed?
|
||||
open? && issues.opened.count.zero?
|
||||
end
|
||||
|
||||
def is_empty?
|
||||
total_items_count.zero?
|
||||
end
|
||||
|
||||
def open?
|
||||
!closed
|
||||
end
|
||||
|
||||
def author_id
|
||||
author_id_of_changes
|
||||
end
|
||||
end
|
||||
|
|
|
@ -48,23 +48,30 @@ class Namespace < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def ensure_dir_exist
|
||||
namespace_dir_path = File.join(Gitlab.config.git_base_path, path)
|
||||
namespace_dir_path = File.join(Gitlab.config.gitolite.repos_path, path)
|
||||
system("mkdir -m 770 #{namespace_dir_path}") unless File.exists?(namespace_dir_path)
|
||||
end
|
||||
|
||||
def move_dir
|
||||
if path_changed?
|
||||
old_path = File.join(Gitlab.config.git_base_path, path_was)
|
||||
new_path = File.join(Gitlab.config.git_base_path, path)
|
||||
old_path = File.join(Gitlab.config.gitolite.repos_path, path_was)
|
||||
new_path = File.join(Gitlab.config.gitolite.repos_path, path)
|
||||
if File.exists?(new_path)
|
||||
raise "Already exists"
|
||||
end
|
||||
system("mv #{old_path} #{new_path}")
|
||||
|
||||
if system("mv #{old_path} #{new_path}")
|
||||
send_update_instructions
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def rm_dir
|
||||
dir_path = File.join(Gitlab.config.git_base_path, path)
|
||||
dir_path = File.join(Gitlab.config.gitolite.repos_path, path)
|
||||
system("rm -rf #{dir_path}")
|
||||
end
|
||||
|
||||
def send_update_instructions
|
||||
projects.each(&:send_move_instructions)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -19,7 +19,7 @@ require 'file_size_validator'
|
|||
|
||||
class Note < ActiveRecord::Base
|
||||
attr_accessible :note, :noteable, :noteable_id, :noteable_type, :project_id,
|
||||
:attachment, :line_code
|
||||
:attachment, :line_code, :commit_id
|
||||
|
||||
attr_accessor :notify
|
||||
attr_accessor :notify_author
|
||||
|
@ -35,10 +35,14 @@ class Note < ActiveRecord::Base
|
|||
validates :line_code, format: { with: /\A\d+_\d+_\d+\Z/ }, allow_blank: true
|
||||
validates :attachment, file_size: { maximum: 10.megabytes.to_i }
|
||||
|
||||
validates :noteable_id, presence: true, if: ->(n) { n.noteable_type.present? && n.noteable_type != 'Commit' }
|
||||
validates :commit_id, presence: true, if: ->(n) { n.noteable_type == 'Commit' }
|
||||
|
||||
mount_uploader :attachment, AttachmentUploader
|
||||
|
||||
# Scopes
|
||||
scope :common, ->{ where(noteable_id: nil) }
|
||||
scope :for_commits, ->{ where(noteable_type: "Commit") }
|
||||
scope :common, ->{ where(noteable_id: nil, commit_id: nil) }
|
||||
scope :today, ->{ where("created_at >= :date", date: Date.today) }
|
||||
scope :last_week, ->{ where("created_at >= :date", date: (Date.today - 7.days)) }
|
||||
scope :since, ->(day) { where("created_at >= :date", date: (day)) }
|
||||
|
@ -122,7 +126,7 @@ class Note < ActiveRecord::Base
|
|||
# override to return commits, which are not active record
|
||||
def noteable
|
||||
if for_commit?
|
||||
project.commit(noteable_id)
|
||||
project.commit(commit_id)
|
||||
else
|
||||
super
|
||||
end
|
||||
|
@ -151,4 +155,12 @@ class Note < ActiveRecord::Base
|
|||
def votable?
|
||||
for_issue? || (for_merge_request? && !for_diff_line?)
|
||||
end
|
||||
|
||||
def noteable_type_name
|
||||
if noteable_type.present?
|
||||
noteable_type.downcase
|
||||
else
|
||||
"wall"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -25,6 +25,9 @@ class Project < ActiveRecord::Base
|
|||
include PushObserver
|
||||
include Authority
|
||||
include Team
|
||||
include NamespacedProject
|
||||
|
||||
class TransferError < StandardError; end
|
||||
|
||||
attr_accessible :name, :path, :description, :default_branch, :issues_enabled,
|
||||
:wall_enabled, :merge_requests_enabled, :wiki_enabled, as: [:default, :admin]
|
||||
|
@ -36,6 +39,10 @@ class Project < ActiveRecord::Base
|
|||
# Relations
|
||||
belongs_to :group, foreign_key: "namespace_id", conditions: "type = 'Group'"
|
||||
belongs_to :namespace
|
||||
|
||||
# TODO: replace owner with creator.
|
||||
# With namespaces a project owner will be a namespace owner
|
||||
# so this field makes sense only for global projects
|
||||
belongs_to :owner, class_name: "User"
|
||||
has_many :users, through: :users_projects
|
||||
has_many :events, dependent: :destroy
|
||||
|
@ -97,7 +104,7 @@ class Project < ActiveRecord::Base
|
|||
namespace_id = Namespace.find_by_path(id.first).id
|
||||
where(namespace_id: namespace_id).find_by_path(id.last)
|
||||
else
|
||||
find_by_path(id)
|
||||
where(path: id, namespace_id: nil).last
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -172,7 +179,7 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def repo_name
|
||||
denied_paths = %w(gitolite-admin groups projects dashboard)
|
||||
denied_paths = %w(gitolite-admin admin dashboard groups help profile projects search)
|
||||
|
||||
if denied_paths.include?(path)
|
||||
errors.add(:path, "like #{path} is not allowed")
|
||||
|
@ -188,7 +195,7 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def web_url
|
||||
[Gitlab.config.url, path].join("/")
|
||||
[Gitlab.config.gitlab.url, path_with_namespace].join("/")
|
||||
end
|
||||
|
||||
def common_notes
|
||||
|
@ -196,15 +203,15 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def build_commit_note(commit)
|
||||
notes.new(noteable_id: commit.id, noteable_type: "Commit")
|
||||
notes.new(commit_id: commit.id, noteable_type: "Commit")
|
||||
end
|
||||
|
||||
def commit_notes(commit)
|
||||
notes.where(noteable_id: commit.id, noteable_type: "Commit").where('line_code IS NULL OR line_code = ""')
|
||||
notes.where(commit_id: commit.id, noteable_type: "Commit").where('line_code IS NULL OR line_code = ""')
|
||||
end
|
||||
|
||||
def commit_line_notes(commit)
|
||||
notes.where(noteable_id: commit.id, noteable_type: "Commit").where("line_code IS NOT NULL")
|
||||
notes.where(commit_id: commit.id, noteable_type: "Commit").where("line_code IS NOT NULL")
|
||||
end
|
||||
|
||||
def public?
|
||||
|
@ -239,51 +246,11 @@ class Project < ActiveRecord::Base
|
|||
gitlab_ci_service && gitlab_ci_service.active
|
||||
end
|
||||
|
||||
def path_with_namespace
|
||||
if namespace
|
||||
namespace.path + '/' + path
|
||||
else
|
||||
path
|
||||
end
|
||||
end
|
||||
|
||||
# For compatibility with old code
|
||||
def code
|
||||
path
|
||||
end
|
||||
|
||||
def transfer(new_namespace)
|
||||
Project.transaction do
|
||||
old_namespace = namespace
|
||||
self.namespace = new_namespace
|
||||
|
||||
old_dir = old_namespace.try(:path) || ''
|
||||
new_dir = new_namespace.try(:path) || ''
|
||||
|
||||
old_repo = if old_dir.present?
|
||||
File.join(old_dir, self.path)
|
||||
else
|
||||
self.path
|
||||
end
|
||||
|
||||
Gitlab::ProjectMover.new(self, old_dir, new_dir).execute
|
||||
|
||||
git_host.move_repository(old_repo, self)
|
||||
|
||||
save!
|
||||
end
|
||||
end
|
||||
|
||||
def name_with_namespace
|
||||
@name_with_namespace ||= begin
|
||||
if namespace
|
||||
namespace.human_name + " / " + name
|
||||
else
|
||||
name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def items_for entity
|
||||
case entity
|
||||
when 'issue' then
|
||||
|
@ -293,7 +260,9 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def namespace_owner
|
||||
namespace.try(:owner)
|
||||
def send_move_instructions
|
||||
self.users_projects.each do |member|
|
||||
Notify.project_was_moved_email(member.id).deliver
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,7 +22,7 @@ class Snippet < ActiveRecord::Base
|
|||
belongs_to :author, class_name: "User"
|
||||
has_many :notes, as: :noteable, dependent: :destroy
|
||||
|
||||
delegate :name, :email, to: :author, prefix: true
|
||||
delegate :name, :email, to: :author, prefix: true, allow_nil: true
|
||||
|
||||
validates :author, presence: true
|
||||
validates :project, presence: true
|
||||
|
|
|
@ -56,12 +56,12 @@ class User < ActiveRecord::Base
|
|||
has_many :issues, foreign_key: :author_id, dependent: :destroy
|
||||
has_many :notes, foreign_key: :author_id, dependent: :destroy
|
||||
has_many :merge_requests, foreign_key: :author_id, dependent: :destroy
|
||||
has_many :my_own_projects, class_name: "Project", foreign_key: :owner_id
|
||||
has_many :events, class_name: "Event", foreign_key: :author_id, dependent: :destroy
|
||||
has_many :recent_events, class_name: "Event", foreign_key: :author_id, order: "id DESC"
|
||||
has_many :assigned_issues, class_name: "Issue", foreign_key: :assignee_id, dependent: :destroy
|
||||
has_many :assigned_merge_requests, class_name: "MergeRequest", foreign_key: :assignee_id, dependent: :destroy
|
||||
|
||||
validates :name, presence: true
|
||||
validates :bio, length: { within: 0..255 }
|
||||
validates :extern_uid, allow_blank: true, uniqueness: {scope: :provider}
|
||||
validates :projects_limit, presence: true, numericality: {greater_than_or_equal_to: 0}
|
||||
|
@ -123,16 +123,4 @@ class User < ActiveRecord::Base
|
|||
self.password = self.password_confirmation = Devise.friendly_token.first(8)
|
||||
end
|
||||
end
|
||||
|
||||
def authorized_groups
|
||||
@authorized_groups ||= begin
|
||||
groups = Group.where(id: self.projects.pluck(:namespace_id)).all
|
||||
groups = groups + self.groups
|
||||
groups.uniq
|
||||
end
|
||||
end
|
||||
|
||||
def authorized_projects
|
||||
Project.authorized_for(self)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -28,6 +28,7 @@ class UsersProject < ActiveRecord::Base
|
|||
|
||||
validates :user, presence: true
|
||||
validates :user_id, uniqueness: { :scope => [:project_id], message: "already exists in project" }
|
||||
validates :project_access, inclusion: { in: [GUEST, REPORTER, DEVELOPER, MASTER] }, presence: true
|
||||
validates :project, presence: true
|
||||
|
||||
delegate :name, :email, to: :user, prefix: true
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue