Commit 4d194502 authored by abubadabu's avatar abubadabu

Merge branch 'master' into request/relative_submodules

parents cb659e4c 7611ce72
......@@ -6,6 +6,13 @@ v 6.8.0
- Drop all tables before restoring a Postgres backup
- Make the repository downloads path configurable
- Create branches via API (sponsored by O'Reilly Media)
- Changed permission of gitlab-satellites directory not to be world accessible
- Protected branch does not allow force push
v 6.7.3
- Fix the merge notification email not being sent (Pierre de La Morinerie)
- Drop all tables before restoring a Postgres backup
- Remove yanked modernizr gem
v 6.7.2
- Fix upgrader script
......
......@@ -29,7 +29,9 @@ If something is wrong but it is not a regression compared to older versions of G
When submitting an issue please conform to the issue submission guidelines listed below.
Not all issues will be addressed and your issue is more likely to be addressed if you submit a merge request which partially or fully addresses the issue.
Do not use the issue tracker for feature requests. We have a specific [feature request forum](http://feedback.gitlab.com) for this purpose.
Do not use the issue tracker for feature requests.
We have a specific [feature request forum](http://feedback.gitlab.com) for this purpose.
Please keep feature requests as small and simple as possible, complex ones might be edited to make them small and simple.
Please send a merge request with a tested solution or a merge request with a failing test instead of opening an issue if you can. If you're unsure where to post, post to the [mailing list](https://groups.google.com/forum/#!forum/gitlabhq) or [Stack Overflow](http://stackoverflow.com/questions/tagged/gitlab) first. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there.
......
......@@ -12,8 +12,6 @@ gem "rails", "~> 4.0.0"
gem "protected_attributes"
gem 'rails-observers'
gem 'actionpack-page_caching'
gem 'actionpack-action_caching'
# Default values for AR models
gem "default_value_for", "~> 3.0.0"
......@@ -102,7 +100,7 @@ gem "acts-as-taggable-on"
# Background jobs
gem 'slim'
gem 'sinatra', require: nil
gem 'sidekiq'
gem 'sidekiq', '2.17.0'
# HTTP requests
gem "httparty"
......@@ -161,7 +159,6 @@ gem 'select2-rails'
gem 'jquery-atwho-rails', "~> 0.3.3"
gem "jquery-rails", "2.1.3"
gem "jquery-ui-rails", "2.0.2"
gem "modernizr", "2.6.2"
gem "raphael-rails", "~> 2.1.2"
gem 'bootstrap-sass', '~> 3.0'
gem "font-awesome-rails", '~> 3.2'
......
......@@ -27,10 +27,6 @@ GEM
erubis (~> 2.7.0)
rack (~> 1.5.2)
rack-test (~> 0.6.2)
actionpack-action_caching (1.1.0)
actionpack (>= 4.0.0, < 5.0)
actionpack-page_caching (1.0.2)
actionpack (>= 4.0.0, < 5)
activemodel (4.0.3)
activesupport (= 4.0.3)
builder (~> 3.1.0)
......@@ -289,8 +285,6 @@ GEM
method_source (0.8.2)
mime-types (1.25.1)
minitest (4.7.5)
modernizr (2.6.2)
sprockets (~> 2.0)
multi_json (1.8.4)
multi_xml (0.5.5)
multipart-post (1.2.0)
......@@ -567,8 +561,6 @@ PLATFORMS
DEPENDENCIES
ace-rails-ap
actionpack-action_caching
actionpack-page_caching
acts-as-taggable-on
annotate (~> 2.6.0.beta2)
asciidoctor
......@@ -622,7 +614,6 @@ DEPENDENCIES
launchy
letter_opener
minitest (~> 4.7.0)
modernizr (= 2.6.2)
mysql2
nprogress-rails
omniauth (~> 1.1.3)
......@@ -653,7 +644,7 @@ DEPENDENCIES
select2-rails
settingslogic
shoulda-matchers (~> 2.1.0)
sidekiq
sidekiq (= 2.17.0)
simplecov
sinatra
six
......
......@@ -18,7 +18,6 @@
#= require turbolinks
#= require jquery.turbolinks
#= require bootstrap
#= require modernizr
#= require select2
#= require raphael
#= require g.raphael-min
......
class CommitFile
constructor: (file) ->
if $('.image', file).length
new ImageFile(file)
this.CommitFile = CommitFile
\ No newline at end of file
@CommitFile = CommitFile
......@@ -125,4 +125,4 @@ class ImageFile
img.on 'load', =>
callback.call(this, domImg.naturalWidth, domImg.naturalHeight)
this.ImageFile = ImageFile
\ No newline at end of file
@ImageFile = ImageFile
......@@ -2,7 +2,7 @@
* This is a manifest file that'll automatically include all the stylesheets available in this directory
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
* the top of the compiled file, but it's generally better to create a new file per style scope.
*= require jquery.ui.gitlab
*= require jquery.ui.datepicker
*= require jquery.atwho
*= require select2
*= require highlightjs.min
......@@ -43,6 +43,7 @@
@import "generic/forms.scss";
@import "generic/selects.scss";
@import "generic/highlight.scss";
@import "generic/jquery.scss";
/**
* Page specific styles (issues, projects etc):
......
.ui-widget {
font-family: $regular_font;
font-size: $font-size-base;
&.ui-datepicker-inline {
border: 1px solid #DDD;
padding: 10px;
width: 270px;
.ui-datepicker-header {
background: #EEE;
border-color: #DDD;
}
.ui-datepicker-calendar td a {
padding: 5px;
text-align: center;
}
}
}
This diff is collapsed.
/** Typo **/
$monospace_font: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono', 'lucida console', monospace;
$regular_font: "Helvetica Neue", Helvetica, Arial, sans-serif;
......@@ -59,9 +59,7 @@ class Projects::IssuesController < Projects::ApplicationController
end
def create
@issue = @project.issues.new(params[:issue])
@issue.author = current_user
@issue.save
@issue = Issues::CreateService.new(project, current_user, params[:issue]).execute
respond_to do |format|
format.html do
......@@ -76,8 +74,7 @@ class Projects::IssuesController < Projects::ApplicationController
end
def update
@issue.update_attributes(params[:issue])
@issue.reset_events_cache
@issue = Issues::UpdateService.new(project, current_user, params[:issue]).execute(issue)
respond_to do |format|
format.js
......
......@@ -76,10 +76,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
def create
@merge_request = MergeRequest.new(params[:merge_request])
@merge_request.author = current_user
@target_branches ||= []
if @merge_request.save
@merge_request = MergeRequests::CreateService.new(project, current_user, params[:merge_request]).execute
if @merge_request.valid?
redirect_to [@merge_request.target_project, @merge_request], notice: 'Merge request was successfully created.'
else
@source_project = @merge_request.source_project
......@@ -89,29 +89,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
def update
# If we close MergeRequest we want to ignore validation
# so we can close broken one (Ex. fork project removed)
if params[:merge_request] == {"state_event"=>"close"}
@merge_request.allow_broken = true
if @merge_request.close
opts = { notice: 'Merge request was successfully closed.' }
else
opts = { alert: 'Failed to close merge request.' }
end
redirect_to [@merge_request.target_project, @merge_request], opts
return
end
# We dont allow change of source/target projects
# after merge request was created
params[:merge_request].delete(:source_project_id)
params[:merge_request].delete(:target_project_id)
if @merge_request.update_attributes(params[:merge_request])
@merge_request.reset_events_cache
@merge_request = MergeRequests::UpdateService.new(project, current_user, params[:merge_request]).execute(@merge_request)
if @merge_request.valid?
respond_to do |format|
format.js
format.html do
......
......@@ -20,7 +20,7 @@ module MergeRequestsHelper
target_project_id: target_project.id,
source_branch: event.branch_name,
target_branch: target_project.repository.root_ref,
title: event.branch_name.humanize
title: event.branch_name.titleize.humanize
}
end
......
......@@ -13,14 +13,15 @@ class Email < ActiveRecord::Base
# Relations
#
belongs_to :user
#
# Validations
#
validates :user_id, presence: true
validates :email, presence: true, email: { strict_mode: true }, uniqueness: true
validate :unique_email, if: ->(email) { email.email_changed? }
after_create :notify
before_validation :cleanup_email
def cleanup_email
......@@ -30,4 +31,8 @@ class Email < ActiveRecord::Base
def unique_email
self.errors.add(:email, 'has already been taken') if User.exists?(email: self.email)
end
end
\ No newline at end of file
def notify
NotificationService.new.new_email(self)
end
end
......@@ -29,6 +29,10 @@ class Key < ActiveRecord::Base
delegate :name, :email, to: :user, prefix: true
after_create :add_to_shell
after_create :notify_user
after_destroy :remove_from_shell
def strip_white_space
self.key = key.strip unless key.blank?
end
......@@ -42,6 +46,26 @@ class Key < ActiveRecord::Base
"key-#{id}"
end
def add_to_shell
GitlabShellWorker.perform_async(
:add_key,
shell_id,
key
)
end
def notify_user
NotificationService.new.new_key(self)
end
def remove_from_shell
GitlabShellWorker.perform_async(
:remove_key,
shell_id,
key,
)
end
private
def generate_fingerpint
......
......@@ -97,6 +97,7 @@ class MergeRequest < ActiveRecord::Base
validates :target_project, presence: true
validates :target_branch, presence: true
validate :validate_branches
validate :validate_fork
scope :of_group, ->(group) { where("source_project_id in (:group_project_ids) OR target_project_id in (:group_project_ids)", group_project_ids: group.project_ids) }
scope :of_user_team, ->(team) { where("(source_project_id in (:team_project_ids) OR target_project_id in (:team_project_ids) AND assignee_id in (:team_member_ids))", team_project_ids: team.project_ids, team_member_ids: team.member_ids) }
......@@ -125,6 +126,22 @@ class MergeRequest < ActiveRecord::Base
end
end
def validate_fork
return true unless target_project && source_project
if target_project == source_project
true
else
# If source and target projects are different
# we should check if source project is actually a fork of target project
if source_project.forked_from?(target_project)
true
else
errors.add :base, "Source project is not a fork of target project"
end
end
end
def update_merge_request_diff
if source_branch_changed? || target_branch_changed?
reload_code
......
......@@ -552,4 +552,8 @@ class Project < ActiveRecord::Base
gitlab_shell.update_repository_head(self.path_with_namespace, branch)
reload_default_branch
end
def forked_from?(project)
forked? && project == forked_from_project
end
end
class EmailObserver < BaseObserver
def after_create(email)
notification.new_email(email)
end
end
class IssueObserver < BaseObserver
def after_create(issue)
notification.new_issue(issue, current_user)
event_service.open_issue(issue, current_user)
issue.create_cross_references!(issue.project, current_user)
execute_hooks(issue)
end
def after_close(issue, transition)
notification.close_issue(issue, current_user)
event_service.close_issue(issue, current_user)
create_note(issue)
execute_hooks(issue)
end
def after_reopen(issue, transition)
event_service.reopen_issue(issue, current_user)
create_note(issue)
execute_hooks(issue)
end
def after_update(issue)
if issue.is_being_reassigned?
notification.reassigned_issue(issue, current_user)
create_assignee_note(issue)
end
issue.notice_added_references(issue.project, current_user)
execute_hooks(issue)
end
protected
# Create issue note with service comment like 'Status changed to closed'
def create_note(issue)
Note.create_status_change_note(issue, issue.project, current_user, issue.state, current_commit)
end
def create_assignee_note(issue)
Note.create_assignee_change_note(issue, issue.project, current_user, issue.assignee)
end
def execute_hooks(issue)
issue.project.execute_hooks(issue.to_hook_data, :issue_hooks)
end
end
class KeyObserver < BaseObserver
def after_create(key)
GitlabShellWorker.perform_async(
:add_key,
key.shell_id,
key.key
)
notification.new_key(key)
end
def after_destroy(key)
GitlabShellWorker.perform_async(
:remove_key,
key.shell_id,
key.key,
)
end
end
class MergeRequestObserver < BaseObserver
def after_create(merge_request)
event_service.open_mr(merge_request, current_user)
notification.new_merge_request(merge_request, current_user)
merge_request.create_cross_references!(merge_request.project, current_user)
execute_hooks(merge_request)
end
def after_close(merge_request, transition)
event_service.close_mr(merge_request, current_user)
notification.close_mr(merge_request, current_user)
create_note(merge_request)
execute_hooks(merge_request)
end
def after_reopen(merge_request, transition)
event_service.reopen_mr(merge_request, current_user)
create_note(merge_request)
execute_hooks(merge_request)
merge_request.reload_code
merge_request.mark_as_unchecked
end
def after_update(merge_request)
notification.reassigned_merge_request(merge_request, current_user) if merge_request.is_being_reassigned?
merge_request.notice_added_references(merge_request.project, current_user)
execute_hooks(merge_request)
end
private
# Create merge request note with service comment like 'Status changed to closed'
def create_note(merge_request)
Note.create_status_change_note(merge_request, merge_request.target_project, current_user, merge_request.state, nil)
end
def execute_hooks(merge_request)
if merge_request.project
merge_request.project.execute_hooks(merge_request.to_hook_data, :merge_request_hooks)
end
end
end
......@@ -10,7 +10,7 @@ class UsersProjectObserver < BaseObserver
end
def after_update(users_project)
notification.update_team_member(users_project)
notification.update_team_member(users_project) if users_project.project_access_changed?
end
def after_destroy(users_project)
......
......@@ -16,4 +16,16 @@ class BaseService
def can?(object, action, subject)
abilities.allowed?(object, action, subject)
end
def notification_service
NotificationService.new
end
def event_service
EventCreateService.new
end
def log_info message
Gitlab::AppLogger.info message
end
end
......@@ -86,10 +86,9 @@ class GitPushService
author = commit_user(commit)
if !issues_to_close.empty? && is_default_branch
Thread.current[:current_user] = author
Thread.current[:current_commit] = commit
issues_to_close.each { |i| i.close && i.save }
issues_to_close.each do |issue|
Issues::CloseService.new(project, author, {}).execute(issue, commit)
end
end
# Create cross-reference notes for any other references. Omit any issues that were referenced in an
......
module Issues
class BaseService < ::BaseService
private
def create_assignee_note(issue)
Note.create_assignee_change_note(issue, issue.project, current_user, issue.assignee)
end
def execute_hooks(issue)
issue.project.execute_hooks(issue.to_hook_data, :issue_hooks)
end
end
end
module Issues
class CloseService < Issues::BaseService
def execute(issue, commit = nil)
if issue.close
notification_service.close_issue(issue, current_user)
event_service.close_issue(issue, current_user)
create_note(issue, commit)
execute_hooks(issue)
end
issue
end
private
def create_note(issue, current_commit)
Note.create_status_change_note(issue, issue.project, current_user, issue.state, current_commit)
end
end
end
module Issues
class CreateService < Issues::BaseService
def execute
issue = project.issues.new(params)
issue.author = current_user
if issue.save
notification_service.new_issue(issue, current_user)
event_service.open_issue(issue, current_user)
issue.create_cross_references!(issue.project, current_user)
execute_hooks(issue)
end
issue
end
end
end
module Issues
class ReopenService < Issues::BaseService
def execute(issue)
if issue.reopen
event_service.reopen_issue(issue, current_user)
create_note(issue)
execute_hooks(issue)
end
issue
end
private
def create_note(issue)
Note.create_status_change_note(issue, issue.project, current_user, issue.state, nil)
end
end
end
module Issues
class UpdateService < Issues::BaseService
def execute(issue)
state = params.delete('state_event')
case state
when 'reopen'
Issues::ReopenService.new(project, current_user, {}).execute(issue)
when 'close'
Issues::CloseService.new(project, current_user, {}).execute(issue)
end
if params.present? && issue.update_attributes(params)
issue.reset_events_cache
if issue.previous_changes.include?('assignee_id')
notification_service.reassigned_issue(issue, current_user)
create_assignee_note(issue)
end
issue.notice_added_references(issue.project, current_user)
execute_hooks(issue)
end
issue
end
end
end
module MergeRequests
class BaseService < ::BaseService
private
def create_assignee_note(merge_request)
Note.create_assignee_change_note(merge_request, merge_request.project, current_user, merge_request.assignee)
end
def create_note(merge_request)
Note.create_status_change_note(merge_request, merge_request.target_project, current_user, merge_request.state, nil)
end
def execute_hooks(merge_request)
if merge_request.project
merge_request.project.execute_hooks(merge_request.to_hook_data, :merge_request_hooks)
end
end
end
end
module MergeRequests
class CloseService < MergeRequests::BaseService
def execute(merge_request, commit = nil)
# If we close MergeRequest we want to ignore validation
# so we can close broken one (Ex. fork project removed)
merge_request.allow_broken = true
if merge_request.close
event_service.close_mr(merge_request, current_user)
notification_service.close_mr(merge_request, current_user)
create_note(merge_request)
execute_hooks(merge_request)
end
merge_request
end
end
end
module MergeRequests
class CreateService < MergeRequests::BaseService
def execute
merge_request = MergeRequest.new(params)
merge_request.source_project = project
merge_request.target_project ||= project
merge_request.author = current_user
if merge_request.save
event_service.open_mr(merge_request, current_user)
notification_service.new_merge_request(merge_request, current_user)
merge_request.create_cross_references!(merge_request.project, current_user)
execute_hooks(merge_request)
end
merge_request
end
end
end
module MergeRequests
class ReopenService < MergeRequests::BaseService
def execute(merge_request)
if merge_request.reopen
event_service.reopen_mr(merge_request, current_user)
create_note(merge_request)
execute_hooks(merge_request)
merge_request.reload_code
merge_request.mark_as_unchecked
end
merge_request
end
end
end
require_relative 'base_service'
require_relative 'reopen_service'
require_relative 'close_service'
module MergeRequests
class UpdateService < MergeRequests::BaseService
def execute(merge_request)
# We dont allow change of s