Commit ad19de19 authored by Grzegorz Bizon's avatar Grzegorz Bizon

Merge branch 'master' into auto-pipelines-vue

* master: (114 commits)
  Remove dashboard.scss
  Update custom_hooks.md for global custom hooks and chained hook info
  Move admin hooks spinach to rspec
  Move admin logs spinach test to rspec
  Fix 404 error when visit group label edit page
  A simpler implementation of finding a merge request
  Encourage bug reporters to mention if they use GitLab.com
  Bump gitlab-shell version to 4.0.3
  Remove confirmation.scss
  Explain "js: true" in "deleted_source_branch_spec.rb"
  Move award emojis to framwork
  Move image styles to framework
  Remove tags.scss
  Remove caching of Repository#has_visible_content?
  Add text example for pipeline status without action
  Use detailed status as CSS class in pipelines list
  Use status text when redering pipelines list
  Improve support for icons in new detailed statuses
  Add status label information to pipeline header
  Untangle status label and text in ci status helper
  ...
parents f55fcef3 e09c6df0
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3-git-2.7-phantomjs-2.1"
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.3-git-2.7-phantomjs-2.1-node-7.1"
cache:
key: "ruby-231"
key: "ruby-233"
paths:
- vendor/ruby
......@@ -235,7 +235,7 @@ rake ee_compat_check:
- /^[\d-]+-stable(-ee)?$/
allow_failure: yes
cache:
key: "ruby231-ee_compat_check_repo"
key: "ruby233-ee_compat_check_repo"
paths:
- ee_compat_check/repo/
- vendor/ruby
......@@ -277,8 +277,6 @@ teaspoon:
stage: test
<<: *use-db
script:
- curl --silent --location https://deb.nodesource.com/setup_6.x | bash -
- apt-get install --assume-yes nodejs
- npm install
- npm link istanbul
- rake teaspoon
......
......@@ -21,6 +21,8 @@ logs, and code as it's very hard to read otherwise.)
### Output of checks
(If you are reporting a bug on GitLab.com, write: This bug happens on GitLab.com)
#### Results of GitLab application Check
(For installations with omnibus-gitlab package run and paste the output of:
......
......@@ -2,6 +2,15 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 8.14.3 (2016-12-02)
- Pass commit data to ProcessCommitWorker to reduce Git overhead. !7744
- Speed up issuable dashboards.
- Don't change relative URLs to absolute URLs in the Help page.
- Fixes "ActionView::Template::Error: undefined method `text?` for nil:NilClass" on MR pages.
- Fix branch validation for GitHub PR where repo/fork was renamed/deleted.
- Validate state param when filtering issuables.
## 8.14.2 (2016-12-01)
- Remove caching of events data. !6578
......@@ -242,6 +251,11 @@ entry.
- Fix "Without projects" filter. !6611 (Ben Bodenmiller)
- Fix 404 when visit /projects page
## 8.13.8 (2016-12-02)
- Pass tag SHA to post-receive hook when tag is created via UI. !7700
- Validate state param when filtering issuables.
## 8.13.7 (2016-11-28)
- fixes 500 error on project show when user is not logged in and project is still empty. !7376
......
......@@ -264,7 +264,7 @@ group :development do
end
group :development, :test do
gem 'byebug', '~> 8.2.1', platform: :mri
gem 'pry-byebug', '~> 3.4.1', platform: :mri
gem 'pry-rails', '~> 0.3.4'
gem 'awesome_print', '~> 1.2.0', require: false
......@@ -338,7 +338,7 @@ gem 'ruby-prof', '~> 0.16.2'
gem 'oauth2', '~> 1.2.0'
# Soft deletion
gem 'paranoia', '~> 2.0'
gem 'paranoia', '~> 2.2'
# Health check
gem 'health_check', '~> 2.2.0'
......
......@@ -91,7 +91,7 @@ GEM
bundler-audit (0.5.0)
bundler (~> 1.2)
thor (~> 0.18)
byebug (8.2.1)
byebug (9.0.6)
capybara (2.6.2)
addressable
mime-types (>= 1.16)
......@@ -460,8 +460,8 @@ GEM
org-ruby (0.9.12)
rubypants (~> 0.2)
orm_adapter (0.5.0)
paranoia (2.1.4)
activerecord (~> 4.0)
paranoia (2.2.0)
activerecord (>= 4.0, < 5.1)
parser (2.3.1.4)
ast (~> 2.2)
pg (0.18.4)
......@@ -483,6 +483,9 @@ GEM
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
pry-byebug (3.4.1)
byebug (~> 9.0)
pry (~> 0.10)
pry-rails (0.3.4)
pry (>= 0.9.10)
pyu-ruby-sasl (0.0.3.3)
......@@ -796,7 +799,6 @@ DEPENDENCIES
browser (~> 2.2)
bullet (~> 5.2.0)
bundler-audit (~> 0.5.0)
byebug (~> 8.2.1)
capybara (~> 2.6.2)
capybara-screenshot (~> 1.0.0)
carrierwave (~> 0.10.0)
......@@ -887,10 +889,11 @@ DEPENDENCIES
omniauth-twitter (~> 1.2.0)
omniauth_crowd (~> 2.2.0)
org-ruby (~> 0.9.12)
paranoia (~> 2.0)
paranoia (~> 2.2)
pg (~> 0.18.2)
poltergeist (~> 1.9.0)
premailer-rails (~> 1.9.0)
pry-byebug (~> 3.4.1)
pry-rails (~> 0.3.4)
rack-attack (~> 4.4.1)
rack-cors (~> 0.4.0)
......
......@@ -76,7 +76,7 @@ GitLab is a Ruby on Rails application that runs on the following software:
- Ubuntu/Debian/CentOS/RHEL
- Ruby (MRI) 2.3
- Git 2.7.4+
- Git 2.8.4+
- Redis 2.8+
- MySQL or PostgreSQL
......
Copyright 2010, 2012, 2014 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, max-len, one-var, camelcase, one-var-declaration-per-line, no-unused-vars, no-unused-expressions, no-sequences, object-shorthand, comma-dangle, prefer-arrow-callback, semi, radix, padded-blocks, max-len */
(function() {
this.Diff = (function() {
var UNFOLD_COUNT;
UNFOLD_COUNT = 20;
function Diff() {
$('.files .diff-file').singleFileDiff();
this.filesCommentButton = $('.files .diff-file').filesCommentButton();
if (this.diffViewType() === 'parallel') {
$('.content-wrapper .container-fluid').removeClass('container-limited');
}
$(document).off('click', '.js-unfold');
$(document).on('click', '.js-unfold', (function(_this) {
return function(event) {
var line_number, link, file, offset, old_line, params, prev_new_line, prev_old_line, ref, ref1, since, target, to, unfold, unfoldBottom;
target = $(event.target);
unfoldBottom = target.hasClass('js-unfold-bottom');
unfold = true;
ref = _this.lineNumbers(target.parent()), old_line = ref[0], line_number = ref[1];
offset = line_number - old_line;
if (unfoldBottom) {
line_number += 1;
since = line_number;
to = line_number + UNFOLD_COUNT;
} else {
ref1 = _this.lineNumbers(target.parent().prev()), prev_old_line = ref1[0], prev_new_line = ref1[1];
line_number -= 1;
to = line_number;
if (line_number - UNFOLD_COUNT > prev_new_line + 1) {
since = line_number - UNFOLD_COUNT;
} else {
since = prev_new_line + 1;
unfold = false;
}
}
file = target.parents('.diff-file');
link = file.data('blob-diff-path');
params = {
since: since,
to: to,
bottom: unfoldBottom,
offset: offset,
unfold: unfold,
view: file.data('view')
};
return $.get(link, params, function(response) {
return target.parent().replaceWith(response);
});
};
})(this));
}
Diff.prototype.diffViewType = function() {
return $('.inline-parallel-buttons a.active').data('view-type');
}
Diff.prototype.lineNumbers = function(line) {
if (!line.children().length) {
return [0, 0];
}
return line.find('.diff-line-num').map(function() {
return parseInt($(this).data('linenumber'));
});
};
return Diff;
})();
}).call(this);
/* eslint-disable class-methods-use-this */
(() => {
const UNFOLD_COUNT = 20;
class Diff {
constructor() {
$('.files .diff-file').singleFileDiff();
$('.files .diff-file').filesCommentButton();
if (this.diffViewType() === 'parallel') {
$('.content-wrapper .container-fluid').removeClass('container-limited');
}
$(document)
.off('click', '.js-unfold, .diff-line-num a')
.on('click', '.js-unfold', this.handleClickUnfold.bind(this))
.on('click', '.diff-line-num a', this.handleClickLineNum.bind(this));
this.highlighSelectedLine();
}
handleClickUnfold(e) {
const $target = $(e.target);
// current babel config relies on iterators implementation, so we cannot simply do:
// const [oldLineNumber, newLineNumber] = this.lineNumbers($target.parent());
const ref = this.lineNumbers($target.parent());
const oldLineNumber = ref[0];
const newLineNumber = ref[1];
const offset = newLineNumber - oldLineNumber;
const bottom = $target.hasClass('js-unfold-bottom');
let since;
let to;
let unfold = true;
if (bottom) {
const lineNumber = newLineNumber + 1;
since = lineNumber;
to = lineNumber + UNFOLD_COUNT;
} else {
const lineNumber = newLineNumber - 1;
since = lineNumber - UNFOLD_COUNT;
to = lineNumber;
// make sure we aren't loading more than we need
const prevNewLine = this.lineNumbers($target.parent().prev())[1];
if (since <= prevNewLine + 1) {
since = prevNewLine + 1;
unfold = false;
}
}
const file = $target.parents('.diff-file');
const link = file.data('blob-diff-path');
const view = file.data('view');
const params = { since, to, bottom, offset, unfold, view };
$.get(link, params, response => $target.parent().replaceWith(response));
}
openAnchoredDiff(anchoredDiff, cb) {
const diffTitle = $(`#file-path-${anchoredDiff}`);
const diffFile = diffTitle.closest('.diff-file');
const nothingHereBlock = $('.nothing-here-block:visible', diffFile);
if (nothingHereBlock.length) {
diffFile.singleFileDiff(true, cb);
} else {
cb();
}
}
handleClickLineNum(e) {
const hash = $(e.currentTarget).attr('href');
e.preventDefault();
if (window.history.pushState) {
window.history.pushState(null, null, hash);
} else {
window.location.hash = hash;
}
this.highlighSelectedLine();
}
diffViewType() {
return $('.inline-parallel-buttons a.active').data('view-type');
}
lineNumbers(line) {
if (!line.children().length) {
return [0, 0];
}
return line.find('.diff-line-num').map((i, elm) => parseInt($(elm).data('linenumber'), 10));
}
highlighSelectedLine() {
const $diffFiles = $('.diff-file');
$diffFiles.find('.hll').removeClass('hll');
if (window.location.hash !== '') {
const hash = window.location.hash.replace('#', '');
$diffFiles
.find(`tr#${hash}:not(.match) td, td#${hash}, td[data-line-code="${hash}"]`)
.addClass('hll');
}
}
}
window.gl = window.gl || {};
window.gl.Diff = Diff;
})();
......@@ -61,7 +61,7 @@
new ZenMode();
break;
case 'projects:compare:show':
new Diff();
new gl.Diff();
break;
case 'projects:issues:new':
case 'projects:issues:edit':
......@@ -74,7 +74,7 @@
break;
case 'projects:merge_requests:new':
case 'projects:merge_requests:edit':
new Diff();
new gl.Diff();
shortcut_handler = new ShortcutsNavigation();
new GLForm($('.merge-request-form'));
new IssuableForm($('.merge-request-form'));
......@@ -91,7 +91,7 @@
new GLForm($('.release-form'));
break;
case 'projects:merge_requests:show':
new Diff();
new gl.Diff();
shortcut_handler = new ShortcutsIssuable(true);
new ZenMode();
new MergedButtons();
......@@ -101,7 +101,7 @@
new MergedButtons();
break;
case "projects:merge_requests:diffs":
new Diff();
new gl.Diff();
new ZenMode();
new MergedButtons();
break;
......@@ -117,7 +117,7 @@
break;
case 'projects:commit:show':
new Commit();
new Diff();
new gl.Diff();
new ZenMode();
shortcut_handler = new ShortcutsNavigation();
break;
......
......@@ -97,6 +97,19 @@
return $('body').data('page').split(':')[0];
};
gl.utils.parseUrl = function (url) {
var parser = document.createElement('a');
parser.href = url;
return parser;
};
gl.utils.parseUrlPathname = function (url) {
var parsedUrl = gl.utils.parseUrl(url);
// parsedUrl.pathname will return an absolute path for Firefox and a relative path for IE11
// We have to make sure we always have an absolute path.
return parsedUrl.pathname.charAt(0) === '/' ? parsedUrl.pathname : '/' + parsedUrl.pathname;
};
gl.utils.isMetaKey = function(e) {
return e.metaKey || e.ctrlKey || e.altKey || e.shiftKey;
};
......
......@@ -40,7 +40,7 @@
if (window.mrTabs) {
window.mrTabs.unbindEvents();
}
window.mrTabs = new MergeRequestTabs(this.opts);
window.mrTabs = new gl.MergeRequestTabs(this.opts);
};
MergeRequest.prototype.showAllCommits = function() {
......
......@@ -14,6 +14,7 @@
COLLAPSED_HTML = '<div class="nothing-here-block diff-collapsed">This diff is collapsed. <a class="click-to-expand">Click to expand it.</a></div>';
function SingleFileDiff(file, forceLoad, cb) {
var clickTarget;
this.file = file;
this.toggleDiff = bind(this.toggleDiff, this);
this.content = $('.diff-content', this.file);
......@@ -31,9 +32,9 @@
this.content.after(this.collapsedContent);
this.$toggleIcon.addClass('fa-caret-down');
}
$('.file-title, .click-to-expand', this.file).on('click', this.toggleDiff);
clickTarget = $('.file-title, .click-to-expand', this.file).on('click', this.toggleDiff);
if (forceLoad) {
this.toggleDiff(null, cb);
this.toggleDiff({ target: clickTarget }, cb);
}
}
......
@import "framework/fonts";
@import "framework/variables";
@import "framework/mixins";
@import 'framework/tw_bootstrap_variables';
......@@ -41,3 +40,6 @@
@import "framework/blank";
@import "framework/wells.scss";
@import "framework/page-header.scss";
@import "framework/awards.scss";
@import "framework/images.scss";
@import "framework/broadcast-messages";
......@@ -127,7 +127,7 @@
.award-control-icon {
float: left;
margin-right: 5px;
font-size: 19px;
font-size: 18px;
}
.award-control-icon-loading {
......
......@@ -32,14 +32,14 @@
.blank-state-title {
margin-top: 0;
margin-bottom: 5px;
font-size: 19px;
font-size: 18px;
font-weight: normal;
}
.blank-state-text {
margin-top: 0;
margin-bottom: $gl-padding;
font-size: 15px;
font-size: 14px;
> strong {
font-weight: 600;
......
.light-well {
background-color: $background-color;
padding: 15px;
}
.centered-light-block {
text-align: center;
color: $gl-gray;
......@@ -274,6 +269,10 @@
}
}
.emoji-icon {
display: inline-block;
}
@media(max-width: $screen-xs-max) {
margin-top: 50px;
text-align: center;
......
.broadcast-message {
@extend .alert-warning;
padding: 10px;
text-align: center;
div,
p {
display: inline;
margin: 0;
a {
color: inherit;
text-decoration: underline;
}
}
}
.broadcast-message-preview {
@extend .broadcast-message;
margin-bottom: 20px;
}
......@@ -33,7 +33,7 @@
.slead {
color: $common-gray;
font-size: 15px;
font-size: 14px;
margin-bottom: 12px;
font-weight: normal;
line-height: 24px;
......@@ -379,7 +379,9 @@ table {
border-top: 1px solid $border-color;
}
.hide-bottom-border { border-bottom: none !important; }
.hide-bottom-border {
border-bottom: none !important;
}
.gl-accessibility {
&:focus {
......@@ -396,3 +398,13 @@ table {
z-index: 1;
}
}
.str-truncated {
&-60 {
@include str-truncated(60%);
}
&-100 {
@include str-truncated(100%);
}
}
......@@ -36,7 +36,7 @@
padding: 6px 8px 6px 10px;
background-color: $dropdown-toggle-bg;
color: $dropdown-toggle-color;
font-size: 15px;
font-size: 14px;
text-align: left;
border: 1px solid $border-color;
border-radius: $border-radius-base;
......@@ -123,7 +123,7 @@
width: 240px;
margin-top: 2px;
margin-bottom: 0;
font-size: 15px;
font-size: 14px;
font-weight: normal;
padding: 8px 0;
background-color: $dropdown-bg;
......@@ -589,7 +589,7 @@
.ui-datepicker-title {
color: $gl-gray;
font-size: 15px;
font-size: 14px;
line-height: 1;
font-weight: normal;
}
......
// Disabling "SpaceAfterPropertyColon" linter because the linter doesn't like
// the way the `src` property is formatted in this file.
// scss-lint:disable SpaceAfterPropertyColon
/* latin-ext */
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 300;
src:
local('Source Sans Pro Light'),
local('SourceSansPro-Light'),
font-url('SourceSansPro-Light.ttf.woff2') format('woff2'),
font-url('SourceSansPro-Light.ttf.woff') format('woff');
}
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 400;
src:
local('Source Sans Pro'),
local('SourceSansPro-Regular'),
font-url('SourceSansPro-Regular.ttf.woff2') format('woff2'),
font-url('SourceSansPro-Regular.ttf.woff') format('woff');
}
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 600;
src:
local('Source Sans Pro Semibold'),
local('SourceSansPro-Semibold'),
font-url('SourceSansPro-Semibold.ttf.woff2') format('woff2'),
font-url('SourceSansPro-Semibold.ttf.woff') format('woff');
}
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 700;
src:
local('Source Sans Pro Bold'),
local('SourceSansPro-Bold'),
font-url('SourceSansPro-Bold.ttf.woff2') format('woff2'),
font-url('SourceSansPro-Bold.ttf.woff') format('woff');
}
......@@ -71,7 +71,7 @@ header {
}
.fa-caret-down {
font-size: 15px;
font-size: 14px;
}
}
......@@ -156,7 +156,7 @@ header {
position: relative;
padding-right: 20px;
margin: 0;
font-size: 19px;
font-size: 18px;
max-width: 385px;
display: inline-block;
line-height: $header-height;
......
......@@ -106,13 +106,13 @@ ul.task-list {
}
}
// Generic content list
ul.content-list {
@include basic-list;
margin: 0;
padding: 0;
> li {
li {
border-color: $table-border-color;
font-size: $list-font-size;
color: $list-text-color;
......@@ -193,6 +193,41 @@ ul.content-list {
}
}
// Content list using flexbox
.flex-list {
.flex-row {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
white-space: nowrap;
}
.row-main-content {
flex: 1 1 auto;
overflow: hidden;
padding-right: 8px;
}
.row-title {
font-weight: 600;
}
.row-second-line {
display: block;
}
.dropdown {
.btn-block {
margin-bottom: 0;
line-height: inherit;
}
}
.label-default {
color: $btn-transparent-color;
}
}
.panel > .content-list > li {
padding: $gl-padding-top $gl-padding;
......
......@@ -49,7 +49,7 @@
padding: $gl-btn-padding;
padding-bottom: 11px;
margin-bottom: -1px;
font-size: 15px;
font-size: 14px;
line-height: 28px;
color: $note-toolbar-color;
border-bottom: 2px solid transparent;
......@@ -268,6 +268,16 @@
width: auto;
}
}
&.multi-line {
.nav-text {
line-height: 20px;
}
.nav-controls {
padding: 17px 0;
}
}
}
.layout-nav {
......
......@@ -34,6 +34,10 @@ table {
background-color: $background-color;
font-weight: normal;
border-bottom: none;
&.wide {
width: 55%;
}
}
td {
......@@ -42,3 +46,16 @@ table {
}
}
}
.responsive-table {
@media (max-width: $screen-sm-max) {
th {
width: 100%;
}
td {
width: 100%;
float: left;
}
}
}
......@@ -102,7 +102,7 @@ $well-light-text-color: #5b6169;
/*
* Text
*/
$gl-font-size: 15px;
$gl-font-size: 14px;
$gl-title-color: #333;
$gl-text-color: #5c5c5c;
$gl-text-color-dark: #5c5d5e;
......@@ -266,7 +266,7 @@ $diff-view-modes-border: #c1c1c1;
* Fonts
*/
$monospace_font: 'Menlo', 'Liberation Mono', 'Consolas', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Courier New', 'andale mono', 'lucida console', monospace;
$regular_font: 'Source Sans Pro', "Helvetica Neue", Helvetica, Arial, sans-serif;
$regular_font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
/*
* Dropdowns
......@@ -380,7 +380,7 @@ $ci-skipped-color: #888;
/*
* Boards
*/
$issue-boards-font-size: 15px;
$issue-boards-font-size: 14px;
$issue-boards-card-shadow: rgba(186, 186, 186, 0.5);
/*
......@@ -427,12 +427,6 @@ $common-gray-dark: #444;
$common-red: $gl-text-red;
$common-green: $gl-text-green;
/*
* Dashboard
*/
$dashboard-project-access-icon-color: #888;
/*
* Editor
*/
......
......@@ -43,3 +43,16 @@
background-color: $well-expand-item;
}
}
.light-well {
background-color: $background-color;
padding: 15px;
}
.well-centered {
h1 {
font-weight: normal;
text-align: center;
font-size: 48px;
}
}
/**
* Admin area
*
*/
.admin-dashboard {
.data {
a {
h1 {
line-height: 48px;
font-size: 48px;
padding: 20px;
text-align: center;
font-weight: normal;
}
}
}
.str-truncated {
max-width: 60%;
}
}
.admin-filter form {
.select2-container {
width: 100%;
}
.controls {
margin-left: 130px;
}
.form-actions {
padding-left: 130px;
background: $white-light;
}
.visibility-levels {
.controls {
margin-bottom: 9px;
}
i {
color: inherit;
}
}
}
.broadcast-messages {
.message {
line-height: 2;
}
}
.broadcast-message {
@extend .alert-warning;
padding: 10px;
text-align: center;
> div,
p {
display: inline;
margin: 0;
a {
color: inherit;
text-decoration: underline;
}
}
}
.broadcast-message-preview {
@extend .broadcast-message;
margin-bottom: 20px;
}
// Users List
.users-list {
.user-row {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
white-space: nowrap;
}
.user-details {
flex: 1 1 auto;
overflow: hidden;
padding-right: 8px;
}
.user-name {
display: inline-block;
font-weight: 600;
}
.user-name,
.user-email {
overflow: hidden;
text-overflow: ellipsis;
}
.dropdown {
.btn-block {
margin-bottom: 0;
line-height: inherit;
}
}
.label-default {
color: $btn-transparent-color;
}
}
.abuse-reports {
.table {
table-layout: fixed;
}
.subheading {
padding-bottom: $gl-padding;
}
.message {
word-wrap: break-word;
}
.btn {
white-space: normal;
padding: $gl-btn-padding;
}
th {
width: 15%;
&.wide {
width: 55%;
}
}
@media (max-width: $screen-sm-max) {
th {
width: 100%;
}
td {
width: 100%;
float: left;
}
}
.no-reports {
.emoji-icon {
margin-left: $btn-side-margin;
margin-top: 3px;
}
span {
font-size: 19px;
}
}
}
.admin-builds-table {
.ci-table td:last-child {
min-width: 120px;
}
}
......@@ -64,6 +64,7 @@
@media (max-width: $screen-sm-max) {
padding-right: 40px;
margin-top: 6px;
.btn-inverted {
display: none;
......
.well-confirmation {
margin-bottom: 20px;
border-bottom: 1px solid $gray-darker;
> h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 400;
}
.lead {
margin-bottom: 20px;
}
ul,
ol {
padding-left: 0;
}
li {
list-style-type: none;
}
}
.confirmation-content {
a {
color: $md-link-color;
}
}
......@@ -109,7 +109,7 @@
&.title {
line-height: 19px;
font-size: 15px;
font-size: 14px;
font-weight: 600;
color: $gl-title-color;
}
......
.dashboard {
.side {
.panel {
.panel-heading {
background: $background-color;
border-top-left-radius: 0;
}
border-top-left-radius: 0;
}
}
}
.dashboard-search-filter {
padding: 5px;
.search-text-input {
float: left;
@extend .col-md-2;
}
.btn {
margin-left: 5px;
float: left;
}
}
.project-access-icon {
margin-left: 10px;
float: left;
margin-right: 15px;
margin-bottom: 15px;
i {
color: $dashboard-project-access-icon-color;
}
}
.dash-project-access-icon {
float: left;
margin-right: 5px;
width: 16px;
}
.error-page {
max-width: 400px;
margin: 0 auto;
h1,
h2,
h3 {
text-align: center;
}
h1 {
font-size: 56px;
line-height: 100px;
font-weight: 300;
}
}
.ci-body {
.incorrect-syntax {
font-size: 19px;
font-size: 18px;
color: $lint-incorrect-color;
}
.correct-syntax {
font-size: 19px;
font-size: 18px;
color: $lint-correct-color;
}
}
......@@ -116,7 +116,7 @@
@media (max-width: $screen-xs-max) {
h4 {
font-size: 15px;
font-size: 14px;
}
p {
......@@ -129,6 +129,11 @@
margin-bottom: 4px;
}
.btn-grouped {
float: none;
margin-right: 0;
}
.accept-action {
width: 100%;
text-align: center;
......
......@@ -129,7 +129,7 @@
.note-edit-form {
display: none;
font-size: 15px;
font-size: 14px;
.md-area {
background-color: $white-light;
......
......@@ -283,6 +283,12 @@
}
}
.admin-builds-table {
.ci-table td:last-child {
min-width: 120px;
}
}
// Pipeline visualization
.toggle-pipeline-btn {
......
......@@ -521,7 +521,7 @@ a.deploy-project-label {
.nav > li > a {
padding: 0;
background-color: transparent;
font-size: 15px;
font-size: 14px;
line-height: 29px;
color: $notes-light-color;
......
.tag-buttons {
line-height: 40px;
.btn:not(.dropdown-toggle) {
margin-left: 10px;
}
}
.votes-inline {
display: inline-block;
margin: 0 8px;
}
......@@ -6,7 +6,12 @@ module MergeRequestsAction
@label = merge_requests_finder.labels.first
@merge_requests = merge_requests_collection
.non_archived
.page(params[:page])
end
private
def filter_params
super.merge(non_archived: true)
end
end
......@@ -5,9 +5,7 @@ class Projects::DiscussionsController < Projects::ApplicationController
before_action :authorize_resolve_discussion!
def resolve
discussion.resolve!(current_user)
MergeRequests::ResolvedDiscussionNotificationService.new(project, current_user).execute(merge_request)
Discussions::ResolveService.new(project, current_user, merge_request: merge_request).execute(discussion)
render json: {
resolved_by: discussion.resolved_by.try(:name),
......
......@@ -46,8 +46,9 @@ class Projects::IssuesController < Projects::ApplicationController
params[:issue] ||= ActionController::Parameters.new(
assignee_id: ""
)
build_params = issue_params.merge(merge_request_for_resolving_discussions: merge_request_for_resolving_discussions)
@issue = @noteable = Issues::BuildService.new(project, current_user, build_params).execute
@issue = @noteable = @project.issues.new(issue_params)
respond_with(@issue)
end
......@@ -75,7 +76,9 @@ class Projects::IssuesController < Projects::ApplicationController
end
def create
@issue = Issues::CreateService.new(project, current_user, issue_params.merge(request: request)).execute
extra_params = { request: request,
merge_request_for_resolving_discussions: merge_request_for_resolving_discussions }
@issue = Issues::CreateService.new(project, current_user, issue_params.merge(extra_params)).execute
respond_to do |format|
format.html do
......@@ -169,6 +172,14 @@ class Projects::IssuesController < Projects::ApplicationController
alias_method :awardable, :issue
alias_method :spammable, :issue
def merge_request_for_resolving_discussions
return unless merge_request_iid = params[:merge_request_for_resolving_discussions]
@merge_request_for_resolving_discussions ||= MergeRequestsFinder.new(current_user, project_id: project.id).
execute.
find_by(iid: merge_request_iid)
end
def authorize_read_issue!
return render_404 unless can?(current_user, :read_issue, @issue)
end
......
......@@ -302,9 +302,13 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
def cancel_merge_when_build_succeeds
return access_denied! unless @merge_request.can_cancel_merge_when_build_succeeds?(current_user)
unless @merge_request.can_cancel_merge_when_build_succeeds?(current_user)
return access_denied!
end
MergeRequests::MergeWhenBuildSucceedsService.new(@project, current_user).cancel(@merge_request)
MergeRequests::MergeWhenPipelineSucceedsService
.new(@project, current_user)
.cancel(@merge_request)
end
def merge
......@@ -331,8 +335,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
if @merge_request.head_pipeline.active?
MergeRequests::MergeWhenBuildSucceedsService.new(@project, current_user, merge_params)
MergeRequests::MergeWhenPipelineSucceedsService
.new(@project, current_user, merge_params)
.execute(@merge_request)
@status = :merge_when_build_succeeds
elsif @merge_request.head_pipeline.success?
# This can be triggered when a user clicks the auto merge button while
......
......@@ -7,7 +7,7 @@
# current_user - which user use
# params:
# scope: 'created-by-me' or 'assigned-to-me' or 'all'
# state: 'open' or 'closed' or 'all'
# state: 'opened' or 'closed' or 'all'
# group_id: integer
# project_id: integer
# milestone_title: string
......@@ -15,6 +15,7 @@
# search: string
# label_name: string
# sort: string
# non_archived: boolean
#
class IssuableFinder
NONE = '0'
......@@ -38,6 +39,7 @@ class IssuableFinder
items = by_author(items)
items = by_label(items)
items = by_due_date(items)
items = by_non_archived(items)
sort(items)
end
......@@ -207,10 +209,13 @@ class IssuableFinder
end
def by_state(items)
params[:state] ||= 'all'
if items.respond_to?(params[:state])
items.public_send(params[:state])
case params[:state].to_s
when 'closed'
items.closed
when 'merged'
items.respond_to?(:merged) ? items.merged : items.closed
when 'opened'
items.opened
else
items
end
......@@ -353,6 +358,10 @@ class IssuableFinder
end
end
def by_non_archived(items)
params[:non_archived].present? ? items.non_archived : items
end
def current_user_related?
params[:scope] == 'created-by-me' || params[:scope] == 'authored' || params[:scope] == 'assigned-to-me'
end
......
......@@ -14,6 +14,7 @@
# search: string
# label_name: string
# sort: string
# non_archived: boolean
#
class MergeRequestsFinder < IssuableFinder
def klass
......
......@@ -5,8 +5,9 @@ module CiStatusHelper
end
def ci_status_with_icon(status, target = nil)
content = ci_icon_for_status(status) + ci_label_for_status(status)
content = ci_icon_for_status(status) + ci_text_for_status(status)
klass = "ci-status ci-#{status}"
if target
link_to content, target, class: klass
else
......@@ -14,7 +15,19 @@ module CiStatusHelper
end
end
def ci_text_for_status(status)
if detailed_status?(status)
status.text
else
status
end
end
def ci_label_for_status(status)
if detailed_status?(status)
return status.label
end
case status
when 'success'
'passed'
......@@ -31,6 +44,10 @@ module CiStatusHelper
end
def ci_icon_for_status(status)
if detailed_status?(status)
return custom_icon(status.icon)
end
icon_name =
case status
when 'success'
......@@ -94,4 +111,10 @@ module CiStatusHelper
class: klass, title: title, data: data
end
end
def detailed_status?(status)
status.respond_to?(:text) &&
status.respond_to?(:label) &&
status.respond_to?(:icon)
end
end
......@@ -174,7 +174,7 @@ module GitlabMarkdownHelper
# Returns a String
def cross_project_reference(project, entity)
if entity.respond_to?(:to_reference)
"#{project.to_reference}#{entity.to_reference}"
entity.to_reference(project)
else
''
end
......
......@@ -82,12 +82,6 @@ module LabelsHelper
span.html_safe
end
def render_colored_cross_project_label(label, source_project = nil, tooltip: true)
label_suffix = source_project ? source_project.name_with_namespace : label.project.name_with_namespace
label_suffix = " <i>in #{escape_once(label_suffix)}</i>"
render_colored_label(label, label_suffix, tooltip: tooltip)
end
def suggested_colors
[
'#0033CC',
......@@ -166,6 +160,5 @@ module LabelsHelper
end
# Required for Banzai::Filter::LabelReferenceFilter
module_function :render_colored_label, :render_colored_cross_project_label,
:text_color_for_bg, :escape_once
module_function :render_colored_label, :text_color_for_bg, :escape_once
end
......@@ -391,20 +391,6 @@ module ProjectsHelper
end
end
def new_readme_path
ref = @repository.root_ref if @repository
ref ||= 'master'
namespace_project_new_blob_path(@project.namespace, @project, tree_join(ref), file_name: 'README.md')
end
def new_license_path
ref = @repository.root_ref if @repository
ref ||= 'master'
namespace_project_new_blob_path(@project.namespace, @project, tree_join(ref), file_name: 'LICENSE')
end
def readme_cache_key
sha = @project.commit.try(:sha) || 'nil'
[@project.path_with_namespace, sha, "readme"].join('-')
......
......@@ -341,6 +341,10 @@ module Ci
.select { |merge_request| merge_request.head_pipeline.try(:id) == self.id }
end
def detailed_status
Gitlab::Ci::Status::Pipeline::Factory.new(self).fabricate!
end
private
def pipeline_data
......
......@@ -4,10 +4,10 @@ module Ci
belongs_to :project, foreign_key: :gl_project_id
validates_uniqueness_of :key, scope: :gl_project_id
validates :key,
presence: true,
length: { within: 0..255 },
uniqueness: { scope: :gl_project_id },
length: { maximum: 255 },
format: { with: /\A[a-zA-Z0-9_]+\z/,
message: "can contain only letters, digits and '_'." }
......
......@@ -92,19 +92,11 @@ class Commit
end
def to_reference(from_project = nil)
if cross_project_reference?(from_project)
project.to_reference + self.class.reference_prefix + self.id
else
self.id
end
commit_reference(from_project, id)
end
def reference_link_text(from_project = nil)
if cross_project_reference?(from_project)
project.to_reference + self.class.reference_prefix + self.short_id
else
self.short_id
end
commit_reference(from_project, short_id)
end
def diff_line_count
......@@ -329,6 +321,16 @@ class Commit
private
def commit_reference(from_project, referable_commit_id)
reference = project.to_reference(from_project)
if reference.present?
"#{reference}#{self.class.reference_prefix}#{referable_commit_id}"
else
referable_commit_id
end
end
def find_author_by_any_email
User.find_by_any_email(author_email.downcase)
end
......
......@@ -90,22 +90,25 @@ class CommitRange
alias_method :id, :to_s
def to_reference(from_project = nil)
if cross_project_reference?(from_project)
project.to_reference + self.class.reference_prefix + self.id
project_reference = project.to_reference(from_project)
if project_reference.present?
project_reference + self.class.reference_prefix + self.id
else
self.id
end
end
def reference_link_text(from_project = nil)
project_reference = project.to_reference(from_project)
reference = ref_from + notation + ref_to
if cross_project_reference?(from_project)
reference = project.to_reference + self.class.reference_prefix + reference
end
if project_reference.present?
project_reference + self.class.reference_prefix + reference
else
reference
end
end
# Return a Hash of parameters for passing to a URL helper
#
......
......@@ -41,7 +41,7 @@ module Issuable
has_one :metrics
validates :author, presence: true
validates :title, presence: true, length: { within: 0..255 }
validates :title, presence: true, length: { maximum: 255 }
scope :authored, ->(user) { where(author_id: user) }
scope :assigned_to, ->(u) { where(assignee_id: u.id)}
......
......@@ -72,17 +72,4 @@ module Referable
}x
end
end
private
# Check if a reference is being done cross-project
#
# from_project - Refering Project object
def cross_project_reference?(from_project)
if self.is_a?(Project)
self != from_project
else
from_project && self.project && self.project != from_project
end
end
end
......@@ -88,6 +88,10 @@ class Discussion
@first_note ||= @notes.first
end
def first_note_to_resolve
@first_note_to_resolve ||= notes.detect(&:to_be_resolved?)
end
def last_note
@last_note ||= @notes.last
end
......
......@@ -9,7 +9,7 @@ class Environment < ActiveRecord::Base
validates :name,
presence: true,
uniqueness: { scope: :project_id },
length: { within: 0..255 },
length: { maximum: 255 },
format: { with: Gitlab::Regex.environment_name_regex,
message: Gitlab::Regex.environment_name_regex_message }
......
......@@ -153,11 +153,7 @@ class Issue < ActiveRecord::Base
def to_reference(from_project = nil)
reference = "#{self.class.reference_prefix}#{iid}"
if cross_project_reference?(from_project)
reference = project.to_reference + reference
end
reference
"#{project.to_reference(from_project)}#{reference}"
end
def referenced_merge_requests(current_user = nil)
......
......@@ -8,10 +8,18 @@ class Key < ActiveRecord::Base
before_validation :generate_fingerprint
validates :title, presence: true, length: { within: 0..255 }
validates :key, presence: true, length: { within: 0..5000 }, format: { with: /\A(ssh|ecdsa)-.*\Z/ }
validates :key, format: { without: /\n|\r/, message: 'should be a single line' }
validates :fingerprint, uniqueness: true, presence: { message: 'cannot be generated' }
validates :title,
presence: true,
length: { maximum: 255 }
validates :key,
presence: true,
length: { maximum: 5000 },
format: { with: /\A(ssh|ecdsa)-.*\Z/ }
validates :key,
format: { without: /\n|\r/, message: 'should be a single line' }
validates :fingerprint,
uniqueness: true,
presence: { message: 'cannot be generated' }
delegate :name, :email, to: :user, prefix: true
......
......@@ -146,7 +146,8 @@ class Label < ActiveRecord::Base
#
# Label.first.to_reference # => "~1"
# Label.first.to_reference(format: :name) # => "~\"bug\""
# Label.first.to_reference(project1, project2) # => "gitlab-org/gitlab-ce~1"
# Label.first.to_reference(project, same_namespace_project) # => "gitlab-ce~1"
# Label.first.to_reference(project, another_namespace_project) # => "gitlab-org/gitlab-ce~1"
#
# Returns a String
#
......@@ -154,8 +155,8 @@ class Label < ActiveRecord::Base
format_reference = label_format_reference(format)
reference = "#{self.class.reference_prefix}#{format_reference}"
if cross_project_reference?(source_project, target_project)
source_project.to_reference + reference
if source_project
"#{source_project.to_reference(target_project)}#{reference}"
else
reference
end
......@@ -169,10 +170,6 @@ class Label < ActiveRecord::Base
private
def cross_project_reference?(source_project, target_project)
source_project && target_project && source_project != target_project
end
def issues_count(user, params = {})
params.merge!(subject_foreign_key => subject.id, label_name: title, scope: 'all')
IssuesFinder.new(user, params.with_indifferent_access).execute.count
......
......@@ -63,6 +63,7 @@ class Member < ActiveRecord::Base
after_create :send_request, if: :request?, unless: :importing?
after_create :create_notification_setting, unless: [:pending?, :importing?]
after_create :post_create_hook, unless: [:pending?, :importing?]
after_create :refresh_member_authorized_projects, if: :importing?
after_update :post_update_hook, unless: [:pending?, :importing?]
after_destroy :post_destroy_hook, unless: :pending?
......
......@@ -176,11 +176,7 @@ class MergeRequest < ActiveRecord::Base
def to_reference(from_project = nil)
reference = "#{self.class.reference_prefix}#{iid}"
if cross_project_reference?(from_project)
reference = project.to_reference + reference
end
reference
"#{project.to_reference(from_project)}#{reference}"
end
def first_commit
......@@ -480,6 +476,14 @@ class MergeRequest < ActiveRecord::Base
@diff_discussions ||= self.notes.diff_notes.discussions
end
def resolvable_discussions
@resolvable_discussions ||= diff_discussions.select(&:to_be_resolved?)
end
def discussions_can_be_resolved_by?(user)
resolvable_discussions.all? { |discussion| discussion.can_resolve?(user) }
end
def find_diff_discussion(discussion_id)
notes = self.notes.diff_notes.where(discussion_id: discussion_id).fresh.to_a
return if notes.empty?
......
......@@ -115,17 +115,14 @@ class Milestone < ActiveRecord::Base
#
# Milestone.first.to_reference # => "%1"
# Milestone.first.to_reference(format: :name) # => "%\"goal\""
# Milestone.first.to_reference(project) # => "gitlab-org/gitlab-ce%1"
# Milestone.first.to_reference(cross_namespace_project) # => "gitlab-org/gitlab-ce%1"
# Milestone.first.to_reference(same_namespace_project) # => "gitlab-ce%1"
#
def to_reference(from_project = nil, format: :iid)
format_reference = milestone_format_reference(format)
reference = "#{self.class.reference_prefix}#{format_reference}"
if cross_project_reference?(from_project)
project.to_reference + reference
else
reference
end
"#{project.to_reference(from_project)}#{reference}"
end
def reference_link_text(from_project = nil)
......
......@@ -12,17 +12,17 @@ class Namespace < ActiveRecord::Base
validates :owner, presence: true, unless: ->(n) { n.type == "Group" }
validates :name,
length: { within: 0..255 },
namespace_name: true,
presence: true,
uniqueness: true
uniqueness: true,
length: { maximum: 255 },
namespace_name: true
validates :description, length: { within: 0..255 }
validates :description, length: { maximum: 255 }
validates :path,
length: { within: 1..255 },
namespace: true,
presence: true,
uniqueness: { case_sensitive: false }
uniqueness: { case_sensitive: false },
length: { maximum: 255 },
namespace: true
delegate :name, to: :owner, allow_nil: true, prefix: true
......
......@@ -99,7 +99,7 @@ class Note < ActiveRecord::Base
end
def discussions
Discussion.for_notes(all)
Discussion.for_notes(fresh)
end
def grouped_diff_discussions
......
......@@ -172,13 +172,13 @@ class Project < ActiveRecord::Base
validates :description, length: { maximum: 2000 }, allow_blank: true
validates :name,
presence: true,
length: { within: 0..255 },
length: { maximum: 255 },
format: { with: Gitlab::Regex.project_name_regex,
message: Gitlab::Regex.project_name_regex_message }
validates :path,
presence: true,
project_path: true,
length: { within: 0..255 },
length: { maximum: 255 },
format: { with: Gitlab::Regex.project_path_regex,
message: Gitlab::Regex.project_path_regex_message }
validates :namespace, presence: true
......@@ -419,7 +419,11 @@ class Project < ActiveRecord::Base
def reference_pattern
name_pattern = Gitlab::Regex::NAMESPACE_REGEX_STR
%r{(?<project>#{name_pattern}/#{name_pattern})}
%r{
((?<namespace>#{name_pattern})\/)?
(?<project>#{name_pattern})
}x
end
def trending
......@@ -650,8 +654,20 @@ class Project < ActiveRecord::Base
end
end
def to_reference(_from_project = nil)
def to_reference(from_project = nil)
if cross_namespace_reference?(from_project)
path_with_namespace
elsif cross_project_reference?(from_project)
path
end
end
def to_human_reference(from_project = nil)
if cross_namespace_reference?(from_project)
name_with_namespace
elsif cross_project_reference?(from_project)
name
end
end
def web_url
......@@ -1327,10 +1343,21 @@ class Project < ActiveRecord::Base
private
# Check if a reference is being done cross-project
#
# from_project - Refering Project object
def cross_project_reference?(from_project)
from_project && self != from_project
end
def pushes_since_gc_redis_key
"projects/#{id}/pushes_since_gc"
end
def cross_namespace_reference?(from_project)
from_project && namespace != from_project.namespace
end
def default_branch_protected?
current_application_settings.default_branch_protection == Gitlab::Access::PROTECTION_FULL ||
current_application_settings.default_branch_protection == Gitlab::Access::PROTECTION_DEV_CAN_MERGE
......
......@@ -85,12 +85,8 @@ class Repository
# This method return true if repository contains some content visible in project page.
#
def has_visible_content?
return @has_visible_content unless @has_visible_content.nil?
@has_visible_content = cache.fetch(:has_visible_content?) do
branch_count > 0
end
end
def commit(ref = 'HEAD')
return nil unless exists?
......@@ -374,12 +370,6 @@ class Repository
return unless empty?
expire_method_caches(%i(empty?))
expire_has_visible_content_cache
end
def expire_has_visible_content_cache
cache.expire(:has_visible_content?)
@has_visible_content = nil
end
def lookup_cache
......@@ -467,7 +457,6 @@ class Repository
# Runs code after a new branch has been created.
def after_create_branch
expire_branches_cache
expire_has_visible_content_cache
repository_event(:push_branch)
end
......@@ -481,7 +470,6 @@ class Repository
# Runs code after an existing branch has been removed.
def after_remove_branch
expire_has_visible_content_cache
expire_branches_cache
end
......
......@@ -27,9 +27,9 @@ class Snippet < ActiveRecord::Base
delegate :name, :email, to: :author, prefix: true, allow_nil: true
validates :author, presence: true
validates :title, presence: true, length: { within: 0..255 }
validates :title, presence: true, length: { maximum: 255 }
validates :file_name,
length: { within: 0..255 },
length: { maximum: 255 },
format: { with: Gitlab::Regex.file_name_regex,
message: Gitlab::Regex.file_name_regex_message }
......@@ -67,12 +67,12 @@ class Snippet < ActiveRecord::Base
def to_reference(from_project = nil)
reference = "#{self.class.reference_prefix}#{id}"
if cross_project_reference?(from_project)
reference = project.to_reference + reference
end
if project.present?
"#{project.to_reference(from_project)}#{reference}"
else
reference
end
end
def self.content_types
[
......@@ -94,6 +94,10 @@ class Snippet < ActiveRecord::Base
0
end
def file_name
super.to_s
end
# alias for compatibility with blobs and highlighting
def path
file_name
......
......@@ -512,7 +512,7 @@ class User < ActiveRecord::Base
end
def require_ssh_key?
keys.count == 0
keys.count == 0 && Gitlab::ProtocolAccess.allowed?('ssh')
end
def require_password?
......
module Ci
class BuildPolicy < CommitStatusPolicy
def rules
can! :read_build if @subject.project.public_builds?
super
# If we can't read build we should also not have that
......
......@@ -12,9 +12,6 @@ class ProjectPolicy < BasePolicy
guest_access!
public_access!
# Allow to read builds for internal projects
can! :read_build if project.public_builds?
if project.request_access_enabled &&
!(owner || user.admin? || project.team.member?(user) || project_group_member?(user))
can! :request_access
......@@ -46,6 +43,11 @@ class ProjectPolicy < BasePolicy
can! :create_note
can! :upload_file
can! :read_cycle_analytics
if project.public_builds?
can! :read_pipeline
can! :read_build
end
end
def reporter_access!
......
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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