Commit 85e50301 authored by tiagonbotelho's avatar tiagonbotelho

Merge branch 'master' into rename-repo-files

parents 28f85155 cd546a78
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 8.11.0 (unreleased)
- Fix of 'Commits being passed to custom hooks are already reachable when using the UI'
v 8.10.0 (unreleased) v 8.10.0 (unreleased)
- Fix profile activity heatmap to show correct day name (eanplatter)
- Expose {should,force}_remove_source_branch (Ben Boeckel) - Expose {should,force}_remove_source_branch (Ben Boeckel)
- Add the functionality to be able to rename a file. !5049 (tiagonbotelho) - Add the functionality to be able to rename a file. !5049 (tiagonbotelho)
- Disable PostgreSQL statement timeout during migrations - Disable PostgreSQL statement timeout during migrations
...@@ -26,6 +29,7 @@ v 8.10.0 (unreleased) ...@@ -26,6 +29,7 @@ v 8.10.0 (unreleased)
- Add a new column `artifacts_size` to table `ci_builds` !4964 - Add a new column `artifacts_size` to table `ci_builds` !4964
- Let Workhorse serve format-patch diffs - Let Workhorse serve format-patch diffs
- Display tooltip for mentioned users and groups !5261 (winniehell) - Display tooltip for mentioned users and groups !5261 (winniehell)
- Allow build email service to be tested
- Added day name to contribution calendar tooltips - Added day name to contribution calendar tooltips
- Make images fit to the size of the viewport !4810 - Make images fit to the size of the viewport !4810
- Fix check for New Branch button on Issue page !4630 (winniehell) - Fix check for New Branch button on Issue page !4630 (winniehell)
...@@ -34,6 +38,7 @@ v 8.10.0 (unreleased) ...@@ -34,6 +38,7 @@ v 8.10.0 (unreleased)
- Fix issue, preventing users w/o push access to sort tags !5105 (redetection) - Fix issue, preventing users w/o push access to sort tags !5105 (redetection)
- Add Spring EmojiOne updates. - Add Spring EmojiOne updates.
- Fix fetching LFS objects for private CI projects - Fix fetching LFS objects for private CI projects
- Add the new 2016 Emoji! Adds 72 new emoji including bacon, facepalm, and selfie. !5237
- Add syntax for multiline blockquote using `>>>` fence !3954 - Add syntax for multiline blockquote using `>>>` fence !3954
- Fix viewing notification settings when a project is pending deletion - Fix viewing notification settings when a project is pending deletion
- Updated compare dropdown menus to use GL dropdown - Updated compare dropdown menus to use GL dropdown
...@@ -56,6 +61,7 @@ v 8.10.0 (unreleased) ...@@ -56,6 +61,7 @@ v 8.10.0 (unreleased)
- Add "Enabled Git access protocols" to Application Settings - Add "Enabled Git access protocols" to Application Settings
- Diffs will create button/diff form on demand no on server side - Diffs will create button/diff form on demand no on server side
- Reduce size of HTML used by diff comment forms - Reduce size of HTML used by diff comment forms
- Protected branches have a "Developers can Merge" setting. !4892 (original implementation by Mathias Vestergaard)
- Fix user creation with stronger minimum password requirements !4054 (nathan-pmt) - Fix user creation with stronger minimum password requirements !4054 (nathan-pmt)
- Only show New Snippet button to users that can create snippets. - Only show New Snippet button to users that can create snippets.
- PipelinesFinder uses git cache data - PipelinesFinder uses git cache data
...@@ -102,6 +108,7 @@ v 8.10.0 (unreleased) ...@@ -102,6 +108,7 @@ v 8.10.0 (unreleased)
- Add min value for project limit field on user's form !3622 (jastkand) - Add min value for project limit field on user's form !3622 (jastkand)
- Reset project pushes_since_gc when we enqueue the git gc call - Reset project pushes_since_gc when we enqueue the git gc call
- Add reminder to not paste private SSH keys !4399 (Ingo Blechschmidt) - Add reminder to not paste private SSH keys !4399 (Ingo Blechschmidt)
- Collapsed diffs lines/size don't acumulate to overflow diffs.
- Remove duplicate `description` field in `MergeRequest` entities (Ben Boeckel) - Remove duplicate `description` field in `MergeRequest` entities (Ben Boeckel)
- Style of import project buttons were fixed in the new project page. !5183 (rdemirbay) - Style of import project buttons were fixed in the new project page. !5183 (rdemirbay)
- Fix GitHub client requests when rate limit is disabled - Fix GitHub client requests when rate limit is disabled
...@@ -113,9 +120,13 @@ v 8.10.0 (unreleased) ...@@ -113,9 +120,13 @@ v 8.10.0 (unreleased)
- Fix last update timestamp on issues not preserved on gitlab.com and project imports - Fix last update timestamp on issues not preserved on gitlab.com and project imports
- Fix issues importing projects from EE to CE - Fix issues importing projects from EE to CE
- Fix creating group with space in group path - Fix creating group with space in group path
- Improve cron_jobs loading error messages !5318
- Create Todos for Issue author when assign or mention himself (Katarzyna Kobierska) - Create Todos for Issue author when assign or mention himself (Katarzyna Kobierska)
- Limit the number of retries on error to 3 for exporting projects - Limit the number of retries on error to 3 for exporting projects
- Allow empty repositories on project import/export - Allow empty repositories on project import/export
- Render only commit message title in builds (Katarzyna Kobierska Ula Budziszewska)
- Allow bulk (un)subscription from issues in issue index
- Fix MR diff encoding issues exporting GitLab projects
v 8.9.6 v 8.9.6
- Fix importing of events under notes for GitLab projects. !5154 - Fix importing of events under notes for GitLab projects. !5154
......
...@@ -52,7 +52,7 @@ gem 'browser', '~> 2.2' ...@@ -52,7 +52,7 @@ gem 'browser', '~> 2.2'
# Extracting information from a git repository # Extracting information from a git repository
# Provide access to Gitlab::Git library # Provide access to Gitlab::Git library
gem 'gitlab_git', '~> 10.2' gem 'gitlab_git', '~> 10.3.2'
# LDAP Auth # LDAP Auth
# GitLab fork with several improvements to original library. For full list of changes # GitLab fork with several improvements to original library. For full list of changes
...@@ -223,7 +223,7 @@ gem 'jquery-turbolinks', '~> 2.1.0' ...@@ -223,7 +223,7 @@ gem 'jquery-turbolinks', '~> 2.1.0'
gem 'addressable', '~> 2.3.8' gem 'addressable', '~> 2.3.8'
gem 'bootstrap-sass', '~> 3.3.0' gem 'bootstrap-sass', '~> 3.3.0'
gem 'font-awesome-rails', '~> 4.6.1' gem 'font-awesome-rails', '~> 4.6.1'
gem 'gemojione', '~> 2.6' gem 'gemojione', '~> 3.0'
gem 'gon', '~> 6.0.1' gem 'gon', '~> 6.0.1'
gem 'jquery-atwho-rails', '~> 1.3.2' gem 'jquery-atwho-rails', '~> 1.3.2'
gem 'jquery-rails', '~> 4.1.0' gem 'jquery-rails', '~> 4.1.0'
...@@ -349,3 +349,6 @@ gem 'health_check', '~> 2.1.0' ...@@ -349,3 +349,6 @@ gem 'health_check', '~> 2.1.0'
# System information # System information
gem 'vmstat', '~> 2.1.0' gem 'vmstat', '~> 2.1.0'
gem 'sys-filesystem', '~> 1.1.6' gem 'sys-filesystem', '~> 1.1.6'
# Secure headers for Content Security Policy
gem 'secure_headers', '~> 3.3'
...@@ -255,7 +255,7 @@ GEM ...@@ -255,7 +255,7 @@ GEM
ruby-progressbar (~> 1.4) ruby-progressbar (~> 1.4)
gemnasium-gitlab-service (0.2.6) gemnasium-gitlab-service (0.2.6)
rugged (~> 0.21) rugged (~> 0.21)
gemojione (2.6.1) gemojione (3.0.1)
json json
get_process_mem (0.2.0) get_process_mem (0.2.0)
gherkin-ruby (0.3.2) gherkin-ruby (0.3.2)
...@@ -274,7 +274,7 @@ GEM ...@@ -274,7 +274,7 @@ GEM
diff-lcs (~> 1.1) diff-lcs (~> 1.1)
mime-types (>= 1.16, < 3) mime-types (>= 1.16, < 3)
posix-spawn (~> 0.3) posix-spawn (~> 0.3)
gitlab_git (10.3.0) gitlab_git (10.3.2)
activesupport (~> 4.0) activesupport (~> 4.0)
charlock_holmes (~> 0.7.3) charlock_holmes (~> 0.7.3)
github-linguist (~> 4.7.0) github-linguist (~> 4.7.0)
...@@ -645,6 +645,8 @@ GEM ...@@ -645,6 +645,8 @@ GEM
sdoc (0.3.20) sdoc (0.3.20)
json (>= 1.1.3) json (>= 1.1.3)
rdoc (~> 3.10) rdoc (~> 3.10)
secure_headers (3.3.2)
useragent
seed-fu (2.3.6) seed-fu (2.3.6)
activerecord (>= 3.1) activerecord (>= 3.1)
activesupport (>= 3.1) activesupport (>= 3.1)
...@@ -767,6 +769,7 @@ GEM ...@@ -767,6 +769,7 @@ GEM
get_process_mem (~> 0) get_process_mem (~> 0)
unicorn (>= 4, < 6) unicorn (>= 4, < 6)
uniform_notifier (1.9.0) uniform_notifier (1.9.0)
useragent (0.16.7)
uuid (2.3.8) uuid (2.3.8)
macaddr (~> 1.0) macaddr (~> 1.0)
version_sorter (2.0.0) version_sorter (2.0.0)
...@@ -857,11 +860,11 @@ DEPENDENCIES ...@@ -857,11 +860,11 @@ DEPENDENCIES
foreman (~> 0.78.0) foreman (~> 0.78.0)
fuubar (~> 2.0.0) fuubar (~> 2.0.0)
gemnasium-gitlab-service (~> 0.2) gemnasium-gitlab-service (~> 0.2)
gemojione (~> 2.6) gemojione (~> 3.0)
github-linguist (~> 4.7.0) github-linguist (~> 4.7.0)
github-markup (~> 1.4) github-markup (~> 1.4)
gitlab-flowdock-git-hook (~> 1.0.1) gitlab-flowdock-git-hook (~> 1.0.1)
gitlab_git (~> 10.2) gitlab_git (~> 10.3.2)
gitlab_meta (= 7.0) gitlab_meta (= 7.0)
gitlab_omniauth-ldap (~> 1.2.1) gitlab_omniauth-ldap (~> 1.2.1)
gollum-lib (~> 4.2) gollum-lib (~> 4.2)
...@@ -944,6 +947,7 @@ DEPENDENCIES ...@@ -944,6 +947,7 @@ DEPENDENCIES
sass-rails (~> 5.0.0) sass-rails (~> 5.0.0)
scss_lint (~> 0.47.0) scss_lint (~> 0.47.0)
sdoc (~> 0.3.20) sdoc (~> 0.3.20)
secure_headers (~> 3.3)
seed-fu (~> 2.3.5) seed-fu (~> 2.3.5)
select2-rails (~> 3.5.9) select2-rails (~> 3.5.9)
sentry-raven (~> 1.1.0) sentry-raven (~> 1.1.0)
......
# GitLab Maintenance Policy # GitLab Maintenance Policy
GitLab is a fast moving and evolving project. We currently don't have the resources to support many releases concurrently. We support exactly one stable release at any given time. GitLab follows the [Semantic Versioning](http://semver.org/) for its releases:
`(Major).(Minor).(Patch)` in a [pragmatic way].
GitLab follows the [Semantic Versioning](http://semver.org/) for its releases: `(Major).(Minor).(Patch)` in a [pragmatic way](https://gist.github.com/jashkenas/cbd2b088e20279ae2c8e). - **Major version**: Whenever there is something significant or any backwards
incompatible changes are introduced to the public API.
- **Minor version**: When new, backwards compatible functionality is introduced
to the public API or a minor feature is introduced, or when a set of smaller
features is rolled out.
- **Patch number**: When backwards compatible bug fixes are introduced that fix
incorrect behavior.
- **Major version**: Whenever there is something significant or any backwards incompatible changes are introduced to the public API. The current stable release will receive security patches and bug fixes
- **Minor version**: When new, backwards compatible functionality is introduced to the public API or a minor feature is introduced, or when a set of smaller features is rolled out. (eg. `8.9.0` -> `8.9.1`). Feature releases will mark the next supported stable
- **Patch number**: When backwards compatible bug fixes are introduced that fix incorrect behavior. release where the minor version is increased numerically by increments of one
(eg. `8.9 -> 8.10`).
The current stable release will receive security patches and bug fixes (eg. `5.0` -> `5.0.1`). Feature releases will mark the next supported stable release where the minor version is increased numerically by increments of one (eg. `5.0 -> 5.1`). Our current policy is to support one stable release at any given time, but for
medium-level security issues, we may consider [backporting to the previous two
monthly releases][rel-sec].
We encourage everyone to run the latest stable release to ensure that you can easily upgrade to the most secure and feature rich GitLab experience. In order to make sure you can easily run the most recent stable release, we are working hard to keep the update process simple and reliable. We encourage everyone to run the latest stable release to ensure that you can
easily upgrade to the most secure and feature-rich GitLab experience. In order
to make sure you can easily run the most recent stable release, we are working
hard to keep the update process simple and reliable.
More information about the release procedures can be found in the doc/release directory. More information about the release procedures can be found in our
[release-tools documentation][rel]. You may also want to read our
[Responsible Disclosure Policy][disclosure].
[rel-sec]: https://gitlab.com/gitlab-org/release-tools/blob/master/doc/security.md#backporting
[rel]: https://gitlab.com/gitlab-org/release-tools/blob/master/doc/
[disclosure]: https://about.gitlab.com/disclosure/
[pragmatic way]: https://gist.github.com/jashkenas/cbd2b088e20279ae2c8e
app/assets/images/emoji.png

1000 KB | W: | H:

app/assets/images/emoji.png

1.04 MB | W: | H:

app/assets/images/emoji.png
app/assets/images/emoji.png
app/assets/images/emoji.png
app/assets/images/emoji.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/emoji@2x.png

2.38 MB | W: | H:

app/assets/images/emoji@2x.png

2.53 MB | W: | H:

app/assets/images/emoji@2x.png
app/assets/images/emoji@2x.png
app/assets/images/emoji@2x.png
app/assets/images/emoji@2x.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -250,6 +250,8 @@ class GitLabDropdown ...@@ -250,6 +250,8 @@ class GitLabDropdown
if self.options.clicked if self.options.clicked
self.options.clicked(selected, $el, e) self.options.clicked(selected, $el, e)
$el.trigger('blur')
# Finds an element inside wrapper element # Finds an element inside wrapper element
getElement: (selector) -> getElement: (selector) ->
@dropdown.find selector @dropdown.find selector
......
...@@ -89,6 +89,7 @@ class @IssuableBulkActions ...@@ -89,6 +89,7 @@ class @IssuableBulkActions
assignee_id : @form.find('input[name="update[assignee_id]"]').val() assignee_id : @form.find('input[name="update[assignee_id]"]').val()
milestone_id : @form.find('input[name="update[milestone_id]"]').val() milestone_id : @form.find('input[name="update[milestone_id]"]').val()
issues_ids : @form.find('input[name="update[issues_ids]"]').val() issues_ids : @form.find('input[name="update[issues_ids]"]').val()
subscription_event : @form.find('input[name="update[subscription_event]"]').val()
add_label_ids : [] add_label_ids : []
remove_label_ids : [] remove_label_ids : []
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
w.gl ?= {} w.gl ?= {}
w.gl.utils ?= {} w.gl.utils ?= {}
w.gl.utils.days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] w.gl.utils.days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
w.gl.utils.formatDate = (datetime) -> w.gl.utils.formatDate = (datetime) ->
dateFormat(datetime, 'mmm d, yyyy h:MMtt Z') dateFormat(datetime, 'mmm d, yyyy h:MMtt Z')
......
$ -> $ ->
$(".protected-branches-list :checkbox").change (e) -> $(".protected-branches-list :checkbox").change (e) ->
name = $(this).attr("name") name = $(this).attr("name")
if name == "developers_can_push" if name == "developers_can_push" || name == "developers_can_merge"
id = $(this).val() id = $(this).val()
checked = $(this).is(":checked") can_push = $(this).is(":checked")
url = $(this).data("url") url = $(this).data("url")
$.ajax $.ajax
type: "PUT" type: "PATCH"
url: url url: url
dataType: "json" dataType: "json"
data: data:
id: id id: id
protected_branch: protected_branch:
developers_can_push: checked "#{name}": can_push
success: -> success: ->
row = $(e.target) row = $(e.target)
......
class @SubscriptionSelect
constructor: ->
$('.js-subscription-event').each (i, el) ->
fieldName = $(el).data("field-name")
$(el).glDropdown(
selectable: true
fieldName: fieldName
toggleLabel: (selected, el, instance) =>
label = 'Subscription'
$item = instance.dropdown.find('.is-active')
label = $item.text() if $item.length
label
clicked: (item, $el, e)->
e.preventDefault()
id: (obj, el) ->
$(el).data("id")
)
...@@ -70,7 +70,7 @@ ...@@ -70,7 +70,7 @@
} }
&.wiki { &.wiki {
padding: $gl-padding; padding: 30px $gl-padding;
.highlight { .highlight {
margin-bottom: 9px; margin-bottom: 9px;
......
...@@ -37,39 +37,41 @@ ...@@ -37,39 +37,41 @@
} }
h1 { h1 {
font-size: 1.3em; font-size: 2em;
font-weight: 600; font-weight: 600;
margin: 24px 0 12px; margin: 1em 0 10px;
padding: 0 0 10px; padding: 0 0 0.3em;
border-bottom: 1px solid #e7e9ed; border-bottom: 1px solid $btn-default-border;
color: $gl-gray-dark; color: $gl-gray-dark;
} }
h2 { h2 {
font-size: 1.2em; font-size: 1.6em;
font-weight: 600; font-weight: 600;
margin: 24px 0 12px; margin: 1em 0 10px;
padding-bottom: 0.3em;
border-bottom: 1px solid $btn-default-border;
color: $gl-gray-dark; color: $gl-gray-dark;
} }
h3 { h3 {
margin: 24px 0 12px; margin: 1em 0 10px;
font-size: 1.1em; font-size: 1.4em;
} }
h4 { h4 {
margin: 24px 0 12px; margin: 1em 0 10px;
font-size: 0.98em; font-size: 1.25em;
} }
h5 { h5 {
margin: 24px 0 12px; margin: 1em 0 10px;
font-size: 0.95em; font-size: 1em;
} }
h6 { h6 {
margin: 24px 0 12px; margin: 1em 0 10px;
font-size: 0.90em; font-size: 0.95em;
} }
blockquote { blockquote {
...@@ -115,7 +117,7 @@ ...@@ -115,7 +117,7 @@
ul, ol { ul, ol {
padding: 0; padding: 0;
margin: 6px 0 6px 28px !important; margin: 3px 0 3px 28px !important;
} }
li { li {
......
...@@ -16,7 +16,7 @@ $border-color: #e5e5e5; ...@@ -16,7 +16,7 @@ $border-color: #e5e5e5;
$focus-border-color: #3aabf0; $focus-border-color: #3aabf0;
$table-border-color: #f0f0f0; $table-border-color: #f0f0f0;
$background-color: #fafafa; $background-color: #fafafa;
$dark-background-color: #f7f7f7; $dark-background-color: #f5f5f5;
$table-text-gray: #8f8f8f; $table-text-gray: #8f8f8f;
/* /*
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -270,7 +270,7 @@ ...@@ -270,7 +270,7 @@
.item-title { .item-title {
@media (min-width: $screen-sm-min) { @media (min-width: $screen-sm-min) {
width: 49%; width: 45%;
} }
} }
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
border-top: 1px solid $table-border-gray; border-top: 1px solid $table-border-gray;
td, th { td, th {
line-height: 23px; line-height: 21px;
} }
&:hover { &:hover {
......
...@@ -10,7 +10,6 @@ module DiffForPath ...@@ -10,7 +10,6 @@ module DiffForPath
diff_commit = commit_for_diff(diff_file) diff_commit = commit_for_diff(diff_file)
blob = diff_file.blob(diff_commit) blob = diff_file.blob(diff_commit)
@expand_all_diffs = true
locals = { locals = {
diff_file: diff_file, diff_file: diff_file,
......
...@@ -226,6 +226,7 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -226,6 +226,7 @@ class Projects::IssuesController < Projects::ApplicationController
:assignee_id, :assignee_id,
:milestone_id, :milestone_id,
:state_event, :state_event,
:subscription_event,
label_ids: [], label_ids: [],
add_label_ids: [], add_label_ids: [],
remove_label_ids: [] remove_label_ids: []
......
...@@ -50,6 +50,6 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController ...@@ -50,6 +50,6 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
end end
def protected_branch_params def protected_branch_params
params.require(:protected_branch).permit(:name, :developers_can_push) params.require(:protected_branch).permit(:name, :developers_can_push, :developers_can_merge)
end end
end end
...@@ -45,8 +45,9 @@ class Projects::ServicesController < Projects::ApplicationController ...@@ -45,8 +45,9 @@ class Projects::ServicesController < Projects::ApplicationController
end end
def test def test
data = Gitlab::PushDataBuilder.build_sample(project, current_user) data = @service.test_data(project, current_user)
outcome = @service.test(data) outcome = @service.test(data)
if outcome[:success] if outcome[:success]
message = { notice: 'We sent a request to the provided URL' } message = { notice: 'We sent a request to the provided URL' }
else else
......
...@@ -12,7 +12,7 @@ module BranchesHelper ...@@ -12,7 +12,7 @@ module BranchesHelper
def can_push_branch?(project, branch_name) def can_push_branch?(project, branch_name)
return false unless project.repository.branch_exists?(branch_name) return false unless project.repository.branch_exists?(branch_name)
::Gitlab::GitAccess.new(current_user, project, 'web').can_push_to_branch?(branch_name) ::Gitlab::UserAccess.new(current_user, project: project).can_push_to_branch?(branch_name)
end end
def project_branches def project_branches
......
...@@ -9,7 +9,7 @@ module DiffHelper ...@@ -9,7 +9,7 @@ module DiffHelper
end end
def expand_all_diffs? def expand_all_diffs?
@expand_all_diffs || params[:expand_all_diffs].present? params[:expand_all_diffs].present?
end end
def diff_view def diff_view
...@@ -23,13 +23,14 @@ module DiffHelper ...@@ -23,13 +23,14 @@ module DiffHelper
end end
def diff_options def diff_options
default_options = Commit.max_diff_options options = { ignore_whitespace_change: hide_whitespace?, no_collapse: expand_all_diffs? }
if action_name == 'diff_for_path' if action_name == 'diff_for_path'
default_options[:paths] = params.values_at(:old_path, :new_path) options[:no_collapse] = true
options[:paths] = params.values_at(:old_path, :new_path)
end end
default_options.merge(ignore_whitespace_change: hide_whitespace?) Commit.max_diff_options.merge(options)
end end
def safe_diff_files(diffs, diff_refs: nil, repository: nil) def safe_diff_files(diffs, diff_refs: nil, repository: nil)
......
...@@ -6,6 +6,7 @@ module Emails ...@@ -6,6 +6,7 @@ module Emails
add_project_headers add_project_headers
add_build_headers('failed') add_build_headers('failed')
mail(to: to, subject: subject("Build failed for #{@project.name}", @build.short_sha)) mail(to: to, subject: subject("Build failed for #{@project.name}", @build.short_sha))
end end
......
...@@ -51,6 +51,10 @@ module Ci ...@@ -51,6 +51,10 @@ module Ci
commit.try(:message) commit.try(:message)
end end
def git_commit_title
commit.try(:title)
end
def short_sha def short_sha
Ci::Pipeline.truncate_sha(sha) Ci::Pipeline.truncate_sha(sha)
end end
......
...@@ -552,7 +552,13 @@ class MergeRequest < ActiveRecord::Base ...@@ -552,7 +552,13 @@ class MergeRequest < ActiveRecord::Base
end end
def can_be_merged_by?(user) def can_be_merged_by?(user)
::Gitlab::GitAccess.new(user, project, 'web').can_push_to_branch?(target_branch) access = ::Gitlab::UserAccess.new(user, project: project)
access.can_push_to_branch?(target_branch) || access.can_merge_to_branch?(target_branch)
end
def can_be_merged_via_command_line_by?(user)
access = ::Gitlab::UserAccess.new(user, project: project)
access.can_push_to_branch?(target_branch)
end end
def mergeable_ci_state? def mergeable_ci_state?
......
class MergeRequestDiff < ActiveRecord::Base class MergeRequestDiff < ActiveRecord::Base
include Sortable include Sortable
include Importable include Importable
include EncodingHelper
# Prevent store of diff if commits amount more then 500 # Prevent store of diff if commits amount more then 500
COMMITS_SAFE_SIZE = 100 COMMITS_SAFE_SIZE = 100
...@@ -211,6 +212,14 @@ class MergeRequestDiff < ActiveRecord::Base ...@@ -211,6 +212,14 @@ class MergeRequestDiff < ActiveRecord::Base
branch_base_commit.try(:sha) branch_base_commit.try(:sha)
end end
def utf8_st_diffs
st_diffs.map do |diff|
diff.each do |k, v|
diff[k] = encode_utf8(v) if v.respond_to?(:encoding)
end
end
end
# #
# #save or #update_attributes providing changes on serialized attributes do a lot of # #save or #update_attributes providing changes on serialized attributes do a lot of
# serialization and deserialization calls resulting in bad performance. # serialization and deserialization calls resulting in bad performance.
......
...@@ -838,6 +838,10 @@ class Project < ActiveRecord::Base ...@@ -838,6 +838,10 @@ class Project < ActiveRecord::Base
protected_branches.matching(branch_name).any?(&:developers_can_push) protected_branches.matching(branch_name).any?(&:developers_can_push)
end end
def developers_can_merge_to_protected_branch?(branch_name)
protected_branches.matching(branch_name).any?(&:developers_can_merge)
end
def forked? def forked?
!(forked_project_link.nil? || forked_project_link.forked_from_project.nil?) !(forked_project_link.nil? || forked_project_link.forked_from_project.nil?)
end end
......
...@@ -42,6 +42,19 @@ class BuildsEmailService < Service ...@@ -42,6 +42,19 @@ class BuildsEmailService < Service
end end
end end
def can_test?
project.builds.count > 0
end
def disabled_title
"Please setup a build on your repository."
end
def test_data(project = nil, user = nil)
build = project.builds.last
Gitlab::BuildDataBuilder.build(build)
end
def fields def fields
[ [
{ type: 'textarea', name: 'recipients', placeholder: 'Emails separated by comma' }, { type: 'textarea', name: 'recipients', placeholder: 'Emails separated by comma' },
...@@ -50,6 +63,20 @@ class BuildsEmailService < Service ...@@ -50,6 +63,20 @@ class BuildsEmailService < Service
] ]
end end
def test(data)
begin
# bypass build status verification when testing
data[:build_status] = "failed"
data[:build_allow_failure] = false
result = execute(data)
rescue StandardError => error
return { success: false, result: error }
end
{ success: true, result: result }
end
def should_build_be_notified?(data) def should_build_be_notified?(data)
case data[:build_status] case data[:build_status]
when 'success' when 'success'
......
...@@ -704,6 +704,7 @@ class Repository ...@@ -704,6 +704,7 @@ class Repository
options[:commit] = { options[:commit] = {
message: message, message: message,
branch: ref, branch: ref,
update_ref: false,
} }
raw_repository.mkdir(path, options) raw_repository.mkdir(path, options)
...@@ -719,6 +720,7 @@ class Repository ...@@ -719,6 +720,7 @@ class Repository
options[:commit] = { options[:commit] = {
message: message, message: message,
branch: ref, branch: ref,
update_ref: false,
} }
options[:file] = { options[:file] = {
...@@ -765,7 +767,8 @@ class Repository ...@@ -765,7 +767,8 @@ class Repository
options[:author] = committer options[:author] = committer
options[:commit] = { options[:commit] = {
message: message, message: message,
branch: ref branch: ref,
update_ref: false,
} }
options[:file] = { options[:file] = {
...@@ -795,9 +798,9 @@ class Repository ...@@ -795,9 +798,9 @@ class Repository
end end
end end
def merge(user, source_sha, target_branch, options = {}) def merge(user, merge_request, options = {})
our_commit = rugged.branches[target_branch].target our_commit = rugged.branches[merge_request.target_branch].target
their_commit = rugged.lookup(source_sha) their_commit = rugged.lookup(merge_request.diff_head_sha)
raise "Invalid merge target" if our_commit.nil? raise "Invalid merge target" if our_commit.nil?
raise "Invalid merge source" if their_commit.nil? raise "Invalid merge source" if their_commit.nil?
...@@ -805,14 +808,15 @@ class Repository ...@@ -805,14 +808,15 @@ class Repository
merge_index = rugged.merge_commits(our_commit, their_commit) merge_index = rugged.merge_commits(our_commit, their_commit)
return false if merge_index.conflicts? return false if merge_index.conflicts?
commit_with_hooks(user, target_branch) do |ref| commit_with_hooks(user, merge_request.target_branch) do
actual_options = options.merge( actual_options = options.merge(
parents: [our_commit, their_commit], parents: [our_commit, their_commit],
tree: merge_index.write_tree(rugged), tree: merge_index.write_tree(rugged),
update_ref: ref
) )
Rugged::Commit.create(rugged, actual_options) commit_id = Rugged::Commit.create(rugged, actual_options)
merge_request.update(in_progress_merge_commit_sha: commit_id)
commit_id
end end
end end
...@@ -822,15 +826,14 @@ class Repository ...@@ -822,15 +826,14 @@ class Repository
return false unless revert_tree_id return false unless revert_tree_id
commit_with_hooks(user, base_branch) do |ref| commit_with_hooks(user, base_branch) do
committer = user_to_committer(user) committer = user_to_committer(user)
source_sha = Rugged::Commit.create(rugged, source_sha = Rugged::Commit.create(rugged,
message: commit.revert_message, message: commit.revert_message,
author: committer, author: committer,
committer: committer, committer: committer,
tree: revert_tree_id, tree: revert_tree_id,
parents: [rugged.lookup(source_sha)], parents: [rugged.lookup(source_sha)])
update_ref: ref)
end end
end end
...@@ -840,7 +843,7 @@ class Repository ...@@ -840,7 +843,7 @@ class Repository
return false unless cherry_pick_tree_id return false unless cherry_pick_tree_id
commit_with_hooks(user, base_branch) do |ref| commit_with_hooks(user, base_branch) do
committer = user_to_committer(user) committer = user_to_committer(user)
source_sha = Rugged::Commit.create(rugged, source_sha = Rugged::Commit.create(rugged,
message: commit.message, message: commit.message,
...@@ -851,8 +854,7 @@ class Repository ...@@ -851,8 +854,7 @@ class Repository
}, },
committer: committer, committer: committer,
tree: cherry_pick_tree_id, tree: cherry_pick_tree_id,
parents: [rugged.lookup(source_sha)], parents: [rugged.lookup(source_sha)])
update_ref: ref)
end end
end end
...@@ -953,20 +955,6 @@ class Repository ...@@ -953,20 +955,6 @@ class Repository
Gitlab::Popen.popen(args, path_to_repo) Gitlab::Popen.popen(args, path_to_repo)
end end
def with_tmp_ref(oldrev = nil)
random_string = SecureRandom.hex
tmp_ref = "refs/tmp/#{random_string}/head"
if oldrev && !Gitlab::Git.blank_ref?(oldrev)
rugged.references.create(tmp_ref, oldrev)
end
# Make commit in tmp ref
yield(tmp_ref)
ensure
rugged.references.delete(tmp_ref) rescue nil
end
def commit_with_hooks(current_user, branch) def commit_with_hooks(current_user, branch)
update_autocrlf_option update_autocrlf_option
...@@ -979,9 +967,8 @@ class Repository ...@@ -979,9 +967,8 @@ class Repository
oldrev = target_branch.target oldrev = target_branch.target
end end
with_tmp_ref(oldrev) do |tmp_ref| # Make commit
# Make commit in tmp ref newrev = yield(ref)
newrev = yield(tmp_ref)
unless newrev unless newrev
raise CommitError.new('Failed to create commit') raise CommitError.new('Failed to create commit')
...@@ -1006,7 +993,6 @@ class Repository ...@@ -1006,7 +993,6 @@ class Repository
newrev newrev
end end
end
def ls_files(ref) def ls_files(ref)
actual_ref = ref || root_ref actual_ref = ref || root_ref
......
...@@ -76,6 +76,10 @@ class Service < ActiveRecord::Base ...@@ -76,6 +76,10 @@ class Service < ActiveRecord::Base
[] []
end end
def test_data(project, user)
Gitlab::PushDataBuilder.build_sample(project, user)
end
def supported_events def supported_events
%w(push tag_push issue merge_request wiki_page) %w(push tag_push issue merge_request wiki_page)
end end
...@@ -94,6 +98,11 @@ class Service < ActiveRecord::Base ...@@ -94,6 +98,11 @@ class Service < ActiveRecord::Base
!project.empty_repo? !project.empty_repo?
end end
# reason why service cannot be tested
def disabled_title
"Please setup a project repository."
end
# Provide convenient accessor methods # Provide convenient accessor methods
# for each serialized property. # for each serialized property.
# Also keep track of updated properties in a similar way as ActiveModel::Dirty # Also keep track of updated properties in a similar way as ActiveModel::Dirty
......
...@@ -23,7 +23,7 @@ module Commits ...@@ -23,7 +23,7 @@ module Commits
private private
def check_push_permissions def check_push_permissions
allowed = ::Gitlab::GitAccess.new(current_user, project, 'web').can_push_to_branch?(@target_branch) allowed = ::Gitlab::UserAccess.new(current_user, project: project).can_push_to_branch?(@target_branch)
unless allowed unless allowed
raise ValidationError.new('You are not allowed to push into this branch') raise ValidationError.new('You are not allowed to push into this branch')
......
...@@ -15,20 +15,18 @@ class CreateBranchService < BaseService ...@@ -15,20 +15,18 @@ class CreateBranchService < BaseService
return error('Branch already exists') return error('Branch already exists')
end end
new_branch = nil new_branch = if source_project != @project
if source_project != @project
repository.with_tmp_ref do |tmp_ref|
repository.fetch_ref( repository.fetch_ref(
source_project.repository.path_to_repo, source_project.repository.path_to_repo,
"refs/heads/#{ref}", "refs/heads/#{ref}",
tmp_ref "refs/heads/#{branch_name}"
) )
new_branch = repository.add_branch(current_user, branch_name, tmp_ref) repository.after_create_branch
end
repository.find_branch(branch_name)
else else
new_branch = repository.add_branch(current_user, branch_name, ref) repository.add_branch(current_user, branch_name, ref)
end end
if new_branch if new_branch
......
...@@ -44,7 +44,7 @@ module Files ...@@ -44,7 +44,7 @@ module Files
end end
def validate def validate
allowed = ::Gitlab::GitAccess.new(current_user, project, 'web').can_push_to_branch?(@target_branch) allowed = ::Gitlab::UserAccess.new(current_user, project: project).can_push_to_branch?(@target_branch)
unless allowed unless allowed
raise_error("You are not allowed to push into this branch") raise_error("You are not allowed to push into this branch")
......
...@@ -89,7 +89,8 @@ class GitPushService < BaseService ...@@ -89,7 +89,8 @@ class GitPushService < BaseService
# Set protection on the default branch if configured # Set protection on the default branch if configured
if current_application_settings.default_branch_protection != PROTECTION_NONE if current_application_settings.default_branch_protection != PROTECTION_NONE
developers_can_push = current_application_settings.default_branch_protection == PROTECTION_DEV_CAN_PUSH ? true : false developers_can_push = current_application_settings.default_branch_protection == PROTECTION_DEV_CAN_PUSH ? true : false
@project.protected_branches.create({ name: @project.default_branch, developers_can_push: developers_can_push }) developers_can_merge = current_application_settings.default_branch_protection == PROTECTION_DEV_CAN_MERGE ? true : false
@project.protected_branches.create({ name: @project.default_branch, developers_can_push: developers_can_push, developers_can_merge: developers_can_merge })
end end
end end
......
...@@ -101,6 +101,7 @@ class IssuableBaseService < BaseService ...@@ -101,6 +101,7 @@ class IssuableBaseService < BaseService
def update(issuable) def update(issuable)
change_state(issuable) change_state(issuable)
change_subscription(issuable)
filter_params filter_params
old_labels = issuable.labels.to_a old_labels = issuable.labels.to_a
...@@ -124,6 +125,15 @@ class IssuableBaseService < BaseService ...@@ -124,6 +125,15 @@ class IssuableBaseService < BaseService
end end
end end
def change_subscription(issuable)
case params.delete(:subscription_event)
when 'subscribe'
issuable.subscribe(current_user)
when 'unsubscribe'
issuable.unsubscribe(current_user)
end
end
def has_changes?(issuable, old_labels: []) def has_changes?(issuable, old_labels: [])
valid_attrs = [:title, :description, :assignee_id, :milestone_id, :target_branch] valid_attrs = [:title, :description, :assignee_id, :milestone_id, :target_branch]
......
...@@ -4,7 +4,7 @@ module Issues ...@@ -4,7 +4,7 @@ module Issues
issues_ids = params.delete(:issues_ids).split(",") issues_ids = params.delete(:issues_ids).split(",")
issue_params = params issue_params = params
%i(state_event milestone_id assignee_id add_label_ids remove_label_ids).each do |key| %i(state_event milestone_id assignee_id add_label_ids remove_label_ids subscription_event).each do |key|
issue_params.delete(key) unless issue_params[key].present? issue_params.delete(key) unless issue_params[key].present?
end end
......
...@@ -34,7 +34,7 @@ module MergeRequests ...@@ -34,7 +34,7 @@ module MergeRequests
committer: committer committer: committer
} }
commit_id = repository.merge(current_user, merge_request.diff_head_sha, merge_request.target_branch, options) commit_id = repository.merge(current_user, merge_request, options)
merge_request.update(merge_commit_sha: commit_id) merge_request.update(merge_commit_sha: commit_id)
rescue GitHooksService::PreReceiveError => e rescue GitHooksService::PreReceiveError => e
merge_request.update(merge_error: e.message) merge_request.update(merge_error: e.message)
...@@ -43,6 +43,8 @@ module MergeRequests ...@@ -43,6 +43,8 @@ module MergeRequests
merge_request.update(merge_error: "Something went wrong during merge") merge_request.update(merge_error: "Something went wrong during merge")
Rails.logger.error(e.message) Rails.logger.error(e.message)
false false
ensure
merge_request.update(in_progress_merge_commit_sha: nil)
end end
def after_merge def after_merge
......
...@@ -48,7 +48,7 @@ module MergeRequests ...@@ -48,7 +48,7 @@ module MergeRequests
end end
def force_push? def force_push?
Gitlab::ForcePushCheck.force_push?(@project, @oldrev, @newrev) Gitlab::Checks::ForcePush.force_push?(@project, @oldrev, @newrev)
end end
# Refresh merge request diff if we push to source or target branch of merge request # Refresh merge request diff if we push to source or target branch of merge request
......
.emoji-menu .emoji-menu
= text_field_tag :emoji_search, "", class: "emoji-search search-input form-control", placeholder: "Seach emojis" = text_field_tag :emoji_search, "", class: "emoji-search search-input form-control", placeholder: "Search emoji"
.emoji-menu-content .emoji-menu-content
- Gitlab::AwardEmoji.emoji_by_category.each do |category, emojis| - Gitlab::AwardEmoji.emoji_by_category.each do |category, emojis|
%h5.emoji-menu-title %h5.emoji-menu-title
......
...@@ -94,9 +94,9 @@ ...@@ -94,9 +94,9 @@
.block .block
.title .title
Commit message Commit title
%p.build-light-text.append-bottom-0 %p.build-light-text.append-bottom-0
#{@build.pipeline.git_commit_message} #{@build.pipeline.git_commit_title}
- if @build.tags.any? - if @build.tags.any?
.block .block
......
...@@ -8,12 +8,12 @@ ...@@ -8,12 +8,12 @@
- elsif blob_text_viewable?(blob) - elsif blob_text_viewable?(blob)
- if !project.repository.diffable?(blob) - if !project.repository.diffable?(blob)
.nothing-here-block This diff was suppressed by a .gitattributes entry. .nothing-here-block This diff was suppressed by a .gitattributes entry.
- elsif diff_file.diff_lines.length > 0 - elsif diff_file.collapsed?
- if diff_file.collapsed_by_default? && !expand_all_diffs?
- url = url_for(params.merge(action: :diff_for_path, old_path: diff_file.old_path, new_path: diff_file.new_path)) - url = url_for(params.merge(action: :diff_for_path, old_path: diff_file.old_path, new_path: diff_file.new_path))
.nothing-here-block.diff-collapsed{data: { diff_for_path: url } } .nothing-here-block.diff-collapsed{data: { diff_for_path: url } }
This diff is collapsed. Click to expand it. This diff is collapsed. Click to expand it.
- elsif diff_view == 'parallel' - elsif diff_file.diff_lines.length > 0
- if diff_view == 'parallel'
= render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob = render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob
- else - else
= render "projects/diffs/text_file", diff_file: diff_file = render "projects/diffs/text_file", diff_file: diff_file
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
.content-block.oneline-block.files-changed .content-block.oneline-block.files-changed
.inline-parallel-buttons .inline-parallel-buttons
- unless expand_all_diffs? - if !expand_all_diffs? && diff_files.any? { |diff_file| diff_file.collapsed? }
= link_to 'Expand all', url_for(params.merge(expand_all_diffs: 1, format: 'html')), class: 'btn btn-default' = link_to 'Expand all', url_for(params.merge(expand_all_diffs: 1, format: 'html')), class: 'btn btn-default'
- if show_whitespace_toggle - if show_whitespace_toggle
- if current_controller?(:commit) - if current_controller?(:commit)
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
%p %p
Please resolve these conflicts or Please resolve these conflicts or
- if @merge_request.can_be_merged_by?(current_user) - if @merge_request.can_be_merged_via_command_line_by?(current_user)
#{link_to "merge this request manually", "#modal_merge_info", class: "how_to_merge_link vlink", "data-toggle" => "modal"}. #{link_to "merge this request manually", "#modal_merge_info", class: "how_to_merge_link vlink", "data-toggle" => "modal"}.
- else - else
ask someone with write access to this repository to merge this request manually. ask someone with write access to this repository to merge this request manually.
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
.table-responsive .table-responsive
%table.table.protected-branches-list %table.table.protected-branches-list
%colgroup %colgroup
%col{ width: "20%" }
%col{ width: "30%" } %col{ width: "30%" }
%col{ width: "25%" } %col{ width: "25%" }
%col{ width: "25%" } %col{ width: "25%" }
...@@ -18,6 +19,7 @@ ...@@ -18,6 +19,7 @@
%th Protected Branch %th Protected Branch
%th Commit %th Commit
%th Developers Can Push %th Developers Can Push
%th Developers Can Merge
- if can_admin_project - if can_admin_project
%th %th
%tbody %tbody
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
(branch was removed from repository) (branch was removed from repository)
%td %td
= check_box_tag("developers_can_push", protected_branch.id, protected_branch.developers_can_push, data: { url: url }) = check_box_tag("developers_can_push", protected_branch.id, protected_branch.developers_can_push, data: { url: url })
%td
= check_box_tag("developers_can_merge", protected_branch.id, protected_branch.developers_can_merge, data: { url: url })
- if can_admin_project - if can_admin_project
%td %td
= link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, protected_branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-warning btn-sm pull-right" = link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, protected_branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-warning btn-sm pull-right"
...@@ -36,6 +36,14 @@ ...@@ -36,6 +36,14 @@
= f.label :developers_can_push, "Developers can push", class: "label-light append-bottom-0" = f.label :developers_can_push, "Developers can push", class: "label-light append-bottom-0"
%p.light.append-bottom-0 %p.light.append-bottom-0
Allow developers to push to this branch Allow developers to push to this branch
.form-group
= f.check_box :developers_can_merge, class: "pull-left"
.prepend-left-20
= f.label :developers_can_merge, "Developers can merge", class: "label-light append-bottom-0"
%p.light.append-bottom-0
Allow developers to accept merge requests to this branch
= f.submit "Protect", class: "btn-create btn protect-branch-btn", disabled: true = f.submit "Protect", class: "btn-create btn protect-branch-btn", disabled: true
%hr %hr
= render "branches_list" = render "branches_list"
...@@ -12,5 +12,5 @@ ...@@ -12,5 +12,5 @@
&nbsp; &nbsp;
- if @service.valid? && @service.activated? - if @service.valid? && @service.activated?
- disabled = @service.can_test? ? '':'disabled' - disabled = @service.can_test? ? '':'disabled'
= link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service.to_param), class: "btn #{disabled}" = link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service), class: "btn #{disabled}", title: @service.disabled_title
= link_to "Cancel", namespace_project_services_path(@project.namespace, @project), class: "btn btn-cancel" = link_to "Cancel", namespace_project_services_path(@project.namespace, @project), class: "btn btn-cancel"
...@@ -44,9 +44,15 @@ ...@@ -44,9 +44,15 @@
placeholder: "Search authors", data: { first_user: (current_user.username if current_user), null_user: true, current_user: true, project_id: @project.id, field_name: "update[assignee_id]" } }) placeholder: "Search authors", data: { first_user: (current_user.username if current_user), null_user: true, current_user: true, project_id: @project.id, field_name: "update[assignee_id]" } })
.filter-item.inline .filter-item.inline
= dropdown_tag("Milestone", options: { title: "Assign milestone", toggle_class: 'js-milestone-select js-extra-options js-filter-submit js-filter-bulk-update', filter: true, dropdown_class: "dropdown-menu-selectable dropdown-menu-milestone", placeholder: "Search milestones", data: { show_no: true, field_name: "update[milestone_id]", project_id: @project.id, milestones: namespace_project_milestones_path(@project.namespace, @project, :json), use_id: true } }) = dropdown_tag("Milestone", options: { title: "Assign milestone", toggle_class: 'js-milestone-select js-extra-options js-filter-submit js-filter-bulk-update', filter: true, dropdown_class: "dropdown-menu-selectable dropdown-menu-milestone", placeholder: "Search milestones", data: { show_no: true, field_name: "update[milestone_id]", project_id: @project.id, milestones: namespace_project_milestones_path(@project.namespace, @project, :json), use_id: true } })
.filter-item.inline.labels-filter .filter-item.inline.labels-filter
= render "shared/issuable/label_dropdown", classes: ['js-filter-bulk-update', 'js-multiselect'], show_create: false, show_footer: false, extra_options: false, filter_submit: false, show_footer: false, data_options: { persist_when_hide: "true", field_name: "update[label_ids][]", show_no: false, show_any: false, use_id: true } = render "shared/issuable/label_dropdown", classes: ['js-filter-bulk-update', 'js-multiselect'], show_create: false, show_footer: false, extra_options: false, filter_submit: false, show_footer: false, data_options: { persist_when_hide: "true", field_name: "update[label_ids][]", show_no: false, show_any: false, use_id: true }
.filter-item.inline
= dropdown_tag("Subscription", options: { toggle_class: "js-subscription-event", title: "Change subscription", dropdown_class: "dropdown-menu-selectable", data: { field_name: "update[subscription_event]" } } ) do
%ul
%li
%a{href: "#", data: {id: "subscribe"}} Subscribe
%li
%a{href: "#", data: {id: "unsubscribe"}} Unsubscribe
= hidden_field_tag 'update[issues_ids]', [] = hidden_field_tag 'update[issues_ids]', []
= hidden_field_tag :state_event, params[:state_event] = hidden_field_tag :state_event, params[:state_event]
...@@ -63,6 +69,7 @@ ...@@ -63,6 +69,7 @@
new LabelsSelect(); new LabelsSelect();
new MilestoneSelect(); new MilestoneSelect();
new IssueStatusSelect(); new IssueStatusSelect();
new SubscriptionSelect();
$('form.filter-form').on('submit', function (event) { $('form.filter-form').on('submit', function (event) {
event.preventDefault(); event.preventDefault();
Turbolinks.visit(this.action + '&' + $(this).serialize()); Turbolinks.visit(this.action + '&' + $(this).serialize());
......
...@@ -76,7 +76,7 @@ module Gitlab ...@@ -76,7 +76,7 @@ module Gitlab
# Enable the asset pipeline # Enable the asset pipeline
config.assets.enabled = true config.assets.enabled = true
config.assets.paths << Gemojione.index.images_path config.assets.paths << Gemojione.images_path
config.assets.precompile << "*.png" config.assets.precompile << "*.png"
config.assets.precompile << "print.css" config.assets.precompile << "print.css"
config.assets.precompile << "notify.css" config.assets.precompile << "notify.css"
......
# CSP headers have to have single quotes, so failures relating to quotes
# inside Ruby string arrays are irrelevant.
# rubocop:disable Lint/PercentStringArray
require 'gitlab/current_settings'
include Gitlab::CurrentSettings
# If Sentry is enabled and the Rails app is running in production mode,
# this will construct the Report URI for Sentry.
if Rails.env.production? && current_application_settings.sentry_enabled
uri = URI.parse(current_application_settings.sentry_dsn)
CSP_REPORT_URI = "#{uri.scheme}://#{uri.host}/api#{uri.path}/csp-report/?sentry_key=#{uri.user}"
else
CSP_REPORT_URI = ''
end
# Content Security Policy Headers
# For more information on CSP see:
# - https://gitlab.com/gitlab-org/gitlab-ce/issues/18231
# - https://developer.mozilla.org/en-US/docs/Web/Security/CSP/CSP_policy_directives
SecureHeaders::Configuration.default do |config|
# Mark all cookies as "Secure", "HttpOnly", and "SameSite=Strict".
config.cookies = {
secure: true,
httponly: true,
samesite: {
strict: true
}
}
config.x_content_type_options = "nosniff"
config.x_xss_protection = "1; mode=block"
config.x_download_options = "noopen"
config.x_permitted_cross_domain_policies = "none"
config.referrer_policy = "origin-when-cross-origin"
config.csp = {
# "Meta" values.
report_only: true,
preserve_schemes: true,
# "Directive" values.
# Default source allows nothing, more permissive values are set per-policy.
default_src: %w('none'),
# (Deprecated) Don't allow iframes.
frame_src: %w('none'),
# Only allow XMLHTTPRequests from the GitLab instance itself.
connect_src: %w('self'),
# Only load local fonts.
font_src: %w('self'),
# Load local images, any external image available over HTTPS.
img_src: %w(* 'self' data:),
# Audio and video can't be played on GitLab currently, so it's disabled.
media_src: %w('none'),
# Don't allow <object>, <embed>, or <applet> elements.
object_src: %w('none'),
# Allow local scripts and inline scripts.
script_src: %w('unsafe-inline' 'unsafe-eval' 'self'),
# Allow local stylesheets and inline styles.
style_src: %w('unsafe-inline' 'self'),
# The URIs that a user agent may use as the document base URL.
base_uri: %w('self'),
# Only allow local iframes and service workers
child_src: %w('self'),
# Only submit form information to the GitLab instance.
form_action: %w('self'),
# Disallow any parents from embedding a page in an iframe.
frame_ancestors: %w('none'),
# Don't allow any plugins (Flash, Shockwave, etc.)
plugin_types: %w(),
# Blocks all mixed (HTTP) content.
block_all_mixed_content: true,
# Upgrades insecure requests to HTTPS when possible.
upgrade_insecure_requests: true
}
# Reports are sent to Sentry if it's enabled.
if current_application_settings.sentry_enabled
config.csp[:report_uri] = %W(#{CSP_REPORT_URI})
end
# Allow Bootstrap Linter in development mode.
if Rails.env.development?
config.csp[:script_src] << "maxcdn.bootstrapcdn.com"
end
# reCAPTCHA
if current_application_settings.recaptcha_enabled
config.csp[:script_src] << "https://www.google.com/recaptcha/"
config.csp[:script_src] << "https://www.gstatic.com/recaptcha/"
config.csp[:frame_src] << "https://www.google.com/recaptcha/"
config.x_frame_options = "SAMEORIGIN"
end
# Gravatar
if current_application_settings.gravatar_enabled?
config.csp[:img_src] << "www.gravatar.com"
config.csp[:img_src] << "secure.gravatar.com"
config.csp[:img_src] << Gitlab.config.gravatar.host
end
# Piwik
if Gitlab.config.extra.has_key?('piwik_url') && Gitlab.config.extra.has_key?('piwik_site_id')
config.csp[:script_src] << Gitlab.config.extra.piwik_url
config.csp[:img_src] << Gitlab.config.extra.piwik_url
end
# Google Analytics
if Gitlab.config.extra.has_key?('google_analytics_id')
config.csp[:script_src] << "https://www.google-analytics.com"
end
end
...@@ -13,7 +13,14 @@ Sidekiq.configure_server do |config| ...@@ -13,7 +13,14 @@ Sidekiq.configure_server do |config|
# UGLY Hack to get nested hash from settingslogic # UGLY Hack to get nested hash from settingslogic
cron_jobs = JSON.parse(Gitlab.config.cron_jobs.to_json) cron_jobs = JSON.parse(Gitlab.config.cron_jobs.to_json)
# UGLY hack: Settingslogic doesn't allow 'class' key # UGLY hack: Settingslogic doesn't allow 'class' key
cron_jobs.each { |k, v| cron_jobs[k]['class'] = cron_jobs[k].delete('job_class') } cron_jobs_required_keys = %w(job_class cron)
cron_jobs.each do |k, v|
if cron_jobs[k] && cron_jobs_required_keys.all? { |s| cron_jobs[k].key?(s) }
cron_jobs[k]['class'] = cron_jobs[k].delete('job_class')
else
raise("Invalid cron_jobs config key: '#{k}'. Check your gitlab config file.")
end
end
Sidekiq::Cron::Job.load_from_hash! cron_jobs Sidekiq::Cron::Job.load_from_hash! cron_jobs
# Database pool should be at least `sidekiq_concurrency` + 2 # Database pool should be at least `sidekiq_concurrency` + 2
......
class AddDevelopersCanMergeToProtectedBranches < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
def change
add_column_with_default :protected_branches, :developers_can_merge, :boolean, default: false, allow_null: false
end
end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddColumnInProgressMergeCommitShaToMergeRequests < ActiveRecord::Migration
def change
add_column :merge_requests, :in_progress_merge_commit_sha, :string
end
end
...@@ -628,8 +628,8 @@ ActiveRecord::Schema.define(version: 20160716115710) do ...@@ -628,8 +628,8 @@ ActiveRecord::Schema.define(version: 20160716115710) do
t.integer "merge_user_id" t.integer "merge_user_id"
t.string "merge_commit_sha" t.string "merge_commit_sha"
t.datetime "deleted_at" t.datetime "deleted_at"
t.string "in_progress_merge_commit_sha"
end end
add_index "merge_requests", ["assignee_id"], name: "index_merge_requests_on_assignee_id", using: :btree add_index "merge_requests", ["assignee_id"], name: "index_merge_requests_on_assignee_id", using: :btree
add_index "merge_requests", ["author_id"], name: "index_merge_requests_on_author_id", using: :btree add_index "merge_requests", ["author_id"], name: "index_merge_requests_on_author_id", using: :btree
add_index "merge_requests", ["created_at", "id"], name: "index_merge_requests_on_created_at_and_id", using: :btree add_index "merge_requests", ["created_at", "id"], name: "index_merge_requests_on_created_at_and_id", using: :btree
...@@ -867,6 +867,7 @@ ActiveRecord::Schema.define(version: 20160716115710) do ...@@ -867,6 +867,7 @@ ActiveRecord::Schema.define(version: 20160716115710) do
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.boolean "developers_can_push", default: false, null: false t.boolean "developers_can_push", default: false, null: false
t.boolean "developers_can_merge", default: false, null: false
end end
add_index "protected_branches", ["project_id"], name: "index_protected_branches_on_project_id", using: :btree add_index "protected_branches", ["project_id"], name: "index_protected_branches_on_project_id", using: :btree
......
...@@ -757,12 +757,13 @@ Introduced in GitLab 8.6 and GitLab Runner v1.1.1. ...@@ -757,12 +757,13 @@ Introduced in GitLab 8.6 and GitLab Runner v1.1.1.
This feature should be used in conjunction with [`artifacts`](#artifacts) and This feature should be used in conjunction with [`artifacts`](#artifacts) and
allows you to define the artifacts to pass between different builds. allows you to define the artifacts to pass between different builds.
Note that `artifacts` from previous [stages](#stages) are passed by default. Note that `artifacts` from all previous [stages](#stages) are passed by default.
To use this feature, define `dependencies` in context of the job and pass To use this feature, define `dependencies` in context of the job and pass
a list of all previous builds from which the artifacts should be downloaded. a list of all previous builds from which the artifacts should be downloaded.
You can only define builds from stages that are executed before the current one. You can only define builds from stages that are executed before the current one.
An error will be shown if you define builds from the current stage or next ones. An error will be shown if you define builds from the current stage or next ones.
Defining an empty array will skip downloading any artifacts for that job.
--- ---
......
...@@ -53,3 +53,8 @@ Generating a sprite file containing all the Emoji can be done by running: ...@@ -53,3 +53,8 @@ Generating a sprite file containing all the Emoji can be done by running:
``` ```
bundle exec rake gemojione:sprite bundle exec rake gemojione:sprite
``` ```
If new emoji are added, the spritesheet may change size. To compensate for
such changes, first generate the `emoji.png` spritesheet with the above Rake
task, then check the dimensions of the new spritesheet and update the
`SPRITESHEET_WIDTH` and `SPRITESHEET_HEIGHT` constants accordingly.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -17,7 +17,7 @@ module API ...@@ -17,7 +17,7 @@ module API
def current_user def current_user
@current_user ||= (find_user_by_private_token || doorkeeper_guard) @current_user ||= (find_user_by_private_token || doorkeeper_guard)
unless @current_user && Gitlab::UserAccess.allowed?(@current_user) unless @current_user && Gitlab::UserAccess.new(@current_user).allowed?
return nil return nil
end end
......
...@@ -17,6 +17,7 @@ module Gitlab ...@@ -17,6 +17,7 @@ module Gitlab
PROTECTION_NONE = 0 PROTECTION_NONE = 0
PROTECTION_DEV_CAN_PUSH = 1 PROTECTION_DEV_CAN_PUSH = 1
PROTECTION_FULL = 2 PROTECTION_FULL = 2
PROTECTION_DEV_CAN_MERGE = 3
class << self class << self
def values def values
...@@ -54,6 +55,7 @@ module Gitlab ...@@ -54,6 +55,7 @@ module Gitlab
def protection_options def protection_options
{ {
"Not protected: Both developers and masters can push new commits, force push, or delete the branch." => PROTECTION_NONE, "Not protected: Both developers and masters can push new commits, force push, or delete the branch." => PROTECTION_NONE,
"Protected against pushes: Developers cannot push new commits, but are allowed to accept merge requests to the branch." => PROTECTION_DEV_CAN_MERGE,
"Partially protected: Developers can push new commits, but cannot force push or delete the branch. Masters can do all of those." => PROTECTION_DEV_CAN_PUSH, "Partially protected: Developers can push new commits, but cannot force push or delete the branch. Masters can do all of those." => PROTECTION_DEV_CAN_PUSH,
"Fully protected: Developers cannot push new commits, force push, or delete the branch. Only masters can do any of those." => PROTECTION_FULL, "Fully protected: Developers cannot push new commits, force push, or delete the branch. Only masters can do any of those." => PROTECTION_FULL,
} }
......
module Gitlab module Gitlab
class AwardEmoji class AwardEmoji
CATEGORIES = { CATEGORIES = {
other: "Other",
objects: "Objects", objects: "Objects",
places: "Places", travel: "Travel",
travel_places: "Travel", symbols: "Symbols",
emoticons: "Emoticons",
objects_symbols: "Symbols",
nature: "Nature", nature: "Nature",
celebration: "Celebration",
people: "People", people: "People",
activity: "Activity", activity: "Activity",
flags: "Flags", flags: "Flags",
food_drink: "Food" food: "Food"
}.with_indifferent_access
CATEGORY_ALIASES = {
symbols: "objects_symbols",
foods: "food_drink",
travel: "travel_places"
}.with_indifferent_access }.with_indifferent_access
def self.normalize_emoji_name(name) def self.normalize_emoji_name(name)
...@@ -35,7 +25,7 @@ module Gitlab ...@@ -35,7 +25,7 @@ module Gitlab
# Skip Fitzpatrick(tone) modifiers # Skip Fitzpatrick(tone) modifiers
next if data["category"] == "modifier" next if data["category"] == "modifier"
category = CATEGORY_ALIASES[data["category"]] || data["category"] category = data["category"]
@emoji_by_category[category] << data @emoji_by_category[category] << data
end end
...@@ -57,7 +47,7 @@ module Gitlab ...@@ -57,7 +47,7 @@ module Gitlab
def self.aliases def self.aliases
@aliases ||= @aliases ||=
begin begin
json_path = File.join(Rails.root, 'fixtures', 'emojis', 'aliases.json' ) json_path = File.join(Rails.root, 'fixtures', 'emojis', 'aliases.json')
JSON.parse(File.read(json_path)) JSON.parse(File.read(json_path))
end end
end end
......
module Gitlab
module Checks
class ChangeAccess
attr_reader :user_access, :project
def initialize(change, user_access:, project:)
@oldrev, @newrev, @ref = change.split(' ')
@branch_name = branch_name(@ref)
@user_access = user_access
@project = project
end
def exec
error = protected_branch_checks || tag_checks || push_checks
if error
GitAccessStatus.new(false, error)
else
GitAccessStatus.new(true)
end
end
protected
def protected_branch_checks
return unless project.protected_branch?(@branch_name)
if forced_push? && user_access.cannot_do_action?(:force_push_code_to_protected_branches)
return "You are not allowed to force push code to a protected branch on this project."
elsif Gitlab::Git.blank_ref?(@newrev) && user_access.cannot_do_action?(:remove_protected_branches)
return "You are not allowed to delete protected branches from this project."
end
if matching_merge_request?
if user_access.can_merge_to_branch?(@branch_name) || user_access.can_push_to_branch?(@branch_name)
return
else
"You are not allowed to merge code into protected branches on this project."
end
else
if user_access.can_push_to_branch?(@branch_name)
return
else
"You are not allowed to push code to protected branches on this project."
end
end
end
def tag_checks
tag_ref = tag_name(@ref)
if tag_ref && protected_tag?(tag_ref) && user_access.cannot_do_action?(:admin_project)
"You are not allowed to change existing tags on this project."
end
end
def push_checks
if user_access.cannot_do_action?(:push_code)
"You are not allowed to push code to this project."
end
end
private
def protected_tag?(tag_name)
project.repository.tag_exists?(tag_name)
end
def forced_push?
Gitlab::Checks::ForcePush.force_push?(@project, @oldrev, @newrev)
end
def matching_merge_request?
Checks::MatchingMergeRequest.new(@newrev, @branch_name, @project).match?
end
def branch_name(ref)
ref = @ref.to_s
if Gitlab::Git.branch_ref?(ref)
Gitlab::Git.ref_name(ref)
else
nil
end
end
def tag_name(ref)
ref = @ref.to_s
if Gitlab::Git.tag_ref?(ref)
Gitlab::Git.ref_name(ref)
else
nil
end
end
end
end
end
module Gitlab
module Checks
class ForcePush
def self.force_push?(project, oldrev, newrev)
return false if project.empty_repo?
# Created or deleted branch
if Gitlab::Git.blank_ref?(oldrev) || Gitlab::Git.blank_ref?(newrev)
false
else
missed_refs, _ = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev}))
missed_refs.split("\n").size > 0
end
end
end
end
end
module Gitlab
module Checks
class MatchingMergeRequest
def initialize(newrev, branch_name, project)
@newrev = newrev
@branch_name = branch_name
@project = project
end
def match?
@project.merge_requests
.with_state(:locked)
.where(in_progress_merge_commit_sha: @newrev, target_branch: @branch_name)
.exists?
end
end
end
end
...@@ -5,7 +5,7 @@ module Gitlab ...@@ -5,7 +5,7 @@ module Gitlab
delegate :new_file, :deleted_file, :renamed_file, delegate :new_file, :deleted_file, :renamed_file,
:old_path, :new_path, :a_mode, :b_mode, :old_path, :new_path, :a_mode, :b_mode,
:submodule?, :too_large?, to: :diff, prefix: false :submodule?, :too_large?, :collapsed?, to: :diff, prefix: false
def initialize(diff, repository:, diff_refs: nil) def initialize(diff, repository:, diff_refs: nil)
@diff = diff @diff = diff
...@@ -68,10 +68,6 @@ module Gitlab ...@@ -68,10 +68,6 @@ module Gitlab
@lines ||= Gitlab::Diff::Parser.new.parse(raw_diff.each_line).to_a @lines ||= Gitlab::Diff::Parser.new.parse(raw_diff.each_line).to_a
end end
def collapsed_by_default?
diff.diff.bytesize > 10240 # 10 KB
end
def highlighted_diff_lines def highlighted_diff_lines
@highlighted_diff_lines ||= Gitlab::Diff::Highlight.new(self, repository: self.repository).highlight @highlighted_diff_lines ||= Gitlab::Diff::Highlight.new(self, repository: self.repository).highlight
end end
......
module Gitlab
class ForcePushCheck
def self.force_push?(project, oldrev, newrev)
return false if project.empty_repo?
# Created or deleted branch
if Gitlab::Git.blank_ref?(oldrev) || Gitlab::Git.blank_ref?(newrev)
false
else
missed_refs, _ = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev}))
missed_refs.split("\n").size > 0
end
end
end
end
# Check a user's access to perform a git action. All public methods in this
# class return an instance of `GitlabAccessStatus`
module Gitlab module Gitlab
class GitAccess class GitAccess
DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive } DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive }
PUSH_COMMANDS = %w{ git-receive-pack } PUSH_COMMANDS = %w{ git-receive-pack }
attr_reader :actor, :project, :protocol attr_reader :actor, :project, :protocol, :user_access
def initialize(actor, project, protocol) def initialize(actor, project, protocol)
@actor = actor @actor = actor
@project = project @project = project
@protocol = protocol @protocol = protocol
end @user_access = UserAccess.new(user, project: project)
def user
return @user if defined?(@user)
@user =
case actor
when User
actor
when DeployKey
nil
when Key
actor.user
end
end
def deploy_key
actor if actor.is_a?(DeployKey)
end
def can_push_to_branch?(ref)
return false unless user
if project.protected_branch?(ref) && !project.developers_can_push_to_protected_branch?(ref)
user.can?(:push_code_to_protected_branches, project)
else
user.can?(:push_code, project)
end
end
def can_read_project?
if user
user.can?(:read_project, project)
elsif deploy_key
deploy_key.projects.include?(project)
else
false
end
end end
def check(cmd, changes = nil) def check(cmd, changes = nil)
...@@ -56,11 +21,11 @@ module Gitlab ...@@ -56,11 +21,11 @@ module Gitlab
return build_status_object(false, "No user or key was provided.") return build_status_object(false, "No user or key was provided.")
end end
if user && !user_allowed? if user && !user_access.allowed?
return build_status_object(false, "Your account has been blocked.") return build_status_object(false, "Your account has been blocked.")
end end
unless project && can_read_project? unless project && (user_access.can_read_project? || deploy_key_can_read_project?)
return build_status_object(false, 'The project you were looking for could not be found.') return build_status_object(false, 'The project you were looking for could not be found.')
end end
...@@ -95,7 +60,7 @@ module Gitlab ...@@ -95,7 +60,7 @@ module Gitlab
end end
def user_download_access_check def user_download_access_check
unless user.can?(:download_code, project) unless user_access.can_do_action?(:download_code)
return build_status_object(false, "You are not allowed to download code from this project.") return build_status_object(false, "You are not allowed to download code from this project.")
end end
...@@ -125,46 +90,8 @@ module Gitlab ...@@ -125,46 +90,8 @@ module Gitlab
build_status_object(true) build_status_object(true)
end end
def can_user_do_action?(action)
@permission_cache ||= {}
@permission_cache[action] ||= user.can?(action, project)
end
def change_access_check(change) def change_access_check(change)
oldrev, newrev, ref = change.split(' ') Checks::ChangeAccess.new(change, user_access: user_access, project: project).exec
action =
if project.protected_branch?(branch_name(ref))
protected_branch_action(oldrev, newrev, branch_name(ref))
elsif (tag_ref = tag_name(ref)) && protected_tag?(tag_ref)
# Prevent any changes to existing git tag unless user has permissions
:admin_project
else
:push_code
end
unless can_user_do_action?(action)
status =
case action
when :force_push_code_to_protected_branches
build_status_object(false, "You are not allowed to force push code to a protected branch on this project.")
when :remove_protected_branches
build_status_object(false, "You are not allowed to deleted protected branches from this project.")
when :push_code_to_protected_branches
build_status_object(false, "You are not allowed to push code to protected branches on this project.")
when :admin_project
build_status_object(false, "You are not allowed to change existing tags on this project.")
else # :push_code
build_status_object(false, "You are not allowed to push code to this project.")
end
return status
end
build_status_object(true)
end
def forced_push?(oldrev, newrev)
Gitlab::ForcePushCheck.force_push?(project, oldrev, newrev)
end end
def protocol_allowed? def protocol_allowed?
...@@ -173,48 +100,38 @@ module Gitlab ...@@ -173,48 +100,38 @@ module Gitlab
private private
def protected_branch_action(oldrev, newrev, branch_name) def matching_merge_request?(newrev, branch_name)
# we dont allow force push to protected branch Checks::MatchingMergeRequest.new(newrev, branch_name, project).match?
if forced_push?(oldrev, newrev)
:force_push_code_to_protected_branches
elsif Gitlab::Git.blank_ref?(newrev)
# and we dont allow remove of protected branch
:remove_protected_branches
elsif project.developers_can_push_to_protected_branch?(branch_name)
:push_code
else
:push_code_to_protected_branches
end
end
def protected_tag?(tag_name)
project.repository.tag_exists?(tag_name)
end end
def user_allowed? def deploy_key
Gitlab::UserAccess.allowed?(user) actor if actor.is_a?(DeployKey)
end end
def branch_name(ref) def deploy_key_can_read_project?
ref = ref.to_s if deploy_key
if Gitlab::Git.branch_ref?(ref) deploy_key.projects.include?(project)
Gitlab::Git.ref_name(ref)
else else
nil false
end end
end end
def tag_name(ref) protected
ref = ref.to_s
if Gitlab::Git.tag_ref?(ref) def user
Gitlab::Git.ref_name(ref) return @user if defined?(@user)
else
@user =
case actor
when User
actor
when DeployKey
nil nil
when Key
actor.user
end end
end end
protected
def build_status_object(status, message = '') def build_status_object(status, message = '')
GitAccessStatus.new(status, message) GitAccessStatus.new(status, message)
end end
......
module Gitlab module Gitlab
class GitAccessWiki < GitAccess class GitAccessWiki < GitAccess
def change_access_check(change) def change_access_check(change)
if user.can?(:create_wiki, project) if user_access.can_do_action?(:create_wiki)
build_status_object(true) build_status_object(true)
else else
build_status_object(false, "You are not allowed to write to this project's wiki.") build_status_object(false, "You are not allowed to write to this project's wiki.")
......
...@@ -2,7 +2,7 @@ module Gitlab ...@@ -2,7 +2,7 @@ module Gitlab
module ImportExport module ImportExport
extend self extend self
VERSION = '0.1.1' VERSION = '0.1.2'
FILENAME_LIMIT = 50 FILENAME_LIMIT = 50
def export_path(relative_path:) def export_path(relative_path:)
......
...@@ -53,7 +53,11 @@ included_attributes: ...@@ -53,7 +53,11 @@ included_attributes:
excluded_attributes: excluded_attributes:
snippets: snippets:
- :expired_at - :expired_at
merge_request_diff:
- :st_diffs
methods: methods:
statuses: statuses:
- :type - :type
merge_request_diff:
- :utf8_st_diffs
\ No newline at end of file
...@@ -33,6 +33,7 @@ module Gitlab ...@@ -33,6 +33,7 @@ module Gitlab
update_project_references update_project_references
reset_ci_tokens if @relation_name == 'Ci::Trigger' reset_ci_tokens if @relation_name == 'Ci::Trigger'
@relation_hash['data'].deep_symbolize_keys! if @relation_name == :events && @relation_hash['data'] @relation_hash['data'].deep_symbolize_keys! if @relation_name == :events && @relation_hash['data']
set_st_diffs if @relation_name == :merge_request_diff
generate_imported_object generate_imported_object
end end
...@@ -129,6 +130,10 @@ module Gitlab ...@@ -129,6 +130,10 @@ module Gitlab
def parsed_relation_hash def parsed_relation_hash
@relation_hash.reject { |k, _v| !relation_class.attribute_method?(k) } @relation_hash.reject { |k, _v| !relation_class.attribute_method?(k) }
end end
def set_st_diffs
@relation_hash['st_diffs'] = @relation_hash.delete('utf8_st_diffs')
end
end end
end end
end end
module Gitlab module Gitlab
module UserAccess class UserAccess
def self.allowed?(user) attr_reader :user, :project
return false if user.blocked?
def initialize(user, project: nil)
@user = user
@project = project
end
def can_do_action?(action)
@permission_cache ||= {}
@permission_cache[action] ||= user.can?(action, project)
end
def cannot_do_action?(action)
!can_do_action?(action)
end
def allowed?
return false if user.blank? || user.blocked?
if user.requires_ldap_check? && user.try_obtain_ldap_lease if user.requires_ldap_check? && user.try_obtain_ldap_lease
return false unless Gitlab::LDAP::Access.allowed?(user) return false unless Gitlab::LDAP::Access.allowed?(user)
...@@ -9,5 +25,31 @@ module Gitlab ...@@ -9,5 +25,31 @@ module Gitlab
true true
end end
def can_push_to_branch?(ref)
return false unless user
if project.protected_branch?(ref) && !project.developers_can_push_to_protected_branch?(ref)
user.can?(:push_code_to_protected_branches, project)
else
user.can?(:push_code, project)
end
end
def can_merge_to_branch?(ref)
return false unless user
if project.protected_branch?(ref) && !project.developers_can_merge_to_protected_branch?(ref)
user.can?(:push_code_to_protected_branches, project)
else
user.can?(:push_code, project)
end
end
def can_read_project?
return false unless user
user.can?(:read_project, project)
end
end end
end end
...@@ -4,7 +4,7 @@ namespace :gemojione do ...@@ -4,7 +4,7 @@ namespace :gemojione do
require 'digest/sha2' require 'digest/sha2'
require 'json' require 'json'
dir = Gemojione.index.images_path dir = Gemojione.images_path
digests = [] digests = []
aliases = Hash.new { |hash, key| hash[key] = [] } aliases = Hash.new { |hash, key| hash[key] = [] }
aliases_path = File.join(Rails.root, 'fixtures', 'emojis', 'aliases.json') aliases_path = File.join(Rails.root, 'fixtures', 'emojis', 'aliases.json')
...@@ -50,9 +50,14 @@ namespace :gemojione do ...@@ -50,9 +50,14 @@ namespace :gemojione do
SIZE = 20 SIZE = 20
RETINA = SIZE * 2 RETINA = SIZE * 2
# Update these values to the width and height of the spritesheet when
# new emoji are added.
SPRITESHEET_WIDTH = 860
SPRITESHEET_HEIGHT = 840
Dir.mktmpdir do |tmpdir| Dir.mktmpdir do |tmpdir|
# Copy the Gemojione assets to the temporary folder for resizing # Copy the Gemojione assets to the temporary folder for resizing
FileUtils.cp_r(Gemojione.index.images_path, tmpdir) FileUtils.cp_r(Gemojione.images_path, tmpdir)
Dir.chdir(tmpdir) do Dir.chdir(tmpdir) do
Dir["**/*.png"].each do |png| Dir["**/*.png"].each do |png|
...@@ -64,7 +69,7 @@ namespace :gemojione do ...@@ -64,7 +69,7 @@ namespace :gemojione do
# Combine the resized assets into a packed sprite and re-generate the SCSS # Combine the resized assets into a packed sprite and re-generate the SCSS
SpriteFactory.cssurl = "image-url('$IMAGE')" SpriteFactory.cssurl = "image-url('$IMAGE')"
SpriteFactory.run!(File.join(tmpdir, 'images'), { SpriteFactory.run!(File.join(tmpdir, 'png'), {
output_style: style_path, output_style: style_path,
output_image: "app/assets/images/emoji.png", output_image: "app/assets/images/emoji.png",
selector: '.emoji-', selector: '.emoji-',
...@@ -97,7 +102,7 @@ namespace :gemojione do ...@@ -97,7 +102,7 @@ namespace :gemojione do
only screen and (min-resolution: 192dpi), only screen and (min-resolution: 192dpi),
only screen and (min-resolution: 2dppx) { only screen and (min-resolution: 2dppx) {
background-image: image-url('emoji@2x.png'); background-image: image-url('emoji@2x.png');
background-size: 840px 820px; background-size: #{SPRITESHEET_WIDTH}px #{SPRITESHEET_HEIGHT}px;
} }
} }
CSS CSS
...@@ -107,7 +112,7 @@ namespace :gemojione do ...@@ -107,7 +112,7 @@ namespace :gemojione do
# Now do it again but for Retina # Now do it again but for Retina
Dir.mktmpdir do |tmpdir| Dir.mktmpdir do |tmpdir|
# Copy the Gemojione assets to the temporary folder for resizing # Copy the Gemojione assets to the temporary folder for resizing
FileUtils.cp_r(Gemojione.index.images_path, tmpdir) FileUtils.cp_r(Gemojione.images_path, tmpdir)
Dir.chdir(tmpdir) do Dir.chdir(tmpdir) do
Dir["**/*.png"].each do |png| Dir["**/*.png"].each do |png|
...@@ -116,7 +121,7 @@ namespace :gemojione do ...@@ -116,7 +121,7 @@ namespace :gemojione do
end end
# Combine the resized assets into a packed sprite and re-generate the SCSS # Combine the resized assets into a packed sprite and re-generate the SCSS
SpriteFactory.run!(File.join(tmpdir, 'images'), { SpriteFactory.run!(File.join(tmpdir), {
output_image: "app/assets/images/emoji@2x.png", output_image: "app/assets/images/emoji@2x.png",
style: false, style: false,
nocomments: true, nocomments: true,
......
...@@ -3,10 +3,11 @@ require 'spec_helper' ...@@ -3,10 +3,11 @@ require 'spec_helper'
feature 'Expand and collapse diffs', js: true, feature: true do feature 'Expand and collapse diffs', js: true, feature: true do
include WaitForAjax include WaitForAjax
let(:branch) { 'expand-collapse-diffs' }
before do before do
login_as :admin login_as :admin
project = create(:project) project = create(:project)
branch = 'expand-collapse-diffs'
# Ensure that undiffable.md is in .gitattributes # Ensure that undiffable.md is in .gitattributes
project.repository.copy_gitattributes(branch) project.repository.copy_gitattributes(branch)
...@@ -167,6 +168,46 @@ feature 'Expand and collapse diffs', js: true, feature: true do ...@@ -167,6 +168,46 @@ feature 'Expand and collapse diffs', js: true, feature: true do
end end
end end
context 'visiting a commit without collapsed diffs' do
let(:branch) { 'feature' }
it 'does not show Expand all button' do
expect(page).not_to have_link('Expand all')
end
end
context 'visiting a commit with more than safe files' do
let(:branch) { 'expand-collapse-files' }
# safe-files -> 100 | safe-lines -> 5000 | commit-files -> 105
it 'does collapsing from the safe number of files to the end on small files' do
expect(page).to have_link('Expand all')
expect(page).to have_selector('.diff-content', count: 105)
expect(page).to have_selector('.diff-collapsed', count: 5)
%w(file-95.txt file-96.txt file-97.txt file-98.txt file-99.txt).each do |filename|
expect(find("[data-blob-diff-path*='#{filename}']")).to have_selector('.diff-collapsed')
end
end
end
context 'visiting a commit with more than safe lines' do
let(:branch) { 'expand-collapse-lines' }
# safe-files -> 100 | safe-lines -> 5000 | commit_files -> 8 (each 1250 lines)
it 'does collapsing from the safe number of lines to the end' do
expect(page).to have_link('Expand all')
expect(page).to have_selector('.diff-content', count: 6)
expect(page).to have_selector('.diff-collapsed', count: 2)
%w(file-4.txt file-5.txt).each do |filename|
expect(find("[data-blob-diff-path*='#{filename}']")).to have_selector('.diff-collapsed')
end
end
end
context 'expanding all diffs' do context 'expanding all diffs' do
before do before do
click_link('Expand all') click_link('Expand all')
......
...@@ -32,10 +32,29 @@ describe DiffHelper do ...@@ -32,10 +32,29 @@ describe DiffHelper do
end end
describe 'diff_options' do describe 'diff_options' do
it 'should return hard limit for a diff' do it 'should return hard limit for a diff if force diff is true' do
allow(controller).to receive(:params) { { force_show_diff: true } } allow(controller).to receive(:params) { { force_show_diff: true } }
expect(diff_options).to include(Commit.max_diff_options) expect(diff_options).to include(Commit.max_diff_options)
end end
it 'should return hard limit for a diff if expand_all_diffs is true' do
allow(controller).to receive(:params) { { expand_all_diffs: true } }
expect(diff_options).to include(Commit.max_diff_options)
end
it 'should return no collapse false' do
expect(diff_options).to include(no_collapse: false)
end
it 'should return no collapse true if expand_all_diffs' do
allow(controller).to receive(:params) { { expand_all_diffs: true } }
expect(diff_options).to include(no_collapse: true)
end
it 'should return no collapse true if action name diff_for_path' do
allow(controller).to receive(:action_name) { 'diff_for_path' }
expect(diff_options).to include(no_collapse: true)
end
end end
describe 'unfold_bottom_class' do describe 'unfold_bottom_class' do
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment