summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG5
-rw-r--r--Gemfile1
-rw-r--r--Gemfile.lock11
-rw-r--r--app/assets/javascripts/application.js.coffee33
-rw-r--r--app/assets/javascripts/diff.js.coffee46
-rw-r--r--app/assets/javascripts/dispatcher.js.coffee12
-rw-r--r--app/assets/javascripts/labels.js.coffee35
-rw-r--r--app/assets/javascripts/pager.js.coffee22
-rw-r--r--app/assets/stylesheets/sections/commits.scss1
-rw-r--r--app/assets/stylesheets/sections/diff.scss3
-rw-r--r--app/assets/stylesheets/sections/login.scss4
-rw-r--r--app/controllers/application_controller.rb13
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb13
-rw-r--r--app/controllers/projects/blob_controller.rb15
-rw-r--r--app/controllers/projects/labels_controller.rb5
-rw-r--r--app/controllers/projects/repositories_controller.rb6
-rw-r--r--app/helpers/commits_helper.rb12
-rw-r--r--app/helpers/labels_helper.rb2
-rw-r--r--app/models/concerns/issuable.rb3
-rw-r--r--app/models/label.rb13
-rw-r--r--app/models/project_services/hipchat_service.rb8
-rw-r--r--app/models/user.rb4
-rw-r--r--app/services/archive_repository_service.rb14
-rw-r--r--app/views/layouts/devise.html.haml2
-rw-r--r--app/views/projects/blob/diff.html.haml19
-rw-r--r--app/views/projects/commits/_diff_file.html.haml13
-rw-r--r--app/views/projects/commits/_text_file.html.haml14
-rw-r--r--app/views/projects/commits/diffs/_match_line.html.haml7
-rw-r--r--app/views/projects/labels/_form.html.haml18
-rw-r--r--app/views/projects/labels/_label.html.haml2
-rw-r--r--app/views/projects/milestones/_form.html.haml2
-rw-r--r--app/workers/post_receive.rb2
-rw-r--r--config/environments/development.rb2
-rw-r--r--config/gitlab.yml.example5
-rw-r--r--config/routes.rb4
-rw-r--r--doc/api/issues.md6
-rw-r--r--doc/api/merge_requests.md19
-rw-r--r--doc/install/installation.md4
-rw-r--r--doc/update/4.0-to-4.1.md2
-rw-r--r--doc/update/4.2-to-5.0.md2
-rw-r--r--doc/update/5.0-to-5.1.md2
-rw-r--r--doc/update/5.2-to-5.3.md2
-rw-r--r--doc/update/5.3-to-5.4.md2
-rw-r--r--doc/update/6.9-to-7.0.md2
-rw-r--r--doc/update/7.0-to-7.1.md2
-rw-r--r--features/project/issues/labels.feature20
-rw-r--r--features/project/merge_requests.feature8
-rw-r--r--features/steps/project/labels.rb30
-rw-r--r--features/steps/project/merge_requests.rb8
-rw-r--r--features/steps/shared/paths.rb14
-rw-r--r--lib/api/entities.rb2
-rw-r--r--lib/api/helpers.rb15
-rw-r--r--lib/api/issues.rb21
-rw-r--r--lib/api/merge_requests.rb12
-rw-r--r--lib/api/repositories.rb10
-rw-r--r--lib/gitlab/diff_parser.rb2
-rw-r--r--lib/gitlab/ldap/access.rb13
-rw-r--r--lib/gitlab/user_access.rb9
-rw-r--r--lib/gt_one_coercion.rb5
-rw-r--r--lib/tasks/gitlab/check.rake6
-rw-r--r--lib/unfold_form.rb11
-rw-r--r--spec/models/user_spec.rb34
-rw-r--r--spec/requests/api/issues_spec.rb20
-rw-r--r--spec/requests/api/merge_requests_spec.rb27
64 files changed, 554 insertions, 127 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 28586bdeb8c..50dc6b8945b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -12,6 +12,11 @@ v 7.2.0
- Test gitlab-shell integration
- Repository import timeout increased from 2 to 4 minutes allowing larger repos to be imported
+v 7.1.1
+ - Fix cpu usage issue in Firefox
+ - Fix redirect loop when changing password by new user
+ - Fix 500 error on new merge request page
+
v 7.1.0
- Remove observers
- Improve MR discussions
diff --git a/Gemfile b/Gemfile
index e61d9b2ff7d..d7aa463d830 100644
--- a/Gemfile
+++ b/Gemfile
@@ -178,6 +178,7 @@ gem "gitlab_emoji", "~> 0.0.1.1"
gem "gon", '~> 5.0.0'
gem 'nprogress-rails'
gem 'request_store'
+gem "virtus"
group :development do
gem "annotate", "~> 2.6.0.beta2"
diff --git a/Gemfile.lock b/Gemfile.lock
index c77d20debd9..500e80ce4ee 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -179,12 +179,12 @@ GEM
mime-types (~> 1.19)
gitlab_emoji (0.0.1.1)
emoji (~> 1.0.1)
- gitlab_git (6.1.0)
+ gitlab_git (6.2.1)
activesupport (~> 4.0)
charlock_holmes (~> 0.6)
gitlab-grit (~> 2.6)
gitlab-linguist (~> 3.0)
- rugged (~> 0.19.0)
+ rugged (~> 0.21.0)
gitlab_meta (7.0)
gitlab_omniauth-ldap (1.0.4)
net-ldap (~> 0.3.1)
@@ -334,7 +334,7 @@ GEM
multi_json (~> 1.0)
websocket-driver (>= 0.2.0)
polyglot (0.3.4)
- posix-spawn (0.3.8)
+ posix-spawn (0.3.9)
pry (0.9.12.4)
coderay (~> 1.0)
method_source (~> 0.8)
@@ -436,7 +436,7 @@ GEM
ruby-progressbar (1.2.0)
rubyntlm (0.1.1)
rubypants (0.2.0)
- rugged (0.19.0)
+ rugged (0.21.0)
safe_yaml (0.9.7)
sanitize (2.1.0)
nokogiri (>= 1.4.4)
@@ -540,7 +540,7 @@ GEM
eventmachine (>= 0.12.8)
http_parser.rb (~> 0.5.1)
simple_oauth (~> 0.1.4)
- tzinfo (1.2.1)
+ tzinfo (1.2.2)
thread_safe (~> 0.1)
uglifier (2.3.2)
execjs (>= 0.3.0)
@@ -692,5 +692,6 @@ DEPENDENCIES
unicorn (~> 4.6.3)
unicorn-worker-killer
version_sorter
+ virtus
webmock
wikicloth (= 0.8.1)
diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee
index a28f76ddd15..1960479321c 100644
--- a/app/assets/javascripts/application.js.coffee
+++ b/app/assets/javascripts/application.js.coffee
@@ -53,15 +53,40 @@ window.split = (val) ->
window.extractLast = (term) ->
return split( term ).pop()
+window.rstrip = (val) ->
+ return val.replace(/\s+$/, '')
+
# Disable button if text field is empty
window.disableButtonIfEmptyField = (field_selector, button_selector) ->
field = $(field_selector)
- closest_submit = field.closest("form").find(button_selector)
+ closest_submit = field.closest('form').find(button_selector)
+
+ closest_submit.disable() if rstrip(field.val()) is ""
+
+ field.on 'input', ->
+ if rstrip($(@).val()) is ""
+ closest_submit.disable()
+ else
+ closest_submit.enable()
+
+# Disable button if any input field with given selector is empty
+window.disableButtonIfAnyEmptyField = (form, form_selector, button_selector) ->
+ closest_submit = form.find(button_selector)
+ empty = false
+ form.find('input').filter(form_selector).each ->
+ empty = true if rstrip($(this).val()) is ""
+
+ if empty
+ closest_submit.disable()
+ else
+ closest_submit.enable()
- closest_submit.disable() if field.val() is ""
+ form.keyup ->
+ empty = false
+ form.find('input').filter(form_selector).each ->
+ empty = true if rstrip($(this).val()) is ""
- field.on "input", ->
- if $(@).val() is ""
+ if empty
closest_submit.disable()
else
closest_submit.enable()
diff --git a/app/assets/javascripts/diff.js.coffee b/app/assets/javascripts/diff.js.coffee
new file mode 100644
index 00000000000..dbe00c487dc
--- /dev/null
+++ b/app/assets/javascripts/diff.js.coffee
@@ -0,0 +1,46 @@
+class Diff
+ UNFOLD_COUNT = 20
+ constructor: ->
+ $(document).on('click', '.js-unfold', (event) =>
+ target = $(event.target)
+ unfoldBottom = target.hasClass('js-unfold-bottom')
+ unfold = true
+
+ [old_line, line_number] = @lineNumbers(target.parent())
+ offset = line_number - old_line
+
+ if unfoldBottom
+ line_number += 1
+ since = line_number
+ to = line_number + UNFOLD_COUNT
+ else
+ [prev_old_line, prev_new_line] = @lineNumbers(target.parent().prev())
+ line_number -= 1
+ to = line_number
+ if line_number - UNFOLD_COUNT > prev_new_line + 1
+ since = line_number - UNFOLD_COUNT
+ else
+ since = prev_new_line + 1
+ unfold = false
+
+ link = target.parents('.diff-file').attr('data-blob-diff-path')
+ params =
+ since: since
+ to: to
+ bottom: unfoldBottom
+ offset: offset
+ unfold: unfold
+
+ $.get(link, params, (response) =>
+ target.parent().replaceWith(response)
+ )
+ )
+
+ lineNumbers: (line) ->
+ return ([0, 0]) unless line.children().length
+ lines = line.children().slice(0, 2)
+ line_numbers = ($(l).attr('data-linenumber') for l in lines)
+ (parseInt(line_number) for line_number in line_numbers)
+
+
+@Diff = Diff
diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee
index ff68b520ad6..a463a2eb194 100644
--- a/app/assets/javascripts/dispatcher.js.coffee
+++ b/app/assets/javascripts/dispatcher.js.coffee
@@ -23,13 +23,21 @@ class Dispatcher
new Issue()
when 'projects:milestones:show'
new Milestone()
- when 'projects:issues:new', 'projects:merge_requests:new'
+ when 'projects:issues:new'
GitLab.GfmAutoComplete.setup()
+ when 'projects:merge_requests:new'
+ GitLab.GfmAutoComplete.setup()
+ new Diff()
+ when 'projects:merge_requests:show'
+ new Diff()
+ when "projects:merge_requests:diffs"
+ new Diff()
when 'dashboard:show'
new Dashboard()
new Activities()
when 'projects:commit:show'
new Commit()
+ new Diff()
when 'groups:show', 'projects:show'
new Activities()
when 'projects:new', 'projects:edit'
@@ -42,6 +50,8 @@ class Dispatcher
new TreeView()
when 'projects:blob:show'
new BlobView()
+ when 'projects:labels:new'
+ new Labels()
switch path.first()
when 'admin' then new Admin()
diff --git a/app/assets/javascripts/labels.js.coffee b/app/assets/javascripts/labels.js.coffee
new file mode 100644
index 00000000000..8e53d6929df
--- /dev/null
+++ b/app/assets/javascripts/labels.js.coffee
@@ -0,0 +1,35 @@
+class Labels
+ constructor: ->
+ form = $('.label-form')
+ @setupLabelForm(form)
+ @cleanBinding()
+ @addBinding()
+ @updateColorPreview
+
+ addBinding: ->
+ $(document).on 'click', '.suggest-colors a', @setSuggestedColor
+ $(document).on 'input', 'input#label_color', @updateColorPreview
+
+ cleanBinding: ->
+ $(document).off 'click', '.suggest-colors a'
+ $(document).off 'input', 'input#label_color'
+
+ # Initializes the form to disable the save button if no color or title is entered
+ setupLabelForm: (form) ->
+ disableButtonIfAnyEmptyField form, '.form-control', form.find('.js-save-button')
+
+ # Updates the the preview color with the hex-color input
+ updateColorPreview: =>
+ previewColor = $('input#label_color').val()
+ $('div.label-color-preview').css('background-color', previewColor)
+
+ # Updates the preview color with a click on a suggested color
+ setSuggestedColor: (e) =>
+ color = $(e.currentTarget).data('color')
+ $('input#label_color').val(color)
+ @updateColorPreview()
+ # Notify the form, that color has changed
+ $('.label-form').trigger('keyup')
+ e.preventDefault()
+
+@Labels = Labels
diff --git a/app/assets/javascripts/pager.js.coffee b/app/assets/javascripts/pager.js.coffee
index 1f763e8b956..fe83dc0410e 100644
--- a/app/assets/javascripts/pager.js.coffee
+++ b/app/assets/javascripts/pager.js.coffee
@@ -1,24 +1,21 @@
@Pager =
- limit: 0
- offset: 0
- disable: false
- init: (limit, preload) ->
- @limit = limit
+ init: (@limit = 0, preload, @disable = false) ->
+ @loading = $(".loading")
if preload
@offset = 0
@getOld()
else
- @offset = limit
+ @offset = @limit
@initLoadMore()
getOld: ->
- $(".loading").show()
+ @loading.show()
$.ajax
type: "GET"
url: location.href
data: "limit=" + @limit + "&offset=" + @offset
- complete: ->
- $(".loading").hide()
+ complete: =>
+ @loading.hide()
success: (data) ->
Pager.append(data.count, data.html)
dataType: "json"
@@ -39,6 +36,7 @@
ceaseFire: ->
Pager.disable
- callback: (i) ->
- $(".loading").show()
- Pager.getOld()
+ callback: (i) =>
+ unless @loading.is(':visible')
+ @loading.show()
+ Pager.getOld()
diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss
index 684e8377a7b..0083d01c460 100644
--- a/app/assets/stylesheets/sections/commits.scss
+++ b/app/assets/stylesheets/sections/commits.scss
@@ -244,6 +244,7 @@ li.commit {
font-family: inherit;
padding-left: $left;
position: relative;
+ resize: vertical;
z-index: 2;
}
}
diff --git a/app/assets/stylesheets/sections/diff.scss b/app/assets/stylesheets/sections/diff.scss
index 88b188dbe8d..488d06919b0 100644
--- a/app/assets/stylesheets/sections/diff.scss
+++ b/app/assets/stylesheets/sections/diff.scss
@@ -48,6 +48,9 @@
background-color: #8F8;
}
}
+ .unfold {
+ cursor: pointer;
+ }
.file-mode-changed {
padding: 10px;
diff --git a/app/assets/stylesheets/sections/login.scss b/app/assets/stylesheets/sections/login.scss
index 54887b7c401..77ebef690c3 100644
--- a/app/assets/stylesheets/sections/login.scss
+++ b/app/assets/stylesheets/sections/login.scss
@@ -13,6 +13,10 @@
max-width: 100%;
margin-bottom: 20px;
}
+
+ &.default-brand-image {
+ margin: 0 80px;
+ }
}
.login-logo{
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index d0546a441e1..5ffec7f75bf 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -201,15 +201,10 @@ class ApplicationController < ActionController::Base
def ldap_security_check
if current_user && current_user.requires_ldap_check?
- gitlab_ldap_access do |access|
- if access.allowed?(current_user)
- current_user.last_credential_check_at = Time.now
- current_user.save
- else
- sign_out current_user
- flash[:alert] = "Access denied for your LDAP account."
- redirect_to new_user_session_path
- end
+ unless Gitlab::LDAP::Access.allowed?(current_user)
+ sign_out current_user
+ flash[:alert] = "Access denied for your LDAP account."
+ redirect_to new_user_session_path
end
end
end
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index ef2afec52dc..3ed6a69c2d8 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -21,13 +21,12 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
@user = Gitlab::LDAP::User.find_or_create(oauth)
@user.remember_me = true if @user.persisted?
- gitlab_ldap_access do |access|
- if access.allowed?(@user)
- sign_in_and_redirect(@user)
- else
- flash[:alert] = "Access denied for your LDAP account."
- redirect_to new_user_session_path
- end
+ # Do additional LDAP checks for the user filter and EE features
+ if Gitlab::LDAP::Access.allowed?(@user)
+ sign_in_and_redirect(@user)
+ else
+ flash[:alert] = "Access denied for your LDAP account."
+ redirect_to new_user_session_path
end
end
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index db3d173b98d..7009e3b1bc8 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -25,6 +25,21 @@ class Projects::BlobController < Projects::ApplicationController
end
end
+ def diff
+ @form = UnfoldForm.new(params)
+ @lines = @blob.data.lines[@form.since - 1..@form.to - 1]
+
+ if @form.bottom?
+ @match_line = ''
+ else
+ lines_length = @lines.length - 1
+ line = [@form.since, lines_length].join(',')
+ @match_line = "@@ -#{line}+#{line} @@"
+ end
+
+ render layout: false
+ end
+
private
def blob
diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb
index d049012f6d8..87d1c942034 100644
--- a/app/controllers/projects/labels_controller.rb
+++ b/app/controllers/projects/labels_controller.rb
@@ -50,7 +50,10 @@ class Projects::LabelsController < Projects::ApplicationController
def destroy
@label.destroy
- redirect_to project_labels_path(@project), notice: 'Label was removed'
+ respond_to do |format|
+ format.html { redirect_to project_labels_path(@project), notice: 'Label was removed' }
+ format.js { render nothing: true }
+ end
end
protected
diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb
index f76ddb34bc4..f30eaadd928 100644
--- a/app/controllers/projects/repositories_controller.rb
+++ b/app/controllers/projects/repositories_controller.rb
@@ -14,11 +14,7 @@ class Projects::RepositoriesController < Projects::ApplicationController
render_404 and return
end
- storage_path = Gitlab.config.gitlab.repository_downloads_path
-
- @repository.clean_old_archives
-
- file_path = @repository.archive_repo(params[:ref], storage_path, params[:format].downcase)
+ file_path = ArchiveRepositoryService.new.execute(@project, params[:ref], params[:format])
if file_path
# Send file to user
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index 9a8b3928bf4..f61aa259154 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -232,4 +232,16 @@ module CommitsHelper
def diff_file_mode_changed?(diff)
diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
end
+
+ def unfold_bottom_class(bottom)
+ (bottom) ? 'js-unfold-bottom' : ''
+ end
+
+ def view_file_btn(commit_sha, diff, project)
+ link_to project_blob_path(project, tree_join(commit_sha, diff.new_path)),
+ class: 'btn btn-small view-file js-view-file' do
+ raw('View file @') + content_tag(:span, commit_sha[0..6],
+ class: 'commit-short-id')
+ end
+ end
end
diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index 37f3832e54f..5bfba4f14f2 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -4,7 +4,7 @@ module LabelsHelper
end
def render_colored_label(label)
- label_color = label.color || "#428bca"
+ label_color = label.color || Label::DEFAULT_COLOR
text_color = text_color_for_bg(label_color)
content_tag :span, class: 'label color-label', style: "background:#{label_color};color:#{text_color}" do
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index 517e4548624..0a5fe24b5af 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -140,7 +140,8 @@ module Issuable
def add_labels_by_names(label_names)
label_names.each do |label_name|
- label = project.labels.find_or_create_by(title: label_name.strip)
+ label = project.labels.create_with(
+ color: Label::DEFAULT_COLOR).find_or_create_by(title: label_name.strip)
self.labels << label
end
end
diff --git a/app/models/label.rb b/app/models/label.rb
index ce982579675..c32efc7c47f 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -1,13 +1,20 @@
class Label < ActiveRecord::Base
+ DEFAULT_COLOR = '#428bca'
+
belongs_to :project
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: true
+ validates :color,
+ format: { with: /\A\#[0-9A-Fa-f]{6}+\Z/ },
+ allow_blank: false
validates :project, presence: true
- # Dont allow '?', '&', and ',' for label titles
- validates :title, presence: true, format: { with: /\A[^&\?,&]*\z/ }
+ # Don't allow '?', '&', and ',' for label titles
+ validates :title,
+ presence: true,
+ format: { with: /\A[^&\?,&]*\z/ },
+ uniqueness: { scope: :project_id }
scope :order_by_name, -> { reorder("labels.title ASC") }
diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb
index 48fe365760b..256debffc51 100644
--- a/app/models/project_services/hipchat_service.rb
+++ b/app/models/project_services/hipchat_service.rb
@@ -59,11 +59,15 @@ class HipchatService < Service
message = ""
message << "#{push[:user_name]} "
if before =~ /000000/
- message << "pushed new branch <a href=\"#{project.web_url}/commits/#{ref}\">#{ref}</a> to <a href=\"#{project.web_url}\">#{project.name_with_namespace.gsub!(/\s/,'')}</a>\n"
+ message << "pushed new branch <a href=\""\
+ "#{project.web_url}/commits/#{URI.escape(ref)}\">#{ref}</a>"\
+ " to <a href=\"#{project.web_url}\">"\
+ "#{project.name_with_namespace.gsub!(/\s/, "")}</a>\n"
elsif after =~ /000000/
message << "removed branch #{ref} from <a href=\"#{project.web_url}\">#{project.name_with_namespace.gsub!(/\s/,'')}</a> \n"
else
- message << "pushed to branch <a href=\"#{project.web_url}/commits/#{ref}\">#{ref}</a> "
+ message << "pushed to branch <a href=\""\
+ "#{project.web_url}/commits/#{URI.escape(ref)}\">#{ref}</a> "
message << "of <a href=\"#{project.web_url}\">#{project.name_with_namespace.gsub!(/\s/,'')}</a> "
message << "(<a href=\"#{project.web_url}/compare/#{before}...#{after}\">Compare changes</a>)"
diff --git a/app/models/user.rb b/app/models/user.rb
index 9ab3ea025c3..f1ff76edd15 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -414,7 +414,9 @@ class User < ActiveRecord::Base
end
def requires_ldap_check?
- if ldap_user?
+ if !Gitlab.config.ldap.enabled
+ false
+ elsif ldap_user?
!last_credential_check_at || (last_credential_check_at + 1.hour) < Time.now
else
false
diff --git a/app/services/archive_repository_service.rb b/app/services/archive_repository_service.rb
new file mode 100644
index 00000000000..8823f6fdc67
--- /dev/null
+++ b/app/services/archive_repository_service.rb
@@ -0,0 +1,14 @@
+class ArchiveRepositoryService
+ def execute(project, ref, format)
+ storage_path = Gitlab.config.gitlab.repository_downloads_path
+
+ unless File.directory?(storage_path)
+ FileUtils.mkdir_p(storage_path)
+ end
+
+ format ||= 'tar.gz'
+ repository = project.repository
+ repository.clean_old_archives
+ repository.archive_repo(ref, storage_path, format.downcase)
+ end
+end
diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml
index 00b1959912f..dd70836cdc9 100644
--- a/app/views/layouts/devise.html.haml
+++ b/app/views/layouts/devise.html.haml
@@ -18,7 +18,7 @@
.brand_text
= brand_text
- else
- .brand-image.hidden-sm.hidden-xs
+ .brand-image.default-brand-image.hidden-sm.hidden-xs
= image_tag 'brand_logo.png'
.brand_text.hidden-xs
%h2 Open source software to collaborate on code
diff --git a/app/views/projects/blob/diff.html.haml b/app/views/projects/blob/diff.html.haml
new file mode 100644
index 00000000000..cfb91d6568a
--- /dev/null
+++ b/app/views/projects/blob/diff.html.haml
@@ -0,0 +1,19 @@
+- if @lines.present?
+ - if @form.unfold? && @form.since != 1 && !@form.bottom?
+ %tr.line_holder{ id: @form.since }
+ = render "projects/commits/diffs/match_line", {line: @match_line,
+ line_old: @form.since, line_new: @form.since, bottom: false}
+
+ - @lines.each_with_index do |line, index|
+ - line_new = index + @form.since
+ - line_old = line_new - @form.offset
+ %tr.line_holder
+ %td.old_line.diff-line-num{data: {linenumber: line_old}}
+ = link_to raw(line_old), "#"
+ %td.new_line= link_to raw(line_new) , "#"
+ %td.line_content.noteable_line= line
+
+ - if @form.unfold? && @form.bottom? && @form.to < @blob.loc
+ %tr.line_holder{ id: @form.to }
+ = render "projects/commits/diffs/match_line", {line: @match_line,
+ line_old: @form.to, line_new: @form.to, bottom: true}
diff --git a/app/views/projects/commits/_diff_file.html.haml b/app/views/projects/commits/_diff_file.html.haml
index 9cbcb84aead..6e6107c8849 100644
--- a/app/views/projects/commits/_diff_file.html.haml
+++ b/app/views/projects/commits/_diff_file.html.haml
@@ -1,15 +1,15 @@
- file = project.repository.blob_for_diff(@commit, diff)
- return unless file
-.diff-file{id: "diff-#{i}"}
+- blob_diff_path = diff_project_blob_path(project,
+ tree_join(@commit.id, diff.new_path))
+.diff-file{id: "diff-#{i}", data: {blob_diff_path: blob_diff_path }}
.diff-header{id: "file-path-#{hexdigest(diff.new_path || diff.old_path)}"}
- if diff.deleted_file
%span= diff.old_path
.diff-btn-group
- if @commit.parent_ids.present?
- = link_to project_blob_path(project, tree_join(@commit.parent_id, diff.new_path)), { class: 'btn btn-small view-file' } do
- View file @
- %span.commit-short-id= @commit.short_id(6)
+ = view_file_btn(@commit.parent_id, diff, project)
- else
%span= diff.new_path
- if diff_file_mode_changed?(diff)
@@ -26,10 +26,7 @@
Edit
&nbsp;
- = link_to project_blob_path(project, tree_join(@commit.id, diff.new_path)), { class: 'btn btn-small view-file' } do
- View file @
- %span.commit-short-id= @commit.short_id(6)
-
+ = view_file_btn(@commit.id, diff, project)
.diff-content
-# Skipp all non non-supported blobs
diff --git a/app/views/projects/commits/_text_file.html.haml b/app/views/projects/commits/_text_file.html.haml
index f5b0d711416..756481c1b21 100644
--- a/app/views/projects/commits/_text_file.html.haml
+++ b/app/views/projects/commits/_text_file.html.haml
@@ -3,18 +3,20 @@
%a.supp_diff_link Changes suppressed. Click to show
%table.text-file{class: "#{'hide' if too_big}"}
+ - last_line = 0
- each_diff_line(diff, index) do |line, type, line_code, line_new, line_old, raw_line|
+ - last_line = line_new
%tr.line_holder{ id: line_code, class: "#{type}" }
- if type == "match"
- %td.old_line= "..."
- %td.new_line= "..."
- %td.line_content.matched= line
+ = render "projects/commits/diffs/match_line", {line: line,
+ line_old: line_old, line_new: line_new, bottom: false}
- else
%td.old_line
= link_to raw(type == "new" ? "&nbsp;" : line_old), "##{line_code}", id: line_code
- if @comments_allowed
= link_to_new_diff_note(line_code)
- %td.new_line= link_to raw(type == "old" ? "&nbsp;" : line_new) , "##{line_code}", id: line_code
+ %td.new_line{data: {linenumber: line_new}}
+ = link_to raw(type == "old" ? "&nbsp;" : line_new) , "##{line_code}", id: line_code
%td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line)
- if @reply_allowed
@@ -22,6 +24,10 @@
- unless comments.empty?
= render "projects/notes/diff_notes_with_reply", notes: comments, line: line
+ - if last_line > 0
+ = render "projects/commits/diffs/match_line", {line: "",
+ line_old: last_line, line_new: last_line, bottom: true}
+
- if diff.diff.blank? && diff_file_mode_changed?(diff)
.file-mode-changed
File mode changed
diff --git a/app/views/projects/commits/diffs/_match_line.html.haml b/app/views/projects/commits/diffs/_match_line.html.haml
new file mode 100644
index 00000000000..4ebe3379733
--- /dev/null
+++ b/app/views/projects/commits/diffs/_match_line.html.haml
@@ -0,0 +1,7 @@
+%td.old_line.diff-line-num.unfold.js-unfold{data: {linenumber: line_old},
+ class: unfold_bottom_class(bottom)}
+ \...
+%td.new_line.diff-line-num.unfold.js-unfold{data: {linenumber: line_new},
+ class: unfold_bottom_class(bottom)}
+ \...
+%td.line_content.matched= line
diff --git a/app/views/projects/labels/_form.html.haml b/app/views/projects/labels/_form.html.haml
index 2a5c907febe..72a01e1c271 100644
--- a/app/views/projects/labels/_form.html.haml
+++ b/app/views/projects/labels/_form.html.haml
@@ -28,22 +28,6 @@
&nbsp;
.form-actions
- = f.submit 'Save', class: 'btn btn-save'
+ = f.submit 'Save', class: 'btn btn-save js-save-button'
= link_to "Cancel", project_labels_path(@project), class: 'btn btn-cancel'
-
-:coffeescript
- updateColorPreview = ->
- previewColor = $('input#label_color').val()
- $('div.label-color-preview').css('background-color', previewColor)
-
- $('.suggest-colors a').on 'click', (e) ->
- color = $(this).data("color")
- $('input#label_color').val(color)
- updateColorPreview()
- e.preventDefault()
-
- $('input#label_color').on 'input', ->
- updateColorPreview()
-
- updateColorPreview()
diff --git a/app/views/projects/labels/_label.html.haml b/app/views/projects/labels/_label.html.haml
index 725bf852078..03a8f0921b7 100644
--- a/app/views/projects/labels/_label.html.haml
+++ b/app/views/projects/labels/_label.html.haml
@@ -7,4 +7,4 @@
- if can? current_user, :admin_label, @project
= link_to 'Edit', edit_project_label_path(@project, label), class: 'btn'
- = link_to 'Remove', project_label_path(@project, label), class: 'btn btn-remove', method: :delete, data: {confirm: "Remove this label? Are you sure?"}
+ = link_to 'Remove', project_label_path(@project, label), class: 'btn btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Remove this label? Are you sure?"}
diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml
index 979c27daa2b..df79125eae6 100644
--- a/app/views/projects/milestones/_form.html.haml
+++ b/app/views/projects/milestones/_form.html.haml
@@ -21,7 +21,7 @@
.form-group
= f.label :description, "Description", class: "control-label"
.col-sm-10
- = f.text_area :description, maxlength: 2000, class: "form-control markdown-area", rows: 10
+ = f.text_area :description, maxlength: 65535, class: "form-control markdown-area", rows: 10
.hint
.pull-left Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}.
.pull-left Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index 3b0cf77d42e..f110e20bf00 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -12,7 +12,7 @@ class PostReceive
log("Check gitlab.yml config for correct gitlab_shell.repos_path variable. \"#{Gitlab.config.gitlab_shell.repos_path}\" does not match \"#{repo_path}\"")
end
- repo_path.gsub!(/.git$/, "")
+ repo_path.gsub!(/\.git$/, "")
repo_path.gsub!(/^\//, "")
project = Project.find_with_namespace(repo_path)
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 356e26bd68c..03af7f07864 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -23,7 +23,7 @@ Gitlab::Application.configure do
config.assets.compress = false
# Expands the lines which load the assets
- config.assets.debug = true
+ # config.assets.debug = true
# For having correct urls in mails
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 7f31fb113c9..d897eb4c02d 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -259,6 +259,11 @@ test:
gitlab:
host: localhost
port: 80
+
+ # When you run tests we clone and setup gitlab-shell
+ # In order to setup it correctly you need to specify
+ # your system username you use to run GitLab
+ # user: YOUR_USERNAME
satellites:
path: tmp/tests/gitlab-satellites/
gitlab_shell:
diff --git a/config/routes.rb b/config/routes.rb
index 261fbb50e38..ce66ea99951 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -193,7 +193,9 @@ Gitlab::Application.routes.draw do
end
scope module: :projects do
- resources :blob, only: [:show, :destroy], constraints: {id: /.+/}
+ resources :blob, only: [:show, :destroy], constraints: { id: /.+/ } do
+ get :diff, on: :member
+ end
resources :raw, only: [:show], constraints: {id: /.+/}
resources :tree, only: [:show], constraints: {id: /.+/, format: /(html|js)/ }
resources :edit_tree, only: [:show, :update], constraints: { id: /.+/ }, path: 'edit' do
diff --git a/doc/api/issues.md b/doc/api/issues.md
index f775d502a6d..a4b3b3e9918 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -157,6 +157,9 @@ Parameters:
- `milestone_id` (optional) - The ID of a milestone to assign issue
- `labels` (optional) - Comma-separated label names for an issue
+If the operation is successful, 200 and the newly created issue is returned.
+If an error occurs, an error number and a message explaining the reason is returned.
+
## Edit issue
Updates an existing project issue. This function is also used to mark an issue as closed.
@@ -176,6 +179,9 @@ Parameters:
- `labels` (optional) - Comma-separated label names for an issue
- `state_event` (optional) - The state event of an issue ('close' to close issue and 'reopen' to reopen it)
+If the operation is successful, 200 and the updated issue is returned.
+If an error occurs, an error number and a message explaining the reason is returned.
+
## Delete existing issue (**Deprecated**)
The function is deprecated and returns a `405 Method Not Allowed` error if called. An issue gets now closed and is done by calling `PUT /projects/:id/issues/:issue_id` with parameter `closed` set to 1.
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index a46472a0812..230f572fc3b 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -42,7 +42,8 @@ Parameters:
"name": "Administrator",
"state": "active",
"created_at": "2012-04-29T08:46:00Z"
- }
+ },
+ "description":"fixed login page css paddings"
}
]
```
@@ -86,7 +87,8 @@ Parameters:
"name": "Administrator",
"state": "active",
"created_at": "2012-04-29T08:46:00Z"
- }
+ },
+ "description":"fixed login page css paddings"
}
```
@@ -132,10 +134,14 @@ Parameters:
"name": "Administrator",
"state": "active",
"created_at": "2012-04-29T08:46:00Z"
- }
+ },
+ "description":"fixed login page css paddings"
}
```
+If the operation is successful, 200 and the newly created merge request is returned.
+If an error occurs, an error number and a message explaining the reason is returned.
+
## Update MR
Updates an existing merge request. You can change branches, title, or even close the MR.
@@ -183,15 +189,18 @@ Parameters:
}
```
+If the operation is successful, 200 and the updated merge request is returned.
+If an error occurs, an error number and a message explaining the reason is returned.
+
## Accept MR
-Merge changes submitted with MR usign this API.
+Merge changes submitted with MR using this API.
If merge success you get 200 OK.
If it has some conflicts and can not be merged - you get 405 and error message 'Branch cannot be merged'
-If merge request is already merged or closed - you get 405 and error message 'Method Not Allowed'
+If merge request is already merged or closed - you get 405 and error message 'Method Not Allowed'
If you dont have permissions to accept this merge request - you get 401
diff --git a/doc/install/installation.md b/doc/install/installation.md
index e502a3ed82c..44742984ca9 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -69,7 +69,7 @@ Is the system packaged Git too old? Remove it and compile from source.
# Download and compile from source
cd /tmp
- curl --progress https://www.kernel.org/pub/software/scm/git/git-2.0.0.tar.gz | tar xz
+ curl -L --progress https://www.kernel.org/pub/software/scm/git/git-2.0.0.tar.gz | tar xz
cd git-2.0.0/
make prefix=/usr/local all
@@ -95,7 +95,7 @@ Remove the old Ruby 1.8 if present
Download Ruby and compile it:
mkdir /tmp/ruby && cd /tmp/ruby
- curl --progress ftp://ftp.ruby-lang.org/pub/ruby/2.1/ruby-2.1.2.tar.gz | tar xz
+ curl -L --progress ftp://ftp.ruby-lang.org/pub/ruby/2.1/ruby-2.1.2.tar.gz | tar xz
cd ruby-2.1.2
./configure --disable-install-rdoc
make
diff --git a/doc/update/4.0-to-4.1.md b/doc/update/4.0-to-4.1.md
index d5e5d62fb15..4149ed6b08d 100644
--- a/doc/update/4.0-to-4.1.md
+++ b/doc/update/4.0-to-4.1.md
@@ -36,7 +36,7 @@ sudo -u gitlab -H bundle exec rake db:migrate RAILS_ENV=production
sudo mv /etc/init.d/gitlab /etc/init.d/gitlab.old
# get new one using sidekiq
-sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlab-recipes/4-1-stable/init.d/gitlab
+sudo curl -L --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlab-recipes/4-1-stable/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
```
diff --git a/doc/update/4.2-to-5.0.md b/doc/update/4.2-to-5.0.md
index 27cc72c1cb6..6ec153f6245 100644
--- a/doc/update/4.2-to-5.0.md
+++ b/doc/update/4.2-to-5.0.md
@@ -116,7 +116,7 @@ sudo chmod -R u+rwX /home/git/gitlab/tmp/pids
```bash
# init.d
sudo rm /etc/init.d/gitlab
-sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlab-recipes/5-0-stable/init.d/gitlab
+sudo curl -L --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlab-recipes/5-0-stable/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
# unicorn
diff --git a/doc/update/5.0-to-5.1.md b/doc/update/5.0-to-5.1.md
index b04f3065a17..0e597abb1a9 100644
--- a/doc/update/5.0-to-5.1.md
+++ b/doc/update/5.0-to-5.1.md
@@ -52,7 +52,7 @@ sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
```bash
# init.d
sudo rm /etc/init.d/gitlab
-sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlab-recipes/5-1-stable/init.d/gitlab
+sudo curl -L --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlab-recipes/5-1-stable/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
```
diff --git a/doc/update/5.2-to-5.3.md b/doc/update/5.2-to-5.3.md
index e39e18d4211..9851f7b2730 100644
--- a/doc/update/5.2-to-5.3.md
+++ b/doc/update/5.2-to-5.3.md
@@ -50,7 +50,7 @@ sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
```bash
sudo rm /etc/init.d/gitlab
-sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/5-3-stable/lib/support/init.d/gitlab
+sudo curl -L --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/5-3-stable/lib/support/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
```
diff --git a/doc/update/5.3-to-5.4.md b/doc/update/5.3-to-5.4.md
index e1749f133b3..b130f4c65bb 100644
--- a/doc/update/5.3-to-5.4.md
+++ b/doc/update/5.3-to-5.4.md
@@ -54,7 +54,7 @@ sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
```bash
sudo rm /etc/init.d/gitlab
-sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/5-4-stable/lib/support/init.d/gitlab
+sudo curl -L --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/5-4-stable/lib/support/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
```
diff --git a/doc/update/6.9-to-7.0.md b/doc/update/6.9-to-7.0.md
index 806a714c49b..99ec441e275 100644
--- a/doc/update/6.9-to-7.0.md
+++ b/doc/update/6.9-to-7.0.md
@@ -32,7 +32,7 @@ Download and compile Ruby:
```bash
mkdir /tmp/ruby && cd /tmp/ruby
-curl --progress ftp://ftp.ruby-lang.org/pub/ruby/2.1/ruby-2.1.2.tar.gz | tar xz
+curl -L --progress ftp://ftp.ruby-lang.org/pub/ruby/2.1/ruby-2.1.2.tar.gz | tar xz
cd ruby-2.1.2
./configure --disable-install-rdoc
make
diff --git a/doc/update/7.0-to-7.1.md b/doc/update/7.0-to-7.1.md
index ba2d9a23a36..569f9160eb3 100644
--- a/doc/update/7.0-to-7.1.md
+++ b/doc/update/7.0-to-7.1.md
@@ -32,7 +32,7 @@ Download and compile Ruby:
```bash
mkdir /tmp/ruby && cd /tmp/ruby
-curl --progress ftp://ftp.ruby-lang.org/pub/ruby/2.1/ruby-2.1.2.tar.gz | tar xz
+curl -L --progress ftp://ftp.ruby-lang.org/pub/ruby/2.1/ruby-2.1.2.tar.gz | tar xz
cd ruby-2.1.2
./configure --disable-install-rdoc
make
diff --git a/features/project/issues/labels.feature b/features/project/issues/labels.feature
index 4a37b6dc9fa..29cf5307271 100644
--- a/features/project/issues/labels.feature
+++ b/features/project/issues/labels.feature
@@ -10,7 +10,7 @@ Feature: Project Labels
And I should see label "feature"
Scenario: I create new label
- Given I visit new label page
+ Given I visit project "Shop" new label page
When I submit new label 'support'
Then I should see label 'support'
@@ -23,3 +23,21 @@ Feature: Project Labels
Scenario: I remove label
When I remove label 'bug'
Then I should not see label 'bug'
+
+ Scenario: I create a label with invalid color
+ Given I visit project "Shop" new label page
+ When I submit new label with invalid color
+ Then I should see label color error message
+
+ Scenario: I create a label that already exists
+ Given I visit project "Shop" new label page
+ When I submit new label 'bug'
+ Then I should see label label exist error message
+
+ Scenario: I create the same label on another project
+ Given I own project "Forum"
+ And I visit project "Forum" labels page
+ And I visit project "Forum" new label page
+ When I submit new label 'bug'
+ Then I should see label 'bug'
+
diff --git a/features/project/merge_requests.feature b/features/project/merge_requests.feature
index d4c71ba336e..8b6c296dfe6 100644
--- a/features/project/merge_requests.feature
+++ b/features/project/merge_requests.feature
@@ -139,3 +139,11 @@ Feature: Project Merge Requests
And I click link "Show inline discussion" of the second file
Then I should see a comment like "Line is wrong" in the second file
And I should still see a comment like "Line is correct" in the first file
+
+ @javascript
+ Scenario: I unfold diff
+ Given project "Shop" have "Bug NS-05" open merge request with diffs inside
+ And I visit merge request page "Bug NS-05"
+ And I switch to the diff tab
+ And I unfold diff
+ Then I should see additional file lines
diff --git a/features/steps/project/labels.rb b/features/steps/project/labels.rb
index 3d9aa29299c..8320405e096 100644
--- a/features/steps/project/labels.rb
+++ b/features/steps/project/labels.rb
@@ -31,6 +31,36 @@ class ProjectLabels < Spinach::FeatureSteps
click_button 'Save'
end
+ step 'I submit new label \'bug\'' do
+ fill_in 'Title', with: 'bug'
+ fill_in 'Background Color', with: '#F95610'
+ click_button 'Save'
+ end
+
+ step 'I submit new label with invalid color' do
+ fill_in 'Title', with: 'support'
+ fill_in 'Background Color', with: '#12'
+ click_button 'Save'
+ end
+
+ step 'I should see label label exist error message' do
+ within '.label-form' do
+ page.should have_content 'Title has already been taken'
+ end
+ end
+
+ step 'I should see label color error message' do
+ within '.label-form' do
+ page.should have_content 'Color is invalid'
+ end
+ end
+
+ step 'I should see label \'bug\'' do
+ within '.manage-labels-list' do
+ page.should have_content 'bug'
+ end
+ end
+
step 'I should not see label \'bug\'' do
within '.manage-labels-list' do
page.should_not have_content 'bug'
diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb
index f0007a039e4..05d3e5067c5 100644
--- a/features/steps/project/merge_requests.rb
+++ b/features/steps/project/merge_requests.rb
@@ -242,6 +242,14 @@ class ProjectMergeRequests < Spinach::FeatureSteps
end
end
+ step 'I unfold diff' do
+ first('.js-unfold').click
+ end
+
+ step 'I should see additional file lines' do
+ expect(first('.text-file')).to have_content('.bundle')
+ end
+
def project
@project ||= Project.find_by!(name: "Shop")
end
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
index 4e97dba20b3..0d06383509f 100644
--- a/features/steps/shared/paths.rb
+++ b/features/steps/shared/paths.rb
@@ -287,10 +287,22 @@ module SharedPaths
end
step 'I visit project "Shop" labels page' do
+ project = Project.find_by(name: 'Shop')
visit project_labels_path(project)
end
- step 'I visit new label page' do
+ step 'I visit project "Forum" labels page' do
+ project = Project.find_by(name: 'Forum')
+ visit project_labels_path(project)
+ end
+
+ step 'I visit project "Shop" new label page' do
+ project = Project.find_by(name: 'Shop')
+ visit new_project_label_path(project)
+ end
+
+ step 'I visit project "Forum" new label page' do
+ project = Project.find_by(name: 'Forum')
visit new_project_label_path(project)
end
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 8731db59e57..fc7d391fd30 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -137,6 +137,8 @@ module API
expose :author, :assignee, using: Entities::UserBasic
expose :source_project_id, :target_project_id
expose :label_names, as: :labels
+ expose :description
+ expose :milestone, using: Entities::Milestone
end
class SSHKey < Grape::Entity
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 8189e433789..d36b29a00b1 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -112,6 +112,21 @@ module API
ActionController::Parameters.new(attrs).permit!
end
+ # Helper method for validating all labels against its names
+ def validate_label_params(params)
+ if params[:labels].present?
+ params[:labels].split(',').each do |label_name|
+ label = user_project.labels.create_with(
+ color: Label::DEFAULT_COLOR).find_or_initialize_by(
+ title: label_name.strip)
+ if label.invalid?
+ return true
+ end
+ end
+ end
+ false
+ end
+
# error helpers
def forbidden!
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index b29118b2fd8..055529ccbd8 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -51,12 +51,18 @@ module API
required_attributes! [:title]
attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id]
+ # Validate label names in advance
+ if validate_label_params(params)
+ return render_api_error!('Label names invalid', 405)
+ end
+
issue = ::Issues::CreateService.new(user_project, current_user, attrs).execute
if issue.valid?
- # Find or create labels and attach to issue
+ # Find or create labels and attach to issue. Labels are valid because
+ # we already checked its name, so there can't be an error here
if params[:labels].present?
- issue.add_labels_by_names(params[:labels].split(","))
+ issue.add_labels_by_names(params[:labels].split(','))
end
present issue, with: Entities::Issue
@@ -83,12 +89,19 @@ module API
authorize! :modify_issue, issue
attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id, :state_event]
+ # Validate label names in advance
+ if validate_label_params(params)
+ return render_api_error!('Label names invalid', 405)
+ end
+
issue = ::Issues::UpdateService.new(user_project, current_user, attrs).execute(issue)
if issue.valid?
- # Find or create labels and attach to issue
+ # Find or create labels and attach to issue. Labels are valid because
+ # we already checked its name, so there can't be an error here
if params[:labels].present?
- issue.add_labels_by_names(params[:labels].split(","))
+ # Create and add labels to the new created issue
+ issue.add_labels_by_names(params[:labels].split(','))
end
present issue, with: Entities::Issue
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index acca7cb6bad..0d765f9280e 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -76,6 +76,12 @@ module API
authorize! :write_merge_request, user_project
required_attributes! [:source_branch, :target_branch, :title]
attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :target_project_id, :description]
+
+ # Validate label names in advance
+ if validate_label_params(params)
+ return render_api_error!('Label names invalid', 405)
+ end
+
merge_request = ::MergeRequests::CreateService.new(user_project, current_user, attrs).execute
if merge_request.valid?
@@ -109,6 +115,12 @@ module API
attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :state_event, :description]
merge_request = user_project.merge_requests.find(params[:merge_request_id])
authorize! :modify_merge_request, merge_request
+
+ # Validate label names in advance
+ if validate_label_params(params)
+ return render_api_error!('Label names invalid', 405)
+ end
+
merge_request = ::MergeRequests::UpdateService.new(user_project, current_user, attrs).execute(merge_request)
if merge_request.valid?
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index 461ce4e59cf..42068bb343d 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -115,21 +115,13 @@ module API
# GET /projects/:id/repository/archive
get ":id/repository/archive", requirements: { format: Gitlab::Regex.archive_formats_regex } do
authorize! :download_code, user_project
- repo = user_project.repository
- ref = params[:sha]
- format = params[:format]
- storage_path = Gitlab.config.gitlab.repository_downloads_path
+ file_path = ArchiveRepositoryService.new.execute(user_project, params[:sha], params[:format])
- file_path = repo.archive_repo(ref, storage_path, format)
if file_path && File.exists?(file_path)
data = File.open(file_path, 'rb').read
-
header["Content-Disposition"] = "attachment; filename=\"#{File.basename(file_path)}\""
-
content_type MIME::Types.type_for(file_path).first.content_type
-
env['api.format'] = :binary
-
present data
else
not_found!
diff --git a/lib/gitlab/diff_parser.rb b/lib/gitlab/diff_parser.rb
index 14bbb328637..b244295027e 100644
--- a/lib/gitlab/diff_parser.rb
+++ b/lib/gitlab/diff_parser.rb
@@ -30,7 +30,7 @@ module Gitlab
line_new = line.match(/\+[0-9]*/)[0].to_i.abs rescue 0
next if line_old == 1 && line_new == 1 #top of file
- yield(full_line, type, nil, nil, nil)
+ yield(full_line, type, nil, line_new, line_old)
next
else
type = identification_type(line)
diff --git a/lib/gitlab/ldap/access.rb b/lib/gitlab/ldap/access.rb
index 4e48ff11871..62709a12942 100644
--- a/lib/gitlab/ldap/access.rb
+++ b/lib/gitlab/ldap/access.rb
@@ -9,6 +9,19 @@ module Gitlab
end
end
+ def self.allowed?(user)
+ self.open do |access|
+ if access.allowed?(user)
+ # GitLab EE LDAP code goes here
+ user.last_credential_check_at = Time.now
+ user.save
+ true
+ else
+ false
+ end
+ end
+ end
+
def initialize(adapter=nil)
@adapter = adapter
end
diff --git a/lib/gitlab/user_access.rb b/lib/gitlab/user_access.rb
index 16df21b49ba..4885baf9526 100644
--- a/lib/gitlab/user_access.rb
+++ b/lib/gitlab/user_access.rb
@@ -3,13 +3,8 @@ module Gitlab
def self.allowed?(user)
return false if user.blocked?
- if Gitlab.config.ldap.enabled
- if user.ldap_user?
- # Check if LDAP user exists and match LDAP user_filter
- Gitlab::LDAP::Access.open do |adapter|
- return false unless adapter.allowed?(user)
- end
- end
+ if user.requires_ldap_check?
+ return false unless Gitlab::LDAP::Access.allowed?(user)
end
true
diff --git a/lib/gt_one_coercion.rb b/lib/gt_one_coercion.rb
new file mode 100644
index 00000000000..ef2dc09767c
--- /dev/null
+++ b/lib/gt_one_coercion.rb
@@ -0,0 +1,5 @@
+class GtOneCoercion < Virtus::Attribute
+ def coerce(value)
+ [1, value.to_i].max
+ end
+end
diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 3f219261abe..032ed5ee370 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -318,7 +318,8 @@ namespace :gitlab do
options = {
"user.name" => "GitLab",
- "user.email" => Gitlab.config.gitlab.email_from
+ "user.email" => Gitlab.config.gitlab.email_from,
+ "core.autocrlf" => "input"
}
correct_options = options.map do |name, value|
run(%W(git config --global --get #{name})).try(:squish) == value
@@ -330,7 +331,8 @@ namespace :gitlab do
puts "no".red
try_fixing_it(
sudo_gitlab("git config --global user.name \"#{options["user.name"]}\""),
- sudo_gitlab("git config --global user.email \"#{options["user.email"]}\"")
+ sudo_gitlab("git config --global user.email \"#{options["user.email"]}\""),
+ sudo_gitlab("git config --global core.autocrlf \"#{options["core.autocrlf"]}\"")
)
for_more_information(
see_installation_guide_section "GitLab"
diff --git a/lib/unfold_form.rb b/lib/unfold_form.rb
new file mode 100644
index 00000000000..46b12beeaaf
--- /dev/null
+++ b/lib/unfold_form.rb
@@ -0,0 +1,11 @@
+require_relative 'gt_one_coercion'
+
+class UnfoldForm
+ include Virtus.model
+
+ attribute :since, GtOneCoercion
+ attribute :to, GtOneCoercion
+ attribute :bottom, Boolean
+ attribute :unfold, Boolean, default: true
+ attribute :offset, Integer
+end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index ef6b8a94502..7221328a45f 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -312,6 +312,40 @@ describe User do
end
end
+ describe :requires_ldap_check? do
+ let(:user) { User.new }
+
+ it 'is false when LDAP is disabled' do
+ # Create a condition which would otherwise cause 'true' to be returned
+ user.stub(ldap_user?: true)
+ user.last_credential_check_at = nil
+ expect(user.requires_ldap_check?).to be_false
+ end
+
+ context 'when LDAP is enabled' do
+ before { Gitlab.config.ldap.stub(enabled: true) }
+
+ it 'is false for non-LDAP users' do
+ user.stub(ldap_user?: false)
+ expect(user.requires_ldap_check?).to be_false
+ end
+
+ context 'and when the user is an LDAP user' do
+ before { user.stub(ldap_user?: true) }
+
+ it 'is true when the user has never had an LDAP check before' do
+ user.last_credential_check_at = nil
+ expect(user.requires_ldap_check?).to be_true
+ end
+
+ it 'is true when the last LDAP check happened over 1 hour ago' do
+ user.last_credential_check_at = 2.hours.ago
+ expect(user.requires_ldap_check?).to be_true
+ end
+ end
+ end
+ end
+
describe '#full_website_url' do
let(:user) { create(:user) }
diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
index dff7f20cb32..d8e8e4f5035 100644
--- a/spec/requests/api/issues_spec.rb
+++ b/spec/requests/api/issues_spec.rb
@@ -5,6 +5,10 @@ describe API::API, api: true do
let(:user) { create(:user) }
let!(:project) { create(:project, namespace: user.namespace ) }
let!(:issue) { create(:issue, author: user, assignee: user, project: project) }
+ let!(:label) do
+ create(:label, title: 'label', color: '#FFAABB', project: project)
+ end
+
before { project.team << [user, :reporter] }
describe "GET /issues" do
@@ -68,6 +72,14 @@ describe API::API, api: true do
post api("/projects/#{project.id}/issues", user), labels: 'label, label2'
response.status.should == 400
end
+
+ it 'should return 405 on invalid label names' do
+ post api("/projects/#{project.id}/issues", user),
+ title: 'new issue',
+ labels: 'label, ?'
+ response.status.should == 405
+ json_response['message'].should == 'Label names invalid'
+ end
end
describe "PUT /projects/:id/issues/:issue_id to update only title" do
@@ -84,6 +96,14 @@ describe API::API, api: true do
title: 'updated title'
response.status.should == 404
end
+
+ it 'should return 405 on invalid label names' do
+ put api("/projects/#{project.id}/issues/#{issue.id}", user),
+ title: 'updated title',
+ labels: 'label, ?'
+ response.status.should == 405
+ json_response['message'].should == 'Label names invalid'
+ end
end
describe "PUT /projects/:id/issues/:issue_id to update state and label" do
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 3611d9d6dc3..58cf7f139dc 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -78,9 +78,14 @@ describe API::API, api: true do
context 'between branches projects' do
it "should return merge_request" do
post api("/projects/#{project.id}/merge_requests", user),
- title: 'Test merge_request', source_branch: "stable", target_branch: "master", author: user
+ title: 'Test merge_request',
+ source_branch: 'stable',
+ target_branch: 'master',
+ author: user,
+ labels: 'label, label2'
response.status.should == 201
json_response['title'].should == 'Test merge_request'
+ json_response['labels'].should == ['label', 'label2']
end
it "should return 422 when source_branch equals target_branch" do
@@ -106,6 +111,17 @@ describe API::API, api: true do
target_branch: 'master', source_branch: 'stable'
response.status.should == 400
end
+
+ it 'should return 405 on invalid label names' do
+ post api("/projects/#{project.id}/merge_requests", user),
+ title: 'Test merge_request',
+ source_branch: 'stable',
+ target_branch: 'master',
+ author: user,
+ labels: 'label, ?'
+ response.status.should == 405
+ json_response['message'].should == 'Label names invalid'
+ end
end
context 'forked projects' do
@@ -235,6 +251,15 @@ describe API::API, api: true do
response.status.should == 200
json_response['target_branch'].should == 'wiki'
end
+
+ it 'should return 405 on invalid label names' do
+ put api("/projects/#{project.id}/merge_request/#{merge_request.id}",
+ user),
+ title: 'new issue',
+ labels: 'label, ?'
+ response.status.should == 405
+ json_response['message'].should == 'Label names invalid'
+ end
end
describe "POST /projects/:id/merge_request/:merge_request_id/comments" do