Commit 11ffdea7 authored by tiagonbotelho's avatar tiagonbotelho

Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce

parents 64232c71 c1f0b7fc
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) v 8.11.0 (unreleased)
- Fix of 'Commits being passed to custom hooks are already reachable when using the UI' - Fix of 'Commits being passed to custom hooks are already reachable when using the UI'
- Limit git rev-list output count to one in forced push check
v 8.10.0 (unreleased) v 8.10.0 (unreleased)
- Fix profile activity heatmap to show correct day name (eanplatter) - Fix profile activity heatmap to show correct day name (eanplatter)
- Speed up ExternalWikiHelper#get_project_wiki_path
- 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
...@@ -34,6 +36,7 @@ v 8.10.0 (unreleased) ...@@ -34,6 +36,7 @@ v 8.10.0 (unreleased)
- 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)
- Fix GFM autocomplete not working on wiki pages
- Fix MR-auto-close text added to description. !4836 - Fix MR-auto-close text added to description. !4836
- Support U2F devices in Firefox. !5177 - Support U2F devices in Firefox. !5177
- 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)
...@@ -133,6 +136,7 @@ v 8.10.0 (unreleased) ...@@ -133,6 +136,7 @@ v 8.10.0 (unreleased)
- Allow bulk (un)subscription from issues in issue index - Allow bulk (un)subscription from issues in issue index
- Fix MR diff encoding issues exporting GitLab projects - Fix MR diff encoding issues exporting GitLab projects
- Export and import avatar as part of project import/export - Export and import avatar as part of project import/export
- Fix migration corrupting import data for old version upgrades
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
......
...@@ -578,7 +578,7 @@ GEM ...@@ -578,7 +578,7 @@ GEM
railties (>= 4.2.0, < 5.1) railties (>= 4.2.0, < 5.1)
rinku (2.0.0) rinku (2.0.0)
rotp (2.1.2) rotp (2.1.2)
rouge (2.0.3) rouge (2.0.5)
rqrcode (0.7.0) rqrcode (0.7.0)
chunky_png chunky_png
rqrcode-rails3 (0.1.7) rqrcode-rails3 (0.1.7)
......
...@@ -49,6 +49,17 @@ ...@@ -49,6 +49,17 @@
border-color: $border-dark; border-color: $border-dark;
color: $color; color: $color;
} }
svg {
path {
fill: $color;
}
use {
stroke: $color;
}
}
} }
@mixin btn-green { @mixin btn-green {
...@@ -173,6 +184,13 @@ ...@@ -173,6 +184,13 @@
.caret { .caret {
margin-left: 5px; margin-left: 5px;
} }
svg {
height: 15px;
width: auto;
position: relative;
top: 2px;
}
} }
.btn-lg { .btn-lg {
......
...@@ -198,6 +198,10 @@ header.header-pinned-nav { ...@@ -198,6 +198,10 @@ header.header-pinned-nav {
.sidebar-collapsed-icon { .sidebar-collapsed-icon {
cursor: pointer; cursor: pointer;
.btn {
background-color: $gray-light;
}
} }
} }
......
...@@ -122,7 +122,8 @@ ...@@ -122,7 +122,8 @@
button { button {
float: right; float: right;
padding: 3px 5px; padding: 1px 5px;
background-color: $gray-light;
} }
} }
......
...@@ -78,6 +78,14 @@ form.edit-issue { ...@@ -78,6 +78,14 @@ form.edit-issue {
} }
} }
.merge-request-ci-status {
svg {
margin-right: 4px;
position: relative;
top: 1px;
}
}
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
.issue-btn-group { .issue-btn-group {
width: 100%; width: 100%;
......
...@@ -60,8 +60,10 @@ ...@@ -60,8 +60,10 @@
.ci_widget { .ci_widget {
border-bottom: 1px solid #eef0f2; border-bottom: 1px solid #eef0f2;
i { svg {
margin-right: 4px; margin-right: 4px;
position: relative;
top: 1px;
} }
&.ci-success { &.ci-success {
...@@ -196,6 +198,16 @@ ...@@ -196,6 +198,16 @@
.merge-request-title { .merge-request-title {
margin-bottom: 2px; margin-bottom: 2px;
.ci-status-link {
svg {
height: 16px;
width: 16px;
position: relative;
top: 3px;
}
}
} }
} }
......
...@@ -49,6 +49,14 @@ ...@@ -49,6 +49,14 @@
.commit-link { .commit-link {
.ci-status {
svg {
top: 1px;
margin-right: 0;
}
}
a:hover { a:hover {
text-decoration: none; text-decoration: none;
} }
...@@ -124,6 +132,15 @@ ...@@ -124,6 +132,15 @@
} }
} }
.stage-cell {
svg {
height: 18px;
width: 18px;
vertical-align: middle;
}
}
.duration, .duration,
.finished-at { .finished-at {
color: $table-text-gray; color: $table-text-gray;
......
...@@ -129,6 +129,17 @@ ...@@ -129,6 +129,17 @@
color: $layout-link-gray; color: $layout-link-gray;
} }
svg {
path {
fill: $layout-link-gray;
}
use {
stroke: $layout-link-gray;
}
}
.fa-caret-down { .fa-caret-down {
margin-left: 3px; margin-left: 3px;
} }
...@@ -486,6 +497,11 @@ pre.light-well { ...@@ -486,6 +497,11 @@ pre.light-well {
> span { > span {
margin-left: 10px; margin-left: 10px;
} }
svg {
position: relative;
top: 2px;
}
} }
} }
......
...@@ -41,6 +41,14 @@ ...@@ -41,6 +41,14 @@
color: $blue-normal; color: $blue-normal;
border-color: $blue-normal; border-color: $blue-normal;
} }
svg {
height: 13px;
width: 13px;
position: relative;
top: 1px;
margin: 0 3px;
}
} }
.ci-status-icon-success { .ci-status-icon-success {
......
.tag-buttons {
line-height: 40px;
.btn:not(.dropdown-toggle) {
margin-left: 10px;
}
}
...@@ -26,18 +26,20 @@ module CiStatusHelper ...@@ -26,18 +26,20 @@ module CiStatusHelper
icon_name = icon_name =
case status case status
when 'success' when 'success'
'check' 'icon_status_success'
when 'success_with_warnings'
'icon_status_warning'
when 'failed' when 'failed'
'close' 'icon_status_failed'
when 'pending' when 'pending'
'clock-o' 'icon_status_pending'
when 'running' when 'running'
'spinner' 'icon_status_running'
else else
'circle' 'icon_status_cancel'
end end
icon(icon_name + ' fw') custom_icon(icon_name)
end end
def render_commit_status(commit, tooltip_placement: 'auto left', cssclass: '') def render_commit_status(commit, tooltip_placement: 'auto left', cssclass: '')
......
module ExternalWikiHelper module ExternalWikiHelper
def get_project_wiki_path(project) def get_project_wiki_path(project)
external_wiki_service = project.services. external_wiki_service = project.external_wiki
find { |service| service.to_param == 'external_wiki' } if external_wiki_service
if external_wiki_service.present? && external_wiki_service.active?
external_wiki_service.properties['external_wiki_url'] external_wiki_service.properties['external_wiki_url']
else else
namespace_project_wiki_path(project.namespace, project, :home) namespace_project_wiki_path(project.namespace, project, :home)
......
module TimeHelper module TimeHelper
def duration_in_words(finished_at, started_at)
if finished_at && started_at
interval_in_seconds = finished_at.to_i - started_at.to_i
elsif started_at
interval_in_seconds = Time.now.to_i - started_at.to_i
end
time_interval_in_words(interval_in_seconds)
end
def time_interval_in_words(interval_in_seconds) def time_interval_in_words(interval_in_seconds)
minutes = interval_in_seconds / 60 minutes = interval_in_seconds / 60
seconds = interval_in_seconds - minutes * 60 seconds = interval_in_seconds - minutes * 60
...@@ -25,9 +15,19 @@ module TimeHelper ...@@ -25,9 +15,19 @@ module TimeHelper
end end
def duration_in_numbers(finished_at, started_at) def duration_in_numbers(finished_at, started_at)
diff_in_seconds = finished_at.to_i - started_at.to_i interval = interval_in_seconds(started_at, finished_at)
time_format = diff_in_seconds < 1.hour ? "%M:%S" : "%H:%M:%S" time_format = interval < 1.hour ? "%M:%S" : "%H:%M:%S"
Time.at(diff_in_seconds).utc.strftime(time_format) Time.at(interval).utc.strftime(time_format)
end
private
def interval_in_seconds(started_at, finished_at = nil)
if started_at && finished_at
finished_at.to_i - started_at.to_i
elsif started_at
Time.now.to_i - started_at.to_i
end
end end
end end
...@@ -650,6 +650,22 @@ class Project < ActiveRecord::Base ...@@ -650,6 +650,22 @@ class Project < ActiveRecord::Base
update_column(:has_external_issue_tracker, services.external_issue_trackers.any?) update_column(:has_external_issue_tracker, services.external_issue_trackers.any?)
end end
def external_wiki
if has_external_wiki.nil?
cache_has_external_wiki # Populate
end
if has_external_wiki
@external_wiki ||= services.external_wikis.first
else
nil
end
end
def cache_has_external_wiki
update_column(:has_external_wiki, services.external_wikis.any?)
end
def build_missing_services def build_missing_services
services_templates = Service.where(template: true) services_templates = Service.where(template: true)
......
...@@ -392,6 +392,11 @@ class Repository ...@@ -392,6 +392,11 @@ class Repository
expire_cache if exists? expire_cache if exists?
# expire cache that don't depend on repository data (when expiring)
expire_tags_cache
expire_tag_count_cache
expire_branches_cache
expire_branch_count_cache
expire_root_ref_cache expire_root_ref_cache
expire_emptiness_caches expire_emptiness_caches
expire_exists_cache expire_exists_cache
......
...@@ -17,6 +17,7 @@ class Service < ActiveRecord::Base ...@@ -17,6 +17,7 @@ class Service < ActiveRecord::Base
after_commit :reset_updated_properties after_commit :reset_updated_properties
after_commit :cache_project_has_external_issue_tracker after_commit :cache_project_has_external_issue_tracker
after_commit :cache_project_has_external_wiki
belongs_to :project, inverse_of: :services belongs_to :project, inverse_of: :services
has_one :service_hook has_one :service_hook
...@@ -25,6 +26,7 @@ class Service < ActiveRecord::Base ...@@ -25,6 +26,7 @@ class Service < ActiveRecord::Base
scope :visible, -> { where.not(type: ['GitlabIssueTrackerService', 'GitlabCiService']) } scope :visible, -> { where.not(type: ['GitlabIssueTrackerService', 'GitlabCiService']) }
scope :issue_trackers, -> { where(category: 'issue_tracker') } scope :issue_trackers, -> { where(category: 'issue_tracker') }
scope :external_wikis, -> { where(type: 'ExternalWikiService') }
scope :active, -> { where(active: true) } scope :active, -> { where(active: true) }
scope :without_defaults, -> { where(default: false) } scope :without_defaults, -> { where(default: false) }
...@@ -212,4 +214,10 @@ class Service < ActiveRecord::Base ...@@ -212,4 +214,10 @@ class Service < ActiveRecord::Base
project.cache_has_external_issue_tracker project.cache_has_external_issue_tracker
end end
end end
def cache_project_has_external_wiki
if project && !project.destroyed?
project.cache_has_external_wiki
end
end
end end
...@@ -854,7 +854,7 @@ class User < ActiveRecord::Base ...@@ -854,7 +854,7 @@ class User < ActiveRecord::Base
groups.joins(:shared_projects).select(:project_id)] groups.joins(:shared_projects).select(:project_id)]
if min_access_level if min_access_level
scope = { access_level: Gitlab::Access.values.select { |access| access >= min_access_level } } scope = { access_level: Gitlab::Access.all_values.select { |access| access >= min_access_level } }
relations = [relations.shift] + relations.map { |relation| relation.where(members: scope) } relations = [relations.shift] + relations.map { |relation| relation.where(members: scope) }
end end
......
- project = @target_project || @project - project = @target_project || @project
- noteable_class = @noteable.class if @noteable.present?
- if @noteable :javascript
:javascript GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_namespace_project_path(project.namespace, project, type: noteable_class, type_id: params[:id])}"
GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_namespace_project_path(project.namespace, project, type: @noteable.class, type_id: params[:id])}" GitLab.GfmAutoComplete.cachedData = undefined;
GitLab.GfmAutoComplete.cachedData = undefined; GitLab.GfmAutoComplete.setup();
GitLab.GfmAutoComplete.setup();
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
- if @build.duration - if @build.duration
%p.build-detail-row %p.build-detail-row
%span.build-light-text Duration: %span.build-light-text Duration:
#{duration_in_words(@build.finished_at, @build.started_at)} = time_interval_in_words(@build.duration)
- if @build.finished_at - if @build.finished_at
%p.build-detail-row %p.build-detail-row
%span.build-light-text Finished: %span.build-light-text Finished:
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
- if current_user && can?(current_user, :fork_project, @project) - if current_user && can?(current_user, :fork_project, @project)
- if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
= link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn has-tooltip' do = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn has-tooltip' do
= icon('code-fork fw') = custom_icon('icon_fork')
Fork Fork
%div.count-with-arrow %div.count-with-arrow
%span.arrow %span.arrow
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
= @project.forks_count = @project.forks_count
- else - else
= link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn has-tooltip' do = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn has-tooltip' do
= icon('code-fork fw') = custom_icon('icon_fork')
Fork Fork
%div.count-with-arrow %div.count-with-arrow
%span.arrow %span.arrow
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
- stages_status = pipeline.statuses.latest.stages_status - stages_status = pipeline.statuses.latest.stages_status
- stages.each do |stage| - stages.each do |stage|
%td %td.stage-cell
- status = stages_status[stage] - status = stages_status[stage]
- tooltip = "#{stage.titleize}: #{status || 'not found'}" - tooltip = "#{stage.titleize}: #{status || 'not found'}"
- if status - if status
......
...@@ -31,11 +31,11 @@ ...@@ -31,11 +31,11 @@
- if current_user && can?(current_user, :fork_project, @project) - if current_user && can?(current_user, :fork_project, @project)
- if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
= link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn btn-new' do = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn btn-new' do
= icon('code-fork fw') = custom_icon('icon_fork')
Fork Fork
- else - else
= link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn btn-new' do = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn btn-new' do
= icon('code-fork fw') = custom_icon('icon_fork')
Fork Fork
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
%td.duration %td.duration
- if generic_commit_status.duration - if generic_commit_status.duration
= icon("clock-o") = icon("clock-o")
#{duration_in_words(generic_commit_status.finished_at, generic_commit_status.started_at)} = time_interval_in_words(generic_commit_status.duration)
%td.timestamp %td.timestamp
- if generic_commit_status.finished_at - if generic_commit_status.finished_at
......
- @no_container = true
- page_title @tag.name, "Tags" - page_title @tag.name, "Tags"
= render "projects/commits/head" = render "projects/commits/head"
.row-content-block %div{ class: container_class }
.pull-right .sub-header-block
- if can?(current_user, :push_code, @project) .pull-right.tag-buttons
= link_to edit_namespace_project_tag_release_path(@project.namespace, @project, @tag.name), class: 'btn-grouped btn has-tooltip', title: 'Edit release notes' do - if can?(current_user, :push_code, @project)
= icon("pencil") = link_to edit_namespace_project_tag_release_path(@project.namespace, @project, @tag.name), class: 'btn has-tooltip', title: 'Edit release notes' do
= link_to namespace_project_tree_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped has-tooltip', title: 'Browse files' do = icon("pencil")
= icon('files-o') = link_to namespace_project_tree_path(@project.namespace, @project, @tag.name), class: 'btn has-tooltip', title: 'Browse files' do
= link_to namespace_project_commits_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped has-tooltip', title: 'Browse commits' do = icon('files-o')
= icon('history') = link_to namespace_project_commits_path(@project.namespace, @project, @tag.name), class: 'btn has-tooltip', title: 'Browse commits' do
- if can? current_user, :download_code, @project = icon('history')
= render 'projects/tags/download', ref: @tag.name, project: @project - if can? current_user, :download_code, @project
- if can?(current_user, :admin_project, @project) = render 'projects/tags/download', ref: @tag.name, project: @project
.pull-right - if can?(current_user, :admin_project, @project)
= link_to namespace_project_tag_path(@project.namespace, @project, @tag.name), class: 'btn btn-remove remove-row grouped has-tooltip', title: "Delete tag", method: :delete, data: { confirm: "Deleting the '#{@tag.name}' tag cannot be undone. Are you sure?" } do .pull-right
%i.fa.fa-trash-o = link_to namespace_project_tag_path(@project.namespace, @project, @tag.name), class: 'btn btn-remove remove-row grouped has-tooltip', title: "Delete tag", method: :delete, data: { confirm: "Deleting the '#{@tag.name}' tag cannot be undone. Are you sure?" } do
.title %i.fa.fa-trash-o
%span.item-title= @tag.name .tag-info.append-bottom-10
- if @commit .title
= render 'projects/branches/commit', commit: @commit, project: @project %span.item-title= @tag.name
- else - if @commit
Cant find HEAD commit for this tag = render 'projects/branches/commit', commit: @commit, project: @project
- if @tag.message.present? - else
%pre.body Cant find HEAD commit for this tag
= strip_gpg_signature(@tag.message) - if @tag.message.present?
%pre.body
= strip_gpg_signature(@tag.message)
.append-bottom-default.prepend-top-default .append-bottom-default.prepend-top-default
- if @release.description.present? - if @release.description.present?
.description .description
.wiki .wiki
= preserve do = preserve do
= markdown @release.description = markdown @release.description
- else - else
This tag has no release notes. This tag has no release notes.
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><circle id="a" cx="4" cy="4" r="4"/><mask id="d" width="8" height="8" x="0" y="0" fill="#fff"><use xlink:href="#a"/></mask><circle id="b" cx="20" cy="4" r="4"/><mask id="e" width="8" height="8" x="0" y="0" fill="#fff"><use xlink:href="#b"/></mask><circle id="c" cx="12" cy="30" r="4"/><mask id="f" width="8" height="8" x="0" y="0" fill="#fff"><use xlink:href="#c"/></mask></defs><g fill="none" fill-rule="evenodd" transform="translate(8 3)"><path fill="#7E7E7E" d="M10 19.667c-4.14-1.29-7.389-5.878-7.389-5.878C2.274 13.353 2 12.545 2 12.01V6h4v5.509c0 .276.166.65.367.831 0 0 1.136 1.028 1.746 1.574C9.617 15.261 11.048 16 12.09 16c1.028 0 2.41-.723 3.858-2.048.588-.54 1.84-1.742 1.84-1.742a.784.784 0 0 0 .211-.502V6h4v6.008c0 .548-.259 1.349-.601 1.795 0 0-3.21 4.707-7.399 5.916V27h-4v-7.333z"/><use stroke="#7E7E7E" stroke-width="4" mask="url(#d)" xlink:href="#a"/><use stroke="#7E7E7E" stroke-width="4" mask="url(#e)" xlink:href="#b"/><use stroke="#7E7E7E" stroke-width="4" mask="url(#f)" xlink:href="#c"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<circle id="a" cx="7" cy="7" r="7"/>
<mask id="b" width="14" height="14" x="0" y="0" fill="white">
<use xlink:href="#a"/>
</mask>
</defs>
<g fill="none" fill-rule="evenodd">
<use stroke="#5C5C5C" stroke-width="2" mask="url(#b)" xlink:href="#a"/>
<rect width="10" height="1" x="2" y="6.5" fill="#5C5C5C" transform="rotate(45 7 7)" rx=".3"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<circle id="a" cx="7" cy="7" r="7"/>
<mask id="b" width="14" height="14" x="0" y="0" fill="white">
<use xlink:href="#a"/>
</mask>
</defs>
<g fill="none" fill-rule="evenodd">
<use stroke="#D22852" stroke-width="2" mask="url(#b)" xlink:href="#a"/>
<path fill="#D22852" d="M7.5,6.5 L7.5,4.30578971 C7.5,4.12531853 7.36809219,4 7.20537567,4 L6.79462433,4 C6.63904572,4 6.5,4.13690672 6.5,4.30578971 L6.5,6.5 L4.30578971,6.5 C4.12531853,6.5 4,6.63190781 4,6.79462433 L4,7.20537567 C4,7.36095428 4.13690672,7.5 4.30578971,7.5 L6.5,7.5 L6.5,9.69421029 C6.5,9.87468147 6.63190781,10 6.79462433,10 L7.20537567,10 C7.36095428,10 7.5,9.86309328 7.5,9.69421029 L7.5,7.5 L9.69421029,7.5 C9.87468147,7.5 10,7.36809219 10,7.20537567 L10,6.79462433 C10,6.63904572 9.86309328,6.5 9.69421029,6.5 L7.5,6.5 Z" transform="rotate(45 7 7)"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<circle id="a" cx="7" cy="7" r="7"/>
<mask id="b" width="14" height="14" x="0" y="0" fill="white">
<use xlink:href="#a"/>
</mask>
</defs>
<g fill="none" fill-rule="evenodd">
<use stroke="#E75E40" stroke-width="2" mask="url(#b)" xlink:href="#a"/>
<rect width="1" height="4" x="5" y="5" fill="#E75E40" rx=".3"/>
<rect width="1" height="4" x="8" y="5" fill="#E75E40" rx=".3"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<circle id="a" cx="7" cy="7" r="7"/>
<mask id="b" width="14" height="14" x="0" y="0" fill="white">
<use xlink:href="#a"/>
</mask>
</defs>
<g fill="none" fill-rule="evenodd">
<use stroke="#2D9FD8" stroke-width="2" mask="url(#b)" xlink:href="#a"/>
<path fill="#2D9FD8" d="M7,3.00800862 C9.09023405,3.13960661 10.7448145,4.87657932 10.7448145,7 C10.7448145,9.209139 8.95395346,11 6.74481446,11 C5.4560962,11 4.30972054,10.3905589 3.57817301,9.44416214 L7,7 L7,3.00800862 Z"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<circle id="a" cx="7" cy="7" r="7"/>
<mask id="b" width="14" height="14" x="0" y="0" fill="white">
<use xlink:href="#a"/>
</mask>
</defs>
<g fill="none" fill-rule="evenodd">
<use stroke="#31AF64" stroke-width="2" mask="url(#b)" xlink:href="#a"/>
<g fill="#31AF64" transform="rotate(45 -.13 10.953)">
<rect width="1" height="5" x="2" rx=".3"/>
<rect width="3" height="1" y="4" rx=".3"/>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<circle id="a" cx="7" cy="7" r="7"/>
<mask id="b" width="14" height="14" x="0" y="0" fill="white">
<use xlink:href="#a"/>
</mask>
</defs>
<g fill="none" fill-rule="evenodd">
<g fill="#FF8A24" transform="translate(6 3)">
<rect width="2" height="5" rx=".5"/>
<rect width="2" height="2" y="6" rx=".5"/>
</g>
<use stroke="#FF8A24" stroke-width="2" mask="url(#b)" xlink:href="#a"/>
</g>
</svg>
...@@ -4,14 +4,7 @@ ...@@ -4,14 +4,7 @@
require 'gitlab/current_settings' require 'gitlab/current_settings'
include Gitlab::CurrentSettings include Gitlab::CurrentSettings
# If Sentry is enabled and the Rails app is running in production mode, CSP_REPORT_URI = ''
# 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 # Content Security Policy Headers
# For more information on CSP see: # For more information on CSP see:
...@@ -71,10 +64,7 @@ SecureHeaders::Configuration.default do |config| ...@@ -71,10 +64,7 @@ SecureHeaders::Configuration.default do |config|
upgrade_insecure_requests: true upgrade_insecure_requests: true
} }
# Reports are sent to Sentry if it's enabled. config.csp[:report_uri] = %W(#{CSP_REPORT_URI})
if current_application_settings.sentry_enabled
config.csp[:report_uri] = %W(#{CSP_REPORT_URI})
end
# Allow Bootstrap Linter in development mode. # Allow Bootstrap Linter in development mode.
if Rails.env.development? if Rails.env.development?
......
...@@ -89,11 +89,10 @@ Rails.application.routes.draw do ...@@ -89,11 +89,10 @@ Rails.application.routes.draw do
mount Grack::AuthSpawner, at: '/', constraints: lambda { |request| /[-\/\w\.]+\.git\/(info\/lfs|gitlab-lfs)/.match(request.path_info) }, via: [:get, :post, :put] mount Grack::AuthSpawner, at: '/', constraints: lambda { |request| /[-\/\w\.]+\.git\/(info\/lfs|gitlab-lfs)/.match(request.path_info) }, via: [:get, :post, :put]
# Help # Help
get 'help' => 'help#index'
get 'help' => 'help#index' get 'help/shortcuts' => 'help#shortcuts'
get 'help/*path' => 'help#show', as: :help_page get 'help/ui' => 'help#ui'
get 'help/shortcuts' get 'help/*path' => 'help#show', as: :help_page
get 'help/ui' => 'help#ui'
# #
# Global snippets # Global snippets
......
...@@ -7,7 +7,13 @@ class RemoveWrongImportUrlFromProjects < ActiveRecord::Migration ...@@ -7,7 +7,13 @@ class RemoveWrongImportUrlFromProjects < ActiveRecord::Migration
class ProjectImportDataFake class ProjectImportDataFake
extend AttrEncrypted extend AttrEncrypted
attr_accessor :credentials attr_accessor :credentials
attr_encrypted :credentials, key: Gitlab::Application.secrets.db_key_base, marshal: true, encode: true, :mode => :per_attribute_iv_and_salt attr_encrypted :credentials,
key: Gitlab::Application.secrets.db_key_base,
marshal: true,
encode: true,
:mode => :per_attribute_iv_and_salt,
insecure_mode: true,
algorithm: 'aes-256-cbc'
end end
def up def up
......
class AddHasExternalWikiToProjects < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
def change
add_column :projects, :has_external_wiki, :boolean
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160716115710) do ActiveRecord::Schema.define(version: 20160718153603) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -843,6 +843,7 @@ ActiveRecord::Schema.define(version: 20160716115710) do ...@@ -843,6 +843,7 @@ ActiveRecord::Schema.define(version: 20160716115710) do
t.boolean "only_allow_merge_if_build_succeeds", default: false, null: false t.boolean "only_allow_merge_if_build_succeeds", default: false, null: false
t.boolean "has_external_issue_tracker" t.boolean "has_external_issue_tracker"
t.string "repository_storage", default: "default", null: false t.string "repository_storage", default: "default", null: false
t.boolean "has_external_wiki"
end end
add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree
......
...@@ -24,7 +24,7 @@ module API ...@@ -24,7 +24,7 @@ module API
pipelines = user_project.pipelines.where(sha: params[:sha]) pipelines = user_project.pipelines.where(sha: params[:sha])
statuses = ::CommitStatus.where(pipeline: pipelines) statuses = ::CommitStatus.where(pipeline: pipelines)
statuses = statuses.latest unless parse_boolean(params[:all]) statuses = statuses.latest unless to_boolean(params[:all])
statuses = statuses.where(ref: params[:ref]) if params[:ref].present? statuses = statuses.where(ref: params[:ref]) if params[:ref].present?
statuses = statuses.where(stage: params[:stage]) if params[:stage].present? statuses = statuses.where(stage: params[:stage]) if params[:stage].present?
statuses = statuses.where(name: params[:name]) if params[:name].present? statuses = statuses.where(name: params[:name]) if params[:name].present?
......
...@@ -5,10 +5,6 @@ module API ...@@ -5,10 +5,6 @@ module API
SUDO_HEADER = "HTTP_SUDO" SUDO_HEADER = "HTTP_SUDO"
SUDO_PARAM = :sudo SUDO_PARAM = :sudo
def parse_boolean(value)
[ true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON' ].include?(value)
end
def to_boolean(value) def to_boolean(value)
return true if value =~ /^(true|t|yes|y|1|on)$/i return true if value =~ /^(true|t|yes|y|1|on)$/i
return false if value =~ /^(false|f|no|n|0|off)$/i return false if value =~ /^(false|f|no|n|0|off)$/i
...@@ -297,7 +293,7 @@ module API ...@@ -297,7 +293,7 @@ module API
def filter_projects(projects) def filter_projects(projects)
# If the archived parameter is passed, limit results accordingly # If the archived parameter is passed, limit results accordingly
if params[:archived].present? if params[:archived].present?
projects = projects.where(archived: parse_boolean(params[:archived])) projects = projects.where(archived: to_boolean(params[:archived]))
end end
if params[:search].present? if params[:search].present?
......
...@@ -242,7 +242,7 @@ module API ...@@ -242,7 +242,7 @@ module API
should_remove_source_branch: params[:should_remove_source_branch] should_remove_source_branch: params[:should_remove_source_branch]
} }
if parse_boolean(params[:merge_when_build_succeeds]) && merge_request.pipeline && merge_request.pipeline.active? if to_boolean(params[:merge_when_build_succeeds]) && merge_request.pipeline && merge_request.pipeline.active?
::MergeRequests::MergeWhenBuildSucceedsService.new(merge_request.target_project, current_user, merge_params). ::MergeRequests::MergeWhenBuildSucceedsService.new(merge_request.target_project, current_user, merge_params).
execute(merge_request) execute(merge_request)
else else
......
...@@ -8,7 +8,7 @@ module API ...@@ -8,7 +8,7 @@ module API
def map_public_to_visibility_level(attrs) def map_public_to_visibility_level(attrs)
publik = attrs.delete(:public) publik = attrs.delete(:public)
if publik.present? && !attrs[:visibility_level].present? if publik.present? && !attrs[:visibility_level].present?
publik = parse_boolean(publik) publik = to_boolean(publik)
# Since setting the public attribute to private could mean either # Since setting the public attribute to private could mean either
# private or internal, use the more conservative option, private. # private or internal, use the more conservative option, private.
attrs[:visibility_level] = (publik == true) ? Gitlab::VisibilityLevel::PUBLIC : Gitlab::VisibilityLevel::PRIVATE attrs[:visibility_level] = (publik == true) ? Gitlab::VisibilityLevel::PUBLIC : Gitlab::VisibilityLevel::PRIVATE
......
...@@ -8,8 +8,8 @@ module Gitlab ...@@ -8,8 +8,8 @@ module Gitlab
if Gitlab::Git.blank_ref?(oldrev) || Gitlab::Git.blank_ref?(newrev) if Gitlab::Git.blank_ref?(oldrev) || Gitlab::Git.blank_ref?(newrev)
false false
else else
missed_refs, _ = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev})) missed_ref, _ = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} --git-dir=#{project.repository.path_to_repo} rev-list --max-count=1 #{oldrev} ^#{newrev}))
missed_refs.split("\n").size > 0 missed_ref.present?
end end
end end
end end
......
...@@ -73,8 +73,8 @@ module Gitlab ...@@ -73,8 +73,8 @@ module Gitlab
diff_refs.complete? diff_refs.complete?
end end
def to_json def to_json(opts = nil)
JSON.generate(self.to_h) JSON.generate(self.to_h, opts)
end end
def type def type
......
...@@ -8,8 +8,8 @@ module Gitlab ...@@ -8,8 +8,8 @@ module Gitlab
@message = message @message = message
end end
def to_json def to_json(opts = nil)
{ status: @status, message: @message }.to_json { status: @status, message: @message }.to_json(opts)
end end
end end
end end
...@@ -5,7 +5,7 @@ module Gitlab ...@@ -5,7 +5,7 @@ module Gitlab
gon.default_avatar_url = URI::join(Gitlab.config.gitlab.url, ActionController::Base.helpers.image_path('no_avatar.png')).to_s gon.default_avatar_url = URI::join(Gitlab.config.gitlab.url, ActionController::Base.helpers.image_path('no_avatar.png')).to_s
gon.max_file_size = current_application_settings.max_attachment_size gon.max_file_size = current_application_settings.max_attachment_size
gon.relative_url_root = Gitlab.config.gitlab.relative_url_root gon.relative_url_root = Gitlab.config.gitlab.relative_url_root
gon.shortcuts_path = help_shortcuts_path gon.shortcuts_path = help_page_path('shortcuts')
gon.user_color_scheme = Gitlab::ColorSchemes.for_user(current_user).css_class gon.user_color_scheme = Gitlab::ColorSchemes.for_user(current_user).css_class
gon.award_menu_url = emojis_path gon.award_menu_url = emojis_path
......
...@@ -63,4 +63,13 @@ describe HelpController do ...@@ -63,4 +63,13 @@ describe HelpController do
end end
end end
end end
describe 'GET #ui' do
context 'for UI Development Kit' do
it 'renders found' do
get :ui
expect(response).to have_http_status(200)
end
end
end
end end
...@@ -7,7 +7,13 @@ describe CiStatusHelper do ...@@ -7,7 +7,13 @@ describe CiStatusHelper do
let(:failed_commit) { double("Ci::Pipeline", status: 'failed') } let(:failed_commit) { double("Ci::Pipeline", status: 'failed') }
describe 'ci_icon_for_status' do describe 'ci_icon_for_status' do
it { expect(helper.ci_icon_for_status(success_commit.status)).to include('fa-check') } it 'renders to correct svg on success' do
it { expect(helper.ci_icon_for_status(failed_commit.status)).to include('fa-close') } expect(helper).to receive(:render).with('shared/icons/icon_status_success.svg', anything)
helper.ci_icon_for_status(success_commit.status)
end
it 'renders the correct svg on failure' do
expect(helper).to receive(:render).with('shared/icons/icon_status_failed.svg', anything)
helper.ci_icon_for_status(failed_commit.status)
end
end end
end end
require 'spec_helper' require 'spec_helper'
describe TimeHelper do describe TimeHelper do
describe "#duration_in_words" do describe "#time_interval_in_words" do
it "returns minutes and seconds" do it "returns minutes and seconds" do
intervals_in_words = { intervals_in_words = {
100 => "1 minute 40 seconds", 100 => "1 minute 40 seconds",
...@@ -11,26 +11,23 @@ describe TimeHelper do ...@@ -11,26 +11,23 @@ describe TimeHelper do
} }
intervals_in_words.each do |interval, expectation| intervals_in_words.each do |interval, expectation|
expect(duration_in_words(Time.now + interval, Time.now)).to eq(expectation) expect(time_interval_in_words(interval)).to eq(expectation)
end end
end end
it "calculates interval from now if there is no finished_at" do
expect(duration_in_words(nil, Time.now - 5)).to eq("5 seconds")
end
end end
describe "#time_interval_in_words" do describe "#duration_in_numbers" do
it "returns minutes and seconds" do it "returns minutes and seconds" do
intervals_in_words = { duration_in_numbers = {
100 => "1 minute 40 seconds", [100, 0] => "01:40",
121 => "2 minutes 1 second", [121, 0] => "02:01",
3721 => "62 minutes 1 second", [3721, 0] => "01:02:01",
0 => "0 seconds" [0, 0] => "00:00",
[nil, Time.now.to_i - 42] => "00:42"
} }
intervals_in_words.each do |interval, expectation| duration_in_numbers.each do |interval, expectation|
expect(time_interval_in_words(interval)).to eq(expectation) expect(duration_in_numbers(*interval)).to eq(expectation)
end end
end end
end end
......
...@@ -338,4 +338,28 @@ describe Gitlab::Diff::Position, lib: true do ...@@ -338,4 +338,28 @@ describe Gitlab::Diff::Position, lib: true do
end end
end end
end end
describe "#to_json" do
let(:hash) do
{
old_path: "files/ruby/popen.rb",
new_path: "files/ruby/popen.rb",
old_line: nil,
new_line: 14,
base_sha: nil,
head_sha: nil,
start_sha: nil
}
end
let(:diff_position) { described_class.new(hash) }
it "returns the position as JSON" do
expect(JSON.parse(diff_position.to_json)).to eq(hash.stringify_keys)
end
it "works when nested under another hash" do
expect(JSON.parse(JSON.generate(pos: diff_position))).to eq('pos' => hash.stringify_keys)
end
end
end end
...@@ -458,6 +458,47 @@ describe Project, models: true do ...@@ -458,6 +458,47 @@ describe Project, models: true do
end end
end end
describe "#cache_has_external_wiki" do
let(:project) { create(:project) }
it "stores true if there is an external wiki" do
services = double(:service, external_wikis: [ExternalWikiService.new])
expect(project).to receive(:services).and_return(services)
expect do
project.cache_has_external_wiki
end.to change { project.has_external_wiki }.to(true)
end
it "stores false if there is no external wiki" do
services = double(:service, external_wikis: [])
expect(project).to receive(:services).and_return(services)
expect do
project.cache_has_external_wiki
end.to change { project.has_external_wiki }.to(false)
end
it "changes to true if an external wiki service is created later" do
expect do
project.cache_has_external_wiki
end.to change { project.has_external_wiki }.to(false)
expect do
create(:service, type: "ExternalWikiService", project: project)
end.to change { project.has_external_wiki }.to(true)
end
it "changes to false if an external wiki service is destroyed later" do
service = create(:service, type: "ExternalWikiService", project: project)
expect(project.has_external_wiki).to be_truthy
expect do
service.destroy
end.to change { project.has_external_wiki }.to(false)
end
end
describe '#open_branches' do describe '#open_branches' do
let(:project) { create(:project) } let(:project) { create(:project) }
......
...@@ -749,6 +749,30 @@ describe Repository, models: true do ...@@ -749,6 +749,30 @@ describe Repository, models: true do
repository.before_delete repository.before_delete
end end
it 'flushes the tags cache' do
expect(repository).to receive(:expire_tags_cache)
repository.before_delete
end
it 'flushes the tag count cache' do
expect(repository).to receive(:expire_tag_count_cache)
repository.before_delete
end
it 'flushes the branches cache' do
expect(repository).to receive(:expire_branches_cache)
repository.before_delete
end
it 'flushes the branch count cache' do
expect(repository).to receive(:expire_branch_count_cache)
repository.before_delete
end
it 'flushes the root ref cache' do it 'flushes the root ref cache' do
expect(repository).to receive(:expire_root_ref_cache) expect(repository).to receive(:expire_root_ref_cache)
...@@ -779,6 +803,30 @@ describe Repository, models: true do ...@@ -779,6 +803,30 @@ describe Repository, models: true do
repository.before_delete repository.before_delete
end end
it 'flushes the tags cache' do
expect(repository).to receive(:expire_tags_cache)
repository.before_delete
end
it 'flushes the tag count cache' do
expect(repository).to receive(:expire_tag_count_cache)
repository.before_delete
end
it 'flushes the branches cache' do
expect(repository).to receive(:expire_branches_cache)
repository.before_delete
end
it 'flushes the branch count cache' do
expect(repository).to receive(:expire_branch_count_cache)
repository.before_delete
end
it 'flushes the root ref cache' do it 'flushes the root ref cache' do
expect(repository).to receive(:expire_root_ref_cache) expect(repository).to receive(:expire_root_ref_cache)
......
...@@ -887,16 +887,25 @@ describe User, models: true do ...@@ -887,16 +887,25 @@ describe User, models: true do
end end
describe '#authorized_projects' do describe '#authorized_projects' do
let!(:user) { create(:user) } context 'with a minimum access level' do
let!(:private_project) { create(:project, :private) } it 'includes projects for which the user is an owner' do
user = create(:user)
project = create(:empty_project, :private, namespace: user.namespace)
before do expect(user.authorized_projects(Gitlab::Access::REPORTER))
private_project.team << [user, Gitlab::Access::MASTER] .to contain_exactly(project)
end end
subject { user.authorized_projects } it 'includes projects for which the user is a master' do
user = create(:user)
project = create(:empty_project, :private)
project.team << [user, Gitlab::Access::MASTER]
it { is_expected.to eq([private_project]) } expect(user.authorized_projects(Gitlab::Access::REPORTER))
.to contain_exactly(project)
end
end
end end
describe '#ci_authorized_runners' do describe '#ci_authorized_runners' do
......
...@@ -116,12 +116,9 @@ describe HelpController, "routing" do ...@@ -116,12 +116,9 @@ describe HelpController, "routing" do
expect(get(path)).to route_to('help#show', expect(get(path)).to route_to('help#show',
path: 'workflow/protected_branches/protected_branches1', path: 'workflow/protected_branches/protected_branches1',
format: 'png') format: 'png')
path = '/help/shortcuts'
expect(get(path)).to route_to('help#show',
path: 'shortcuts')
path = '/help/ui' path = '/help/ui'
expect(get(path)).to route_to('help#show', expect(get(path)).to route_to('help#ui')
path: 'ui')
end end
end end
......
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