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:
Riyad Preukschas 2012-12-23 01:03:57 +01:00
commit db2c15369c
276 changed files with 4466 additions and 2603 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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