Commit 51807dca authored by Rémy Coutable's avatar Rémy Coutable

Merge remote-tracking branch 'origin/master' into 8-6-stable

parents f86f8f38 f728e4b5
......@@ -4,6 +4,7 @@ v 8.6.0 (unreleased)
- Bump gitlab_git to 9.0.3 (Stan Hu)
- Support Golang subpackage fetching (Stan Hu)
- Bump Capybara gem to 2.6.2 (Stan Hu)
- New branch button appears on issues where applicable
- Contributions to forked projects are included in calendar
- Improve the formatting for the user page bio (Connor Shea)
- Removed the default password from the initial admin account created during
......@@ -11,10 +12,12 @@ v 8.6.0 (unreleased)
GitLab will ask the user to create a new one upon first visit.
- Fix issue when pushing to projects ending in .wiki
- Add support for wiki with UTF-8 page names (Hiroyuki Sato)
- Fix wiki search results point to raw source (Hiroyuki Sato)
- Don't load all of GitLab in mail_room
- Update `omniauth-saml` to 1.5.0 to allow for custom response attributes to be set
- Memoize @group in Admin::GroupsController (Yatish Mehta)
- Indicate how much an MR diverged from the target branch (Pierre de La Morinerie)
- Added omniauth-auth0 Gem (Daniel Carraro)
- Strip leading and trailing spaces in URL validator (evuez)
- Add "last_sign_in_at" and "confirmed_at" to GET /users/* API endpoints for admins (evuez)
- Return empty array instead of 404 when commit has no statuses in commit status API
......@@ -39,8 +42,10 @@ v 8.6.0 (unreleased)
- Add main language of a project in the list of projects (Tiago Botelho)
- Add ability to show archived projects on dashboard, explore and group pages
- Move group activity to separate page
- Create external users which are excluded of internal and private projects unless access was explicitly granted
- Continue parameters are checked to ensure redirection goes to the same instance
- User deletion is now done in the background so the request can not time out
- Canceled builds are now ignored in compound build status if marked as `allowed to fail`
v 8.5.7
- Bump Git version requirement to 2.7.3
......
......@@ -22,6 +22,7 @@ gem 'devise', '~> 3.5.4'
gem 'devise-async', '~> 0.9.0'
gem 'doorkeeper', '~> 2.2.0'
gem 'omniauth', '~> 1.3.1'
gem 'omniauth-auth0', '~> 1.4.1'
gem 'omniauth-azure-oauth2', '~> 0.0.6'
gem 'omniauth-bitbucket', '~> 0.0.2'
gem 'omniauth-cas3', '~> 1.1.2'
......
......@@ -498,6 +498,8 @@ GEM
omniauth (1.3.1)
hashie (>= 1.2, < 4)
rack (>= 1.0, < 3)
omniauth-auth0 (1.4.1)
omniauth-oauth2 (~> 1.1)
omniauth-azure-oauth2 (0.0.6)
jwt (~> 1.0)
omniauth (~> 1.0)
......@@ -973,6 +975,7 @@ DEPENDENCIES
oauth2 (~> 1.0.0)
octokit (~> 3.8.0)
omniauth (~> 1.3.1)
omniauth-auth0 (~> 1.4.1)
omniauth-azure-oauth2 (~> 0.0.6)
omniauth-bitbucket (~> 0.0.2)
omniauth-cas3 (~> 1.1.2)
......
......@@ -23,7 +23,7 @@
margin-bottom: -$gl-padding;
background-color: $background-color;
padding: $gl-padding;
margin-bottom: 0px;
margin-bottom: 0;
border-top: 1px solid $border-color;
border-bottom: 1px solid $border-color;
color: $gl-gray;
......
......@@ -37,23 +37,23 @@
}
@mixin btn-green {
@include btn-color($green-light, $border-green-light, $green-normal, $border-green-normal, $green-dark, $border-green-dark, #FFFFFF);
@include btn-color($green-light, $border-green-light, $green-normal, $border-green-normal, $green-dark, $border-green-dark, #fff);
}
@mixin btn-blue {
@include btn-color($blue-light, $border-blue-light, $blue-normal, $border-blue-normal, $blue-dark, $border-blue-dark, #FFFFFF);
@include btn-color($blue-light, $border-blue-light, $blue-normal, $border-blue-normal, $blue-dark, $border-blue-dark, #fff);
}
@mixin btn-blue-medium {
@include btn-color($blue-medium-light, $border-blue-light, $blue-medium, $border-blue-normal, $blue-medium-dark, $border-blue-dark, #FFFFFF);
@include btn-color($blue-medium-light, $border-blue-light, $blue-medium, $border-blue-normal, $blue-medium-dark, $border-blue-dark, #fff);
}
@mixin btn-orange {
@include btn-color($orange-light, $border-orange-light, $orange-normal, $border-orange-normal, $orange-dark, $border-orange-dark, #FFFFFF);
@include btn-color($orange-light, $border-orange-light, $orange-normal, $border-orange-normal, $orange-dark, $border-orange-dark, #fff);
}
@mixin btn-red {
@include btn-color($red-light, $border-red-light, $red-normal, $border-red-normal, $red-dark, $border-red-dark, #FFFFFF);
@include btn-color($red-light, $border-red-light, $red-normal, $border-red-normal, $red-dark, $border-red-dark, #fff);
}
@mixin btn-gray {
......@@ -127,7 +127,7 @@
margin-right: 7px;
float: left;
&:last-child {
margin-right: 0px;
margin-right: 0;
}
&.btn-xs {
margin-right: 3px;
......@@ -139,7 +139,6 @@
.caret {
margin-left: 5px;
color: $gray-darkest;
}
}
......@@ -170,7 +169,7 @@
margin-right: 7px;
float: left;
&:last-child {
margin-right: 0px;
margin-right: 0;
}
}
}
......
......@@ -33,19 +33,19 @@
}
.q2 {
fill: #ACD5F2 !important;
fill: #acd5f2 !important;
}
.q3 {
fill: #7FA8D1 !important;
fill: #7fa8d1 !important;
}
.q4 {
fill: #49729B !important;
fill: #49729b !important;
}
.q5 {
fill: #254E77 !important;
fill: #254e77 !important;
}
.domain-background {
......
......@@ -39,6 +39,6 @@
}
.bs-callout-success {
background-color: #dff0d8;
border-color: #5cA64d;
border-color: #5ca64d;
color: #3c763d;
}
/** COLORS **/
.cgray { color: $gl-gray; }
.clgray { color: #BBB }
.clgray { color: #bbb }
.cred { color: $gl-text-red; }
.cgreen { color: $gl-text-green; }
.cdark { color: #444 }
......@@ -8,20 +8,20 @@
/** COMMON CLASSES **/
.prepend-top-0 { margin-top: 0; }
.prepend-top-5 { margin-top: 5px; }
.prepend-top-10 { margin-top:10px }
.prepend-top-10 { margin-top: 10px }
.prepend-top-default { margin-top: $gl-padding !important; }
.prepend-top-20 { margin-top:20px }
.prepend-left-10 { margin-left:10px }
.prepend-top-20 { margin-top: 20px }
.prepend-left-10 { margin-left: 10px }
.prepend-left-default { margin-left: $gl-padding; }
.prepend-left-20 { margin-left:20px }
.prepend-left-20 { margin-left: 20px }
.append-right-5 { margin-right: 5px }
.append-right-10 { margin-right:10px }
.append-right-10 { margin-right: 10px }
.append-right-default { margin-right: $gl-padding; }
.append-right-20 { margin-right:20px }
.append-bottom-0 { margin-bottom:0 }
.append-bottom-10 { margin-bottom:10px }
.append-bottom-15 { margin-bottom:15px }
.append-bottom-20 { margin-bottom:20px }
.append-right-20 { margin-right: 20px }
.append-bottom-0 { margin-bottom: 0 }
.append-bottom-10 { margin-bottom: 10px }
.append-bottom-15 { margin-bottom: 15px }
.append-bottom-20 { margin-bottom: 20px }
.append-bottom-default { margin-bottom: $gl-padding; }
.inline { display: inline-block }
.center { text-align: center }
......@@ -51,7 +51,7 @@ pre {
}
&.well-pre {
border: 1px solid #EEE;
border: 1px solid #eee;
background: #f9f9f9;
border-radius: 0;
color: #555;
......@@ -103,7 +103,7 @@ span.update-author {
}
.user-mention {
color: #2FA0BB;
color: #2fa0bb;
font-weight: bold;
}
......@@ -134,10 +134,10 @@ p.time {
// Fix issue with notes & lists creating a bunch of bottom borders.
li.note {
img { max-width:100% }
img { max-width: 100% }
.note-title {
li {
border-bottom:none !important;
border-bottom: none !important;
}
}
}
......@@ -187,9 +187,9 @@ li.note {
.error-message {
padding: 10px;
background: #C67;
background: #c67;
margin: 0;
color: #FFF;
color: #fff;
a {
color: #fff;
......@@ -200,7 +200,7 @@ li.note {
.browser-alert {
padding: 10px;
text-align: center;
background: #C67;
background: #c67;
color: #fff;
font-weight: bold;
a {
......@@ -271,7 +271,7 @@ img.emoji {
table {
td.permission-x {
background: #D9EDF7 !important;
background: #d9edf7 !important;
text-align: center;
}
}
......@@ -280,7 +280,7 @@ table {
float: left;
text-align: center;
font-size: 32px;
color: #AAA;
color: #aaa;
width: 60px;
}
......@@ -347,7 +347,7 @@ table {
.profiler-button,
.profiler-controls {
border-color: #EEE !important;
border-color: #eee !important;
}
}
......
......@@ -4,7 +4,7 @@
height: 0;
margin-left: 2px;
vertical-align: middle;
border-top: $caret-width-base dashed $dropdown-caret-color;
border-top: $caret-width-base dashed;
border-right: $caret-width-base solid transparent;
border-left: $caret-width-base solid transparent;
}
......@@ -260,7 +260,7 @@
position: absolute;
top: 10px;
right: 10px;
color: #C7C7C7;
color: #c7c7c7;
font-size: 12px;
pointer-events: none;
}
......
......@@ -30,7 +30,7 @@
right: 15px;
.btn {
padding: 0px 10px;
padding: 0 10px;
font-size: 13px;
line-height: 28px;
}
......@@ -84,7 +84,7 @@
&.blob-no-preview {
background: #eee;
text-shadow: 0 1px 2px #FFF;
text-shadow: 0 1px 2px #fff;
padding: 100px 0;
}
......@@ -124,7 +124,7 @@
}
td.line-numbers {
float: none;
border-left: 1px solid #DDD;
border-left: 1px solid #ddd;
}
td.lines {
padding: 0;
......
......@@ -41,8 +41,8 @@ input[type='search'].search-input {
}
input[type='text'].danger {
background: #F2DEDE!important;
border-color: #D66;
background: #f2dede!important;
border-color: #d66;
text-shadow: 0 1px 1px #fff
}
......
......@@ -23,13 +23,13 @@
&:hover {
background-color: $color-darker;
a {
color: #FFF;
color: #fff;
}
}
}
.collapse-nav a {
color: #FFF;
color: #fff;
background: $color;
}
......@@ -42,7 +42,7 @@
&:hover {
background-color: $color-dark;
color: #FFF;
color: #fff;
text-decoration: none;
}
}
......@@ -71,7 +71,7 @@
}
&.active a {
color: #FFF;
color: #fff;
background: $color-dark;
&.no-highlight {
......@@ -79,42 +79,42 @@
}
i {
color: #FFF
color: #fff
}
}
}
}
}
$theme-blue: #2980B9;
$theme-blue: #2980b9;
$theme-charcoal: #333c47;
$theme-graphite: #888888;
$theme-graphite: #888;
$theme-gray: #373737;
$theme-green: #019875;
$theme-violet: #554488;
$theme-violet: #548;
body {
&.ui_blue {
@include gitlab-theme(#BECDE9, $theme-blue, #1970A9, #096099);
@include gitlab-theme(#becde9, $theme-blue, #1970a9, #096099);
}
&.ui_charcoal {
@include gitlab-theme(#c5d0de, $theme-charcoal, #2b333d, #24272D);
@include gitlab-theme(#c5d0de, $theme-charcoal, #2b333d, #24272d);
}
&.ui_graphite {
@include gitlab-theme(#CCCCCC, $theme-graphite, #777777, #666666);
@include gitlab-theme(#ccc, $theme-graphite, #777, #666);
}
&.ui_gray {
@include gitlab-theme(#979797, $theme-gray, #272727, #222222);
@include gitlab-theme(#979797, $theme-gray, #272727, #222);
}
&.ui_green {
@include gitlab-theme(#AADDCC, $theme-green, #018865, #017855);
@include gitlab-theme(#adc, $theme-green, #018865, #017855);
}
&.ui_violet {
@include gitlab-theme(#9988CC, $theme-violet, #443366, #332255);
@include gitlab-theme(#98c, $theme-violet, #436, #325);
}
}
\ No newline at end of file
......@@ -7,8 +7,8 @@ header {
&.navbar-empty {
height: 58px;
background: #FFF;
border-bottom: 1px solid #EEE;
background: #fff;
border-bottom: 1px solid #eee;
.center-logo {
margin: 11px 0;
......@@ -28,7 +28,7 @@ header {
min-height: $header-height;
background-color: #fff;
border: none;
border-bottom: 1px solid #EEE;
border-bottom: 1px solid #eee;
.container-fluid {
width: 100% !important;
......@@ -47,7 +47,7 @@ header {
text-align: center;
&:hover, &:focus, &:active {
background-color: #FFF;
background-color: #fff;
}
}
......@@ -59,7 +59,7 @@ header {
right: 2px;
&:hover {
background-color: #EEE;
background-color: #eee;
}
&.active {
color: #7f8fa4;
......@@ -162,7 +162,7 @@ header {
font-size: 18px;
.navbar-nav {
margin: 0px;
margin: 0;
float: none !important;
.visible-xs, .visable-sm {
......
.file-content.code {
border: none;
box-shadow: none;
margin: 0px;
padding: 0px;
margin: 0;
padding: 0;
table-layout: fixed;
pre {
......
......@@ -20,7 +20,7 @@
display: block;
float: left;
margin-right: 10px;
color: #FFF;
color: #fff;
font-size: $gl-font-size;
line-height: 25px;
......
......@@ -3,13 +3,13 @@
font-size: $font-size-base;
&.ui-datepicker-inline {
border: 1px solid #DDD;
border: 1px solid #ddd;
padding: 10px;
width: 270px;
.ui-datepicker-header {
background: #FFF;
border-color: #DDD;
background: #fff;
border-color: #ddd;
}
.ui-datepicker-calendar td a {
......@@ -19,7 +19,7 @@
}
&.ui-autocomplete {
border-color: #DDD;
border-color: #ddd;
padding: 0;
margin-top: 2px;
z-index: 1001;
......@@ -30,20 +30,20 @@
}
.ui-state-default {
border: 1px solid #FFF;
background: #FFF;
border: 1px solid #fff;
background: #fff;
color: #777;
}
.ui-state-highlight {
border: 1px solid #EEE;
background: #EEE;
border: 1px solid #eee;
background: #eee;
}
.ui-state-active {
border: 1px solid $gl-primary;
background: $gl-primary;
color: #FFF;
color: #fff;
}
.ui-state-hover,
......
......@@ -71,7 +71,7 @@
}
.md-preview-holder {
background: #FFF;
background: #fff;
border: 1px solid #ddd;
min-height: 169px;
padding: 5px;
......@@ -80,7 +80,7 @@
.markdown-area {
@include border-radius(0);
background: #FFF;
background: #fff;
border: 1px solid #ddd;
min-height: 140px;
max-height: 500px;
......
......@@ -67,17 +67,17 @@
* Base mixin for lists in GitLab
*/
@mixin basic-list {
margin: 5px 0px;
padding: 0px;
margin: 5px 0;
padding: 0;
list-style: none;
> li {
@include clearfix;
padding: 10px 0;
border-bottom: 1px solid #EEE;
border-bottom: 1px solid #eee;
display: block;
margin: 0px;
margin: 0;
&:last-child {
border-bottom: none;
......
......@@ -128,12 +128,12 @@
.show-aside {
display: none;
position: fixed;
right: 0px;
right: 0;
top: 30%;
padding: 5px 15px;
background: #EEE;
background: #eee;
font-size: 20px;
color: #777;
z-index: 100;
@include box-shadow(0 1px 2px #DDD);
@include box-shadow(0 1px 2px #ddd);
}
......@@ -26,7 +26,7 @@
}
&.active a {
color: #000000;
color: #000;
border-bottom: 2px solid #4688f1;
}
......@@ -41,7 +41,7 @@
.top-area {
@include clearfix;
border-bottom: 1px solid #EEE;
border-bottom: 1px solid #eee;
.nav-text {
padding-top: 16px;
......@@ -59,7 +59,7 @@
.nav-links {
display: inline-block;
width: 50%;
margin-bottom: 0px;
margin-bottom: 0;
border-bottom: none;
/* Small devices (phones, tablets, 768px and lower) */
......@@ -74,7 +74,7 @@
float: right;
text-align: right;
padding: 11px 0;
margin-bottom: 0px;
margin-bottom: 0;
> .dropdown {
margin-right: $gl-padding-top;
......
......@@ -151,7 +151,7 @@
padding: 2px 25px 2px 5px;
background: #fff image-url('select2.png');
background-repeat: no-repeat;
background-position: right 0px bottom 6px;
background-position: right 0 bottom 6px;
border: 1px solid $input-border;
@include border-radius($border-radius-default);
@include transition(border-color ease-in-out .15s, box-shadow ease-in-out .15s);
......@@ -229,7 +229,7 @@
.namespace-result {
.namespace-kind {
color: #AAA;
color: #aaa;
font-weight: normal;
}
.namespace-path {
......
......@@ -16,7 +16,7 @@
.gitlab-text-container-link {
z-index: 1;
position: absolute;
left: 0px;
left: 0;
}
#logo {
......@@ -47,7 +47,7 @@
width: 100%;
.container-fluid {
background: #FFF;
background: #fff;
padding: 0 $gl-padding;
&.container-blank {
......@@ -103,7 +103,7 @@
}
&:hover {
background-color: #EEE;
background-color: #eee;
}
}
......@@ -143,7 +143,7 @@
overflow: hidden;
&.navbar-collapse {
padding: 0px !important;
padding: 0 !important;
}
li {
......@@ -182,7 +182,7 @@
.count {
float: right;
background: #eee;
padding: 0px 8px;
padding: 0 8px;
@include border-radius(6px);
}
......@@ -194,8 +194,8 @@
}
.sidebar-subnav {
margin-left: 0px;
padding-left: 0px;
margin-left: 0;
padding-left: 0;
li {
list-style: none;
......
......@@ -95,7 +95,7 @@
}
&.label-inverse {
background-color: #333333;
background-color: #333;
}
}
......@@ -138,7 +138,7 @@
}
.btn-clipboard {
min-width: 0px;
min-width: 0;
}
}
......
......@@ -57,7 +57,7 @@ $component-active-bg: $brand-info;
$input-color: $text-color;
$input-border: #e7e9ed;
$input-border-focus: #7F8FA4;
$input-border-focus: #7f8fa4;
$legend-color: $text-color;
......@@ -125,8 +125,8 @@ $panel-inner-border: $border-color;
//
//##
$well-bg: #F9F9F9;
$well-border: #EEE;
$well-bg: #f9f9f9;
$well-border: #eee;
//== Code
//
......
......@@ -27,13 +27,13 @@
line-height: 10px;
color: #555;
vertical-align: middle;
background-color: #FCFCFC;
background-color: #fcfcfc;
border-width: 1px;
border-style: solid;
border-color: #CCC #CCC #BBB;
border-color: #ccc #ccc #bbb;
border-image: none;
border-radius: 3px;
box-shadow: 0px -1px 0px #BBB inset;
box-shadow: 0 -1px 0 #bbb inset;
}
h1 {
......@@ -187,7 +187,7 @@ body {
}
.page-title-empty {
margin-top: 0px;
margin-top: 0;
line-height: 1.3;
font-size: 1.25em;
font-weight: 600;
......
$row-hover: #f4f8fe;
$gl-text-color: #54565B;
$gl-text-green: #4A2;
$gl-text-red: #D12F19;
$gl-text-orange: #D90;
$gl-text-color: #54565b;
$gl-text-green: #4a2;
$gl-text-red: #d12f19;
$gl-text-orange: #d90;
$gl-header-color: #323232;
$gl-link-color: #333c48;
$md-text-color: #444;
......@@ -27,27 +27,27 @@ $gl-gray: #5a5a5a;
$gl-padding: 16px;
$gl-btn-padding: 10px;
$gl-vert-padding: 6px;
$gl-padding-top:10px;
$gl-padding-top: 10px;
$gl-avatar-size: 40px;
$secondary-text: #7f8fa4;
$error-exclamation-point: #E62958;
$error-exclamation-point: #e62958;
$border-radius-default: 3px;
$list-title-color: #333333;
$list-text-color: #555555;
$list-title-color: #333;
$list-text-color: #555;
$btn-transparent-color: #8F8F8F;
$btn-transparent-color: #8f8f8f;
$ssh-key-icon-color: #8F8F8F;
$ssh-key-icon-color: #8f8f8f;
$ssh-key-icon-size: 18px;
$provider-btn-group-border: #E5E5E5;
$provider-btn-not-active-color: #4688F1;
$provider-btn-group-border: #e5e5e5;
$provider-btn-not-active-color: #4688f1;
/*
* Color schema
*/
$white-light: #FFFFFF;
$white-light: #fff;
$white-normal: #ededed;
$white-dark: #ededed;
......@@ -57,55 +57,55 @@ $gray-dark: #ededed;
$gray-darkest: #c9c9c9;
$green-light: #38ae67;
$green-normal: #2FAA60;
$green-dark: #2CA05B;
$green-normal: #2faa60;
$green-dark: #2ca05b;
$blue-light: #2EA8E5;
$blue-normal: #2D9FD8;
$blue-dark: #2897CE;
$blue-light: #2ea8e5;
$blue-normal: #2d9fd8;
$blue-dark: #2897ce;
$blue-medium-light: #3498CB;
$blue-medium: #2F8EBF;
$blue-medium-dark: #2D86B4;
$blue-medium-light: #3498cb;
$blue-medium: #2f8ebf;
$blue-medium-dark: #2d86b4;
$orange-light: rgba(252, 109, 38, 0.80);
$orange-normal: #E75E40;
$orange-dark: #CE5237;
$orange-normal: #e75e40;
$orange-dark: #ce5237;
$red-light: #F06559;
$red-normal: #E52C5A;
$red-dark: #D22852;
$red-light: #f06559;
$red-normal: #e52c5a;
$red-dark: #d22852;
$border-white-light: #F1F2F4;
$border-white-normal: #D6DAE2;
$border-white-dark: #C6CACF;
$border-white-light: #f1f2f4;
$border-white-normal: #d6dae2;
$border-white-dark: #c6cacf;
$border-gray-light: rgba(0, 0, 0, 0.06);
$border-gray-normal: rgba(0, 0, 0, 0.10);;
$border-gray-dark: #C6CACF;
$border-gray-dark: #c6cacf;
$border-green-light: #2FAA60;
$border-green-normal: #2CA05B;
$border-green-light: #2faa60;
$border-green-normal: #2ca05b;
$border-green-dark: #279654;
$border-blue-light: #2D9FD8;
$border-blue-normal: #2897CE;
$border-blue-dark: #258DC1;
$border-blue-light: #2d9fd8;
$border-blue-normal: #2897ce;
$border-blue-dark: #258dc1;
$border-orange-light: #fc6d26;
$border-orange-normal: #CE5237;
$border-orange-dark: #C14E35;
$border-orange-normal: #ce5237;
$border-orange-dark: #c14e35;
$border-red-light: #F24F41;
$border-red-normal: #D22852;
$border-red-dark: #CA264F;
$border-red-light: #f24f41;
$border-red-normal: #d22852;
$border-red-dark: #ca264f;
$help-well-bg: #FAFAFA;
$help-well-border: #E5E5E5;
$help-well-bg: #fafafa;
$help-well-border: #e5e5e5;
$warning-message-bg: #FBF2D9;
$warning-message-color: #9E8E60;
$warning-message-border: #F0E2BB;
$warning-message-bg: #fbf2d9;
$warning-message-color: #9e8e60;
$warning-message-border: #f0e2bb;
/* header */
$light-grey-header: #faf9f9;
......@@ -143,23 +143,22 @@ $dropdown-border-color: rgba(#000, .1);
$dropdown-shadow-color: rgba(#000, .1);
$dropdown-divider-color: rgba(#000, .1);
$dropdown-header-color: #959494;
$dropdown-caret-color: #54565B;
$dropdown-title-btn-color: #BFBFBF;
$dropdown-input-color: #C7C7C7;
$dropdown-title-btn-color: #bfbfbf;
$dropdown-input-color: #c7c7c7;
$dropdown-input-focus-border: rgb(58, 171, 240);
$dropdown-input-focus-shadow: rgba(#000, .2);
$dropdown-loading-bg: rgba(#fff, .6);
$dropdown-toggle-bg: #fff;
$dropdown-toggle-color: #626262;
$dropdown-toggle-border-color: #EAEAEA;
$dropdown-toggle-border-color: #eaeaea;
$dropdown-toggle-hover-border-color: darken($dropdown-toggle-border-color, 15%);
$dropdown-toggle-icon-color: #C4C4C4;
$dropdown-toggle-icon-color: #c4c4c4;
$dropdown-toggle-hover-icon-color: $dropdown-toggle-hover-border-color;
/*
* Award emoji
*/
$award-emoji-menu-bg: #FFF;
$award-emoji-menu-border: #F1F2F4;
$award-emoji-new-btn-icon-color: #DCDCDC;
$award-emoji-menu-bg: #fff;
$award-emoji-menu-border: #f1f2f4;
$award-emoji-new-btn-icon-color: #dcdcdc;
......@@ -2,7 +2,7 @@
a.js-zen-enter {
color: $gl-gray;
position: absolute;
top: 0px;
top: 0;
right: 4px;
line-height: 56px;
}
......
......@@ -43,12 +43,12 @@
// Search result highlight
span.highlight_word {
background-color: #ffe792 !important;
color: #000000 !important;
color: #000 !important;
}
.hll { background-color: #373b41 }
.c { color: #969896 } /* Comment */
.err { color: #cc6666 } /* Error */
.err { color: #c66 } /* Error */
.k { color: #b294bb } /* Keyword */
.l { color: #de935f } /* Literal */
.n { color: #c5c8c6 } /* Name */
......@@ -58,7 +58,7 @@
.cp { color: #969896 } /* Comment.Preproc */
.c1 { color: #969896 } /* Comment.Single */
.cs { color: #969896 } /* Comment.Special */
.gd { color: #cc6666 } /* Generic.Deleted */
.gd { color: #c66 } /* Generic.Deleted */
.ge { font-style: italic } /* Generic.Emph */
.gh { color: #c5c8c6; font-weight: bold } /* Generic.Heading */
.gi { color: #b5bd68 } /* Generic.Inserted */
......@@ -77,17 +77,17 @@
.na { color: #81a2be } /* Name.Attribute */
.nb { color: #c5c8c6 } /* Name.Builtin */
.nc { color: #f0c674 } /* Name.Class */
.no { color: #cc6666 } /* Name.Constant */
.no { color: #c66 } /* Name.Constant */
.nd { color: #8abeb7 } /* Name.Decorator */
.ni { color: #c5c8c6 } /* Name.Entity */
.ne { color: #cc6666 } /* Name.Exception */
.ne { color: #c66 } /* Name.Exception */
.nf { color: #81a2be } /* Name.Function */
.nl { color: #c5c8c6 } /* Name.Label */
.nn { color: #f0c674 } /* Name.Namespace */
.nx { color: #81a2be } /* Name.Other */
.py { color: #c5c8c6 } /* Name.Property */
.nt { color: #8abeb7 } /* Name.Tag */
.nv { color: #cc6666 } /* Name.Variable */
.nv { color: #c66 } /* Name.Variable */
.ow { color: #8abeb7 } /* Operator.Word */
.w { color: #c5c8c6 } /* Text.Whitespace */
.mf { color: #de935f } /* Literal.Number.Float */
......@@ -106,8 +106,8 @@
.s1 { color: #b5bd68 } /* Literal.String.Single */
.ss { color: #b5bd68 } /* Literal.String.Symbol */
.bp { color: #c5c8c6 } /* Name.Builtin.Pseudo */
.vc { color: #cc6666 } /* Name.Variable.Class */
.vg { color: #cc6666 } /* Name.Variable.Global */
.vi { color: #cc6666 } /* Name.Variable.Instance */
.vc { color: #c66 } /* Name.Variable.Class */
.vg { color: #c66 } /* Name.Variable.Global */
.vi { color: #c66 } /* Name.Variable.Instance */
.il { color: #de935f } /* Literal.Number.Integer.Long */
}
......@@ -43,7 +43,7 @@
// Search result highlight
span.highlight_word {
background-color: #ffe792 !important;
color: #000000 !important;
color: #000 !important;
}
.hll { background-color: #49483e }
......
......@@ -96,7 +96,7 @@
.m { color: #2aa198 } /* Literal.Number */
.s { color: #2aa198 } /* Literal.String */
.na { color: #93a1a1 } /* Name.Attribute */
.nb { color: #B58900 } /* Name.Builtin */
.nb { color: #b58900 } /* Name.Builtin */
.nc { color: #268bd2 } /* Name.Class */
.no { color: #cb4b16 } /* Name.Constant */
.nd { color: #268bd2 } /* Name.Decorator */
......
......@@ -96,7 +96,7 @@
.m { color: #2aa198 } /* Literal.Number */
.s { color: #2aa198 } /* Literal.String */
.na { color: #586e75 } /* Name.Attribute */
.nb { color: #B58900 } /* Name.Builtin */
.nb { color: #b58900 } /* Name.Builtin */
.nc { color: #268bd2 } /* Name.Class */
.no { color: #cb4b16 } /* Name.Constant */
.nd { color: #268bd2 } /* Name.Decorator */
......
......@@ -23,7 +23,7 @@
.line_holder {
.diff-line-num {
&.old {
background: #ffdddd;
background: #fdd;
border-color: #f1c0c0;
}
......@@ -68,66 +68,66 @@
}
.hll { background-color: #f8f8f8 }
.c { color: #999988; font-style: italic; }
.c { color: #998; font-style: italic; }
.err { color: #a61717; background-color: #e3d2d2; }
.k { font-weight: bold; }
.o { font-weight: bold; }
.cm { color: #999988; font-style: italic; }
.cp { color: #999999; font-weight: bold; }
.c1 { color: #999988; font-style: italic; }
.cs { color: #999999; font-weight: bold; font-style: italic; }
.gd { color: #000000; background-color: #ffdddd; }
.gd .x { color: #000000; background-color: #ffaaaa; }
.cm { color: #998; font-style: italic; }
.cp { color: #999; font-weight: bold; }
.c1 { color: #998; font-style: italic; }
.cs { color: #999; font-weight: bold; font-style: italic; }
.gd { color: #000; background-color: #fdd; }
.gd .x { color: #000; background-color: #faa; }
.ge { font-style: italic; }
.gr { color: #aa0000; }
.gh { color: #999999; }
.gi { color: #000000; background-color: #ddffdd; }
.gi .x { color: #000000; background-color: #aaffaa; }
.go { color: #888888; }
.gp { color: #555555; }
.gr { color: #a00; }
.gh { color: #999; }
.gi { color: #000; background-color: #dfd; }
.gi .x { color: #000; background-color: #afa; }
.go { color: #888; }
.gp { color: #555; }
.gs { font-weight: bold; }
.gu { color: #800080; font-weight: bold; }
.gt { color: #aa0000; }
.gt { color: #a00; }
.kc { font-weight: bold; }
.kd { font-weight: bold; }
.kn { font-weight: bold; }
.kp { font-weight: bold; }
.kr { font-weight: bold; }
.kt { color: #445588; font-weight: bold; }
.m { color: #009999; }
.s { color: #dd1144; }
.n { color: #333333; }
.kt { color: #458; font-weight: bold; }
.m { color: #099; }
.s { color: #d14; }
.n { color: #333; }
.na { color: teal; }
.nb { color: #0086b3; }
.nc { color: #445588; font-weight: bold; }
.nc { color: #458; font-weight: bold; }
.no { color: teal; }
.ni { color: purple; }
.ne { color: #990000; font-weight: bold; }
.nf { color: #990000; font-weight: bold; }
.nn { color: #555555; }
.ne { color: #900; font-weight: bold; }
.nf { color: #900; font-weight: bold; }
.nn { color: #555; }
.nt { color: navy; }
.nv { color: teal; }
.ow { font-weight: bold; }
.w { color: #bbbbbb; }
.mf { color: #009999; }
.mh { color: #009999; }
.mi { color: #009999; }
.mo { color: #009999; }
.sb { color: #dd1144; }
.sc { color: #dd1144; }
.sd { color: #dd1144; }
.s2 { color: #dd1144; }
.se { color: #dd1144; }
.sh { color: #dd1144; }
.si { color: #dd1144; }
.sx { color: #dd1144; }
.w { color: #bbb; }
.mf { color: #099; }
.mh { color: #099; }
.mi { color: #099; }
.mo { color: #099; }
.sb { color: #d14; }
.sc { color: #d14; }
.sd { color: #d14; }
.s2 { color: #d14; }
.se { color: #d14; }
.sh { color: #d14; }
.si { color: #d14; }
.sx { color: #d14; }
.sr { color: #009926; }
.s1 { color: #dd1144; }
.s1 { color: #d14; }
.ss { color: #990073; }
.bp { color: #999999; }
.bp { color: #999; }
.vc { color: teal; }
.vg { color: teal; }
.vi { color: teal; }
.il { color: #009999; }
.gc { color: #999; background-color: #EAF2F5; }
.il { color: #099; }
.gc { color: #999; background-color: #eaf2f5; }
}
......@@ -4,7 +4,7 @@
}
.appearance-light-logo-preview {
background-color: $background-color;
background-color: $background-color;
max-width: 72px;
padding: 10px;
margin-bottom: 10px;
......
.build-page {
pre.trace {
background: #111111;
background: #111;
color: #fff;
font-family: $monospace_font;
white-space: pre;
......
......@@ -55,7 +55,7 @@
padding: 10px 0;
li {
padding: 3px 0px;
padding: 3px 0;
line-height: 20px;
}
}
......
......@@ -9,7 +9,7 @@
.lists-separator {
margin: 10px 0;
border-color: #DDD;
border-color: #ddd;
}
.commits-row {
......@@ -76,7 +76,7 @@ li.commit {
.commit-row-description {
font-size: 14px;
border-left: 1px solid #EEE;
border-left: 1px solid #eee;
padding: 10px 15px;
margin: 5px 0 10px 5px;
background: #f9f9f9;
......@@ -152,7 +152,7 @@ li.commit {
.count {
padding-top: 6px;
padding-bottom: 0px;
padding-bottom: 0;
font-size: 12px;
color: #333;
display: block;
......
......@@ -11,15 +11,15 @@
}
.dashboard-search-filter {
padding:5px;
padding: 5px;
.search-text-input {
float:left;
float: left;
@extend .col-md-2;
}
.btn {
margin-left: 5px;
float:left;
float: left;
}
}
......
......@@ -29,7 +29,7 @@
.diff-content {
overflow: auto;
overflow-y: hidden;
background: #FFF;
background: #fff;
color: #333;
.unfold {
......@@ -57,8 +57,8 @@
font-family: $monospace_font;
border: none;
border-collapse: separate;
margin: 0px;
padding: 0px;
margin: 0;
padding: 0;
.line_holder td {
line-height: $code_line_height;
font-size: $code_font_size;
......@@ -76,10 +76,10 @@
}
.old_line, .new_line {
margin: 0px;
padding: 0px;
margin: 0;
padding: 0;
border: none;
padding: 0px 5px;
padding: 0 5px;
border-right: 1px solid;
text-align: right;
min-width: 35px;
......@@ -97,8 +97,8 @@
}
.line_content {
display: block;
margin: 0px;
padding: 0px 0.5em;
margin: 0;
padding: 0 0.5em;
border: none;
&.parallel {
display: table-cell;
......@@ -118,7 +118,7 @@
background-color: #fff;
line-height: 0;
img {
border: 1px solid #FFF;
border: 1px solid #fff;
background: image-url('trans_bg.gif');
max-width: 100%;
}
......@@ -183,7 +183,7 @@
height: 14px;
width: 15px;
position: absolute;
top: 0px;
top: 0;
background: image-url('swipemode_sprites.gif') 0 3px no-repeat;
}
.bottom-handle {
......@@ -191,7 +191,7 @@
height: 14px;
width: 15px;
position: absolute;
bottom: 0px;
bottom: 0;
background: image-url('swipemode_sprites.gif') 0 -11px no-repeat;
}
}
......@@ -206,8 +206,8 @@
.frame.added, .frame.deleted {
position: absolute;
display: block;
top: 0px;
left: 0px;
top: 0;
left: 0;
}
.controls {
display: block;
......@@ -215,7 +215,7 @@
width: 300px;
z-index: 100;
position: absolute;
bottom: 0px;
bottom: 0;
left: 50%;
margin-left: -150px;
......@@ -231,11 +231,11 @@
.dragger {
display: block;
position: absolute;
left: 0px;
top: 0px;
left: 0;
top: 0;
height: 14px;
width: 14px;
background: image-url('onion_skin_sprites.gif') 0px -34px repeat-x;
background: image-url('onion_skin_sprites.gif') 0 -34px repeat-x;
cursor: pointer;
}
......@@ -243,17 +243,17 @@
display: block;
position: absolute;
top: 2px;
right: 0px;
right: 0;
height: 10px;
width: 10px;
background: image-url('onion_skin_sprites.gif') -2px 0px no-repeat;
background: image-url('onion_skin_sprites.gif') -2px 0 no-repeat;
}
.opaque {
display: block;
position: absolute;
top: 2px;
left: 0px;
left: 0;
height: 10px;
width: 10px;
background: image-url('onion_skin_sprites.gif') -2px -10px no-repeat;
......@@ -265,7 +265,7 @@
.view-modes {
padding: 10px;
text-align: center;
background: #EEE;
background: #eee;
ul, li {
list-style: none;
......
......@@ -14,9 +14,9 @@
}
.cancel-btn {
color: #B94A48;
color: #b94a48;
&:hover {
color: #B94A48;
color: #b94a48;
}
}
......
.emoji-0023-20E3 { background-position: 0px 0px; }
.emoji-002A-20E3 { background-position: -20px 0px; }
.emoji-0030-20E3 { background-position: 0px -20px; }
.emoji-0023-20E3 { background-position: 0 0; }
.emoji-002A-20E3 { background-position: -20px 0; }
.emoji-0030-20E3 { background-position: 0 -20px; }
.emoji-0031-20E3 { background-position: -20px -20px; }
.emoji-0032-20E3 { background-position: -40px 0px; }
.emoji-0032-20E3 { background-position: -40px 0; }
.emoji-0033-20E3 { background-position: -40px -20px; }
.emoji-0034-20E3 { background-position: 0px -40px; }
.emoji-0034-20E3 { background-position: 0 -40px; }
.emoji-0035-20E3 { background-position: -20px -40px; }
.emoji-0036-20E3 { background-position: -40px -40px; }
.emoji-0037-20E3 { background-position: -60px 0px; }
.emoji-0037-20E3 { background-position: -60px 0; }
.emoji-0038-20E3 { background-position: -60px -20px; }
.emoji-0039-20E3 { background-position: -60px -40px; }
.emoji-00A9 { background-position: 0px -60px; }
.emoji-00A9 { background-position: 0 -60px; }
.emoji-00AE { background-position: -20px -60px; }
.emoji-1F004 { background-position: -40px -60px; }
.emoji-1F0CF { background-position: -60px -60px; }
.emoji-1F170 { background-position: -80px 0px; }
.emoji-1F170 { background-position: -80px 0; }
.emoji-1F171 { background-position: -80px -20px; }
.emoji-1F17E { background-position: -80px -40px; }
.emoji-1F17F { background-position: -80px -60px; }
.emoji-1F18E { background-position: 0px -80px; }
.emoji-1F18E { background-position: 0 -80px; }
.emoji-1F191 { background-position: -20px -80px; }
.emoji-1F192 { background-position: -40px -80px; }
.emoji-1F193 { background-position: -60px -80px; }
.emoji-1F194 { background-position: -80px -80px; }
.emoji-1F195 { background-position: -100px 0px; }
.emoji-1F195 { background-position: -100px 0; }
.emoji-1F196 { background-position: -100px -20px; }
.emoji-1F197 { background-position: -100px -40px; }
.emoji-1F198 { background-position: -100px -60px; }
.emoji-1F199 { background-position: -100px -80px; }
.emoji-1F19A { background-position: 0px -100px; }
.emoji-1F19A { background-position: 0 -100px; }
.emoji-1F1E6-1F1E8 { background-position: -20px -100px; }
.emoji-1F1E6-1F1E9 { background-position: -40px -100px; }
.emoji-1F1E6-1F1EA { background-position: -60px -100px; }
.emoji-1F1E6-1F1EB { background-position: -80px -100px; }
.emoji-1F1E6-1F1EC { background-position: -100px -100px; }
.emoji-1F1E6-1F1EE { background-position: -120px 0px; }
.emoji-1F1E6-1F1EE { background-position: -120px 0; }
.emoji-1F1E6-1F1F1 { background-position: -120px -20px; }
.emoji-1F1E6-1F1F2 { background-position: -120px -40px; }
.emoji-1F1E6-1F1F4 { background-position: -120px -60px; }
.emoji-1F1E6-1F1F6 { background-position: -120px -80px; }
.emoji-1F1E6-1F1F7 { background-position: -120px -100px; }
.emoji-1F1E6-1F1F8 { background-position: 0px -120px; }
.emoji-1F1E6-1F1F8 { background-position: 0 -120px; }
.emoji-1F1E6-1F1F9 { background-position: -20px -120px; }
.emoji-1F1E6-1F1FA { background-position: -40px -120px; }
.emoji-1F1E6-1F1FC { background-position: -60px -120px; }
.emoji-1F1E6-1F1FD { background-position: -80px -120px; }
.emoji-1F1E6-1F1FF { background-position: -100px -120px; }
.emoji-1F1E7-1F1E6 { background-position: -120px -120px; }
.emoji-1F1E7-1F1E7 { background-position: -140px 0px; }
.emoji-1F1E7-1F1E7 { background-position: -140px 0; }
.emoji-1F1E7-1F1E9 { background-position: -140px -20px; }
.emoji-1F1E7-1F1EA { background-position: -140px -40px; }
.emoji-1F1E7-1F1EB { background-position: -140px -60px; }
.emoji-1F1E7-1F1EC { background-position: -140px -80px; }
.emoji-1F1E7-1F1ED { background-position: -140px -100px; }
.emoji-1F1E7-1F1EE { background-position: -140px -120px; }
.emoji-1F1E7-1F1EF { background-position: 0px -140px; }
.emoji-1F1E7-1F1EF { background-position: 0 -140px; }
.emoji-1F1E7-1F1F1 { background-position: -20px -140px; }
.emoji-1F1E7-1F1F2 { background-position: -40px -140px; }
.emoji-1F1E7-1F1F3 { background-position: -60px -140px; }
......@@ -62,7 +62,7 @@
.emoji-1F1E7-1F1F6 { background-position: -100px -140px; }
.emoji-1F1E7-1F1F7 { background-position: -120px -140px; }
.emoji-1F1E7-1F1F8 { background-position: -140px -140px; }
.emoji-1F1E7-1F1F9 { background-position: -160px 0px; }
.emoji-1F1E7-1F1F9 { background-position: -160px 0; }
.emoji-1F1E7-1F1FB { background-position: -160px -20px; }
.emoji-1F1E7-1F1FC { background-position: -160px -40px; }
.emoji-1F1E7-1F1FE { background-position: -160px -60px; }
......@@ -70,7 +70,7 @@
.emoji-1F1E8-1F1E6 { background-position: -160px -100px; }
.emoji-1F1E8-1F1E8 { background-position: -160px -120px; }
.emoji-1F1E8-1F1E9 { background-position: -160px -140px; }
.emoji-1F1E8-1F1EB { background-position: 0px -160px; }
.emoji-1F1E8-1F1EB { background-position: 0 -160px; }
.emoji-1F1E8-1F1EC { background-position: -20px -160px; }
.emoji-1F1E8-1F1ED { background-position: -40px -160px; }
.emoji-1F1E8-1F1EE { background-position: -60px -160px; }
......@@ -79,7 +79,7 @@
.emoji-1F1E8-1F1F2 { background-position: -120px -160px; }
.emoji-1F1E8-1F1F3 { background-position: -140px -160px; }
.emoji-1F1E8-1F1F4 { background-position: -160px -160px; }
.emoji-1F1E8-1F1F5 { background-position: -180px 0px; }
.emoji-1F1E8-1F1F5 { background-position: -180px 0; }
.emoji-1F1E8-1F1F7 { background-position: -180px -20px; }
.emoji-1F1E8-1F1FA { background-position: -180px -40px; }
.emoji-1F1E8-1F1FB { background-position: -180px -60px; }
......@@ -88,7 +88,7 @@
.emoji-1F1E8-1F1FE { background-position: -180px -120px; }
.emoji-1F1E8-1F1FF { background-position: -180px -140px; }
.emoji-1F1E9-1F1EA { background-position: -180px -160px; }
.emoji-1F1E9-1F1EC { background-position: 0px -180px; }
.emoji-1F1E9-1F1EC { background-position: 0 -180px; }
.emoji-1F1E9-1F1EF { background-position: -20px -180px; }
.emoji-1F1E9-1F1F0 { background-position: -40px -180px; }
.emoji-1F1E9-1F1F2 { background-position: -60px -180px; }
......@@ -98,7 +98,7 @@
.emoji-1F1EA-1F1E8 { background-position: -140px -180px; }
.emoji-1F1EA-1F1EA { background-position: -160px -180px; }
.emoji-1F1EA-1F1EC { background-position: -180px -180px; }
.emoji-1F1EA-1F1ED { background-position: -200px 0px; }
.emoji-1F1EA-1F1ED { background-position: -200px 0; }
.emoji-1F1EA-1F1F7 { background-position: -200px -20px; }
.emoji-1F1EA-1F1F8 { background-position: -200px -40px; }
.emoji-1F1EA-1F1F9 { background-position: -200px -60px; }
......@@ -108,7 +108,7 @@
.emoji-1F1EB-1F1F0 { background-position: -200px -140px; }
.emoji-1F1EB-1F1F2 { background-position: -200px -160px; }
.emoji-1F1EB-1F1F4 { background-position: -200px -180px; }
.emoji-1F1EB-1F1F7 { background-position: 0px -200px; }
.emoji-1F1EB-1F1F7 { background-position: 0 -200px; }
.emoji-1F1EC-1F1E6 { background-position: -20px -200px; }
.emoji-1F1EC-1F1E7 { background-position: -40px -200px; }
.emoji-1F1EC-1F1E9 { background-position: -60px -200px; }
......@@ -119,7 +119,7 @@
.emoji-1F1EC-1F1EE { background-position: -160px -200px; }
.emoji-1F1EC-1F1F1 { background-position: -180px -200px; }
.emoji-1F1EC-1F1F2 { background-position: -200px -200px; }
.emoji-1F1EC-1F1F3 { background-position: -220px 0px; }
.emoji-1F1EC-1F1F3 { background-position: -220px 0; }
.emoji-1F1EC-1F1F5 { background-position: -220px -20px; }
.emoji-1F1EC-1F1F6 { background-position: -220px -40px; }
.emoji-1F1EC-1F1F7 { background-position: -220px -60px; }
......@@ -130,7 +130,7 @@
.emoji-1F1EC-1F1FE { background-position: -220px -160px; }
.emoji-1F1ED-1F1F0 { background-position: -220px -180px; }
.emoji-1F1ED-1F1F2 { background-position: -220px -200px; }
.emoji-1F1ED-1F1F3 { background-position: 0px -220px; }
.emoji-1F1ED-1F1F3 { background-position: 0 -220px; }
.emoji-1F1ED-1F1F7 { background-position: -20px -220px; }
.emoji-1F1ED-1F1F9 { background-position: -40px -220px; }
.emoji-1F1ED-1F1FA { background-position: -60px -220px; }
......@@ -142,7 +142,7 @@
.emoji-1F1EE-1F1F3 { background-position: -180px -220px; }
.emoji-1F1EE-1F1F4 { background-position: -200px -220px; }
.emoji-1F1EE-1F1F6 { background-position: -220px -220px; }
.emoji-1F1EE-1F1F7 { background-position: -240px 0px; }
.emoji-1F1EE-1F1F7 { background-position: -240px 0; }
.emoji-1F1EE-1F1F8 { background-position: -240px -20px; }
.emoji-1F1EE-1F1F9 { background-position: -240px -40px; }
.emoji-1F1EF-1F1EA { background-position: -240px -60px; }
......@@ -154,7 +154,7 @@
.emoji-1F1F0-1F1ED { background-position: -240px -180px; }
.emoji-1F1F0-1F1EE { background-position: -240px -200px; }
.emoji-1F1F0-1F1F2 { background-position: -240px -220px; }
.emoji-1F1F0-1F1F3 { background-position: 0px -240px; }
.emoji-1F1F0-1F1F3 { background-position: 0 -240px; }
.emoji-1F1F0-1F1F5 { background-position: -20px -240px; }
.emoji-1F1F0-1F1F7 { background-position: -40px -240px; }
.emoji-1F1F0-1F1FC { background-position: -60px -240px; }
......@@ -167,7 +167,7 @@
.emoji-1F1F1-1F1F0 { background-position: -200px -240px; }
.emoji-1F1F1-1F1F7 { background-position: -220px -240px; }
.emoji-1F1F1-1F1F8 { background-position: -240px -240px; }
.emoji-1F1F1-1F1F9 { background-position: -260px 0px; }
.emoji-1F1F1-1F1F9 { background-position: -260px 0; }
.emoji-1F1F1-1F1FA { background-position: -260px -20px; }
.emoji-1F1F1-1F1FB { background-position: -260px -40px; }
.emoji-1F1F1-1F1FE { background-position: -260px -60px; }
......@@ -180,7 +180,7 @@
.emoji-1F1F2-1F1ED { background-position: -260px -200px; }
.emoji-1F1F2-1F1F0 { background-position: -260px -220px; }
.emoji-1F1F2-1F1F1 { background-position: -260px -240px; }
.emoji-1F1F2-1F1F2 { background-position: 0px -260px; }
.emoji-1F1F2-1F1F2 { background-position: 0 -260px; }
.emoji-1F1F2-1F1F3 { background-position: -20px -260px; }
.emoji-1F1F2-1F1F4 { background-position: -40px -260px; }
.emoji-1F1F2-1F1F5 { background-position: -60px -260px; }
......@@ -194,7 +194,7 @@
.emoji-1F1F2-1F1FD { background-position: -220px -260px; }
.emoji-1F1F2-1F1FE { background-position: -240px -260px; }
.emoji-1F1F2-1F1FF { background-position: -260px -260px; }
.emoji-1F1F3-1F1E6 { background-position: -280px 0px; }
.emoji-1F1F3-1F1E6 { background-position: -280px 0; }
.emoji-1F1F3-1F1E8 { background-position: -280px -20px; }
.emoji-1F1F3-1F1EA { background-position: -280px -40px; }
.emoji-1F1F3-1F1EB { background-position: -280px -60px; }
......@@ -208,7 +208,7 @@
.emoji-1F1F3-1F1FF { background-position: -280px -220px; }
.emoji-1F1F4-1F1F2 { background-position: -280px -240px; }
.emoji-1F1F5-1F1E6 { background-position: -280px -260px; }
.emoji-1F1F5-1F1EA { background-position: 0px -280px; }
.emoji-1F1F5-1F1EA { background-position: 0 -280px; }
.emoji-1F1F5-1F1EB { background-position: -20px -280px; }
.emoji-1F1F5-1F1EC { background-position: -40px -280px; }
.emoji-1F1F5-1F1ED { background-position: -60px -280px; }
......@@ -223,7 +223,7 @@
.emoji-1F1F5-1F1FE { background-position: -240px -280px; }
.emoji-1F1F6-1F1E6 { background-position: -260px -280px; }
.emoji-1F1F7-1F1EA { background-position: -280px -280px; }
.emoji-1F1F7-1F1F4 { background-position: -300px 0px; }
.emoji-1F1F7-1F1F4 { background-position: -300px 0; }
.emoji-1F1F7-1F1F8 { background-position: -300px -20px; }
.emoji-1F1F7-1F1FA { background-position: -300px -40px; }
.emoji-1F1F7-1F1FC { background-position: -300px -60px; }
......@@ -238,7 +238,7 @@
.emoji-1F1F8-1F1EF { background-position: -300px -240px; }
.emoji-1F1F8-1F1F0 { background-position: -300px -260px; }
.emoji-1F1F8-1F1F1 { background-position: -300px -280px; }
.emoji-1F1F8-1F1F2 { background-position: 0px -300px; }
.emoji-1F1F8-1F1F2 { background-position: 0 -300px; }
.emoji-1F1F8-1F1F3 { background-position: -20px -300px; }
.emoji-1F1F8-1F1F4 { background-position: -40px -300px; }
.emoji-1F1F8-1F1F7 { background-position: -60px -300px; }
......@@ -254,7 +254,7 @@
.emoji-1F1F9-1F1EB { background-position: -260px -300px; }
.emoji-1F1F9-1F1EC { background-position: -280px -300px; }
.emoji-1F1F9-1F1ED { background-position: -300px -300px; }
.emoji-1F1F9-1F1EF { background-position: -320px 0px; }
.emoji-1F1F9-1F1EF { background-position: -320px 0; }
.emoji-1F1F9-1F1F0 { background-position: -320px -20px; }
.emoji-1F1F9-1F1F1 { background-position: -320px -40px; }
.emoji-1F1F9-1F1F2 { background-position: -320px -60px; }
......@@ -270,7 +270,7 @@
.emoji-1F1FA-1F1F2 { background-position: -320px -260px; }
.emoji-1F1FA-1F1F8 { background-position: -320px -280px; }
.emoji-1F1FA-1F1FE { background-position: -320px -300px; }
.emoji-1F1FA-1F1FF { background-position: 0px -320px; }
.emoji-1F1FA-1F1FF { background-position: 0 -320px; }
.emoji-1F1FB-1F1E6 { background-position: -20px -320px; }
.emoji-1F1FB-1F1E8 { background-position: -40px -320px; }
.emoji-1F1FB-1F1EA { background-position: -60px -320px; }
......@@ -287,7 +287,7 @@
.emoji-1F1FF-1F1F2 { background-position: -280px -320px; }
.emoji-1F1FF-1F1FC { background-position: -300px -320px; }
.emoji-1F201 { background-position: -320px -320px; }
.emoji-1F202 { background-position: -340px 0px; }
.emoji-1F202 { background-position: -340px 0; }
.emoji-1F21A { background-position: -340px -20px; }
.emoji-1F22F { background-position: -340px -40px; }
.emoji-1F232 { background-position: -340px -60px; }
......@@ -304,7 +304,7 @@
.emoji-1F300 { background-position: -340px -280px; }
.emoji-1F301 { background-position: -340px -300px; }
.emoji-1F302 { background-position: -340px -320px; }
.emoji-1F303 { background-position: 0px -340px; }
.emoji-1F303 { background-position: 0 -340px; }
.emoji-1F304 { background-position: -20px -340px; }
.emoji-1F305 { background-position: -40px -340px; }
.emoji-1F306 { background-position: -60px -340px; }
......@@ -322,7 +322,7 @@
.emoji-1F312 { background-position: -300px -340px; }
.emoji-1F313 { background-position: -320px -340px; }
.emoji-1F314 { background-position: -340px -340px; }
.emoji-1F315 { background-position: -360px 0px; }
.emoji-1F315 { background-position: -360px 0; }
.emoji-1F316 { background-position: -360px -20px; }
.emoji-1F317 { background-position: -360px -40px; }
.emoji-1F318 { background-position: -360px -60px; }
......@@ -340,7 +340,7 @@
.emoji-1F326 { background-position: -360px -300px; }
.emoji-1F327 { background-position: -360px -320px; }
.emoji-1F328 { background-position: -360px -340px; }
.emoji-1F329 { background-position: 0px -360px; }
.emoji-1F329 { background-position: 0 -360px; }
.emoji-1F32A { background-position: -20px -360px; }
.emoji-1F32B { background-position: -40px -360px; }
.emoji-1F32C { background-position: -60px -360px; }
......@@ -359,7 +359,7 @@
.emoji-1F339 { background-position: -320px -360px; }
.emoji-1F33A { background-position: -340px -360px; }
.emoji-1F33B { background-position: -360px -360px; }
.emoji-1F33C { background-position: -380px 0px; }
.emoji-1F33C { background-position: -380px 0; }
.emoji-1F33D { background-position: -380px -20px; }
.emoji-1F33E { background-position: -380px -40px; }
.emoji-1F33F { background-position: -380px -60px; }
......@@ -378,7 +378,7 @@
.emoji-1F34C { background-position: -380px -320px; }
.emoji-1F34D { background-position: -380px -340px; }
.emoji-1F34E { background-position: -380px -360px; }
.emoji-1F34F { background-position: 0px -380px; }
.emoji-1F34F { background-position: 0 -380px; }
.emoji-1F350 { background-position: -20px -380px; }
.emoji-1F351 { background-position: -40px -380px; }
.emoji-1F352 { background-position: -60px -380px; }
......@@ -398,7 +398,7 @@
.emoji-1F360 { background-position: -340px -380px; }
.emoji-1F361 { background-position: -360px -380px; }
.emoji-1F362 { background-position: -380px -380px; }
.emoji-1F363 { background-position: -400px 0px; }
.emoji-1F363 { background-position: -400px 0; }
.emoji-1F364 { background-position: -400px -20px; }
.emoji-1F365 { background-position: -400px -40px; }
.emoji-1F366 { background-position: -400px -60px; }
......@@ -418,7 +418,7 @@
.emoji-1F374 { background-position: -400px -340px; }
.emoji-1F375 { background-position: -400px -360px; }
.emoji-1F376 { background-position: -400px -380px; }
.emoji-1F377 { background-position: 0px -400px; }
.emoji-1F377 { background-position: 0 -400px; }
.emoji-1F378 { background-position: -20px -400px; }
.emoji-1F379 { background-position: -40px -400px; }
.emoji-1F37A { background-position: -60px -400px; }
......@@ -439,7 +439,7 @@
.emoji-1F385-1F3FE { background-position: -360px -400px; }
.emoji-1F385-1F3FF { background-position: -380px -400px; }
.emoji-1F386 { background-position: -400px -400px; }
.emoji-1F387 { background-position: -420px 0px; }
.emoji-1F387 { background-position: -420px 0; }
.emoji-1F388 { background-position: -420px -20px; }
.emoji-1F389 { background-position: -420px -40px; }
.emoji-1F38A { background-position: -420px -60px; }
......@@ -460,7 +460,7 @@
.emoji-1F399 { background-position: -420px -360px; }
.emoji-1F39A { background-position: -420px -380px; }
.emoji-1F39B { background-position: -420px -400px; }
.emoji-1F39C { background-position: 0px -420px; }
.emoji-1F39C { background-position: 0 -420px; }
.emoji-1F39D { background-position: -20px -420px; }
.emoji-1F39E { background-position: -40px -420px; }
.emoji-1F39F { background-position: -60px -420px; }
......@@ -482,7 +482,7 @@
.emoji-1F3AF { background-position: -380px -420px; }
.emoji-1F3B0 { background-position: -400px -420px; }
.emoji-1F3B1 { background-position: -420px -420px; }
.emoji-1F3B2 { background-position: -440px 0px; }
.emoji-1F3B2 { background-position: -440px 0; }
.emoji-1F3B3 { background-position: -440px -20px; }
.emoji-1F3B4 { background-position: -440px -40px; }
.emoji-1F3B5 { background-position: -440px -60px; }
......@@ -504,7 +504,7 @@
.emoji-1F3C3-1F3FC { background-position: -440px -380px; }
.emoji-1F3C3-1F3FD { background-position: -440px -400px; }
.emoji-1F3C3-1F3FE { background-position: -440px -420px; }
.emoji-1F3C3-1F3FF { background-position: 0px -440px; }
.emoji-1F3C3-1F3FF { background-position: 0 -440px; }
.emoji-1F3C4 { background-position: -20px -440px; }
.emoji-1F3C4-1F3FB { background-position: -40px -440px; }
.emoji-1F3C4-1F3FC { background-position: -60px -440px; }
......@@ -527,7 +527,7 @@
.emoji-1F3CA-1F3FD { background-position: -400px -440px; }
.emoji-1F3CA-1F3FE { background-position: -420px -440px; }
.emoji-1F3CA-1F3FF { background-position: -440px -440px; }
.emoji-1F3CB { background-position: -460px 0px; }
.emoji-1F3CB { background-position: -460px 0; }
.emoji-1F3CB-1F3FB { background-position: -460px -20px; }
.emoji-1F3CB-1F3FC { background-position: -460px -40px; }
.emoji-1F3CB-1F3FD { background-position: -460px -60px; }
......@@ -550,7 +550,7 @@
.emoji-1F3DA { background-position: -460px -400px; }
.emoji-1F3DB { background-position: -460px -420px; }
.emoji-1F3DC { background-position: -460px -440px; }
.emoji-1F3DD { background-position: 0px -460px; }
.emoji-1F3DD { background-position: 0 -460px; }
.emoji-1F3DE { background-position: -20px -460px; }
.emoji-1F3DF { background-position: -40px -460px; }
.emoji-1F3E0 { background-position: -60px -460px; }
......@@ -574,7 +574,7 @@
.emoji-1F3F2 { background-position: -420px -460px; }
.emoji-1F3F3 { background-position: -440px -460px; }
.emoji-1F3F4 { background-position: -460px -460px; }
.emoji-1F3F5 { background-position: -480px 0px; }
.emoji-1F3F5 { background-position: -480px 0; }
.emoji-1F3F6 { background-position: -480px -20px; }
.emoji-1F3F7 { background-position: -480px -40px; }
.emoji-1F3F8 { background-position: -480px -60px; }
......@@ -598,7 +598,7 @@
.emoji-1F40A { background-position: -480px -420px; }
.emoji-1F40B { background-position: -480px -440px; }
.emoji-1F40C { background-position: -480px -460px; }
.emoji-1F40D { background-position: 0px -480px; }
.emoji-1F40D { background-position: 0 -480px; }
.emoji-1F40E { background-position: -20px -480px; }
.emoji-1F40F { background-position: -40px -480px; }
.emoji-1F410 { background-position: -60px -480px; }
......@@ -623,7 +623,7 @@
.emoji-1F423 { background-position: -440px -480px; }
.emoji-1F424 { background-position: -460px -480px; }
.emoji-1F425 { background-position: -480px -480px; }
.emoji-1F426 { background-position: -500px 0px; }
.emoji-1F426 { background-position: -500px 0; }
.emoji-1F427 { background-position: -500px -20px; }
.emoji-1F428 { background-position: -500px -40px; }
.emoji-1F429 { background-position: -500px -60px; }
......@@ -648,7 +648,7 @@
.emoji-1F43C { background-position: -500px -440px; }
.emoji-1F43D { background-position: -500px -460px; }
.emoji-1F43E { background-position: -500px -480px; }
.emoji-1F43F { background-position: 0px -500px; }
.emoji-1F43F { background-position: 0 -500px; }
.emoji-1F440 { background-position: -20px -500px; }
.emoji-1F441 { background-position: -40px -500px; }
.emoji-1F441-1F5E8 { background-position: -60px -500px; }
......@@ -674,7 +674,7 @@
.emoji-1F446-1F3FF { background-position: -460px -500px; }
.emoji-1F447 { background-position: -480px -500px; }
.emoji-1F447-1F3FB { background-position: -500px -500px; }
.emoji-1F447-1F3FC { background-position: -520px 0px; }
.emoji-1F447-1F3FC { background-position: -520px 0; }
.emoji-1F447-1F3FD { background-position: -520px -20px; }
.emoji-1F447-1F3FE { background-position: -520px -40px; }
.emoji-1F447-1F3FF { background-position: -520px -60px; }
......@@ -700,7 +700,7 @@
.emoji-1F44B-1F3FB { background-position: -520px -460px; }
.emoji-1F44B-1F3FC { background-position: -520px -480px; }
.emoji-1F44B-1F3FD { background-position: -520px -500px; }
.emoji-1F44B-1F3FE { background-position: 0px -520px; }
.emoji-1F44B-1F3FE { background-position: 0 -520px; }
.emoji-1F44B-1F3FF { background-position: -20px -520px; }
.emoji-1F44C { background-position: -40px -520px; }
.emoji-1F44C-1F3FB { background-position: -60px -520px; }
......@@ -727,7 +727,7 @@
.emoji-1F44F-1F3FE { background-position: -480px -520px; }
.emoji-1F44F-1F3FF { background-position: -500px -520px; }
.emoji-1F450 { background-position: -520px -520px; }
.emoji-1F450-1F3FB { background-position: -540px 0px; }
.emoji-1F450-1F3FB { background-position: -540px 0; }
.emoji-1F450-1F3FC { background-position: -540px -20px; }
.emoji-1F450-1F3FD { background-position: -540px -40px; }
.emoji-1F450-1F3FE { background-position: -540px -60px; }
......@@ -754,7 +754,7 @@
.emoji-1F464 { background-position: -540px -480px; }
.emoji-1F465 { background-position: -540px -500px; }
.emoji-1F466 { background-position: -540px -520px; }
.emoji-1F466-1F3FB { background-position: 0px -540px; }
.emoji-1F466-1F3FB { background-position: 0 -540px; }
.emoji-1F466-1F3FC { background-position: -20px -540px; }
.emoji-1F466-1F3FD { background-position: -40px -540px; }
.emoji-1F466-1F3FE { background-position: -60px -540px; }
......@@ -782,7 +782,7 @@
.emoji-1F468-1F469-1F467-1F467 { background-position: -500px -540px; }
.emoji-1F468-2764-1F468 { background-position: -520px -540px; }
.emoji-1F468-2764-1F48B-1F468 { background-position: -540px -540px; }
.emoji-1F469 { background-position: -560px 0px; }
.emoji-1F469 { background-position: -560px 0; }
.emoji-1F469-1F3FB { background-position: -560px -20px; }
.emoji-1F469-1F3FC { background-position: -560px -40px; }
.emoji-1F469-1F3FD { background-position: -560px -60px; }
......@@ -810,7 +810,7 @@
.emoji-1F470-1F3FB { background-position: -560px -500px; }
.emoji-1F470-1F3FC { background-position: -560px -520px; }
.emoji-1F470-1F3FD { background-position: -560px -540px; }
.emoji-1F470-1F3FE { background-position: 0px -560px; }
.emoji-1F470-1F3FE { background-position: 0 -560px; }
.emoji-1F470-1F3FF { background-position: -20px -560px; }
.emoji-1F471 { background-position: -40px -560px; }
.emoji-1F471-1F3FB { background-position: -60px -560px; }
......@@ -839,7 +839,7 @@
.emoji-1F475 { background-position: -520px -560px; }
.emoji-1F475-1F3FB { background-position: -540px -560px; }
.emoji-1F475-1F3FC { background-position: -560px -560px; }
.emoji-1F475-1F3FD { background-position: -580px 0px; }
.emoji-1F475-1F3FD { background-position: -580px 0; }
.emoji-1F475-1F3FE { background-position: -580px -20px; }
.emoji-1F475-1F3FF { background-position: -580px -40px; }
.emoji-1F476 { background-position: -580px -60px; }
......@@ -868,7 +868,7 @@
.emoji-1F47C-1F3FC { background-position: -580px -520px; }
.emoji-1F47C-1F3FD { background-position: -580px -540px; }
.emoji-1F47C-1F3FE { background-position: -580px -560px; }
.emoji-1F47C-1F3FF { background-position: 0px -580px; }
.emoji-1F47C-1F3FF { background-position: 0 -580px; }
.emoji-1F47D { background-position: -20px -580px; }
.emoji-1F47E { background-position: -40px -580px; }
.emoji-1F47F { background-position: -60px -580px; }
......@@ -898,7 +898,7 @@
.emoji-1F485-1F3FD { background-position: -540px -580px; }
.emoji-1F485-1F3FE { background-position: -560px -580px; }
.emoji-1F485-1F3FF { background-position: -580px -580px; }
.emoji-1F486 { background-position: -600px 0px; }
.emoji-1F486 { background-position: -600px 0; }
.emoji-1F486-1F3FB { background-position: -600px -20px; }
.emoji-1F486-1F3FC { background-position: -600px -40px; }
.emoji-1F486-1F3FD { background-position: -600px -60px; }
......@@ -928,7 +928,7 @@
.emoji-1F497 { background-position: -600px -540px; }
.emoji-1F498 { background-position: -600px -560px; }
.emoji-1F499 { background-position: -600px -580px; }
.emoji-1F49A { background-position: 0px -600px; }
.emoji-1F49A { background-position: 0 -600px; }
.emoji-1F49B { background-position: -20px -600px; }
.emoji-1F49C { background-position: -40px -600px; }
.emoji-1F49D { background-position: -60px -600px; }
......@@ -959,7 +959,7 @@
.emoji-1F4B1 { background-position: -560px -600px; }
.emoji-1F4B2 { background-position: -580px -600px; }
.emoji-1F4B3 { background-position: -600px -600px; }
.emoji-1F4B4 { background-position: -620px 0px; }
.emoji-1F4B4 { background-position: -620px 0; }
.emoji-1F4B5 { background-position: -620px -20px; }
.emoji-1F4B6 { background-position: -620px -40px; }
.emoji-1F4B7 { background-position: -620px -60px; }
......@@ -990,7 +990,7 @@
.emoji-1F4D0 { background-position: -620px -560px; }
.emoji-1F4D1 { background-position: -620px -580px; }
.emoji-1F4D2 { background-position: -620px -600px; }
.emoji-1F4D3 { background-position: 0px -620px; }
.emoji-1F4D3 { background-position: 0 -620px; }
.emoji-1F4D4 { background-position: -20px -620px; }
.emoji-1F4D5 { background-position: -40px -620px; }
.emoji-1F4D6 { background-position: -60px -620px; }
......@@ -1022,7 +1022,7 @@
.emoji-1F4F0 { background-position: -580px -620px; }
.emoji-1F4F1 { background-position: -600px -620px; }
.emoji-1F4F2 { background-position: -620px -620px; }
.emoji-1F4F3 { background-position: -640px 0px; }
.emoji-1F4F3 { background-position: -640px 0; }
.emoji-1F4F4 { background-position: -640px -20px; }
.emoji-1F4F5 { background-position: -640px -40px; }
.emoji-1F4F6 { background-position: -640px -60px; }
......@@ -1054,7 +1054,7 @@
.emoji-1F510 { background-position: -640px -580px; }
.emoji-1F511 { background-position: -640px -600px; }
.emoji-1F512 { background-position: -640px -620px; }
.emoji-1F513 { background-position: 0px -640px; }
.emoji-1F513 { background-position: 0 -640px; }
.emoji-1F514 { background-position: -20px -640px; }
.emoji-1F515 { background-position: -40px -640px; }
.emoji-1F516 { background-position: -60px -640px; }
......@@ -1087,7 +1087,7 @@
.emoji-1F531 { background-position: -600px -640px; }
.emoji-1F532 { background-position: -620px -640px; }
.emoji-1F533 { background-position: -640px -640px; }
.emoji-1F534 { background-position: -660px 0px; }
.emoji-1F534 { background-position: -660px 0; }
.emoji-1F535 { background-position: -660px -20px; }
.emoji-1F536 { background-position: -660px -40px; }
.emoji-1F537 { background-position: -660px -60px; }
......@@ -1120,7 +1120,7 @@
.emoji-1F55B { background-position: -660px -600px; }
.emoji-1F55C { background-position: -660px -620px; }
.emoji-1F55D { background-position: -660px -640px; }
.emoji-1F55E { background-position: 0px -660px; }
.emoji-1F55E { background-position: 0 -660px; }
.emoji-1F55F { background-position: -20px -660px; }
.emoji-1F560 { background-position: -40px -660px; }
.emoji-1F561 { background-position: -60px -660px; }
......@@ -1154,7 +1154,7 @@
.emoji-1F578 { background-position: -620px -660px; }
.emoji-1F579 { background-position: -640px -660px; }
.emoji-1F57B { background-position: -660px -660px; }
.emoji-1F57E { background-position: -680px 0px; }
.emoji-1F57E { background-position: -680px 0; }
.emoji-1F57F { background-position: -680px -20px; }
.emoji-1F581 { background-position: -680px -40px; }
.emoji-1F582 { background-position: -680px -60px; }
......@@ -1188,7 +1188,7 @@
.emoji-1F595-1F3FF { background-position: -680px -620px; }
.emoji-1F596 { background-position: -680px -640px; }
.emoji-1F596-1F3FB { background-position: -680px -660px; }
.emoji-1F596-1F3FC { background-position: 0px -680px; }
.emoji-1F596-1F3FC { background-position: 0 -680px; }
.emoji-1F596-1F3FD { background-position: -20px -680px; }
.emoji-1F596-1F3FE { background-position: -40px -680px; }
.emoji-1F596-1F3FF { background-position: -60px -680px; }
......@@ -1223,7 +1223,7 @@
.emoji-1F5C4 { background-position: -640px -680px; }
.emoji-1F5C6 { background-position: -660px -680px; }
.emoji-1F5C7 { background-position: -680px -680px; }
.emoji-1F5C9 { background-position: -700px 0px; }
.emoji-1F5C9 { background-position: -700px 0; }
.emoji-1F5CA { background-position: -700px -20px; }
.emoji-1F5CE { background-position: -700px -40px; }
.emoji-1F5CF { background-position: -700px -60px; }
......@@ -1258,7 +1258,7 @@
.emoji-1F5F8 { background-position: -700px -640px; }
.emoji-1F5F9 { background-position: -700px -660px; }
.emoji-1F5FA { background-position: -700px -680px; }
.emoji-1F5FB { background-position: 0px -700px; }
.emoji-1F5FB { background-position: 0 -700px; }
.emoji-1F5FC { background-position: -20px -700px; }
.emoji-1F5FD { background-position: -40px -700px; }
.emoji-1F5FE { background-position: -60px -700px; }
......@@ -1294,7 +1294,7 @@
.emoji-1F61C { background-position: -660px -700px; }
.emoji-1F61D { background-position: -680px -700px; }
.emoji-1F61E { background-position: -700px -700px; }
.emoji-1F61F { background-position: -720px 0px; }
.emoji-1F61F { background-position: -720px 0; }
.emoji-1F620 { background-position: -720px -20px; }
.emoji-1F621 { background-position: -720px -40px; }
.emoji-1F622 { background-position: -720px -60px; }
......@@ -1330,7 +1330,7 @@
.emoji-1F640 { background-position: -720px -660px; }
.emoji-1F641 { background-position: -720px -680px; }
.emoji-1F642 { background-position: -720px -700px; }
.emoji-1F643 { background-position: 0px -720px; }
.emoji-1F643 { background-position: 0 -720px; }
.emoji-1F644 { background-position: -20px -720px; }
.emoji-1F645 { background-position: -40px -720px; }
.emoji-1F645-1F3FB { background-position: -60px -720px; }
......@@ -1367,7 +1367,7 @@
.emoji-1F64C-1F3FF { background-position: -680px -720px; }
.emoji-1F64D { background-position: -700px -720px; }
.emoji-1F64D-1F3FB { background-position: -720px -720px; }
.emoji-1F64D-1F3FC { background-position: -740px 0px; }
.emoji-1F64D-1F3FC { background-position: -740px 0; }
.emoji-1F64D-1F3FD { background-position: -740px -20px; }
.emoji-1F64D-1F3FE { background-position: -740px -40px; }
.emoji-1F64D-1F3FF { background-position: -740px -60px; }
......@@ -1404,7 +1404,7 @@
.emoji-1F692 { background-position: -740px -680px; }
.emoji-1F693 { background-position: -740px -700px; }
.emoji-1F694 { background-position: -740px -720px; }
.emoji-1F695 { background-position: 0px -740px; }
.emoji-1F695 { background-position: 0 -740px; }
.emoji-1F696 { background-position: -20px -740px; }
.emoji-1F697 { background-position: -40px -740px; }
.emoji-1F698 { background-position: -60px -740px; }
......@@ -1442,7 +1442,7 @@
.emoji-1F6B3 { background-position: -700px -740px; }
.emoji-1F6B4 { background-position: -720px -740px; }
.emoji-1F6B4-1F3FB { background-position: -740px -740px; }
.emoji-1F6B4-1F3FC { background-position: -760px 0px; }
.emoji-1F6B4-1F3FC { background-position: -760px 0; }
.emoji-1F6B4-1F3FD { background-position: -760px -20px; }
.emoji-1F6B4-1F3FE { background-position: -760px -40px; }
.emoji-1F6B4-1F3FF { background-position: -760px -60px; }
......@@ -1480,7 +1480,7 @@
.emoji-1F6C5 { background-position: -760px -700px; }
.emoji-1F6C6 { background-position: -760px -720px; }
.emoji-1F6C7 { background-position: -760px -740px; }
.emoji-1F6C8 { background-position: 0px -760px; }
.emoji-1F6C8 { background-position: 0 -760px; }
.emoji-1F6C9 { background-position: -20px -760px; }
.emoji-1F6CA { background-position: -40px -760px; }
.emoji-1F6CB { background-position: -60px -760px; }
......@@ -1519,7 +1519,7 @@
.emoji-1F918-1F3FC { background-position: -720px -760px; }
.emoji-1F918-1F3FD { background-position: -740px -760px; }
.emoji-1F918-1F3FE { background-position: -760px -760px; }
.emoji-1F918-1F3FF { background-position: -780px 0px; }
.emoji-1F918-1F3FF { background-position: -780px 0; }
.emoji-1F980 { background-position: -780px -20px; }
.emoji-1F981 { background-position: -780px -40px; }
.emoji-1F982 { background-position: -780px -60px; }
......@@ -1558,7 +1558,7 @@
.emoji-24C2 { background-position: -780px -720px; }
.emoji-25AA { background-position: -780px -740px; }
.emoji-25AB { background-position: -780px -760px; }
.emoji-25B6 { background-position: 0px -780px; }
.emoji-25B6 { background-position: 0 -780px; }
.emoji-25C0 { background-position: -20px -780px; }
.emoji-25FB { background-position: -40px -780px; }
.emoji-25FC { background-position: -60px -780px; }
......@@ -1598,7 +1598,7 @@
.emoji-264D { background-position: -740px -780px; }
.emoji-264E { background-position: -760px -780px; }
.emoji-264F { background-position: -780px -780px; }
.emoji-2650 { background-position: -800px 0px; }
.emoji-2650 { background-position: -800px 0; }
.emoji-2651 { background-position: -800px -20px; }
.emoji-2652 { background-position: -800px -40px; }
.emoji-2653 { background-position: -800px -60px; }
......@@ -1638,7 +1638,7 @@
.emoji-26F0 { background-position: -800px -740px; }
.emoji-26F1 { background-position: -800px -760px; }
.emoji-26F2 { background-position: -800px -780px; }
.emoji-26F3 { background-position: 0px -800px; }
.emoji-26F3 { background-position: 0 -800px; }
.emoji-26F4 { background-position: -20px -800px; }
.emoji-26F5 { background-position: -40px -800px; }
.emoji-26F7 { background-position: -60px -800px; }
......@@ -1679,7 +1679,7 @@
.emoji-270D-1F3FD { background-position: -760px -800px; }
.emoji-270D-1F3FE { background-position: -780px -800px; }
.emoji-270D-1F3FF { background-position: -800px -800px; }
.emoji-270F { background-position: -820px 0px; }
.emoji-270F { background-position: -820px 0; }
.emoji-2712 { background-position: -820px -20px; }
.emoji-2714 { background-position: -820px -40px; }
.emoji-2716 { background-position: -820px -60px; }
......
......@@ -63,7 +63,7 @@
.note-image-attach {
margin-top: 4px;
margin-left: 0px;
margin-left: 0;
max-width: 200px;
float: none;
}
......@@ -83,10 +83,10 @@
.event_icon {
position: relative;
float: right;
border: 1px solid #EEE;
border: 1px solid #eee;
padding: 5px;
@include border-radius(5px);
background: #F9F9F9;
background: #f9f9f9;
margin-left: 10px;
top: -6px;
img {
......@@ -94,7 +94,7 @@
}
}
&:last-child { border:none }
&:last-child { border: none }
.event_commits {
li {
......@@ -138,7 +138,7 @@
@include str-truncated(100%);
padding: 5px 0;
font-size: 13px;
float:left;
float: left;
margin-right: -150px;
padding-right: 150px;
line-height: 20px;
......@@ -160,7 +160,7 @@
.event-body {
margin: 0;
border-left: 2px solid #DDD;
border-left: 2px solid #ddd;
padding-left: 10px;
}
......
......@@ -6,11 +6,11 @@
font-size: 14px;
padding: 5px;
border-bottom: 1px solid $border-color;
background: #EEE;
background: #eee;
}
.network-graph {
background: #FFF;
background: #fff;
height: 500px;
overflow-y: scroll;
overflow-x: hidden;
......
i.icon-gitorious {
display: inline-block;
background-position: 0px 0px;
background-position: 0 0;
background-size: contain;
background-repeat: no-repeat;
}
......
......@@ -59,7 +59,7 @@
.issuable-sidebar {
.block {
@include clearfix;
padding: $gl-padding 0;
padding: $gl-padding 0;
border-bottom: 1px solid $border-gray-light;
// This prevents the mess when resizing the sidebar
// of elements repositioning themselves..
......@@ -222,7 +222,7 @@
width: 100%;
text-align: center;
padding-bottom: 10px;
color: #999999;
color: #999;
span {
display: block;
......@@ -237,7 +237,7 @@
}
i {
color: #999999;
color: #999;
}
}
}
......
......@@ -49,7 +49,7 @@ form.edit-issue {
margin: 0;
}
.merge-requests-title {
.merge-requests-title, .related-branches-title {
font-size: 16px;
font-weight: 600;
}
......@@ -68,18 +68,18 @@ form.edit-issue {
.merge-request,
.issue {
&.today {
background: #EFE;
border-color: #CEC;
background: #efe;
border-color: #cec;
}
&.closed {
background: #F9F9F9;
border-color: #E5E5E5;
background: #f9f9f9;
border-color: #e5e5e5;
}
&.merged {
background: #F9F9F9;
border-color: #E5E5E5;
background: #f9f9f9;
border-color: #e5e5e5;
}
}
......
......@@ -28,7 +28,7 @@
img {
max-width: 100%;
margin-bottom: 30px;
margin-bottom: 30px;
}
a {
......@@ -39,7 +39,7 @@
.login-box{
background: #fafafa;
border-radius: 10px;
box-shadow: 0 0px 2px #CCC;
box-shadow: 0 0 2px #ccc;
padding: 15px;
.login-heading h3 {
......@@ -74,7 +74,7 @@
&.top {
@include border-radius(5px 5px 0 0);
margin-bottom: 0px;
margin-bottom: 0;
}
&.bottom {
......@@ -85,12 +85,12 @@
&.middle {
border-top: 0;
margin-bottom:0px;
margin-bottom: 0;
@include border-radius(0);
}
&:active, &:focus {
background-color: #FFF;
background-color: #fff;
}
}
......
......@@ -113,7 +113,7 @@
}
.mr-widget-footer {
border-top: 1px solid #EEE;
border-top: 1px solid #eee;
}
.ci-coverage {
......@@ -222,7 +222,7 @@
margin-bottom: 20px;
span {
color: #B2B2B2;
color: #b2b2b2;
a {
color: $md-link-color;
......
......@@ -156,7 +156,7 @@
.comment-hints {
color: #999;
background: #FFF;
background: #fff;
padding: 7px;
margin-top: -7px;
border: 1px solid $border-color;
......
......@@ -3,16 +3,16 @@
*/
@-webkit-keyframes targe3-note {
from { background:#fffff0; }
50% { background:#ffffd3; }
to { background:#fffff0; }
from { background: #fffff0; }
50% { background: #ffffd3; }
to { background: #fffff0; }
}
ul.notes {
display: block;
list-style: none;
margin: 0px;
padding: 0px;
margin: 0;
padding: 0;
.timeline-icon {
float: left;
......@@ -30,7 +30,7 @@ ul.notes {
font-size: 14px;
padding-top: 10px;
padding-bottom: 10px;
background: #FDFDFD;
background: #fdfdfd;
.timeline-icon {
.avatar {
......@@ -93,12 +93,12 @@ ul.notes {
.discussion {
overflow: hidden;
display: block;
position:relative;
position: relative;
}
.note {
display: block;
position:relative;
position: relative;
.note-body {
overflow: auto;
......@@ -108,6 +108,13 @@ ul.notes {
word-wrap: break-word;
@include md-typography;
// On diffs code should wrap nicely and not overflow
pre {
code {
white-space: pre-wrap;
}
}
// Reset ul style types since we're nested inside a ul already
& > ul {
list-style-type: disc;
......@@ -129,7 +136,7 @@ ul.notes {
hr {
// Darken 'whitesmoke' a bit to make it more visible in note bodies
border-color: darken(#F5F5F5, 8%);
border-color: darken(#f5f5f5, 8%);
margin: 10px 0;
}
}
......@@ -166,7 +173,7 @@ ul.notes {
vertical-align: middle;
text-align: center;
padding: 10px 0;
background: #FFF;
background: #fff;
color: $text-color;
}
&.notes_line2 {
......@@ -232,7 +239,7 @@ ul.notes {
.add-diff-note {
margin-top: -4px;
@include border-radius(40px);
background: #FFF;
background: #fff;
padding: 4px;
font-size: 16px;
color: $gl-link-color;
......@@ -249,7 +256,7 @@ ul.notes {
&:hover {
background: $gl-info;
color: #FFF;
color: #fff;
@include show-add-diff-note;
}
}
......
......@@ -30,7 +30,7 @@
.btn {
line-height: 40px;
height: 42px;
padding: 0px 12px;
padding: 0 12px;
img {
width: 32px;
......
......@@ -85,7 +85,7 @@
.project-repo-buttons {
margin-top: 20px;
margin-bottom: 0px;
margin-bottom: 0;
.count-buttons {
display: block;
......@@ -140,7 +140,7 @@
left: 1px;
margin-top: -9px;
border-width: 10px 7px 10px 0;
border-right-color: #FFF;
border-right-color: #fff;
}
}
.count {
......@@ -162,10 +162,10 @@
cursor: pointer;
background-image: none;
white-space: nowrap;
margin: 0 11px 0px 4px;
margin: 0 11px 0 4px;
&:hover {
background: #FFF;
background: #fff;
}
}
}
......@@ -210,7 +210,7 @@
}
.project_member_row form {
margin: 0px;
margin: 0;
}
.transfer-project .select2-container {
......@@ -286,11 +286,11 @@ table.table.protected-branches-list tr.no-border {
padding-bottom: 4px;
ul.nav {
display:inline-block;
display: inline-block;
}
.nav li {
display:inline;
display: inline;
}
.nav > li > a {
......@@ -303,11 +303,11 @@ table.table.protected-branches-list tr.no-border {
}
li {
display:inline;
display: inline;
}
a {
float:left;
float: left;
font-size: 17px;
}
......@@ -462,7 +462,7 @@ pre.light-well {
.form-control {
@extend .monospace;
background: #FFF;
background: #fff;
font-size: 14px;
margin-left: -1px;
cursor: auto;
......@@ -472,16 +472,16 @@ pre.light-well {
.cannot-be-merged,
.cannot-be-merged:hover {
color: #E62958;
color: #e62958;
margin-top: 2px;
}
.private-forks-notice .private-fork-icon {
i:nth-child(1) {
color: #2AA056;
color: #2aa056;
}
i:nth-child(2) {
color: #FFFFFF;
color: #fff;
}
}
.runner-state {
padding: 6px 12px;
margin-right: 10px;
color: #FFF;
color: #fff;
&.runner-state-shared {
background: #32b186;
......
......@@ -16,7 +16,7 @@
margin-bottom: 20px;
input {
border-color: #BBB;
border-color: #bbb;
font-weight: bold;
}
}
......
......@@ -13,13 +13,13 @@ table .sherlock-code {
}
.sherlock-line-samples-table {
margin-bottom: 0px !important;
margin-bottom: 0 !important;
thead tr th,
tbody tr td {
font-size: 13px !important;
text-align: right;
padding: 0px 10px !important;
padding: 0 10px !important;
}
}
......
.ci-status {
padding: 2px 7px;
margin-right: 5px;
border: 1px solid #EEE;
border: 1px solid #eee;
white-space: nowrap;
@include border-radius(4px);
......
......@@ -61,7 +61,7 @@
.note-image-attach {
margin-top: 4px;
margin-left: 0px;
margin-left: 0;
max-width: 200px;
float: none;
}
......@@ -89,7 +89,7 @@
.todo-body {
margin: 0;
border-left: 2px solid #DDD;
border-left: 2px solid #ddd;
padding-left: 10px;
}
}
......
......@@ -46,7 +46,7 @@
img {
position: relative;
top:-1px;
top: -1px;
}
}
......
......@@ -7,7 +7,7 @@
.example {
&:before {
content: "Example";
color: #BBB;
color: #bbb;
}
padding: 15px;
......
......@@ -2,23 +2,23 @@
// color codes are based on http://en.wikipedia.org/wiki/File:Xterm_256color_chart.svg
// see also: https://gist.github.com/jasonm23/2868981
$black: #000000;
$black: #000;
$red: #cd0000;
$green: #00cd00;
$yellow: #cdcd00;
$blue: #0000ee; // according to wikipedia, this is the xterm standard
$blue: #00e; // according to wikipedia, this is the xterm standard
//$blue: #1e90ff; // this is used by all the terminals I tried (when configured with the xterm color profile)
$magenta: #cd00cd;
$cyan: #00cdcd;
$white: #e5e5e5;
$l-black: #7f7f7f;
$l-red: #ff0000;
$l-green: #00ff00;
$l-yellow: #ffff00;
$l-red: #f00;
$l-green: #0f0;
$l-yellow: #ff0;
$l-blue: #5c5cff;
$l-magenta: #ff00ff;
$l-cyan: #00ffff;
$l-white: #ffffff;
$l-magenta: #f0f;
$l-cyan: #0ff;
$l-white: #fff;
.term-bold {
font-weight: bold;
......@@ -136,7 +136,7 @@
.xterm-fg-0 {
color: #000000;
color: #000;
}
.xterm-fg-1 {
color: #800000;
......@@ -163,28 +163,28 @@
color: #808080;
}
.xterm-fg-9 {
color: #ff0000;
color: #f00;
}
.xterm-fg-10 {
color: #00ff00;
color: #0f0;
}
.xterm-fg-11 {
color: #ffff00;
color: #ff0;
}
.xterm-fg-12 {
color: #0000ff;
color: #00f;
}
.xterm-fg-13 {
color: #ff00ff;
color: #f0f;
}
.xterm-fg-14 {
color: #00ffff;
color: #0ff;
}
.xterm-fg-15 {
color: #ffffff;
color: #fff;
}
.xterm-fg-16 {
color: #000000;
color: #000;
}
.xterm-fg-17 {
color: #00005f;
......@@ -199,7 +199,7 @@
color: #0000d7;
}
.xterm-fg-21 {
color: #0000ff;
color: #00f;
}
.xterm-fg-22 {
color: #005f00;
......@@ -274,7 +274,7 @@
color: #00d7ff;
}
.xterm-fg-46 {
color: #00ff00;
color: #0f0;
}
.xterm-fg-47 {
color: #00ff5f;
......@@ -289,7 +289,7 @@
color: #00ffd7;
}
.xterm-fg-51 {
color: #00ffff;
color: #0ff;
}
.xterm-fg-52 {
color: #5f0000;
......@@ -724,7 +724,7 @@
color: #d7ffff;
}
.xterm-fg-196 {
color: #ff0000;
color: #f00;
}
.xterm-fg-197 {
color: #ff005f;
......@@ -739,7 +739,7 @@
color: #ff00d7;
}
.xterm-fg-201 {
color: #ff00ff;
color: #f0f;
}
.xterm-fg-202 {
color: #ff5f00;
......@@ -814,7 +814,7 @@
color: #ffd7ff;
}
.xterm-fg-226 {
color: #ffff00;
color: #ff0;
}
.xterm-fg-227 {
color: #ffff5f;
......@@ -829,7 +829,7 @@
color: #ffffd7;
}
.xterm-fg-231 {
color: #ffffff;
color: #fff;
}
.xterm-fg-232 {
color: #080808;
......@@ -850,7 +850,7 @@
color: #3a3a3a;
}
.xterm-fg-238 {
color: #444444;
color: #444;
}
.xterm-fg-239 {
color: #4e4e4e;
......@@ -901,6 +901,6 @@
color: #e4e4e4;
}
.xterm-fg-255 {
color: #eeeeee;
color: #eee;
}
}
......@@ -150,7 +150,7 @@ class Admin::UsersController < Admin::ApplicationController
:email, :remember_me, :bio, :name, :username,
:skype, :linkedin, :twitter, :website_url, :color_scheme_id, :theme_id, :force_random_password,
:extern_uid, :provider, :password_expires_at, :avatar, :hide_no_ssh_key, :hide_no_password,
:projects_limit, :can_create_group, :admin, :key_id
:projects_limit, :can_create_group, :admin, :key_id, :external
)
end
......
class Projects::BadgesController < Projects::ApplicationController
before_action :set_no_cache
before_action :no_cache_headers
def build
respond_to do |format|
......@@ -10,15 +10,4 @@ class Projects::BadgesController < Projects::ApplicationController
end
end
end
private
def set_no_cache
expires_now
# Add some deprecated headers for older agents
#
response.headers['Pragma'] = 'no-cache'
response.headers['Expires'] = 'Fri, 01 Jan 1990 00:00:00 GMT'
end
end
......@@ -9,7 +9,7 @@ class Projects::BranchesController < Projects::ApplicationController
@sort = params[:sort] || 'name'
@branches = @repository.branches_sorted_by(@sort)
@branches = Kaminari.paginate_array(@branches).page(params[:page]).per(PER_PAGE)
@max_commits = @branches.reduce(0) do |memo, branch|
diverging_commit_counts = repository.diverging_commit_counts(branch)
[memo, diverging_commit_counts[:behind], diverging_commit_counts[:ahead]].max
......@@ -23,11 +23,15 @@ class Projects::BranchesController < Projects::ApplicationController
def create
branch_name = sanitize(strip_tags(params[:branch_name]))
branch_name = Addressable::URI.unescape(branch_name)
ref = sanitize(strip_tags(params[:ref]))
ref = Addressable::URI.unescape(ref)
result = CreateBranchService.new(project, current_user).
execute(branch_name, ref)
if params[:issue_iid]
issue = @project.issues.find_by(iid: params[:issue_iid])
SystemNoteService.new_issue_branch(issue, @project, current_user, branch_name) if issue
end
if result[:status] == :success
@branch = result[:branch]
redirect_to namespace_project_tree_path(@project.namespace, @project,
......@@ -49,4 +53,15 @@ class Projects::BranchesController < Projects::ApplicationController
format.js { render status: status[:return_code] }
end
end
private
def ref
if params[:ref]
ref_escaped = sanitize(strip_tags(params[:ref]))
Addressable::URI.unescape(ref_escaped)
else
@project.default_branch
end
end
end
......@@ -65,6 +65,7 @@ class Projects::IssuesController < Projects::ApplicationController
@notes = @issue.notes.nonawards.with_associations.fresh
@noteable = @issue
@merge_requests = @issue.referenced_merge_requests(current_user)
@related_branches = @issue.related_branches - @merge_requests.map(&:source_branch)
respond_with(@issue)
end
......
......@@ -40,25 +40,26 @@ class ProjectsFinder
private
def group_projects(current_user, group)
if current_user
[
group_projects_for_user(current_user, group),
group.projects.public_and_internal_only,
group.shared_projects.visible_to_user(current_user)
]
return [group.projects.public_only] unless current_user
user_group_projects = [
group_projects_for_user(current_user, group),
group.shared_projects.visible_to_user(current_user)
]
if current_user.external?
user_group_projects << group.projects.public_only
else
[group.projects.public_only]
user_group_projects << group.projects.public_and_internal_only
end
end
def all_projects(current_user)
if current_user
[
current_user.authorized_projects,
public_and_internal_projects
]
return [public_projects] unless current_user
if current_user.external?
[current_user.authorized_projects, public_projects]
else
[Project.public_only]
[current_user.authorized_projects, public_and_internal_projects]
end
end
......
......@@ -109,23 +109,10 @@ class Ability
key = "/user/#{user.id}/project/#{project.id}"
RequestStore.store[key] ||= begin
team = project.team
# Push abilities on the users team role
rules.push(*project_team_rules(project.team, user))
# Rules based on role in project
if team.master?(user)
rules.push(*project_master_rules)
elsif team.developer?(user)
rules.push(*project_dev_rules)
elsif team.reporter?(user)
rules.push(*project_report_rules)
elsif team.guest?(user)
rules.push(*project_guest_rules)
end
if project.public? || project.internal?
if project.public? || (project.internal? && !user.external?)
rules.push(*public_project_rules)
# Allow to read builds for internal projects
......@@ -148,6 +135,19 @@ class Ability
end
end
def project_team_rules(team, user)
# Rules based on role in project
if team.master?(user)
project_master_rules
elsif team.developer?(user)
project_dev_rules
elsif team.reporter?(user)
project_report_rules
elsif team.guest?(user)
project_guest_rules
end
end
def public_project_rules
@public_project_rules ||= project_guest_rules + [
:download_code,
......@@ -356,7 +356,7 @@ class Ability
]
end
if snippet.public? || snippet.internal?
if snippet.public? || (snippet.internal? && !user.external?)
rules << :read_personal_snippet
end
......
......@@ -114,7 +114,7 @@ class CommitStatus < ActiveRecord::Base
end
def ignored?
failed? && allow_failure?
allow_failure? && (failed? || canceled?)
end
def duration
......
......@@ -87,11 +87,21 @@ class Issue < ActiveRecord::Base
end
def referenced_merge_requests(current_user = nil)
Gitlab::ReferenceExtractor.lazily do
[self, *notes].flat_map do |note|
note.all_references(current_user).merge_requests
end
end.sort_by(&:iid)
@referenced_merge_requests ||= {}
@referenced_merge_requests[current_user] ||= begin
Gitlab::ReferenceExtractor.lazily do
[self, *notes].flat_map do |note|
note.all_references(current_user).merge_requests
end
end.sort_by(&:iid).uniq
end
end
def related_branches
return [] if self.project.empty_repo?
self.project.repository.branch_names.select do |branch|
branch =~ /\A#{iid}-(?!\d+-stable)/i
end
end
# Reset issue events cache
......@@ -120,4 +130,15 @@ class Issue < ActiveRecord::Base
note.all_references(current_user).merge_requests
end.uniq.select { |mr| mr.open? && mr.closes_issue?(self) }
end
def to_branch_name
"#{iid}-#{title.parameterize}"
end
def can_be_worked_on?(current_user)
!self.closed? &&
!self.project.forked? &&
self.related_branches.empty? &&
self.closed_by_merge_requests(current_user).empty?
end
end
......@@ -254,12 +254,6 @@ class Project < ActiveRecord::Base
where('projects.last_activity_at < ?', 6.months.ago)
end
def publicish(user)
visibility_levels = [Project::PUBLIC]
visibility_levels << Project::INTERNAL if user
where(visibility_level: visibility_levels)
end
def with_push
joins(:events).where('events.action = ?', Event::PUSHED)
end
......
......@@ -758,12 +758,15 @@ class Repository
def parse_search_result(result)
ref = nil
filename = nil
basename = nil
startline = 0
result.each_line.each_with_index do |line, index|
if line =~ /^.*:.*:\d+:/
ref, filename, startline = line.split(':')
startline = startline.to_i - index
extname = File.extname(filename)
basename = filename.sub(/#{extname}$/, '')
break
end
end
......@@ -776,6 +779,7 @@ class Repository
OpenStruct.new(
filename: filename,
basename: basename,
ref: ref,
startline: startline,
data: data
......
......@@ -59,6 +59,7 @@
# hide_project_limit :boolean default(FALSE)
# unlock_token :string
# otp_grace_period_started_at :datetime
# external :boolean default(FALSE)
#
require 'carrierwave/orm/activerecord'
......@@ -77,6 +78,7 @@ class User < ActiveRecord::Base
add_authentication_token_field :authentication_token
default_value_for :admin, false
default_value_for :external, false
default_value_for :can_create_group, gitlab_config.default_can_create_group
default_value_for :can_create_team, false
default_value_for :hide_no_ssh_key, false
......@@ -171,6 +173,7 @@ class User < ActiveRecord::Base
after_update :update_emails_with_primary_email, if: ->(user) { user.email_changed? }
before_save :ensure_authentication_token
before_save :ensure_external_user_rights
after_save :ensure_namespace_correct
after_initialize :set_projects_limit
after_create :post_create_hook
......@@ -218,6 +221,7 @@ class User < ActiveRecord::Base
# Scopes
scope :admins, -> { where(admin: true) }
scope :blocked, -> { with_states(:blocked, :ldap_blocked) }
scope :external, -> { where(external: true) }
scope :active, -> { with_state(:active) }
scope :not_in_project, ->(project) { project.users.present? ? where("id not in (:ids)", ids: project.users.map(&:id) ) : all }
scope :without_projects, -> { where('id NOT IN (SELECT DISTINCT(user_id) FROM members)') }
......@@ -273,6 +277,8 @@ class User < ActiveRecord::Base
self.with_two_factor
when 'wop'
self.without_projects
when 'external'
self.external
else
self.active
end
......@@ -841,4 +847,11 @@ class User < ActiveRecord::Base
def send_devise_notification(notification, *args)
devise_mailer.send(notification, self, *args).deliver_later
end
def ensure_external_user_rights
return unless self.external?
self.can_create_group = false
self.projects_limit = 0
end
end
......@@ -47,6 +47,21 @@ module MergeRequests
merge_request.title = merge_request.source_branch.titleize.humanize
end
# When your branch name starts with an iid followed by a dash this pattern will
# be interpreted as the use wants to close that issue on this project
# Pattern example: 112-fix-mep-mep
# Will lead to appending `Closes #112` to the description
if match = merge_request.source_branch.match(/\A(\d+)-/)
iid = match[1]
closes_issue = "Closes ##{iid}"
if merge_request.description.present?
merge_request.description << closes_issue.prepend("\n")
else
merge_request.description = closes_issue
end
end
merge_request
end
......
......@@ -207,6 +207,18 @@ class SystemNoteService
create_note(noteable: noteable, project: project, author: author, note: body)
end
# Called when a branch is created from the 'new branch' button on a issue
# Example note text:
#
# "Started branch `201-issue-branch-button`"
def self.new_issue_branch(issue, project, author, branch)
h = Gitlab::Application.routes.url_helpers
link = h.namespace_project_compare_url(project.namespace, project, from: project.default_branch, to: branch)
body = "Started branch [`#{branch}`](#{link})"
create_note(noteable: issue, project: project, author: author, note: body)
end
# Called when a Mentionable references a Noteable
#
# noteable - Noteable object being referenced
......
......@@ -58,9 +58,15 @@
= f.label :admin, class: 'control-label'
- if current_user == @user
.col-sm-10= f.check_box :admin, disabled: true
.col-sm-10 You cannot remove your own admin rights
.col-sm-10 You cannot remove your own admin rights.
- else
.col-sm-10= f.check_box :admin
.form-group
= f.label :external, class: 'control-label'
.col-sm-10= f.check_box :external
.col-sm-10 External users cannot see internal or private projects unless access is explicitly granted. Also, external users cannot create projects or groups.
%fieldset
%legend Profile
.form-group
......
......@@ -19,6 +19,10 @@
= link_to admin_users_path(filter: 'two_factor_disabled') do
2FA Disabled
%small.badge= number_with_delimiter(User.without_two_factor.count)
%li.filter-external{class: "#{'active' if params[:filter] == 'external'}"}
= link_to admin_users_path(filter: 'external') do
External
%small.badge= number_with_delimiter(User.external.count)
%li{class: "#{'active' if params[:filter] == "blocked"}"}
= link_to admin_users_path(filter: "blocked") do
Blocked
......@@ -70,12 +74,14 @@
%li
.list-item-name
- if user.blocked?
%i.fa.fa-lock.cred
= icon("lock", class: "cred")
- else
%i.fa.fa-user.cgreen
= icon("user", class: "cgreen")
= link_to user.name, [:admin, user]
- if user.admin?
%strong.cred (Admin)
- if user.external?
%strong.cred (External)
- if user == current_user
%span.cred It's you!
.pull-right
......
......@@ -47,6 +47,10 @@
- else
Disabled
%li
%span.light External User:
%strong
= @user.external? ? "Yes" : "No"
%li
%span.light Can create groups:
%strong
......
- publicish_project_count = Project.publicish(current_user).count
- publicish_project_count = ProjectsFinder.new.execute(current_user).count
%h3.page-title Welcome to GitLab!
%p.light Self hosted Git management application.
%hr
......@@ -18,7 +18,7 @@
- if current_user.can_create_project?
.link_holder
= link_to new_project_path, class: "btn btn-new" do
%i.fa.fa-plus
= icon('plus')
New Project
- if current_user.can_create_group?
......
-if @merge_requests.any?
- if @merge_requests.any?
%h2.merge-requests-title
= pluralize(@merge_requests.count, 'Related Merge Request')
%ul.unstyled-list
......
- if current_user && can?(current_user, :push_code, @project) && @issue.can_be_worked_on?(current_user)
.pull-right
= link_to namespace_project_branches_path(@project.namespace, @project, branch_name: @issue.to_branch_name, issue_iid: @issue.iid), method: :post, class: 'btn', title: @issue.to_branch_name do
= icon('code-fork')
New Branch
- if @related_branches.any?
%h2.related-branches-title
= pluralize(@related_branches.count, 'Related Branch')
%ul.unstyled-list
- @related_branches.each do |branch|
%li
- sha = @project.repository.find_branch(branch).target
- ci_commit = @project.ci_commit(sha) if sha
- if ci_commit
%span.related-branch-ci-status
= render_ci_status(ci_commit)
%span.related-branch-info
%strong
= link_to namespace_project_compare_path(@project.namespace, @project, from: @project.default_branch, to: branch), class: "label-branch" do
= branch
......@@ -70,8 +70,10 @@
.merge-requests
= render 'merge_requests'
= render 'related_branches'
.content-block.content-block-small
= render 'new_branch'
= render 'votes/votes_block', votable: @issue
.row
......
......@@ -2,9 +2,9 @@
.blob-result
.file-holder
.file-title
= link_to namespace_project_wiki_path(@project.namespace, @project, wiki_blob.filename) do
= link_to namespace_project_wiki_path(@project.namespace, @project, wiki_blob.basename) do
%i.fa.fa-file
%strong
= wiki_blob.filename
= wiki_blob.basename
.file-content.code.term
= render 'shared/file_highlight', blob: wiki_blob, first_line_number: wiki_blob.startline
class PostReceive
include Sidekiq::Worker
include Gitlab::Identifier
sidekiq_options queue: :post_receive
......@@ -11,51 +10,44 @@ class PostReceive
log("Check gitlab.yml config for correct gitlab_shell.repos_path variable. \"#{Gitlab.config.gitlab_shell.repos_path}\" does not match \"#{repo_path}\"")
end
repo_path.gsub!(/\.git\z/, "")
repo_path.gsub!(/\A\//, "")
post_received = Gitlab::GitPostReceive.new(repo_path, identifier, changes)
project = Project.find_with_namespace(repo_path)
if project.nil?
if post_received.project.nil?
log("Triggered hook for non-existing project with full path \"#{repo_path} \"")
return false
end
changes = Base64.decode64(changes) unless changes.include?(" ")
changes = utf8_encode_changes(changes)
changes = changes.lines
if post_received.wiki?
# Nothing defined here yet.
elsif post_received.regular_project?
process_project_changes(post_received)
else
log("Triggered hook for unidentifiable repository type with full path \"#{repo_path} \"")
false
end
end
changes.each do |change|
def process_project_changes(post_received)
post_received.changes.each do |change|
oldrev, newrev, ref = change.strip.split(' ')
@user ||= identify(identifier, project, newrev)
@user ||= post_received.identify(newrev)
unless @user
log("Triggered hook for non-existing user \"#{identifier} \"")
log("Triggered hook for non-existing user \"#{post_received.identifier} \"")
return false
end
if Gitlab::Git.tag_ref?(ref)
GitTagPushService.new.execute(project, @user, oldrev, newrev, ref)
GitTagPushService.new.execute(post_received.project, @user, oldrev, newrev, ref)
else
GitPushService.new(project, @user, oldrev: oldrev, newrev: newrev, ref: ref).execute
GitPushService.new(post_received.project, @user, oldrev: oldrev, newrev: newrev, ref: ref).execute
end
end
end
def utf8_encode_changes(changes)
changes = changes.dup
changes.force_encoding("UTF-8")
return changes if changes.valid_encoding?
# Convert non-UTF-8 branch/tag names to UTF-8 so they can be dumped as JSON.
detection = CharlockHolmes::EncodingDetector.detect(changes)
return changes unless detection && detection[:encoding]
CharlockHolmes::Converter.convert(changes, detection[:encoding], 'UTF-8')
end
private
def log(message)
Gitlab::GitLogger.error("POST-RECEIVE: #{message}")
end
......
......@@ -357,6 +357,12 @@ production: &base
# crowd_server_url: 'CROWD SERVER URL',
# application_name: 'YOUR_APP_NAME',
# application_password: 'YOUR_APP_PASSWORD' } }
#
# - { name: 'auth0',
# args: {
# client_id: 'YOUR_AUTH0_CLIENT_ID',
# client_secret: 'YOUR_AUTH0_CLIENT_SECRET',
# namespace: 'YOUR_AUTH0_DOMAIN' } }
# SSO maximum session duration in seconds. Defaults to CAS default of 8 hours.
# cas3:
......
class AddExternalFlagToUsers < ActiveRecord::Migration
def change
add_column :users, :external, :boolean, default: false
end
end
class CiRunnersTokenIndex < ActiveRecord::Migration
disable_ddl_transaction!
def change
args = [:ci_runners, :token]
if Gitlab::Database.postgresql?
args << { algorithm: :concurrently }
end
add_index(*args)
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160314143402) do
ActiveRecord::Schema.define(version: 20160316123110) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
......@@ -260,6 +260,7 @@ ActiveRecord::Schema.define(version: 20160314143402) do
end
add_index "ci_runners", ["description"], name: "index_ci_runners_on_description_trigram", using: :gin, opclasses: {"description"=>"gin_trgm_ops"}
add_index "ci_runners", ["token"], name: "index_ci_runners_on_token", using: :btree
add_index "ci_runners", ["token"], name: "index_ci_runners_on_token_trigram", using: :gin, opclasses: {"token"=>"gin_trgm_ops"}
create_table "ci_services", force: :cascade do |t|
......@@ -775,9 +776,9 @@ ActiveRecord::Schema.define(version: 20160314143402) do
t.string "type"
t.string "title"
t.integer "project_id"
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "active", default: false, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "active", null: false
t.text "properties"
t.boolean "template", default: false
t.boolean "push_events", default: true
......@@ -939,6 +940,7 @@ ActiveRecord::Schema.define(version: 20160314143402) do
t.string "unlock_token"
t.datetime "otp_grace_period_started_at"
t.boolean "ldap_email", default: false, null: false
t.boolean "external", default: false
end
add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
......
......@@ -8,7 +8,7 @@
- [Importing to GitLab](workflow/importing/README.md).
- [Markdown](markdown/markdown.md) GitLab's advanced formatting system.
- [Migrating from SVN](workflow/importing/migrating_from_svn.md) Convert a SVN repository to Git and GitLab
- [Permissions](permissions/permissions.md) Learn what each role in a project (guest/reporter/developer/master/owner) can do.
- [Permissions](permissions/permissions.md) Learn what each role in a project (external/guest/reporter/developer/master/owner) can do.
- [Profile Settings](profile/README.md)
- [Project Services](project_services/project_services.md) Integrate a project with external services, such as CI and chat.
- [Public access](public_access/public_access.md) Learn how you can allow public and internal access to projects.
......
......@@ -194,6 +194,7 @@ Parameters:
- `admin` (optional) - User is admin - true or false (default)
- `can_create_group` (optional) - User can create groups - true or false
- `confirm` (optional) - Require confirmation - true (default) or false
- `external` (optional) - Flags the user as external - true or false(default)
## User modification
......@@ -219,6 +220,7 @@ Parameters:
- `bio` - User's biography
- `admin` (optional) - User is admin - true or false (default)
- `can_create_group` (optional) - User can create groups - true or false
- `external` (optional) - Flags the user as external - true or false(default)
Note, at the moment this method does only return a 404 error,
even in cases where a 409 (Conflict) would be more appropriate,
......@@ -560,7 +562,7 @@ Parameters:
- `uid` (required) - id of specified user
Will return `200 OK` on success, `404 User Not Found` is user cannot be found or
Will return `200 OK` on success, `404 User Not Found` is user cannot be found or
`403 Forbidden` when trying to block an already blocked user by LDAP synchronization.
## Unblock user
......
......@@ -89,7 +89,7 @@ We also use two secure variables:
In GitLab CI 7.12 a new feature was introduced: Secure Variables.
Secure Variables can added by going to `Project > Variables > Add Variable`.
**This feature requires `gitlab-runner` with version equal or greater than 0.4.0.**
The variables that are defined in the project settings are send along with the build script to the runner.
The variables that are defined in the project settings are sent along with the build script to the runner.
The secure variables are stored out of the repository. Never store secrets in your projects' .gitlab-ci.yml.
It is also important that secret's value is hidden in the build log.
......
......@@ -135,6 +135,9 @@ thus allowing to fine tune them.
### cache
>**Note:**
Introduced in GitLab Runner v0.7.0.
`cache` is used to specify a list of files and directories which should be
cached between builds.
......@@ -143,15 +146,55 @@ cached between builds.
If `cache` is defined outside the scope of the jobs, it means it is set
globally and all jobs will use its definition.
To cache all git untracked files and files in `binaries`:
Cache all files in `binaries` and `.config`:
```yaml
rspec:
script: test
cache:
paths:
- binaries/
- .config
```
Cache all Git untracked files:
```yaml
rspec:
script: test
cache:
untracked: true
```
Cache all Git untracked files and files in `binaries`:
```yaml
rspec:
script: test
cache:
untracked: true
paths:
- binaries/
```
Locally defined cache overwrites globally defined options. This will cache only
`binaries/`:
```yaml
cache:
untracked: true
paths:
- binaries/
- my/files
rspec:
script: test
cache:
paths:
- binaries/
```
The cache is provided on best effort basis, so don't expect that cache will be
always present. For implementation details please check GitLab Runner.
#### cache:key
>**Note:**
......@@ -418,14 +461,14 @@ artifacts:
- .config
```
Send all git untracked files:
Send all Git untracked files:
```yaml
artifacts:
untracked: true
```
Send all git untracked files and files in `binaries`:
Send all Git untracked files and files in `binaries`:
```yaml
artifacts:
......@@ -579,63 +622,6 @@ deploy:
script: make deploy
```
### cache
>**Note:**
Introduced in GitLab Runner v0.7.0.
`cache` is used to specify list of files and directories which should be cached
between builds. Below are some examples:
Cache all files in `binaries` and `.config`:
```yaml
rspec:
script: test
cache:
paths:
- binaries/
- .config
```
Cache all git untracked files:
```yaml
rspec:
script: test
cache:
untracked: true
```
Cache all git untracked files and files in `binaries`:
```yaml
rspec:
script: test
cache:
untracked: true
paths:
- binaries/
```
Locally defined cache overwrites globally defined options. This will cache only
`binaries/`:
```yaml
cache:
paths:
- my/files
rspec:
script: test
cache:
paths:
- binaries/
```
The cache is provided on best effort basis, so don't expect that cache will be
always present. For implementation details please check GitLab Runner.
## Hidden jobs
>**Note:**
......
......@@ -22,7 +22,7 @@ If the highest number stable branch is unclear please check the [GitLab Blog](ht
This guide is long because it covers many cases and includes all commands you need, this is [one of the few installation scripts that actually works out of the box](https://twitter.com/robinvdvleuten/status/424163226532986880).
This installation guide was created for and tested on **Debian/Ubuntu** operating systems. Please read [doc/install/requirements.md](./requirements.md) for hardware and operating system requirements. If you want to install on RHEL/CentOS we recommend using the [Omnibus packages](https://about.gitlab.com/downloads/).
This installation guide was created for and tested on **Debian/Ubuntu** operating systems. Please read [requirements.md](requirements.md) for hardware and operating system requirements. If you want to install on RHEL/CentOS we recommend using the [Omnibus packages](https://about.gitlab.com/downloads/).
This is the official installation guide to set up a production server. To set up a **development installation** or for many other installation options please see [the installation section of the readme](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/README.md#installation).
......@@ -89,8 +89,9 @@ Is the system packaged Git too old? Remove it and compile from source.
# Download and compile from source
cd /tmp
curl -L --progress https://www.kernel.org/pub/software/scm/git/git-2.4.3.tar.gz | tar xz
cd git-2.4.3/
curl -O --progress https://www.kernel.org/pub/software/scm/git/git-2.7.3.tar.gz
echo '30d067499b61caddedaf1a407b4947244f14d10842d100f7c7c6ea1c288280cd git-2.7.3.tar.gz' | shasum -a256 -c - && tar -xzf git-2.7.3.tar.gz
cd git-2.7.3/
./configure
make prefix=/usr/local all
......@@ -143,7 +144,7 @@ use 64-bit Linux. You can find downloads for other platforms at the [Go download
page](https://golang.org/dl).
curl -O --progress https://storage.googleapis.com/golang/go1.5.3.linux-amd64.tar.gz
echo '43afe0c5017e502630b1aea4d44b8a7f059bf60d7f29dfd58db454d4e4e0ae53 go1.5.3.linux-amd64.tar.gz' | shasum -c - && \
echo '43afe0c5017e502630b1aea4d44b8a7f059bf60d7f29dfd58db454d4e4e0ae53 go1.5.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
sudo tar -C /usr/local -xzf go1.5.3.linux-amd64.tar.gz
sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
rm go1.5.3.linux-amd64.tar.gz
......@@ -160,19 +161,12 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da
# Install the database packages
sudo apt-get install -y postgresql postgresql-client libpq-dev
# Login to PostgreSQL
sudo -u postgres psql -d template1
# Create a user for GitLab
# Do not type the 'template1=#', this is part of the prompt
template1=# CREATE USER git CREATEDB;
sudo -u postgres psql -d template1 -c "CREATE USER git CREATEDB;"
# Create the GitLab production database & grant all privileges on database
template1=# CREATE DATABASE gitlabhq_production OWNER git;
# Quit the database session
template1=# \q
sudo -u postgres psql -d template1 -c "CREATE DATABASE gitlabhq_production OWNER git;"
# Try connecting to the new database with the new user
sudo -u git -H psql -d gitlabhq_production
......
......@@ -22,7 +22,7 @@ For the installations options please see [the installation page on the GitLab we
- FreeBSD
On the above unsupported distributions is still possible to install GitLab yourself.
Please see the [installation from source guide](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md) and the [unofficial installation guides](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Unofficial-Installation-Guides) on the public wiki for more information.
Please see the [installation from source guide](installation.md) and the [installation guides](https://about.gitlab.com/installation/) for more information.
### Non-Unix operating systems such as Windows
......
# Auth0 OmniAuth Provider
To enable the Auth0 OmniAuth provider, you must create an Auth0 account, and an
application.
1. Sign in to the [Auth0 Console](https://manage.auth0.com). If you need to
create an account, you can do so at the same link.
1. Select "New App/API".
1. Provide the Application Name ('GitLab' works fine).
1. Once created, you should see the Quick Start options. Disregard them and
select 'Settings' above the Quick Start options.
1. At the top of the Settings screen, you should see your Domain, Client ID and
Client Secret. Take note of these as you'll need to put them in the
configuration file. For example:
- Domain: `test1234.auth0.com`
- Client ID: `t6X8L2465bNePWLOvt9yi41i`
- Client Secret: `KbveM3nqfjwCbrhaUy_gDu2dss8TIlHIdzlyf33pB7dEK5u_NyQdp65O_o02hXs2`
1. Fill in the Allowed Callback URLs:
- http://`YOUR_GITLAB_URL`/users/auth/auth0/callback (or)
- https://`YOUR_GITLAB_URL`/users/auth/auth0/callback
1. Fill in the Allowed Origins (CORS):
- http://`YOUR_GITLAB_URL` (or)
- https://`YOUR_GITLAB_URL`
1. On your GitLab server, open the configuration file.
For omnibus package:
```sh
sudo editor /etc/gitlab/gitlab.rb
```
For installations from source:
```sh
cd /home/git/gitlab
sudo -u git -H editor config/gitlab.yml
```
1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration)
for initial settings.
1. Add the provider configuration:
For omnibus package:
```ruby
gitlab_rails['omniauth_providers'] = [
{
"name" => "auth0",
"args" => { client_id: 'YOUR_AUTH0_CLIENT_ID'',
client_secret: 'YOUR_AUTH0_CLIENT_SECRET',
namespace: 'YOUR_AUTH0_DOMAIN'
}
}
]
```
For installations from source:
```yaml
- { name: 'auth0',
args: {
client_id: 'YOUR_AUTH0_CLIENT_ID',
client_secret: 'YOUR_AUTH0_CLIENT_SECRET',
namespace: 'YOUR_AUTH0_DOMAIN'
}
}
```
1. Change `YOUR_AUTH0_CLIENT_ID` to the client ID from the Auth0 Console page
from step 5.
1. Change `YOUR_AUTH0_CLIENT_SECRET` to the client secret from the Auth0 Console
page from step 5.
1. Save the file and [reconfigure GitLab](../administration/restart_gitlab.md)
for the changes to take effect.
On the sign in page there should now be an Auth0 icon below the regular sign in
form. Click the icon to begin the authentication process. Auth0 will ask the
user to sign in and authorize the GitLab application. If everything goes well
the user will be returned to GitLab and will be signed in.
......@@ -28,6 +28,7 @@ contains some settings that are common for all providers.
- [SAML](saml.md)
- [Crowd](crowd.md)
- [Azure](azure.md)
- [Auth0](auth0.md)
## Initial OmniAuth Configuration
......
......@@ -71,3 +71,24 @@ Any user can remove themselves from a group, unless they are the last Owner of t
| Create project in group | | | | ✓ | ✓ |
| Manage group members | | | | | ✓ |
| Remove group | | | | | ✓ |
## External Users
In cases where it is desired that a user has access only to some internal or
private projects, there is the option of creating **External Users**. This
feature may be useful when for example a contractor is working on a given
project and should only have access to that project.
External users can only access projects to which they are explicitly granted
access, thus hiding all other internal or private ones from them. Access can be
granted by adding the user as member to the project or group.
They will, like usual users, receive a role in the project or group with all
the abilities that are mentioned in the table above. They cannot however create
groups or projects, and they have the same access as logged out users in all
other cases.
An administrator can flag a user as external [through the API](../api/users.md)
or by checking the checkbox on the admin panel. As an administrator, navigate
to **Admin > Users** to create a new user or edit an existing one. There, you
will find the option to flag the user as external.
......@@ -21,7 +21,7 @@ class Spinach::Features::ProjectBadgesBuild < Spinach::FeatureSteps
end
step 'I should see a badge that has not been cached' do
expect(page.response_headers).to include('Cache-Control' => 'no-cache')
expect(page.response_headers['Cache-Control']).to include 'no-cache'
end
def expect_badge(status)
......
......@@ -100,7 +100,7 @@ class Spinach::Features::Search < Spinach::FeatureSteps
step 'I should see "test_wiki" link in the search results' do
page.within('.results') do
find(:css, '.search-results').should have_link 'test_wiki.md'
expect(find(:css, '.search-results')).to have_link 'test_wiki'
end
end
......
......@@ -31,6 +31,7 @@ module API
expose :can_create_group?, as: :can_create_group
expose :can_create_project?, as: :can_create_project
expose :two_factor_enabled
expose :external
end
class UserLogin < UserFull
......
......@@ -61,19 +61,20 @@ module API
# admin - User is admin - true or false (default)
# can_create_group - User can create groups - true or false
# confirm - Require user confirmation - true (default) or false
# external - Flags the user as external - true or false(default)
# Example Request:
# POST /users
post do
authenticated_as_admin!
required_attributes! [:email, :password, :name, :username]
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :bio, :can_create_group, :admin, :confirm]
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :bio, :can_create_group, :admin, :confirm, :external]
admin = attrs.delete(:admin)
confirm = !(attrs.delete(:confirm) =~ (/(false|f|no|0)$/i))
user = User.build_user(attrs)
user.admin = admin unless admin.nil?
user.skip_confirmation! unless confirm
identity_attrs = attributes_for_keys [:provider, :extern_uid]
if identity_attrs.any?
user.identities.build(identity_attrs)
end
......@@ -107,12 +108,13 @@ module API
# bio - Bio
# admin - User is admin - true or false (default)
# can_create_group - User can create groups - true or false
# external - Flags the user as external - true or false(default)
# Example Request:
# PUT /users/:id
put ":id" do
authenticated_as_admin!
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :website_url, :projects_limit, :username, :bio, :can_create_group, :admin]
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :website_url, :projects_limit, :username, :bio, :can_create_group, :admin, :external]
user = User.find(params[:id])
not_found!('User') unless user
......
module Gitlab
class GitPostReceive
include Gitlab::Identifier
attr_reader :repo_path, :identifier, :changes, :project
def initialize(repo_path, identifier, changes)
repo_path.gsub!(/\.git\z/, '')
repo_path.gsub!(/\A\//, '')
@repo_path = repo_path
@identifier = identifier
@changes = deserialize_changes(changes)
retrieve_project_and_type
end
def wiki?
@type == :wiki
end
def regular_project?
@type == :project
end
def identify(revision)
super(identifier, project, revision)
end
private
def retrieve_project_and_type
@type = :project
@project = Project.find_with_namespace(@repo_path)
if @repo_path.end_with?('.wiki') && !@project
@type = :wiki
@project = Project.find_with_namespace(@repo_path.gsub(/\.wiki\z/, ''))
end
end
def deserialize_changes(changes)
changes = Base64.decode64(changes) unless changes.include?(' ')
changes = utf8_encode_changes(changes)
changes.lines
end
def utf8_encode_changes(changes)
changes = changes.dup
changes.force_encoding('UTF-8')
return changes if changes.valid_encoding?
# Convert non-UTF-8 branch/tag names to UTF-8 so they can be dumped as JSON.
detection = CharlockHolmes::EncodingDetector.detect(changes)
return changes unless detection && detection[:encoding]
CharlockHolmes::Converter.convert(changes, detection[:encoding], 'UTF-8')
end
end
end
......@@ -47,6 +47,7 @@ namespace :gemojione do
# let's simplify it
system(%Q(sed -i '' "s/width: #{SIZE}px; height: #{SIZE}px; background: image-url('emoji.png')/background-position:/" #{style_path}))
system(%Q(sed -i '' "s/ no-repeat//" #{style_path}))
system(%Q(sed -i '' "s/ 0px/ 0/" #{style_path}))
# Append a generic rule that applies to all Emojis
File.open(style_path, 'a') do |f|
......
......@@ -17,49 +17,79 @@ describe Projects::BranchesController do
describe "POST create" do
render_views
before do
post :create,
namespace_id: project.namespace.to_param,
project_id: project.to_param,
branch_name: branch,
ref: ref
end
context "on creation of a new branch" do
before do
post :create,
namespace_id: project.namespace.to_param,
project_id: project.to_param,
branch_name: branch,
ref: ref
end
context "valid branch name, valid source" do
let(:branch) { "merge_branch" }
let(:ref) { "master" }
it 'redirects' do
expect(subject).
to redirect_to("/#{project.path_with_namespace}/tree/merge_branch")
context "valid branch name, valid source" do
let(:branch) { "merge_branch" }
let(:ref) { "master" }
it 'redirects' do
expect(subject).
to redirect_to("/#{project.path_with_namespace}/tree/merge_branch")
end
end
context "invalid branch name, valid ref" do
let(:branch) { "<script>alert('merge');</script>" }
let(:ref) { "master" }
it 'redirects' do
expect(subject).
to redirect_to("/#{project.path_with_namespace}/tree/alert('merge');")
end
end
context "valid branch name, invalid ref" do
let(:branch) { "merge_branch" }
let(:ref) { "<script>alert('ref');</script>" }
it { is_expected.to render_template('new') }
end
context "invalid branch name, invalid ref" do
let(:branch) { "<script>alert('merge');</script>" }
let(:ref) { "<script>alert('ref');</script>" }
it { is_expected.to render_template('new') }
end
context "valid branch name with encoded slashes" do
let(:branch) { "feature%2Ftest" }
let(:ref) { "<script>alert('ref');</script>" }
it { is_expected.to render_template('new') }
it { project.repository.branch_names.include?('feature/test') }
end
end
context "invalid branch name, valid ref" do
let(:branch) { "<script>alert('merge');</script>" }
let(:ref) { "master" }
describe "created from the new branch button on issues" do
let(:branch) { "1-feature-branch" }
let!(:issue) { create(:issue, project: project) }
it 'redirects' do
post :create,
namespace_id: project.namespace.to_param,
project_id: project.to_param,
branch_name: branch,
issue_iid: issue.iid
expect(subject).
to redirect_to("/#{project.path_with_namespace}/tree/alert('merge');")
to redirect_to("/#{project.path_with_namespace}/tree/1-feature-branch")
end
end
context "valid branch name, invalid ref" do
let(:branch) { "merge_branch" }
let(:ref) { "<script>alert('ref');</script>" }
it { is_expected.to render_template('new') }
end
it 'posts a system note' do
expect(SystemNoteService).to receive(:new_issue_branch).with(issue, project, user, "1-feature-branch")
context "invalid branch name, invalid ref" do
let(:branch) { "<script>alert('merge');</script>" }
let(:ref) { "<script>alert('ref');</script>" }
it { is_expected.to render_template('new') }
end
post :create,
namespace_id: project.namespace.to_param,
project_id: project.to_param,
branch_name: branch,
issue_iid: issue.iid
end
context "valid branch name with encoded slashes" do
let(:branch) { "feature%2Ftest" }
let(:ref) { "<script>alert('ref');</script>" }
it { is_expected.to render_template('new') }
it { project.repository.branch_names.include?('feature/test')}
end
end
......
require 'rails_helper'
feature 'Start new branch from an issue', feature: true do
let!(:project) { create(:project) }
let!(:issue) { create(:issue, project: project) }
let!(:user) { create(:user)}
context "for team members" do
before do
project.team << [user, :master]
login_as(user)
end
it 'shown the new branch button', js: false do
visit namespace_project_issue_path(project.namespace, project, issue)
expect(page).to have_link "New Branch"
end
context "when there is a referenced merge request" do
let(:note) do
create(:note, :on_issue, :system, project: project,
note: "mentioned in !#{referenced_mr.iid}")
end
let(:referenced_mr) do
create(:merge_request, :simple, source_project: project, target_project: project,
description: "Fixes ##{issue.iid}")
end
before do
issue.notes << note
visit namespace_project_issue_path(project.namespace, project, issue)
end
it "hides the new branch button", js: true do
expect(page).not_to have_link "New Branch"
expect(page).to have_content /1 Related Merge Request/
end
end
end
context "for visiters" do
it 'no button is shown', js: false do
visit namespace_project_issue_path(project.namespace, project, issue)
expect(page).not_to have_link "New Branch"
end
end
end
......@@ -8,10 +8,12 @@ describe "Internal Project Access", feature: true do
let(:master) { create(:user) }
let(:guest) { create(:user) }
let(:reporter) { create(:user) }
let(:external_team_member) { create(:user, external: true) }
before do
# full access
project.team << [master, :master]
project.team << [external_team_member, :master]
# readonly
project.team << [reporter, :reporter]
......@@ -34,6 +36,8 @@ describe "Internal Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -45,6 +49,8 @@ describe "Internal Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -56,6 +62,8 @@ describe "Internal Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -67,6 +75,8 @@ describe "Internal Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -78,6 +88,8 @@ describe "Internal Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -89,22 +101,23 @@ describe "Internal Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
describe "GET /:project_path/blob" do
before do
commit = project.repository.commit
path = '.gitignore'
@blob_path = namespace_project_blob_path(project.namespace, project, File.join(commit.id, path))
end
let(:commit) { project.repository.commit }
subject { namespace_project_blob_path(project.namespace, project, File.join(commit.id, '.gitignore')) }
it { expect(@blob_path).to be_allowed_for master }
it { expect(@blob_path).to be_allowed_for reporter }
it { expect(@blob_path).to be_allowed_for :admin }
it { expect(@blob_path).to be_allowed_for guest }
it { expect(@blob_path).to be_allowed_for :user }
it { expect(@blob_path).to be_denied_for :visitor }
it { is_expected.to be_allowed_for master }
it { is_expected.to be_allowed_for reporter }
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
describe "GET /:project_path/edit" do
......@@ -115,6 +128,8 @@ describe "Internal Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -126,6 +141,8 @@ describe "Internal Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -137,6 +154,8 @@ describe "Internal Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -149,6 +168,8 @@ describe "Internal Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -160,6 +181,8 @@ describe "Internal Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -171,6 +194,8 @@ describe "Internal Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -182,6 +207,8 @@ describe "Internal Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -193,6 +220,8 @@ describe "Internal Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -209,6 +238,8 @@ describe "Internal Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -225,6 +256,8 @@ describe "Internal Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -236,6 +269,8 @@ describe "Internal Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
end
......@@ -8,10 +8,12 @@ describe "Private Project Access", feature: true do
let(:master) { create(:user) }
let(:guest) { create(:user) }
let(:reporter) { create(:user) }
let(:external_team_member) { create(:user, external: true) }
before do
# full access
project.team << [master, :master]
project.team << [external_team_member, :master]
# readonly
project.team << [reporter, :reporter]
......@@ -34,6 +36,8 @@ describe "Private Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -45,6 +49,8 @@ describe "Private Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -56,6 +62,8 @@ describe "Private Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -67,6 +75,7 @@ describe "Private Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -78,6 +87,8 @@ describe "Private Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -89,22 +100,23 @@ describe "Private Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
describe "GET /:project_path/blob" do
before do
commit = project.repository.commit
path = '.gitignore'
@blob_path = namespace_project_blob_path(project.namespace, project, File.join(commit.id, path))
end
let(:commit) { project.repository.commit }
subject { namespace_project_blob_path(project.namespace, project, File.join(commit.id, '.gitignore'))}
it { expect(@blob_path).to be_allowed_for master }
it { expect(@blob_path).to be_allowed_for reporter }
it { expect(@blob_path).to be_allowed_for :admin }
it { expect(@blob_path).to be_denied_for guest }
it { expect(@blob_path).to be_denied_for :user }
it { expect(@blob_path).to be_denied_for :visitor }
it { is_expected.to be_allowed_for master }
it { is_expected.to be_allowed_for reporter }
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
describe "GET /:project_path/edit" do
......@@ -115,6 +127,8 @@ describe "Private Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -126,6 +140,8 @@ describe "Private Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -137,6 +153,8 @@ describe "Private Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -149,6 +167,8 @@ describe "Private Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -160,6 +180,8 @@ describe "Private Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -171,6 +193,8 @@ describe "Private Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -187,6 +211,8 @@ describe "Private Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -203,6 +229,8 @@ describe "Private Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
......@@ -214,6 +242,8 @@ describe "Private Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_allowed_for external_team_member }
it { is_expected.to be_denied_for :visitor }
end
end
......@@ -38,6 +38,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :external }
it { is_expected.to be_allowed_for :visitor }
end
......@@ -49,6 +50,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :external }
it { is_expected.to be_allowed_for :visitor }
end
......@@ -60,6 +62,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :external }
it { is_expected.to be_allowed_for :visitor }
end
......@@ -71,6 +74,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :external }
it { is_expected.to be_allowed_for :visitor }
end
......@@ -82,6 +86,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :external }
it { is_expected.to be_allowed_for :visitor }
end
......@@ -93,6 +98,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_denied_for :visitor }
end
......@@ -107,6 +113,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :external }
it { is_expected.to be_allowed_for :visitor }
end
......@@ -118,6 +125,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_denied_for :visitor }
end
end
......@@ -135,6 +143,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :external }
it { is_expected.to be_allowed_for :visitor }
end
......@@ -146,23 +155,22 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_denied_for :visitor }
end
end
describe "GET /:project_path/blob" do
before do
commit = project.repository.commit
path = '.gitignore'
@blob_path = namespace_project_blob_path(project.namespace, project, File.join(commit.id, path))
end
let(:commit) { project.repository.commit }
subject { namespace_project_blob_path(project.namespace, project, File.join(commit.id, '.gitignore')) }
it { expect(@blob_path).to be_allowed_for master }
it { expect(@blob_path).to be_allowed_for reporter }
it { expect(@blob_path).to be_allowed_for :admin }
it { expect(@blob_path).to be_allowed_for guest }
it { expect(@blob_path).to be_allowed_for :user }
it { expect(@blob_path).to be_allowed_for :visitor }
it { is_expected.to be_allowed_for master }
it { is_expected.to be_allowed_for reporter }
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :visitor }
end
describe "GET /:project_path/edit" do
......@@ -173,6 +181,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_denied_for :visitor }
end
......@@ -184,6 +193,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_denied_for :visitor }
end
......@@ -195,6 +205,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :external }
it { is_expected.to be_allowed_for :visitor }
end
......@@ -207,6 +218,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_denied_for :visitor }
end
......@@ -218,6 +230,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :external }
it { is_expected.to be_allowed_for :visitor }
end
......@@ -229,6 +242,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_denied_for :visitor }
end
......@@ -240,6 +254,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :external }
it { is_expected.to be_allowed_for :visitor }
end
......@@ -251,6 +266,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_denied_for :visitor }
end
......@@ -267,6 +283,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :external }
it { is_expected.to be_allowed_for :visitor }
end
......@@ -283,6 +300,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_allowed_for guest }
it { is_expected.to be_allowed_for :user }
it { is_expected.to be_allowed_for :external }
it { is_expected.to be_allowed_for :visitor }
end
......@@ -294,6 +312,7 @@ describe "Public Project Access", feature: true do
it { is_expected.to be_allowed_for :admin }
it { is_expected.to be_denied_for guest }
it { is_expected.to be_denied_for :user }
it { is_expected.to be_denied_for :external }
it { is_expected.to be_denied_for :visitor }
end
end
......@@ -48,6 +48,29 @@ describe Ci::Status do
it { is_expected.to eq 'success' }
end
context 'success and canceled' do
let(:statuses) do
[create(type, status: :success), create(type, status: :canceled)]
end
it { is_expected.to eq 'failed' }
end
context 'all canceled' do
let(:statuses) do
[create(type, status: :canceled), create(type, status: :canceled)]
end
it { is_expected.to eq 'canceled' }
end
context 'success and canceled but allowed to fail' do
let(:statuses) do
[create(type, status: :success),
create(type, status: :canceled, allow_failure: true)]
end
it { is_expected.to eq 'success' }
end
context 'one finished and second running but allowed to fail' do
let(:statuses) do
[create(type, status: :success),
......
......@@ -130,6 +130,15 @@ describe Issue, models: true do
end
end
describe '#related_branches' do
it "should " do
allow(subject.project.repository).to receive(:branch_names).
and_return(["mpempe", "#{subject.iid}mepmep", subject.to_branch_name])
expect(subject.related_branches).to eq [subject.to_branch_name]
end
end
it_behaves_like 'an editable mentionable' do
subject { create(:issue) }
......@@ -140,4 +149,12 @@ describe Issue, models: true do
it_behaves_like 'a Taskable' do
let(:subject) { create :issue }
end
describe "#to_branch_name" do
let(:issue) { build(:issue, title: 'a' * 30) }
it "starts with the issue iid" do
expect(issue.to_branch_name).to match /\A#{issue.iid}-a+\z/
end
end
end
......@@ -101,13 +101,29 @@ describe Repository, models: true do
end
describe 'parsing result' do
subject { repository.parse_search_result(results.first) }
subject { repository.parse_search_result(search_result) }
let(:search_result) { results.first }
it { is_expected.to be_an OpenStruct }
it { expect(subject.filename).to eq('CHANGELOG') }
it { expect(subject.basename).to eq('CHANGELOG') }
it { expect(subject.ref).to eq('master') }
it { expect(subject.startline).to eq(186) }
it { expect(subject.data.lines[2]).to eq(" - Feature: Replace teams with group membership\n") }
context "when filename has extension" do
let(:search_result) { "master:CONTRIBUTE.md:5:- [Contribute to GitLab](#contribute-to-gitlab)\n" }
it { expect(subject.filename).to eq('CONTRIBUTE.md') }
it { expect(subject.basename).to eq('CONTRIBUTE') }
end
context "when file under directory" do
let(:search_result) { "master:a/b/c.md:5:a b c\n" }
it { expect(subject.filename).to eq('a/b/c.md') }
it { expect(subject.basename).to eq('a/b/c') }
end
end
end
......
......@@ -180,6 +180,20 @@ describe User, models: true do
it { is_expected.to respond_to(:is_admin?) }
it { is_expected.to respond_to(:name) }
it { is_expected.to respond_to(:private_token) }
it { is_expected.to respond_to(:external?) }
end
describe 'before save hook' do
context 'when saving an external user' do
let(:user) { create(:user) }
let(:external_user) { create(:user, external: true) }
it "sets other properties aswell" do
expect(external_user.can_create_team).to be_falsey
expect(external_user.can_create_group).to be_falsey
expect(external_user.projects_limit).to be 0
end
end
end
describe '#confirm' do
......@@ -404,6 +418,7 @@ describe User, models: true do
expect(user.projects_limit).to eq(Gitlab.config.gitlab.default_projects_limit)
expect(user.can_create_group).to eq(Gitlab.config.gitlab.default_can_create_group)
expect(user.theme_id).to eq(Gitlab.config.gitlab.default_theme)
expect(user.external).to be_falsey
end
end
......
......@@ -120,6 +120,26 @@ describe API::API, api: true do
expect(response.status).to eq(201)
end
it 'creates non-external users by default' do
post api("/users", admin), attributes_for(:user)
expect(response.status).to eq(201)
user_id = json_response['id']
new_user = User.find(user_id)
expect(new_user).not_to eq nil
expect(new_user.external).to be_falsy
end
it 'should allow an external user to be created' do
post api("/users", admin), attributes_for(:user, external: true)
expect(response.status).to eq(201)
user_id = json_response['id']
new_user = User.find(user_id)
expect(new_user).not_to eq nil
expect(new_user.external).to be_truthy
end
it "should not create user with invalid email" do
post api('/users', admin),
email: 'invalid email',
......@@ -262,6 +282,13 @@ describe API::API, api: true do
expect(user.reload.admin).to eq(true)
end
it "should update external status" do
put api("/users/#{user.id}", admin), { external: true }
expect(response.status).to eq 200
expect(json_response['external']).to eq(true)
expect(user.reload.external?).to be_truthy
end
it "should not update admin status" do
put api("/users/#{admin_user.id}", admin), { can_create_group: false }
expect(response.status).to eq(200)
......
......@@ -280,6 +280,18 @@ describe SystemNoteService, services: true do
end
end
describe '.new_issue_branch' do
subject { described_class.new_issue_branch(noteable, project, author, "1-mepmep") }
it_behaves_like 'a system note'
context 'when a branch is created from the new branch button' do
it 'sets the note text' do
expect(subject.note).to match /\AStarted branch [`1-mepmep`]/
end
end
end
describe '.cross_reference' do
subject { described_class.cross_reference(noteable, mentioner, author) }
......
......@@ -15,6 +15,8 @@ module AccessMatchers
logout
when :admin
login_as(create(:admin))
when :external
login_as(create(:user, external: true))
when User
login_as(user)
else
......
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