Commit 5335b7f6 authored by Robert Speicher's avatar Robert Speicher

Merge remote-tracking branch 'ce/master'

parents dd570f1e 3b303feb
...@@ -76,7 +76,7 @@ Style/BlockEndNewline: ...@@ -76,7 +76,7 @@ Style/BlockEndNewline:
Description: 'Put end statement of multiline block on its own line.' Description: 'Put end statement of multiline block on its own line.'
Enabled: true Enabled: true
Style/Blocks: Style/BlockDelimiters:
Description: >- Description: >-
Avoid using {...} for multi-line blocks (multiline chaining is Avoid using {...} for multi-line blocks (multiline chaining is
always ugly). always ugly).
...@@ -232,6 +232,10 @@ Style/EvenOdd: ...@@ -232,6 +232,10 @@ Style/EvenOdd:
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#predicate-methods' StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#predicate-methods'
Enabled: false Enabled: false
Style/ExtraSpacing:
Description: 'Do not use unnecessary spacing.'
Enabled: false
Style/FileName: Style/FileName:
Description: 'Use snake_case for source file names.' Description: 'Use snake_case for source file names.'
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#snake-case-files' StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#snake-case-files'
...@@ -431,6 +435,14 @@ Style/OpMethod: ...@@ -431,6 +435,14 @@ Style/OpMethod:
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#other-arg' StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#other-arg'
Enabled: false Enabled: false
Style/ParallelAssignment:
Description: >-
Check for simple usages of parallel assignment.
It will only warn when the number of variables
matches on both sides of the assignment.
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parallel-assignment'
Enabled: false
Style/ParenthesesAroundCondition: Style/ParenthesesAroundCondition:
Description: >- Description: >-
Don't use parentheses around the condition of an Don't use parentheses around the condition of an
...@@ -669,6 +681,13 @@ Style/TrailingWhitespace: ...@@ -669,6 +681,13 @@ Style/TrailingWhitespace:
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-whitespace' StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-whitespace'
Enabled: false Enabled: false
Style/TrailingUnderscoreVariable:
Description: >-
Checks for the usage of unneeded trailing underscores at the
end of parallel variable assignment.
AllowNamedUnderscoreVariables: true
Enabled: false
Style/TrivialAccessors: Style/TrivialAccessors:
Description: 'Prefer attr_* methods to trivial readers/writers.' Description: 'Prefer attr_* methods to trivial readers/writers.'
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#attr_family' StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#attr_family'
...@@ -690,11 +709,6 @@ Style/UnneededPercentQ: ...@@ -690,11 +709,6 @@ Style/UnneededPercentQ:
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-q' StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-q'
Enabled: false Enabled: false
Style/UnneededPercentX:
Description: 'Checks for %x when `` would do.'
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-x'
Enabled: false
Style/VariableInterpolation: Style/VariableInterpolation:
Description: >- Description: >-
Don't interpolate global, instance and class variables Don't interpolate global, instance and class variables
...@@ -778,6 +792,10 @@ Metrics/MethodLength: ...@@ -778,6 +792,10 @@ Metrics/MethodLength:
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#short-methods' StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#short-methods'
Enabled: false Enabled: false
Metrics/ModuleLength:
Description: 'Avoid modules longer than 100 lines of code.'
Enabled: false
#################### Lint ################################ #################### Lint ################################
### Warnings ### Warnings
...@@ -961,6 +979,12 @@ Rails/ActionFilter: ...@@ -961,6 +979,12 @@ Rails/ActionFilter:
Description: 'Enforces consistent use of action filter methods.' Description: 'Enforces consistent use of action filter methods.'
Enabled: true Enabled: true
Rails/Date:
Description: >-
Checks the correct usage of date aware methods,
such as Date.today, Date.current etc.
Enabled: false
Rails/DefaultScope: Rails/DefaultScope:
Description: 'Checks if the argument passed to default_scope is a block.' Description: 'Checks if the argument passed to default_scope is a block.'
Enabled: false Enabled: false
...@@ -987,6 +1011,12 @@ Rails/ScopeArgs: ...@@ -987,6 +1011,12 @@ Rails/ScopeArgs:
Description: 'Checks the arguments of ActiveRecord scopes.' Description: 'Checks the arguments of ActiveRecord scopes.'
Enabled: false Enabled: false
Rails/TimeZone:
Description: 'Checks the correct usage of time zone aware methods.'
StyleGuide: 'https://github.com/bbatsov/rails-style-guide#time'
Reference: 'http://danilenko.org/2012/7/6/rails_timezones'
Enabled: false
Rails/Validation: Rails/Validation:
Description: 'Use validates :attribute, hash of validations.' Description: 'Use validates :attribute, hash of validations.'
Enabled: false Enabled: false
......
...@@ -2,6 +2,8 @@ Please view this file on the master branch, on stable branches it's out of date. ...@@ -2,6 +2,8 @@ Please view this file on the master branch, on stable branches it's out of date.
v 8.3.0 (unreleased) v 8.3.0 (unreleased)
- Merge when build succeeds (Zeger-Jan van de Weg) - Merge when build succeeds (Zeger-Jan van de Weg)
- API support for starred projects for authorized user (Zeger-Jan van de Weg)
- Add open_issues_count to project API (Stan Hu)
- Expand character set of usernames created by Omniauth (Corey Hinshaw) - Expand character set of usernames created by Omniauth (Corey Hinshaw)
- Add button to automatically merge a merge request when the build succeeds (Zeger-Jan van de Weg) - Add button to automatically merge a merge request when the build succeeds (Zeger-Jan van de Weg)
- Merge when build succeeds (Zeger-Jan van de Weg) - Merge when build succeeds (Zeger-Jan van de Weg)
...@@ -64,8 +66,6 @@ v 8.2.3 ...@@ -64,8 +66,6 @@ v 8.2.3
- Update documentation for "Guest" permissions - Update documentation for "Guest" permissions
- Properly convert Emoji-only comments into Award Emojis - Properly convert Emoji-only comments into Award Emojis
- Enable devise paranoid mode to prevent user enumeration attack - Enable devise paranoid mode to prevent user enumeration attack
v 8.2.3
- Webhook payload has an added, modified and removed properties for each commit - Webhook payload has an added, modified and removed properties for each commit
- Update documentation for "Guest" permissions - Update documentation for "Guest" permissions
- Properly convert Emoji-only comments into Award Emojis - Properly convert Emoji-only comments into Award Emojis
......
...@@ -222,7 +222,7 @@ group :development do ...@@ -222,7 +222,7 @@ group :development do
gem "annotate", "~> 2.6.0" gem "annotate", "~> 2.6.0"
gem "letter_opener", '~> 1.1.2' gem "letter_opener", '~> 1.1.2'
gem 'quiet_assets', '~> 1.0.2' gem 'quiet_assets', '~> 1.0.2'
gem 'rerun', '~> 0.10.0' gem 'rerun', '~> 0.11.0'
gem 'bullet', require: false gem 'bullet', require: false
gem 'rblineprof', platform: :mri, require: false gem 'rblineprof', platform: :mri, require: false
gem 'web-console', '~> 2.0' gem 'web-console', '~> 2.0'
...@@ -258,7 +258,7 @@ group :development, :test do ...@@ -258,7 +258,7 @@ group :development, :test do
gem 'capybara', '~> 2.4.0' gem 'capybara', '~> 2.4.0'
gem 'capybara-screenshot', '~> 1.0.0' gem 'capybara-screenshot', '~> 1.0.0'
gem 'poltergeist', '~> 1.6.0' gem 'poltergeist', '~> 1.8.1'
gem 'teaspoon', '~> 1.0.0' gem 'teaspoon', '~> 1.0.0'
gem 'teaspoon-jasmine', '~> 2.2.0' gem 'teaspoon-jasmine', '~> 2.2.0'
...@@ -268,7 +268,7 @@ group :development, :test do ...@@ -268,7 +268,7 @@ group :development, :test do
gem 'spring-commands-spinach', '~> 1.0.0' gem 'spring-commands-spinach', '~> 1.0.0'
gem 'spring-commands-teaspoon', '~> 0.0.2' gem 'spring-commands-teaspoon', '~> 0.0.2'
gem 'rubocop', '~> 0.28.0', require: false gem 'rubocop', '~> 0.35.0', require: false
gem 'coveralls', '~> 0.8.2', require: false gem 'coveralls', '~> 0.8.2', require: false
gem 'simplecov', '~> 0.10.0', require: false gem 'simplecov', '~> 0.10.0', require: false
gem 'flog', require: false gem 'flog', require: false
......
...@@ -117,23 +117,6 @@ GEM ...@@ -117,23 +117,6 @@ GEM
activemodel (>= 3.2.0) activemodel (>= 3.2.0)
activesupport (>= 3.2.0) activesupport (>= 3.2.0)
json (>= 1.7) json (>= 1.7)
celluloid (0.17.2)
celluloid-essentials
celluloid-extras
celluloid-fsm
celluloid-pool
celluloid-supervision
timers (>= 4.1.1)
celluloid-essentials (0.20.5)
timers (>= 4.1.1)
celluloid-extras (0.20.5)
timers (>= 4.1.1)
celluloid-fsm (0.20.5)
timers (>= 4.1.1)
celluloid-pool (0.20.5)
timers (>= 4.1.1)
celluloid-supervision (0.20.5)
timers (>= 4.1.1)
charlock_holmes (0.7.3) charlock_holmes (0.7.3)
chunky_png (1.3.5) chunky_png (1.3.5)
cliver (0.3.2) cliver (0.3.2)
...@@ -374,7 +357,6 @@ GEM ...@@ -374,7 +357,6 @@ GEM
hipchat (1.5.2) hipchat (1.5.2)
httparty httparty
mimemagic mimemagic
hitimes (1.2.3)
html-pipeline (1.11.0) html-pipeline (1.11.0)
activesupport (>= 2) activesupport (>= 2)
nokogiri (~> 1.4) nokogiri (~> 1.4)
...@@ -415,8 +397,7 @@ GEM ...@@ -415,8 +397,7 @@ GEM
addressable (~> 2.3) addressable (~> 2.3)
letter_opener (1.1.2) letter_opener (1.1.2)
launchy (~> 2.2) launchy (~> 2.2)
listen (2.9.0) listen (3.0.5)
celluloid (>= 0.15.2)
rb-fsevent (>= 0.9.3) rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9) rb-inotify (>= 0.9)
loofah (2.0.3) loofah (2.0.3)
...@@ -429,7 +410,7 @@ GEM ...@@ -429,7 +410,7 @@ GEM
method_source (0.8.2) method_source (0.8.2)
mime-types (1.25.1) mime-types (1.25.1)
mimemagic (0.3.0) mimemagic (0.3.0)
mini_portile (0.6.2) mini_portile2 (2.0.0)
minitest (5.7.0) minitest (5.7.0)
mousetrap-rails (1.4.6) mousetrap-rails (1.4.6)
multi_json (1.11.2) multi_json (1.11.2)
...@@ -444,8 +425,8 @@ GEM ...@@ -444,8 +425,8 @@ GEM
grape grape
newrelic_rpm newrelic_rpm
newrelic_rpm (3.9.4.245) newrelic_rpm (3.9.4.245)
nokogiri (1.6.6.4) nokogiri (1.6.7)
mini_portile (~> 0.6.0) mini_portile2 (~> 2.0.0.rc2)
nprogress-rails (0.1.6.7) nprogress-rails (0.1.6.7)
oauth (0.4.7) oauth (0.4.7)
oauth2 (1.0.0) oauth2 (1.0.0)
...@@ -512,13 +493,13 @@ GEM ...@@ -512,13 +493,13 @@ GEM
parser (2.2.3.0) parser (2.2.3.0)
ast (>= 1.1, < 3.0) ast (>= 1.1, < 3.0)
pg (0.18.4) pg (0.18.4)
poltergeist (1.6.0) poltergeist (1.8.1)
capybara (~> 2.1) capybara (~> 2.1)
cliver (~> 0.3.1) cliver (~> 0.3.1)
multi_json (~> 1.0) multi_json (~> 1.0)
websocket-driver (>= 0.2.0) websocket-driver (>= 0.2.0)
posix-spawn (0.3.11) posix-spawn (0.3.11)
powerpack (0.0.9) powerpack (0.1.1)
pry (0.10.3) pry (0.10.3)
coderay (~> 1.1.0) coderay (~> 1.1.0)
method_source (~> 0.8.1) method_source (~> 0.8.1)
...@@ -606,8 +587,8 @@ GEM ...@@ -606,8 +587,8 @@ GEM
redis-store (1.1.7) redis-store (1.1.7)
redis (>= 2.2) redis (>= 2.2)
request_store (1.2.1) request_store (1.2.1)
rerun (0.10.0) rerun (0.11.0)
listen (~> 2.7, >= 2.7.3) listen (~> 3.0)
responders (2.1.0) responders (2.1.0)
railties (>= 4.2.0, < 5) railties (>= 4.2.0, < 5)
rest-client (1.8.0) rest-client (1.8.0)
...@@ -642,12 +623,13 @@ GEM ...@@ -642,12 +623,13 @@ GEM
rspec-mocks (~> 3.3.0) rspec-mocks (~> 3.3.0)
rspec-support (~> 3.3.0) rspec-support (~> 3.3.0)
rspec-support (3.3.0) rspec-support (3.3.0)
rubocop (0.28.0) rubocop (0.35.1)
astrolabe (~> 1.3) astrolabe (~> 1.3)
parser (>= 2.2.0.pre.7, < 3.0) parser (>= 2.2.3.0, < 3.0)
powerpack (~> 0.0.6) powerpack (~> 0.1)
rainbow (>= 1.99.1, < 3.0) rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.4) ruby-progressbar (~> 1.7)
tins (<= 1.6.0)
ruby-fogbugz (0.2.1) ruby-fogbugz (0.2.1)
crack (~> 0.4) crack (~> 0.4)
ruby-progressbar (1.7.5) ruby-progressbar (1.7.5)
...@@ -763,8 +745,6 @@ GEM ...@@ -763,8 +745,6 @@ GEM
thor (0.19.1) thor (0.19.1)
thread_safe (0.3.5) thread_safe (0.3.5)
tilt (1.4.1) tilt (1.4.1)
timers (4.1.1)
hitimes
timfel-krb5-auth (0.8.3) timfel-krb5-auth (0.8.3)
tinder (1.10.1) tinder (1.10.1)
eventmachine (~> 1.0) eventmachine (~> 1.0)
...@@ -934,7 +914,7 @@ DEPENDENCIES ...@@ -934,7 +914,7 @@ DEPENDENCIES
org-ruby (~> 0.9.12) org-ruby (~> 0.9.12)
paranoia (~> 2.0) paranoia (~> 2.0)
pg (~> 0.18.2) pg (~> 0.18.2)
poltergeist (~> 1.6.0) poltergeist (~> 1.8.1)
pry-rails pry-rails
quiet_assets (~> 1.0.2) quiet_assets (~> 1.0.2)
rack-attack (~> 4.3.0) rack-attack (~> 4.3.0)
...@@ -949,12 +929,12 @@ DEPENDENCIES ...@@ -949,12 +929,12 @@ DEPENDENCIES
redis-namespace redis-namespace
redis-rails (~> 4.0.0) redis-rails (~> 4.0.0)
request_store (~> 1.2.0) request_store (~> 1.2.0)
rerun (~> 0.10.0) rerun (~> 0.11.0)
responders (~> 2.0) responders (~> 2.0)
rouge (~> 1.10.1) rouge (~> 1.10.1)
rqrcode-rails3 (~> 0.1.7) rqrcode-rails3 (~> 0.1.7)
rspec-rails (~> 3.3.0) rspec-rails (~> 3.3.0)
rubocop (~> 0.28.0) rubocop (~> 0.35.0)
ruby-fogbugz (~> 0.2.1) ruby-fogbugz (~> 0.2.1)
sanitize (~> 2.0) sanitize (~> 2.0)
sass-rails (~> 4.0.5) sass-rails (~> 4.0.5)
......
...@@ -18,7 +18,7 @@ class @IssuableContext ...@@ -18,7 +18,7 @@ class @IssuableContext
$('.issuable-affix').affix offset: $('.issuable-affix').affix offset:
top: -> top: ->
@top = ($('.issuable-affix').offset().top - 60) @top = ($('.issuable-affix').offset().top - 70)
bottom: -> bottom: ->
@bottom = $('.footer').outerHeight(true) @bottom = $('.footer').outerHeight(true)
......
...@@ -10,12 +10,12 @@ class @Issue ...@@ -10,12 +10,12 @@ class @Issue
@initTaskList() @initTaskList()
initTaskList: -> initTaskList: ->
$('.issue-details .js-task-list-container').taskList('enable') $('.detail-page-description .js-task-list-container').taskList('enable')
$(document).on 'tasklist:changed', '.issue-details .js-task-list-container', @updateTaskList $(document).on 'tasklist:changed', '.detail-page-description .js-task-list-container', @updateTaskList
disableTaskList: -> disableTaskList: ->
$('.issue-details .js-task-list-container').taskList('disable') $('.detail-page-description .js-task-list-container').taskList('disable')
$(document).off 'tasklist:changed', '.issue-details .js-task-list-container' $(document).off 'tasklist:changed', '.detail-page-description .js-task-list-container'
# TODO (rspeicher): Make the issue description inline-editable like a note so # TODO (rspeicher): Make the issue description inline-editable like a note so
# that we can re-use its form here # that we can re-use its form here
......
...@@ -40,12 +40,12 @@ class @MergeRequest ...@@ -40,12 +40,12 @@ class @MergeRequest
this.$('.all-commits').removeClass 'hide' this.$('.all-commits').removeClass 'hide'
initTaskList: -> initTaskList: ->
$('.merge-request-details .js-task-list-container').taskList('enable') $('.detail-page-description .js-task-list-container').taskList('enable')
$(document).on 'tasklist:changed', '.merge-request-details .js-task-list-container', @updateTaskList $(document).on 'tasklist:changed', '.detail-page-description .js-task-list-container', @updateTaskList
disableTaskList: -> disableTaskList: ->
$('.merge-request-details .js-task-list-container').taskList('disable') $('.detail-page-description .js-task-list-container').taskList('disable')
$(document).off 'tasklist:changed', '.merge-request-details .js-task-list-container' $(document).off 'tasklist:changed', '.detail-page-description .js-task-list-container'
# TODO (rspeicher): Make the merge request description inline-editable like a # TODO (rspeicher): Make the merge request description inline-editable like a
# note so that we can re-use its form here # note so that we can re-use its form here
......
...@@ -410,6 +410,11 @@ table { ...@@ -410,6 +410,11 @@ table {
border-bottom: 1px solid $border-color; border-bottom: 1px solid $border-color;
height: 57px; height: 57px;
} }
&.wide {
margin-left: -$gl-padding;
margin-right: -$gl-padding;
}
} }
.center-middle-menu { .center-middle-menu {
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* *
*/ */
.issue-box { .status-box {
@include border-radius(2px); @include border-radius(2px);
display: block; display: block;
...@@ -14,22 +14,22 @@ ...@@ -14,22 +14,22 @@
margin-right: 10px; margin-right: 10px;
font-size: $gl-font-size; font-size: $gl-font-size;
&.issue-box-closed { &.status-box-closed {
background-color: $gl-danger; background-color: $gl-danger;
color: #FFF; color: #FFF;
} }
&.issue-box-merged { &.status-box-merged {
background-color: $gl-primary; background-color: $gl-primary;
color: #FFF; color: #FFF;
} }
&.issue-box-open { &.status-box-open {
background-color: #019875; background-color: #019875;
color: #FFF; color: #FFF;
} }
&.issue-box-expired { &.status-box-expired {
background: #cea61b; background: #cea61b;
color: #FFF; color: #FFF;
} }
......
...@@ -143,7 +143,11 @@ ul.controls { ...@@ -143,7 +143,11 @@ ul.controls {
> li { > li {
float: left; float: left;
padding-right: 10px; margin-right: 10px;
&:last-child {
margin-right: 0;
}
.author_link { .author_link {
display: inline-block; display: inline-block;
......
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
.new_note, .new_note,
.edit_note, .edit_note,
.issuable-description, .detail-page-description,
.milestone-description, .milestone-description,
.wiki-content, .wiki-content,
.merge-request-form { .merge-request-form {
......
...@@ -10,8 +10,7 @@ ...@@ -10,8 +10,7 @@
margin-left: -$gl-padding; margin-left: -$gl-padding;
margin-right: -$gl-padding; margin-right: -$gl-padding;
color: $gl-gray; color: $gl-gray;
border-bottom: 1px solid #ECEEF1; border-bottom: 1px solid $border-white-light;
border-right: 1px solid #ECEEF1;
&:target { &:target {
background: $hover; background: $hover;
......
...@@ -19,7 +19,7 @@ $border-color: #dce0e6; ...@@ -19,7 +19,7 @@ $border-color: #dce0e6;
$table-border-color: #eef0f2; $table-border-color: #eef0f2;
$background-color: #F7F8FA; $background-color: #F7F8FA;
$header-height: 58px; $header-height: 58px;
$fixed-layout-width: 1200px; $fixed-layout-width: 1280px;
$gl-gray: #7f8fa4; $gl-gray: #7f8fa4;
$gl-padding: 16px; $gl-padding: 16px;
$gl-avatar-size: 46px; $gl-avatar-size: 46px;
......
.detail-page-header {
margin: -$gl-padding;
padding: 7px $gl-padding;
margin-bottom: 0px;
border-bottom: 1px solid $border-color;
color: #5c5d5e;
font-size: 16px;
line-height: 42px;
.author {
color: #5c5d5e;
}
.identifier {
color: #5c5d5e;
}
}
.detail-page-description {
.title {
margin: 0;
font-size: 23px;
color: #313236;
}
.description {
margin-top: 6px;
p:last-child {
margin-bottom: 0;
}
}
}
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
&.affix { &.affix {
position: fixed; position: fixed;
top: 60px; top: 70px;
margin-right: 35px; margin-right: 35px;
} }
} }
...@@ -36,33 +36,12 @@ ...@@ -36,33 +36,12 @@
} }
.issuable-details { .issuable-details {
.issue-title {
margin: 0;
font-size: 23px;
color: #313236;
}
.description {
margin-top: 6px;
p:last-child {
margin-bottom: 0;
}
}
section { section {
border-right: 1px solid #ECEEF1; border-right: 1px solid $border-white-light;
> .tab-content { .issuable-discussion {
margin-right: 1px; margin-right: 1px;
} }
.issue-discussion > .gray-content-block,
> .gray-content-block {
margin-top: 0;
border-top: none;
margin-right: -15px;
}
} }
} }
...@@ -136,21 +115,3 @@ ...@@ -136,21 +115,3 @@
margin-right: 2px; margin-right: 2px;
} }
} }
.issuable-title {
margin: -$gl-padding;
padding: 7px $gl-padding;
margin-bottom: 0px;
border-bottom: 1px solid $border-color;
color: #5c5d5e;
font-size: 16px;
line-height: 42px;
.author {
color: #5c5d5e;
}
.issuable-id {
color: #5c5d5e;
}
}
...@@ -141,11 +141,6 @@ form.edit-issue { ...@@ -141,11 +141,6 @@ form.edit-issue {
} }
} }
.issue-closed-by-widget {
padding: 16px 0;
margin: 0px;
}
.issue-form .select2-container { .issue-form .select2-container {
width: 250px !important; width: 250px !important;
} }
...@@ -191,7 +191,7 @@ ...@@ -191,7 +191,7 @@
.btn-clipboard { .btn-clipboard {
@extend .pull-right; @extend .pull-right;
margin-right: 18px; margin-right: 20px;
margin-top: 5px; margin-top: 5px;
position: absolute; position: absolute;
right: 0; right: 0;
......
...@@ -79,7 +79,6 @@ ...@@ -79,7 +79,6 @@
padding: $gl-padding; padding: $gl-padding;
margin-left: -$gl-padding; margin-left: -$gl-padding;
margin-right: -$gl-padding; margin-right: -$gl-padding;
border-right: 1px solid $border-color;
border-top: 1px solid $border-color; border-top: 1px solid $border-color;
margin-bottom: -$gl-padding; margin-bottom: -$gl-padding;
} }
......
...@@ -35,3 +35,20 @@ ...@@ -35,3 +35,20 @@
border-color: $gl-warning; border-color: $gl-warning;
} }
} }
.ci-status-icon-success {
@extend .cgreen;
}
.ci-status-icon-failed {
@extend .cred;
}
.ci-status-icon-running,
.ci-status-icon-pending {
// These are standard text color
}
.ci-status-icon-canceled,
.ci-status-icon-disabled,
.ci-status-icon-not-found,
.ci-status-icon-skipped {
@extend .cgray;
}
class Dashboard::SnippetsController < Dashboard::ApplicationController class Dashboard::SnippetsController < Dashboard::ApplicationController
def index def index
@snippets = SnippetsFinder.new.execute(current_user, @snippets = SnippetsFinder.new.execute(
current_user,
filter: :by_user, filter: :by_user,
user: current_user, user: current_user,
scope: params[:scope] scope: params[:scope]
......
...@@ -7,7 +7,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -7,7 +7,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
before_action :closes_issues, only: [:edit, :update, :show, :diffs, :commits, :builds] before_action :closes_issues, only: [:edit, :update, :show, :diffs, :commits, :builds]
before_action :validates_merge_request, only: [:show, :diffs, :commits, :builds] before_action :validates_merge_request, only: [:show, :diffs, :commits, :builds]
before_action :define_show_vars, only: [:show, :diffs, :commits, :builds] before_action :define_show_vars, only: [:show, :diffs, :commits, :builds]
before_action :define_widget_vars, only: [:merge, :cancel_merge_when_build_succeeds] before_action :define_widget_vars, only: [:merge, :cancel_merge_when_build_succeeds, :merge_check]
before_action :ensure_ref_fetched, only: [:show, :diffs, :commits, :builds] before_action :ensure_ref_fetched, only: [:show, :diffs, :commits, :builds]
# Allow read any merge_request # Allow read any merge_request
...@@ -159,11 +159,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -159,11 +159,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end end
def merge_check def merge_check
if @merge_request.unchecked? @merge_request.check_if_can_be_merged if @merge_request.unchecked?
@merge_request.check_if_can_be_merged
end
closes_issues
render partial: "projects/merge_requests/widget/show.html.haml", layout: false render partial: "projects/merge_requests/widget/show.html.haml", layout: false
end end
...@@ -185,7 +181,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -185,7 +181,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@merge_request.update(merge_error: nil) @merge_request.update(merge_error: nil)
if params[:merge_when_build_succeeds] && @merge_request.ci_commit && @merge_request.ci_commit.active? if params[:merge_when_build_succeeds].present? && @merge_request.ci_commit && @merge_request.ci_commit.active?
MergeRequests::MergeWhenBuildSucceedsService.new(@project, current_user, merge_params) MergeRequests::MergeWhenBuildSucceedsService.new(@project, current_user, merge_params)
.execute(@merge_request) .execute(@merge_request)
@status = :merge_when_build_succeeds @status = :merge_when_build_succeeds
...@@ -341,6 +337,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -341,6 +337,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def define_widget_vars def define_widget_vars
@ci_commit = @merge_request.ci_commit @ci_commit = @merge_request.ci_commit
closes_issues
end end
def invalid_mr def invalid_mr
......
...@@ -69,7 +69,7 @@ class Projects::NotesController < Projects::ApplicationController ...@@ -69,7 +69,7 @@ class Projects::NotesController < Projects::ApplicationController
data = { data = {
author: current_user, author: current_user,
is_award: true, is_award: true,
note: note_params[:note].gsub(":", '') note: note_params[:note].delete(":")
} }
note = noteable.notes.find_by(data) note = noteable.notes.find_by(data)
......
...@@ -21,7 +21,7 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController ...@@ -21,7 +21,7 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
if protected_branch && if protected_branch &&
protected_branch.update_attributes( protected_branch.update_attributes(
developers_can_push: params[:developers_can_push] developers_can_push: params[:developers_can_push]
) )
respond_to do |format| respond_to do |format|
......
...@@ -61,7 +61,7 @@ module ApplicationHelper ...@@ -61,7 +61,7 @@ module ApplicationHelper
options[:class] ||= '' options[:class] ||= ''
options[:class] << ' identicon' options[:class] << ' identicon'
bg_key = project.id % 7 bg_key = project.id % 7
style = "background-color: ##{ allowed_colors.values[bg_key] }; color: #555" style = "background-color: ##{allowed_colors.values[bg_key]}; color: #555"
content_tag(:div, class: options[:class], style: style) do content_tag(:div, class: options[:class], style: style) do
project.name[0, 1].upcase project.name[0, 1].upcase
...@@ -204,12 +204,16 @@ module ApplicationHelper ...@@ -204,12 +204,16 @@ module ApplicationHelper
# Returns an HTML-safe String # Returns an HTML-safe String
def time_ago_with_tooltip(time, placement: 'top', html_class: 'time_ago', skip_js: false) def time_ago_with_tooltip(time, placement: 'top', html_class: 'time_ago', skip_js: false)
element = content_tag :time, time.to_s, element = content_tag :time, time.to_s,
class: "#{html_class} js-timeago", class: "#{html_class} js-timeago js-timeago-pending",
datetime: time.to_time.getutc.iso8601, datetime: time.to_time.getutc.iso8601,
title: time.in_time_zone.stamp('Aug 21, 2011 9:23pm'), title: time.in_time_zone.stamp('Aug 21, 2011 9:23pm'),
data: { toggle: 'tooltip', placement: placement, container: 'body' } data: { toggle: 'tooltip', placement: placement, container: 'body' }
element += javascript_tag "$('.js-timeago').last().timeago()" unless skip_js unless skip_js
element << javascript_tag(
"$('.js-timeago-pending').removeClass('js-timeago-pending').timeago()"
)
end
element element
end end
......
...@@ -10,8 +10,8 @@ module ButtonHelper ...@@ -10,8 +10,8 @@ module ButtonHelper
# # => "<button class='...' data-clipboard-text='Foo'>...</button>" # # => "<button class='...' data-clipboard-text='Foo'>...</button>"
# #
# # Define the target element # # Define the target element
# clipboard_button(clipboard_target: "#foo") # clipboard_button(clipboard_target: "div#foo")
# # => "<button class='...' data-clipboard-target='#foo'>...</button>" # # => "<button class='...' data-clipboard-target='div#foo'>...</button>"
# #
# See http://clipboardjs.com/#usage # See http://clipboardjs.com/#usage
def clipboard_button(data = {}) def clipboard_button(data = {})
......
...@@ -12,19 +12,6 @@ module CiStatusHelper ...@@ -12,19 +12,6 @@ module CiStatusHelper
ci_label_for_status(ci_commit.status) ci_label_for_status(ci_commit.status)
end end
def ci_status_color(ci_commit)
case ci_commit.status
when 'success'
'green'
when 'failed'
'red'
when 'running', 'pending'
'yellow'
else
'gray'
end
end
def ci_status_with_icon(status) def ci_status_with_icon(status)
content_tag :span, class: "ci-status ci-#{status}" do content_tag :span, class: "ci-status ci-#{status}" do
ci_icon_for_status(status) + '&nbsp;'.html_safe + ci_label_for_status(status) ci_icon_for_status(status) + '&nbsp;'.html_safe + ci_label_for_status(status)
...@@ -56,12 +43,11 @@ module CiStatusHelper ...@@ -56,12 +43,11 @@ module CiStatusHelper
end end
def render_ci_status(ci_commit) def render_ci_status(ci_commit)
link_to ci_status_path(ci_commit), link_to ci_status_icon(ci_commit),
class: "ci-status-link c#{ci_status_color(ci_commit)}", ci_status_path(ci_commit),
class: "ci-status-link ci-status-icon-#{ci_commit.status.dasherize}",
title: "Build #{ci_status_label(ci_commit)}", title: "Build #{ci_status_label(ci_commit)}",
data: { toggle: 'tooltip', placement: 'left' } do data: { toggle: 'tooltip', placement: 'left' }
ci_status_icon(ci_commit)
end
end end
def no_runners_for_project?(project) def no_runners_for_project?(project)
......
module ExternalWikiHelper module ExternalWikiHelper
def get_project_wiki_path(project) def get_project_wiki_path(project)
external_wiki_service = project.services. external_wiki_service = project.services.
select { |service| service.to_param == 'external_wiki' }.first find { |service| service.to_param == 'external_wiki' }
if external_wiki_service.present? && external_wiki_service.active? if external_wiki_service.present? && external_wiki_service.active?
external_wiki_service.properties['external_wiki_url'] external_wiki_service.properties['external_wiki_url']
else else
......
...@@ -20,7 +20,7 @@ module GitlabMarkdownHelper ...@@ -20,7 +20,7 @@ module GitlabMarkdownHelper
end end
user = current_user if defined?(current_user) user = current_user if defined?(current_user)
gfm_body = Gitlab::Markdown.render(escaped_body, project: @project, current_user: user, pipeline: :single_line) gfm_body = Banzai.render(escaped_body, project: @project, current_user: user, pipeline: :single_line)
fragment = Nokogiri::HTML::DocumentFragment.parse(gfm_body) fragment = Nokogiri::HTML::DocumentFragment.parse(gfm_body)
if fragment.children.size == 1 && fragment.children[0].name == 'a' if fragment.children.size == 1 && fragment.children[0].name == 'a'
...@@ -50,7 +50,7 @@ module GitlabMarkdownHelper ...@@ -50,7 +50,7 @@ module GitlabMarkdownHelper
context[:project] ||= @project context[:project] ||= @project
html = Gitlab::Markdown.render(text, context) html = Banzai.render(text, context)
context.merge!( context.merge!(
current_user: (current_user if defined?(current_user)), current_user: (current_user if defined?(current_user)),
...@@ -61,11 +61,12 @@ module GitlabMarkdownHelper ...@@ -61,11 +61,12 @@ module GitlabMarkdownHelper
ref: @ref ref: @ref
) )
Gitlab::Markdown.post_process(html, context) Banzai.post_process(html, context)
end end
def asciidoc(text) def asciidoc(text)
Gitlab::Asciidoc.render(text, Gitlab::Asciidoc.render(
text,
project: @project, project: @project,
current_user: (current_user if defined?(current_user)), current_user: (current_user if defined?(current_user)),
......
...@@ -57,15 +57,15 @@ module IssuesHelper ...@@ -57,15 +57,15 @@ module IssuesHelper
options_from_collection_for_select(milestones, 'id', 'title', object.milestone_id) options_from_collection_for_select(milestones, 'id', 'title', object.milestone_id)
end end
def issue_box_class(item) def status_box_class(item)
if item.respond_to?(:expired?) && item.expired? if item.respond_to?(:expired?) && item.expired?
'issue-box-expired' 'status-box-expired'
elsif item.respond_to?(:merged?) && item.merged? elsif item.respond_to?(:merged?) && item.merged?
'issue-box-merged' 'status-box-merged'
elsif item.closed? elsif item.closed?
'issue-box-closed' 'status-box-closed'
else else
'issue-box-open' 'status-box-open'
end end
end end
...@@ -121,6 +121,6 @@ module IssuesHelper ...@@ -121,6 +121,6 @@ module IssuesHelper
end end
end end
# Required for Gitlab::Markdown::IssueReferenceFilter # Required for Banzai::Filter::IssueReferenceFilter
module_function :url_for_issue module_function :url_for_issue
end end
...@@ -107,6 +107,6 @@ module LabelsHelper ...@@ -107,6 +107,6 @@ module LabelsHelper
options_from_collection_for_select(grouped_labels, 'name', 'title', params[:label_name]) options_from_collection_for_select(grouped_labels, 'name', 'title', params[:label_name])
end end
# Required for Gitlab::Markdown::LabelReferenceFilter # Required for Banzai::Filter::LabelReferenceFilter
module_function :render_colored_label, :text_color_for_bg, :escape_once module_function :render_colored_label, :text_color_for_bg, :escape_once
end end
...@@ -343,10 +343,9 @@ module ProjectsHelper ...@@ -343,10 +343,9 @@ module ProjectsHelper
def filename_path(project, filename) def filename_path(project, filename)
if project && blob = project.repository.send(filename) if project && blob = project.repository.send(filename)
namespace_project_blob_path( namespace_project_blob_path(
project.namespace, project.namespace,
project, project,
tree_join(project.default_branch, tree_join(project.default_branch, blob.name)
blob.name)
) )
end end
end end
......
...@@ -79,7 +79,7 @@ module TreeHelper ...@@ -79,7 +79,7 @@ module TreeHelper
part_path = File.join(part_path, part) unless part_path.empty? part_path = File.join(part_path, part) unless part_path.empty?
part_path = part if part_path.empty? part_path = part if part_path.empty?
next unless parts.last(2).include?(part) if parts.count > max_links next if parts.count > max_links && !parts.last(2).include?(part)
yield(part, tree_join(@ref, part_path)) yield(part, tree_join(@ref, part_path))
end end
end end
......
...@@ -18,7 +18,7 @@ class Notify < BaseMailer ...@@ -18,7 +18,7 @@ class Notify < BaseMailer
subject: subject, subject: subject,
body: body.html_safe, body: body.html_safe,
content_type: 'text/html' content_type: 'text/html'
) )
end end
# Splits "gitlab.corp.company.com" up into "gitlab.corp.company.com", # Splits "gitlab.corp.company.com" up into "gitlab.corp.company.com",
......
...@@ -127,12 +127,12 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -127,12 +127,12 @@ class ApplicationSetting < ActiveRecord::Base
def restricted_signup_domains_raw=(values) def restricted_signup_domains_raw=(values)
self.restricted_signup_domains = [] self.restricted_signup_domains = []
self.restricted_signup_domains = values.split( self.restricted_signup_domains = values.split(
/\s*[,;]\s* # comma or semicolon, optionally surrounded by whitespace /\s*[,;]\s* # comma or semicolon, optionally surrounded by whitespace
| # or | # or
\s # any whitespace character \s # any whitespace character
| # or | # or
[\r\n] # any number of newline characters [\r\n] # any number of newline characters
/x) /x)
self.restricted_signup_domains.reject! { |d| d.empty? } self.restricted_signup_domains.reject! { |d| d.empty? }
end end
end end
...@@ -23,7 +23,7 @@ module Mentionable ...@@ -23,7 +23,7 @@ module Mentionable
included do included do
if self < Participable if self < Participable
participant ->(current_user) { mentioned_users(current_user, load_lazy_references: false) } participant ->(current_user) { mentioned_users(current_user) }
end end
end end
...@@ -43,15 +43,15 @@ module Mentionable ...@@ -43,15 +43,15 @@ module Mentionable
self self
end end
def all_references(current_user = self.author, text = nil, load_lazy_references: true) def all_references(current_user = self.author, text = nil)
ext = Gitlab::ReferenceExtractor.new(self.project, current_user, load_lazy_references: load_lazy_references) ext = Gitlab::ReferenceExtractor.new(self.project, current_user)
if text if text
ext.analyze(text) ext.analyze(text)
else else
self.class.mentionable_attrs.each do |attr, options| self.class.mentionable_attrs.each do |attr, options|
text = send(attr) text = send(attr)
options[:cache_key] = [self, attr] if options.delete(:cache) options[:cache_key] = [self, attr] if options.delete(:cache) && self.persisted?
ext.analyze(text, options) ext.analyze(text, options)
end end
end end
...@@ -59,13 +59,13 @@ module Mentionable ...@@ -59,13 +59,13 @@ module Mentionable
ext ext
end end
def mentioned_users(current_user = nil, load_lazy_references: true) def mentioned_users(current_user = nil)
all_references(current_user, load_lazy_references: load_lazy_references).users all_references(current_user).users
end end
# Extract GFM references to other Mentionables from this Mentionable. Always excludes its #local_reference. # Extract GFM references to other Mentionables from this Mentionable. Always excludes its #local_reference.
def referenced_mentionables(current_user = self.author, text = nil, load_lazy_references: true) def referenced_mentionables(current_user = self.author, text = nil)
refs = all_references(current_user, text, load_lazy_references: load_lazy_references) refs = all_references(current_user, text)
refs = (refs.issues + refs.merge_requests + refs.commits) refs = (refs.issues + refs.merge_requests + refs.commits)
# We're using this method instead of Array diffing because that requires # We're using this method instead of Array diffing because that requires
......
...@@ -38,20 +38,21 @@ module Participable ...@@ -38,20 +38,21 @@ module Participable
# Be aware that this method makes a lot of sql queries. # Be aware that this method makes a lot of sql queries.
# Save result into variable if you are going to reuse it inside same request # Save result into variable if you are going to reuse it inside same request
def participants(current_user = self.author, load_lazy_references: true) def participants(current_user = self.author, load_lazy_references: true)
participants = self.class.participant_attrs.flat_map do |attr| participants =
value = Gitlab::ReferenceExtractor.lazily do
if attr.respond_to?(:call) self.class.participant_attrs.flat_map do |attr|
instance_exec(current_user, &attr) value =
else if attr.respond_to?(:call)
send(attr) instance_exec(current_user, &attr)
end else
send(attr)
end
participants_for(value, current_user) participants_for(value, current_user)
end.compact.uniq end.compact.uniq
end
if load_lazy_references
participants = Gitlab::Markdown::ReferenceFilter::LazyReference.load(participants).uniq
unless Gitlab::ReferenceExtractor.lazy?
participants.select! do |user| participants.select! do |user|
user.can?(:read_project, project) user.can?(:read_project, project)
end end
...@@ -64,12 +65,12 @@ module Participable ...@@ -64,12 +65,12 @@ module Participable
def participants_for(value, current_user = nil) def participants_for(value, current_user = nil)
case value case value
when User, Gitlab::Markdown::ReferenceFilter::LazyReference when User, Banzai::LazyReference
[value] [value]
when Enumerable, ActiveRecord::Relation when Enumerable, ActiveRecord::Relation
value.flat_map { |v| participants_for(v, current_user) } value.flat_map { |v| participants_for(v, current_user) }
when Participable when Participable
value.participants(current_user, load_lazy_references: false) value.participants(current_user)
end end
end end
end end
...@@ -13,7 +13,7 @@ module TokenAuthenticatable ...@@ -13,7 +13,7 @@ module TokenAuthenticatable
@token_fields << token_field @token_fields << token_field
define_singleton_method("find_by_#{token_field}") do |token| define_singleton_method("find_by_#{token_field}") do |token|
where(token_field => token).first if token find_by(token_field => token) if token
end end
define_method("ensure_#{token_field}") do define_method("ensure_#{token_field}") do
...@@ -37,7 +37,7 @@ module TokenAuthenticatable ...@@ -37,7 +37,7 @@ module TokenAuthenticatable
def generate_token_for(token_field) def generate_token_for(token_field)
loop do loop do
token = Devise.friendly_token token = Devise.friendly_token
break token unless self.class.unscoped.where(token_field => token).first break token unless self.class.unscoped.find_by(token_field => token)
end end
end end
end end
...@@ -84,11 +84,11 @@ class Issue < ActiveRecord::Base ...@@ -84,11 +84,11 @@ class Issue < ActiveRecord::Base
end end
def referenced_merge_requests def referenced_merge_requests
references = [self, *notes].flat_map do |note| Gitlab::ReferenceExtractor.lazily do
note.all_references(load_lazy_references: false).merge_requests [self, *notes].flat_map do |note|
end.uniq note.all_references(load_lazy_references: false).merge_requests
end
Gitlab::Markdown::ReferenceFilter::LazyReference.load(references).uniq.sort_by(&:iid) end.sort_by(&:iid)
end end
# Reset issue events cache # Reset issue events cache
......
...@@ -197,9 +197,7 @@ class MergeRequest < ActiveRecord::Base ...@@ -197,9 +197,7 @@ class MergeRequest < ActiveRecord::Base
similar_mrs = similar_mrs.where('id not in (?)', self.id) if self.id similar_mrs = similar_mrs.where('id not in (?)', self.id) if self.id
if similar_mrs.any? if similar_mrs.any?
errors.add :validate_branches, errors.add :validate_branches,
"Cannot Create: This merge request already exists: #{ "Cannot Create: This merge request already exists: #{similar_mrs.pluck(:title)}"
similar_mrs.pluck(:title)
}"
end end
end end
end end
......
...@@ -45,7 +45,7 @@ class Namespace < ActiveRecord::Base ...@@ -45,7 +45,7 @@ class Namespace < ActiveRecord::Base
class << self class << self
def by_path(path) def by_path(path)
where('lower(path) = :value', value: path.downcase).first find_by('lower(path) = :value', value: path.downcase)
end end
# Case insensetive search for namespace by path or name # Case insensetive search for namespace by path or name
...@@ -148,6 +148,6 @@ class Namespace < ActiveRecord::Base ...@@ -148,6 +148,6 @@ class Namespace < ActiveRecord::Base
end end
def find_fork_of(project) def find_fork_of(project)
projects.joins(:forked_project_link).where('forked_project_links.forked_from_project_id = ?', project.id).first projects.joins(:forked_project_link).find_by('forked_project_links.forked_from_project_id = ?', project.id)
end end
end end
...@@ -373,11 +373,11 @@ class Note < ActiveRecord::Base ...@@ -373,11 +373,11 @@ class Note < ActiveRecord::Base
end end
def contains_emoji_only? def contains_emoji_only?
note =~ /\A#{Gitlab::Markdown::EmojiFilter.emoji_pattern}\s?\Z/ note =~ /\A#{Banzai::Filter::EmojiFilter.emoji_pattern}\s?\Z/
end end
def award_emoji_name def award_emoji_name
original_name = note.match(Gitlab::Markdown::EmojiFilter.emoji_pattern)[1] original_name = note.match(Banzai::Filter::EmojiFilter.emoji_pattern)[1]
AwardEmoji.normilize_emoji_name(original_name) AwardEmoji.normilize_emoji_name(original_name)
end end
end end
...@@ -291,7 +291,7 @@ class Project < ActiveRecord::Base ...@@ -291,7 +291,7 @@ class Project < ActiveRecord::Base
joins(:namespace). joins(:namespace).
iwhere('namespaces.path' => namespace_path) iwhere('namespaces.path' => namespace_path)
projects.where('projects.path' => project_path).take || projects.find_by('projects.path' => project_path) ||
projects.iwhere('projects.path' => project_path).take projects.iwhere('projects.path' => project_path).take
end end
...@@ -532,7 +532,7 @@ class Project < ActiveRecord::Base ...@@ -532,7 +532,7 @@ class Project < ActiveRecord::Base
end end
def external_issue_tracker def external_issue_tracker
@external_issues_tracker ||= external_issues_trackers.select(&:activated?).first @external_issues_tracker ||= external_issues_trackers.find(&:activated?)
end end
def can_have_issues_tracker_id? def can_have_issues_tracker_id?
...@@ -578,7 +578,7 @@ class Project < ActiveRecord::Base ...@@ -578,7 +578,7 @@ class Project < ActiveRecord::Base
end end
def ci_service def ci_service
@ci_service ||= ci_services.select(&:activated?).first @ci_service ||= ci_services.find(&:activated?)
end end
def jira_tracker? def jira_tracker?
...@@ -637,7 +637,7 @@ class Project < ActiveRecord::Base ...@@ -637,7 +637,7 @@ class Project < ActiveRecord::Base
end end
def project_member_by_name_or_email(name = nil, email = nil) def project_member_by_name_or_email(name = nil, email = nil)
user = users.where('name like ? or email like ?', name, email).first user = users.find_by('name like ? or email like ?', name, email)
project_members.where(user: user) if user project_members.where(user: user) if user
end end
...@@ -822,7 +822,7 @@ class Project < ActiveRecord::Base ...@@ -822,7 +822,7 @@ class Project < ActiveRecord::Base
end end
def project_member(user) def project_member(user)
project_members.where(user_id: user).first project_members.find_by(user_id: user)
end end
def default_branch def default_branch
...@@ -976,4 +976,8 @@ class Project < ActiveRecord::Base ...@@ -976,4 +976,8 @@ class Project < ActiveRecord::Base
def build_timeout_in_minutes=(value) def build_timeout_in_minutes=(value)
self.build_timeout = value.to_i * 60 self.build_timeout = value.to_i * 60
end end
def open_issues_count
issues.opened.count
end
end end
...@@ -27,12 +27,10 @@ class BambooService < CiService ...@@ -27,12 +27,10 @@ class BambooService < CiService
validates :build_key, presence: true, if: :activated? validates :build_key, presence: true, if: :activated?
validates :username, validates :username,
presence: true, presence: true,
if: ->(service) { service.password? }, if: ->(service) { service.activated? && service.password }
if: :activated?
validates :password, validates :password,
presence: true, presence: true,
if: ->(service) { service.username? }, if: ->(service) { service.activated? && service.username }
if: :activated?
attr_accessor :response attr_accessor :response
......
...@@ -58,6 +58,6 @@ class FlowdockService < Service ...@@ -58,6 +58,6 @@ class FlowdockService < Service
repo_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}", repo_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}",
commit_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/commit/%s", commit_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/commit/%s",
diff_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/compare/%s...%s", diff_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/compare/%s...%s",
) )
end end
end end
...@@ -57,6 +57,6 @@ class GemnasiumService < Service ...@@ -57,6 +57,6 @@ class GemnasiumService < Service
token: token, token: token,
api_key: api_key, api_key: api_key,
repo: project.repository.path_to_repo repo: project.repository.path_to_repo
) )
end end
end end
...@@ -27,12 +27,10 @@ class TeamcityService < CiService ...@@ -27,12 +27,10 @@ class TeamcityService < CiService
validates :build_type, presence: true, if: :activated? validates :build_type, presence: true, if: :activated?
validates :username, validates :username,
presence: true, presence: true,
if: ->(service) { service.password? }, if: ->(service) { service.activated? && service.password }
if: :activated?
validates :password, validates :password,
presence: true, presence: true,
if: ->(service) { service.username? }, if: ->(service) { service.activated? && service.username }
if: :activated?
attr_accessor :response attr_accessor :response
...@@ -147,6 +145,6 @@ class TeamcityService < CiService ...@@ -147,6 +145,6 @@ class TeamcityService < CiService
'</build>', '</build>',
headers: { 'Content-type' => 'application/xml' }, headers: { 'Content-type' => 'application/xml' },
basic_auth: auth basic_auth: auth
) )
end end
end end
...@@ -223,9 +223,9 @@ class User < ActiveRecord::Base ...@@ -223,9 +223,9 @@ class User < ActiveRecord::Base
def find_for_database_authentication(warden_conditions) def find_for_database_authentication(warden_conditions)
conditions = warden_conditions.dup conditions = warden_conditions.dup
if login = conditions.delete(:login) if login = conditions.delete(:login)
where(conditions).where(["lower(username) = :value OR lower(email) = :value", { value: login.downcase }]).first where(conditions).find_by("lower(username) = :value OR lower(email) = :value", value: login.downcase)
else else
where(conditions).first find_by(conditions)
end end
end end
...@@ -292,7 +292,7 @@ class User < ActiveRecord::Base ...@@ -292,7 +292,7 @@ class User < ActiveRecord::Base
end end
def by_username_or_id(name_or_id) def by_username_or_id(name_or_id)
where('users.username = ? OR users.id = ?', name_or_id.to_s, name_or_id.to_i).first find_by('users.username = ? OR users.id = ?', name_or_id.to_s, name_or_id.to_i)
end end
def build_user(attrs = {}) def build_user(attrs = {})
......
...@@ -127,7 +127,7 @@ module MergeRequests ...@@ -127,7 +127,7 @@ module MergeRequests
merge_requests_for_source_branch.each do |merge_request| merge_requests_for_source_branch.each do |merge_request|
SystemNoteService.change_branch_presence( SystemNoteService.change_branch_presence(
merge_request, merge_request.project, @current_user, merge_request, merge_request.project, @current_user,
:source, @branch_name, presence) :source, @branch_name, presence)
end end
end end
......
- page_title @milestone.title, "Milestones" - page_title @milestone.title, "Milestones"
- header_title "Milestones", dashboard_milestones_path - header_title "Milestones", dashboard_milestones_path
.issuable-details .detail-page-header
.page-title .status-box{ class: "status-box-#{@milestone.closed? ? 'closed' : 'open'}" }
.issue-box{ class: "issue-box-#{@milestone.closed? ? 'closed' : 'open'}" } - if @milestone.closed?
- if @milestone.closed? Closed
Closed - else
- else Open
Open %span.identifier
Milestone #{@milestone.title} Milestone #{@milestone.title}
.gray-content-block.middle-block .detail-page-description.gray-content-block.second-block
%h2.issue-title %h2.title
= markdown escape_once(@milestone.title), pipeline: :single_line = markdown escape_once(@milestone.title), pipeline: :single_line
- if @milestone.complete? && @milestone.active? - if @milestone.complete? && @milestone.active?
.alert.alert-success.prepend-top-default .alert.alert-success.prepend-top-default
......
- page_title @milestone.title, "Milestones" - page_title @milestone.title, "Milestones"
= render "header_title" = render "header_title"
.issuable-details .detail-page-header
.page-title .status-box{ class: "status-box-#{@milestone.closed? ? 'closed' : 'open'}" }
.issue-box{ class: "issue-box-#{@milestone.closed? ? 'closed' : 'open'}" } - if @milestone.closed?
- if @milestone.closed? Closed
Closed - else
- else Open
Open %span.identifier
Milestone #{@milestone.title} Milestone #{@milestone.title}
.pull-right .pull-right
- if can?(current_user, :admin_milestones, @group) - if can?(current_user, :admin_milestones, @group)
- if @milestone.active? - if @milestone.active?
= link_to 'Close Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-grouped btn-close" = link_to 'Close Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-grouped btn-close"
- else - else
= link_to 'Reopen Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-grouped btn-reopen" = link_to 'Reopen Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-grouped btn-reopen"
.gray-content-block.middle-block .detail-page-description.gray-content-block.second-block
%h2.issue-title %h2.title
= markdown escape_once(@milestone.title), pipeline: :single_line = markdown escape_once(@milestone.title), pipeline: :single_line
- if @milestone.complete? && @milestone.active? - if @milestone.complete? && @milestone.active?
.alert.alert-success.prepend-top-default .alert.alert-success.prepend-top-default
......
%div
"#{link_to @note.author_name, user_url(@note.author)} wrote:"
%div %div
= markdown(@note.note, pipeline: :email) = markdown(@note.note, pipeline: :email)
...@@ -20,8 +20,8 @@ ...@@ -20,8 +20,8 @@
%p %p
%span.light Commit %span.light Commit
= link_to @commit.id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace", data: { clipboard_text: @commit.id } = link_to @commit.id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace"
= clipboard_button = clipboard_button(clipboard_text: @commit.id)
.commit-info-row .commit-info-row
%span.light Authored by %span.light Authored by
%strong %strong
......
...@@ -19,11 +19,11 @@ ...@@ -19,11 +19,11 @@
- if defined?(commit_sha) && commit_sha - if defined?(commit_sha) && commit_sha
%td %td
= link_to commit_status.short_sha, namespace_project_commit_path(@project.namespace, @project, commit_status.sha), class: "monospace" = link_to commit_status.short_sha, namespace_project_commit_path(commit_status.project.namespace, commit_status.project, commit_status.sha), class: "monospace"
%td %td
- if commit_status.ref - if commit_status.ref
= link_to commit_status.ref, namespace_project_commits_path(@project.namespace, @project, commit_status.ref) = link_to commit_status.ref, namespace_project_commits_path(commit_status.project.namespace, commit_status.project, commit_status.ref)
- else - else
.light none .light none
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
%td %td
.pull-right .pull-right
- if current_user && can?(current_user, :download_build_artifacts, @project) && commit_status.download_url - if current_user && can?(current_user, :download_build_artifacts, commit_status.project) && commit_status.download_url
= link_to commit_status.download_url, title: 'Download artifacts' do = link_to commit_status.download_url, title: 'Download artifacts' do
%i.fa.fa-download %i.fa.fa-download
- if current_user && can?(current_user, :manage_builds, commit_status.project) - if current_user && can?(current_user, :manage_builds, commit_status.project)
......
.issue-closed-by-widget .issue-closed-by-widget.gray-content-block.second-block.white
= icon('check')
This issue will be closed automatically when merge request #{markdown(merge_requests_sentence(@closed_by_merge_requests), pipeline: :gfm)} is accepted. This issue will be closed automatically when merge request #{markdown(merge_requests_sentence(@closed_by_merge_requests), pipeline: :gfm)} is accepted.
...@@ -5,8 +5,5 @@ ...@@ -5,8 +5,5 @@
- else - else
= link_to 'Close Issue', issue_path(@issue, issue: {state_event: :close}, status_only: true), method: :put, class: 'btn btn-grouped btn-close js-note-target-close', title: 'Close Issue' = link_to 'Close Issue', issue_path(@issue, issue: {state_event: :close}, status_only: true), method: :put, class: 'btn btn-grouped btn-close js-note-target-close', title: 'Close Issue'
.gray-content-block.second-block.oneline-block
= render 'votes/votes_block', votable: @issue
#notes #notes
= render 'projects/notes/notes_with_form' = render 'projects/notes/notes_with_form'
...@@ -2,60 +2,65 @@ ...@@ -2,60 +2,65 @@
= render "header_title" = render "header_title"
.issue .issue
.issue-details.issuable-details .detail-page-header
.issuable-title .status-box{ class: status_box_class(@issue) }
.issue-box{ class: issue_box_class(@issue) } - if @issue.closed?
Closed
- else
Open
%span.identifier
Issue ##{@issue.iid}
%span.creator
&middot;
opened by #{link_to_member(@project, @issue.author, size: 24)}
&middot;
= time_ago_with_tooltip(@issue.created_at, placement: 'bottom', html_class: 'issue_created_ago')
- if @issue.updated_at != @issue.created_at
%span
&middot;
= icon('edit', title: 'edited')
= time_ago_with_tooltip(@issue.updated_at, placement: 'bottom', html_class: 'issue_edited_ago')
.pull-right
- if can?(current_user, :create_issue, @project)
= link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'btn btn-grouped new-issue-link', title: 'New Issue', id: 'new_issue_link' do
= icon('plus')
New Issue
- if can?(current_user, :update_issue, @issue)
- if @issue.closed? - if @issue.closed?
Closed = link_to 'Reopen', issue_path(@issue, issue: {state_event: :reopen}, status_only: true), method: :put, class: 'btn btn-grouped btn-reopen'
- else - else
Open = link_to 'Close', issue_path(@issue, issue: {state_event: :close}, status_only: true), method: :put, class: 'btn btn-grouped btn-close', title: 'Close Issue'
%span.issuable-id Issue ##{@issue.iid}
%span.creator
&middot;
opened by #{link_to_member(@project, @issue.author, size: 24)}
&middot;
= time_ago_with_tooltip(@issue.created_at, placement: 'bottom', html_class: 'issue_created_ago')
- if @issue.updated_at != @issue.created_at
%span
&middot;
= icon('edit', title: 'edited')
= time_ago_with_tooltip(@issue.updated_at, placement: 'bottom', html_class: 'issue_edited_ago')
.pull-right = link_to edit_namespace_project_issue_path(@project.namespace, @project, @issue), class: 'btn btn-grouped issuable-edit' do
- if can?(current_user, :create_issue, @project) = icon('pencil-square-o')
= link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'btn btn-grouped new-issue-link', title: 'New Issue', id: 'new_issue_link' do Edit
= icon('plus')
New Issue
- if can?(current_user, :update_issue, @issue)
- if @issue.closed?
= link_to 'Reopen', issue_path(@issue, issue: {state_event: :reopen}, status_only: true), method: :put, class: 'btn btn-grouped btn-reopen'
- else
= link_to 'Close', issue_path(@issue, issue: {state_event: :close}, status_only: true), method: :put, class: 'btn btn-grouped btn-close', title: 'Close Issue'
= link_to edit_namespace_project_issue_path(@project.namespace, @project, @issue), class: 'btn btn-grouped issuable-edit' do .issue-details.issuable-details
= icon('pencil-square-o') .detail-page-description.gray-content-block.second-block
Edit %h2.title
= markdown escape_once(@issue.title), pipeline: :single_line
%div
- if @issue.description.present?
.description{class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : ''}
.wiki
= preserve do
= markdown(@issue.description, cache_key: [@issue, "description"])
%textarea.hidden.js-task-list-field
= @issue.description
.row .merge-requests
%section.col-md-9 = render 'merge_requests'
.gray-content-block
%h2.issue-title .gray-content-block.second-block.oneline-block
= markdown escape_once(@issue.title), pipeline: :single_line = render 'votes/votes_block', votable: @issue
%div
- if @issue.description.present?
.description{class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : ''}
.wiki
= preserve do
= markdown(@issue.description, cache_key: [@issue, "description"])
%textarea.hidden.js-task-list-field
= @issue.description
.merge-requests - if @closed_by_merge_requests.present?
= render 'merge_requests' = render 'projects/issues/closed_by_box'
- if @closed_by_merge_requests.present? .row
= render 'projects/issues/closed_by_box' %section.col-md-9
.issue-discussion .issuable-discussion
= render 'projects/issues/discussion' = render 'projects/issues/discussion'
%aside.col-md-3 %aside.col-md-3
......
...@@ -5,7 +5,4 @@ ...@@ -5,7 +5,4 @@
- if @merge_request.closed? - if @merge_request.closed?
= link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn btn-grouped btn-reopen reopen-mr-link js-note-target-reopen", title: "Reopen merge request" = link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn btn-grouped btn-reopen reopen-mr-link js-note-target-reopen", title: "Reopen merge request"
.gray-content-block.second-block.oneline-block
= render 'votes/votes_block', votable: @merge_request
#notes= render "projects/notes/notes_with_form" #notes= render "projects/notes/notes_with_form"
...@@ -23,15 +23,15 @@ ...@@ -23,15 +23,15 @@
= link_to url_for(params), data: {target: 'div#commits', action: 'commits', toggle: 'tab'} do = link_to url_for(params), data: {target: 'div#commits', action: 'commits', toggle: 'tab'} do
Commits Commits
%span.badge= @commits.size %span.badge= @commits.size
%li.diffs-tab.active
= link_to url_for(params), data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'} do
Changes
%span.badge= @diffs.size
- if @ci_commit - if @ci_commit
%li.builds-tab.active %li.builds-tab.active
= link_to url_for(params), data: {target: 'div#builds', action: 'builds', toggle: 'tab'} do = link_to url_for(params), data: {target: 'div#builds', action: 'builds', toggle: 'tab'} do
Builds Builds
%span.badge= @statuses.size %span.badge= @statuses.size
%li.diffs-tab.active
= link_to url_for(params), data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'} do
Changes
%span.badge= @diffs.size
.tab-content .tab-content
#commits.commits.tab-pane #commits.commits.tab-pane
......
...@@ -5,81 +5,84 @@ ...@@ -5,81 +5,84 @@
- fluid_layout true - fluid_layout true
.merge-request{'data-url' => merge_request_path(@merge_request)} .merge-request{'data-url' => merge_request_path(@merge_request)}
.merge-request-details.issuable-details = render "projects/merge_requests/show/mr_title"
= render "projects/merge_requests/show/mr_title"
.row
%section.col-md-9
= render "projects/merge_requests/show/mr_box"
.append-bottom-default.mr-source-target.prepend-top-default
- if @merge_request.open?
.pull-right
- if @merge_request.source_branch_exists?
= link_to "#modal_merge_info", class: "btn btn-sm", "data-toggle" => "modal" do
= icon('cloud-download fw')
Check out branch
%span.dropdown .merge-request-details.issuable-details
%a.btn.btn-sm.dropdown-toggle{ data: {toggle: :dropdown} } = render "projects/merge_requests/show/mr_box"
= icon('download') .append-bottom-default.mr-source-target.prepend-top-default
Download as - if @merge_request.open?
%span.caret .pull-right
%ul.dropdown-menu - if @merge_request.source_branch_exists?
%li= link_to "Email Patches", merge_request_path(@merge_request, format: :patch) = link_to "#modal_merge_info", class: "btn btn-sm", "data-toggle" => "modal" do
%li= link_to "Plain Diff", merge_request_path(@merge_request, format: :diff) = icon('cloud-download fw')
.normal Check out branch
%span Request to merge
%span.label-branch= source_branch_with_namespace(@merge_request)
%span into
= link_to namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch" do
= @merge_request.target_branch
= render "projects/merge_requests/show/how_to_merge" %span.dropdown
= render "projects/merge_requests/widget/show.html.haml" %a.btn.btn-sm.dropdown-toggle{ data: {toggle: :dropdown} }
= icon('download')
Download as
%span.caret
%ul.dropdown-menu
%li= link_to "Email Patches", merge_request_path(@merge_request, format: :patch)
%li= link_to "Plain Diff", merge_request_path(@merge_request, format: :diff)
.normal
%span Request to merge
%span.label-branch= source_branch_with_namespace(@merge_request)
%span into
= link_to namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch" do
= @merge_request.target_branch
- if @merge_request.open? && @merge_request.source_branch_exists? && @merge_request.can_be_merged? && @merge_request.can_be_merged_by?(current_user) = render "projects/merge_requests/show/how_to_merge"
.light.prepend-top-default = render "projects/merge_requests/widget/show.html.haml"
You can also accept this merge request manually using the
= succeed '.' do
= link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal"
- if @commits.present? - if @merge_request.open? && @merge_request.source_branch_exists? && @merge_request.can_be_merged? && @merge_request.can_be_merged_by?(current_user)
%ul.merge-request-tabs.center-top-menu.no-top.no-bottom .light.prepend-top-default
%li.notes-tab You can also accept this merge request manually using the
= link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#notes', action: 'notes', toggle: 'tab'} do = succeed '.' do
Discussion = link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal"
%span.badge= @merge_request.mr_and_commit_notes.user.count
%li.commits-tab
= link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#commits', action: 'commits', toggle: 'tab'} do
Commits
%span.badge= @commits.size
%li.diffs-tab
= link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'} do
Changes
%span.badge= @merge_request.diffs.size
- if @ci_commit
%li.builds-tab
= link_to builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#builds', action: 'builds', toggle: 'tab'} do
Builds
%span.badge= @statuses.size
.tab-content - if @commits.present?
#notes.notes.tab-pane.voting_notes %ul.merge-request-tabs.center-top-menu.no-top.no-bottom
= render "projects/merge_requests/discussion" %li.notes-tab
#commits.commits.tab-pane = link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#notes', action: 'notes', toggle: 'tab'} do
- # This tab is always loaded via AJAX Discussion
#diffs.diffs.tab-pane %span.badge= @merge_request.mr_and_commit_notes.user.count
- # This tab is always loaded via AJAX %li.commits-tab
#builds.builds.tab-pane = link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#commits', action: 'commits', toggle: 'tab'} do
- # This tab is always loaded via AJAX Commits
%span.badge= @commits.size
- if @ci_commit
%li.builds-tab
= link_to builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#builds', action: 'builds', toggle: 'tab'} do
Builds
%span.badge= @statuses.size
%li.diffs-tab
= link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'} do
Changes
%span.badge= @merge_request.diffs.size
.mr-loading-status .tab-content
= spinner #notes.notes.tab-pane.voting_notes
.gray-content-block.second-block.oneline-block
= render 'votes/votes_block', votable: @merge_request
%aside.col-md-3 .row
= render 'shared/issuable/sidebar', issuable: @merge_request %section.col-md-9
.issuable-discussion
= render "projects/merge_requests/discussion"
%aside.col-md-3
= render 'shared/issuable/sidebar', issuable: @merge_request
= render 'shared/show_aside'
= render 'shared/show_aside' #commits.commits.tab-pane
- # This tab is always loaded via AJAX
#builds.builds.tab-pane
- # This tab is always loaded via AJAX
#diffs.diffs.tab-pane
- # This tab is always loaded via AJAX
.mr-loading-status
= spinner
:javascript :javascript
var merge_request; var merge_request;
......
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
%p %p
%strong Step 1. %strong Step 1.
Fetch and check out the branch for this merge request Fetch and check out the branch for this merge request
= clipboard_button = clipboard_button(clipboard_target: 'pre#merge-info-1')
%pre.dark %pre.dark#merge-info-1
- if @merge_request.for_fork? - if @merge_request.for_fork?
:preserve :preserve
git fetch #{h @merge_request.source_project.http_url_to_repo} #{h @merge_request.source_branch} git fetch #{h @merge_request.source_project.http_url_to_repo} #{h @merge_request.source_branch}
...@@ -25,8 +25,8 @@ ...@@ -25,8 +25,8 @@
%p %p
%strong Step 3. %strong Step 3.
Merge the branch and fix any conflicts that come up Merge the branch and fix any conflicts that come up
= clipboard_button = clipboard_button(clipboard_target: 'pre#merge-info-3')
%pre.dark %pre.dark#merge-info-3
- if @merge_request.for_fork? - if @merge_request.for_fork?
:preserve :preserve
git checkout #{h @merge_request.target_branch} git checkout #{h @merge_request.target_branch}
...@@ -38,8 +38,8 @@ ...@@ -38,8 +38,8 @@
%p %p
%strong Step 4. %strong Step 4.
Push the result of the merge to GitLab Push the result of the merge to GitLab
= clipboard_button = clipboard_button(clipboard_target: 'pre#merge-info-4')
%pre.dark %pre.dark#merge-info-4
:preserve :preserve
git push origin #{h @merge_request.target_branch} git push origin #{h @merge_request.target_branch}
- unless @merge_request.can_be_merged_by?(current_user) - unless @merge_request.can_be_merged_by?(current_user)
......
.gray-content-block.middle-block .detail-page-description.gray-content-block.second-block
%h2.issue-title %h2.title
= markdown escape_once(@merge_request.title), pipeline: :single_line = markdown escape_once(@merge_request.title), pipeline: :single_line
%div %div
......
.issuable-title .detail-page-header
.issue-box{ class: issue_box_class(@merge_request) } .status-box{ class: status_box_class(@merge_request) }
= @merge_request.state_human_name = @merge_request.state_human_name
%span.issuable-id Merge Request ##{@merge_request.iid} %span.identifier
Merge Request ##{@merge_request.iid}
%span.creator %span.creator
&middot; &middot;
opened by #{link_to_member(@project, @merge_request.author, size: 24)} opened by #{link_to_member(@project, @merge_request.author, size: 24)}
......
...@@ -7,13 +7,13 @@ ...@@ -7,13 +7,13 @@
.accept-action .accept-action
- if @ci_commit && @ci_commit.active? - if @ci_commit && @ci_commit.active?
%span.btn-group %span.btn-group
= link_to "#", class: "btn btn-create merge_when_build_succeeds" do = button_tag class: "btn btn-create js-merge-button merge_when_build_succeeds" do
Merge When Build Succeeds Merge When Build Succeeds
%a.btn.btn-success.dropdown-toggle{ 'data-toggle' => 'dropdown' } = button_tag class: "btn btn-success dropdown-toggle", 'data-toggle' => 'dropdown' do
%span.caret %span.caret
%span.sr-only %span.sr-only
Select Merge Moment Select Merge Moment
%ul.dropdown-menu.dropdown-menu-right{ role: 'menu' } %ul.js-merge-dropdown.dropdown-menu.dropdown-menu-right{ role: 'menu' }
%li %li
= link_to "#", class: "merge_when_build_succeeds" do = link_to "#", class: "merge_when_build_succeeds" do
= icon('check fw') = icon('check fw')
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
= icon('warning fw') = icon('warning fw')
Merge Immediately Merge Immediately
- else - else
= f.button class: "btn btn-create btn-grouped accept_merge_request #{status_class}" do = f.button class: "btn btn-create btn-grouped js-merge-button accept_merge_request #{status_class}" do
Accept Merge Request Accept Merge Request
- if @merge_request.can_remove_source_branch?(current_user) - if @merge_request.can_remove_source_branch?(current_user)
.accept-control.checkbox .accept-control.checkbox
...@@ -42,21 +42,19 @@ ...@@ -42,21 +42,19 @@
= hidden_field_tag :merge_when_build_succeeds, "", autocomplete: "off" = hidden_field_tag :merge_when_build_succeeds, "", autocomplete: "off"
:javascript :javascript
$('.accept_merge_request').on('click', function() {
$(this).html("<i class='fa fa-spinner fa-spin'></i> Merge in progress");
});
$('.accept-mr-form').on('ajax:send', function() { $('.accept-mr-form').on('ajax:send', function() {
$(".accept-mr-form :input").disable(); $(".accept-mr-form :input").disable();
}); });
$('a.accept_merge_request').on('click', function(e) { $('.accept_merge_request').on('click', function() {
e.preventDefault(); $('.js-merge-button').html("<i class='fa fa-spinner fa-spin'></i> Merge in progress");
$(this).closest("form").submit();
}); });
$('a.merge_when_build_succeeds').on('click', function(e) { $('.merge_when_build_succeeds').on('click', function() {
e.preventDefault();
$("#merge_when_build_succeeds").val("1"); $("#merge_when_build_succeeds").val("1");
});
$('.js-merge-dropdown a').on('click', function(e) {
e.preventDefault();
$(this).closest("form").submit(); $(this).closest("form").submit();
}); });
- page_title @milestone.title, "Milestones" - page_title @milestone.title, "Milestones"
= render "header_title" = render "header_title"
.issuable-details .detail-page-header
.page-title .status-box{ class: status_box_class(@milestone) }
.issue-box{ class: issue_box_class(@milestone) } - if @milestone.closed?
- if @milestone.closed? Closed
Closed - elsif @milestone.expired?
- elsif @milestone.expired? Expired
Expired - else
- else Open
Open %span.identifier
Milestone ##{@milestone.iid} Milestone ##{@milestone.iid}
- if @milestone.expires_at - if @milestone.expires_at
%span.creator %span.creator
&middot; &middot;
= @milestone.expires_at = @milestone.expires_at
.pull-right .pull-right
- if can?(current_user, :admin_milestone, @project) - if can?(current_user, :admin_milestone, @project)
= link_to edit_namespace_project_milestone_path(@project.namespace, @project, @milestone), class: "btn btn-grouped" do - if @milestone.active?
%i.fa.fa-pencil-square-o = link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-close btn-grouped"
Edit - else
= link_to 'Reopen Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-grouped"
- if @milestone.active? = link_to namespace_project_milestone_path(@project.namespace, @project, @milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-grouped btn-remove" do
= link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-close btn-grouped" %i.fa.fa-trash-o
- else Delete
= link_to 'Reopen Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-grouped"
= link_to namespace_project_milestone_path(@project.namespace, @project, @milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-grouped btn-remove" do = link_to edit_namespace_project_milestone_path(@project.namespace, @project, @milestone), class: "btn btn-grouped" do
%i.fa.fa-trash-o %i.fa.fa-pencil-square-o
Delete Edit
.gray-content-block.middle-block .detail-page-description.gray-content-block.second-block
%h2.issue-title %h2.title
= markdown escape_once(@milestone.title), pipeline: :single_line = markdown escape_once(@milestone.title), pipeline: :single_line
%div %div
- if @milestone.description.present? - if @milestone.description.present?
.description .description
.wiki .wiki
= preserve do = preserve do
= markdown @milestone.description = markdown @milestone.description
- if @milestone.issues.any? && @milestone.can_be_closed? - if @milestone.issues.any? && @milestone.can_be_closed?
.alert.alert-success.prepend-top-default .alert.alert-success.prepend-top-default
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
- else - else
Start the title with <code>[WIP]</code> or <code>WIP:</code> to prevent a Start the title with <code>[WIP]</code> or <code>WIP:</code> to prevent a
<strong>Work In Progress</strong> merge request from being merged before it's ready. <strong>Work In Progress</strong> merge request from being merged before it's ready.
.form-group.issuable-description .form-group.detail-page-description
= f.label :description, 'Description', class: 'control-label' = f.label :description, 'Description', class: 'control-label'
.col-sm-10 .col-sm-10
......
.issuable-sidebar.issuable-affix .issuable-sidebar.issuable-affix
= form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f| = form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f|
.block
.title
Cross-project reference
.cross-project-reference
%span#cross-project-reference
= cross_project_reference(@project, issuable)
= clipboard_button(clipboard_target: 'span#cross-project-reference')
.block.assignee .block.assignee
.title .title
%label %label
...@@ -62,6 +54,14 @@ ...@@ -62,6 +54,14 @@
= f.collection_select :label_ids, issuable.project.labels.all, :id, :name, = f.collection_select :label_ids, issuable.project.labels.all, :id, :name,
{ selected: issuable.label_ids }, multiple: true, class: 'select2 js-select2', data: { placeholder: "Select labels" } { selected: issuable.label_ids }, multiple: true, class: 'select2 js-select2', data: { placeholder: "Select labels" }
.block
.title
Cross-project reference
.cross-project-reference
%span#cross-project-reference
= cross_project_reference(@project, issuable)
= clipboard_button(clipboard_target: 'span#cross-project-reference')
= render "shared/issuable/participants", participants: issuable.participants(current_user) = render "shared/issuable/participants", participants: issuable.participants(current_user)
- if current_user - if current_user
......
.issuable-details .detail-page-header
.page-title .snippet-box.has_tooltip{class: visibility_level_color(@snippet.visibility_level), title: snippet_visibility_level_description(@snippet.visibility_level, @snippet), data: { container: 'body' }}
.snippet-box.has_tooltip{class: visibility_level_color(@snippet.visibility_level), title: snippet_visibility_level_description(@snippet.visibility_level, @snippet), data: { container: 'body' }} = visibility_level_icon(@snippet.visibility_level, fw: false)
= visibility_level_icon(@snippet.visibility_level, fw: false) = visibility_level_label(@snippet.visibility_level)
= visibility_level_label(@snippet.visibility_level) %span.identifier
Snippet ##{@snippet.id} Snippet ##{@snippet.id}
%span.creator %span.creator
&middot; created by #{link_to_member(@project, @snippet.author, size: 24)} &middot; created by #{link_to_member(@project, @snippet.author, size: 24)}
&middot; &middot;
= time_ago_with_tooltip(@snippet.created_at, placement: 'bottom', html_class: 'snippet_updated_ago') = time_ago_with_tooltip(@snippet.created_at, placement: 'bottom', html_class: 'snippet_updated_ago')
- if @snippet.updated_at != @snippet.created_at - if @snippet.updated_at != @snippet.created_at
%span %span
&middot; &middot;
= icon('edit', title: 'edited') = icon('edit', title: 'edited')
= time_ago_with_tooltip(@snippet.updated_at, placement: 'bottom', html_class: 'snippet_edited_ago') = time_ago_with_tooltip(@snippet.updated_at, placement: 'bottom', html_class: 'snippet_edited_ago')
.pull-right .pull-right
- if @snippet.project_id? - if @snippet.project_id?
= render "projects/snippets/actions" = render "projects/snippets/actions"
- else - else
= render "snippets/actions" = render "snippets/actions"
.gray-content-block.middle-block .detail-page-description.gray-content-block.second-block
%h2.issue-title %h2.title
= markdown escape_once(@snippet.title), pipeline: :single_line = markdown escape_once(@snippet.title), pipeline: :single_line
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
.user-calendar-activities .user-calendar-activities
%ul.center-top-menu.no-top.no-bottom.bottom-border %ul.center-top-menu.no-top.no-bottom.bottom-border.wide
%li.active %li.active
= link_to "#activity", 'data-toggle' => 'tab' do = link_to "#activity", 'data-toggle' => 'tab' do
Activity Activity
......
...@@ -31,11 +31,11 @@ if File.exists?(aws_file) ...@@ -31,11 +31,11 @@ if File.exists?(aws_file)
if Rails.env.test? if Rails.env.test?
Fog.mock! Fog.mock!
connection = ::Fog::Storage.new( connection = ::Fog::Storage.new(
aws_access_key_id: AWS_CONFIG['access_key_id'], aws_access_key_id: AWS_CONFIG['access_key_id'],
aws_secret_access_key: AWS_CONFIG['secret_access_key'], aws_secret_access_key: AWS_CONFIG['secret_access_key'],
provider: 'AWS', provider: 'AWS',
region: AWS_CONFIG['region'] region: AWS_CONFIG['region']
) )
connection.directories.create(key: AWS_CONFIG['bucket']) connection.directories.create(key: AWS_CONFIG['bucket'])
end end
end end
...@@ -482,7 +482,7 @@ Rails.application.routes.draw do ...@@ -482,7 +482,7 @@ Rails.application.routes.draw do
scope do scope do
post( post(
'/create_dir/*id', '/create_dir/*id',
to: 'tree#create_dir', to: 'tree#create_dir',
constraints: { id: /.+/ }, constraints: { id: /.+/ },
as: 'create_dir' as: 'create_dir'
......
...@@ -26,7 +26,8 @@ class MigrateCiToProject < ActiveRecord::Migration ...@@ -26,7 +26,8 @@ class MigrateCiToProject < ActiveRecord::Migration
def migrate_project_column(column, new_column = nil) def migrate_project_column(column, new_column = nil)
new_column ||= column new_column ||= column
subquery = "SELECT ci_projects.#{column} FROM ci_projects WHERE projects.id = ci_projects.gitlab_id" subquery = "SELECT ci_projects.#{column} FROM ci_projects WHERE projects.id = ci_projects.gitlab_id " \
'ORDER BY ci_projects.updated_at DESC LIMIT 1'
execute("UPDATE projects SET #{new_column}=(#{subquery}) WHERE (#{subquery}) IS NOT NULL") execute("UPDATE projects SET #{new_column}=(#{subquery}) WHERE (#{subquery}) IS NOT NULL")
end end
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
- [GitLab Basics](gitlab-basics/README.md) Find step by step how to start working on your commandline and on GitLab. - [GitLab Basics](gitlab-basics/README.md) Find step by step how to start working on your commandline and on GitLab.
- [Importing to GitLab](workflow/importing/README.md). - [Importing to GitLab](workflow/importing/README.md).
- [Markdown](markdown/markdown.md) GitLab's advanced formatting system. - [Markdown](markdown/markdown.md) GitLab's advanced formatting system.
- [Migrating from SVN](migration/README.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 (guest/reporter/developer/master/owner) can do.
- [Profile Settings](profile/README.md) - [Profile Settings](profile/README.md)
- [Project Services](project_services/project_services.md) Integrate a project with external services, such as CI and chat. - [Project Services](project_services/project_services.md) Integrate a project with external services, such as CI and chat.
......
...@@ -58,6 +58,7 @@ Parameters: ...@@ -58,6 +58,7 @@ Parameters:
"path": "diaspora-client", "path": "diaspora-client",
"path_with_namespace": "diaspora/diaspora-client", "path_with_namespace": "diaspora/diaspora-client",
"issues_enabled": true, "issues_enabled": true,
"open_issues_count": 1,
"merge_requests_enabled": true, "merge_requests_enabled": true,
"builds_enabled": true, "builds_enabled": true,
"wiki_enabled": true, "wiki_enabled": true,
...@@ -100,6 +101,7 @@ Parameters: ...@@ -100,6 +101,7 @@ Parameters:
"path": "puppet", "path": "puppet",
"path_with_namespace": "brightbox/puppet", "path_with_namespace": "brightbox/puppet",
"issues_enabled": true, "issues_enabled": true,
"open_issues_count": 1,
"merge_requests_enabled": true, "merge_requests_enabled": true,
"builds_enabled": true, "builds_enabled": true,
"wiki_enabled": true, "wiki_enabled": true,
...@@ -137,6 +139,21 @@ Parameters: ...@@ -137,6 +139,21 @@ Parameters:
- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
- `search` (optional) - Return list of authorized projects according to a search criteria - `search` (optional) - Return list of authorized projects according to a search criteria
### List starred projects
Get a list of projects which are starred by the authenticated user.
```
GET /projects/starred
```
Parameters:
- `archived` (optional) - if passed, limit by archived status
- `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at`
- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
- `search` (optional) - Return list of authorized projects according to a search criteria
### List ALL projects ### List ALL projects
Get a list of all GitLab projects (admin only). Get a list of all GitLab projects (admin only).
...@@ -189,6 +206,7 @@ Parameters: ...@@ -189,6 +206,7 @@ Parameters:
"path": "diaspora-project-site", "path": "diaspora-project-site",
"path_with_namespace": "diaspora/diaspora-project-site", "path_with_namespace": "diaspora/diaspora-project-site",
"issues_enabled": true, "issues_enabled": true,
"open_issues_count": 1,
"merge_requests_enabled": true, "merge_requests_enabled": true,
"builds_enabled": true, "builds_enabled": true,
"wiki_enabled": true, "wiki_enabled": true,
......
# Using Docker Images # Using Docker Images
GitLab CI in conjuction with [GitLab Runner](../runners/README.md) can use GitLab CI in conjunction with [GitLab Runner](../runners/README.md) can use
[Docker Engine](https://www.docker.com/) to test and build any application. [Docker Engine](https://www.docker.com/) to test and build any application.
Docker is an open-source project that allows you to use predefined images to Docker is an open-source project that allows you to use predefined images to
run applications in independent "containers" that are run within a single Linux run applications in independent "containers" that are run within a single Linux
instance. [Docker Hub][hub] has a rich database of prebuilt images that can be instance. [Docker Hub][hub] has a rich database of pre-built images that can be
used to test and build your applications. used to test and build your applications.
Docker, when used with GitLab CI, runs each build in a separate and isolated Docker, when used with GitLab CI, runs each build in a separate and isolated
...@@ -136,6 +136,24 @@ Look for the `[runners.docker]` section: ...@@ -136,6 +136,24 @@ Look for the `[runners.docker]` section:
The image and services defined this way will be added to all builds run by The image and services defined this way will be added to all builds run by
that runner. that runner.
## Define an image from a private Docker registry
Starting with GitLab Runner 0.6.0, you are able to define images located to
private registries that could also require authentication.
All you have to do is be explicit on the image definition in `.gitlab-ci.yml`.
```yaml
image: my.registry.tld:5000/namepace/image:tag
```
In the example above, GitLab Runner will look at `my.registry.tld:5000` for the
image `namespace/image:tag`.
If the repository is private you need to authenticate your GitLab Runner in the
registry. Learn how to do that on
[GitLab Runner's documentation][runner-priv-reg].
## Accessing the services ## Accessing the services
Let's say that you need a Wordpress instance to test some API integration with Let's say that you need a Wordpress instance to test some API integration with
...@@ -258,3 +276,4 @@ creation. ...@@ -258,3 +276,4 @@ creation.
[tutum/wordpress]: https://registry.hub.docker.com/u/tutum/wordpress/ [tutum/wordpress]: https://registry.hub.docker.com/u/tutum/wordpress/
[postgres-hub]: https://registry.hub.docker.com/u/library/postgres/ [postgres-hub]: https://registry.hub.docker.com/u/library/postgres/
[mysql-hub]: https://registry.hub.docker.com/u/library/mysql/ [mysql-hub]: https://registry.hub.docker.com/u/library/mysql/
[runner-priv-reg]: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/configuration/advanced-configuration.md#using-a-private-docker-registry
This diff is collapsed.
...@@ -348,7 +348,7 @@ GitLab Shell is an SSH access and repository management software developed speci ...@@ -348,7 +348,7 @@ GitLab Shell is an SSH access and repository management software developed speci
cd /home/git cd /home/git
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git
cd gitlab-workhorse cd gitlab-workhorse
sudo -u git -H git checkout 0.4.2 sudo -u git -H git checkout 0.5.1
sudo -u git -H make sudo -u git -H make
### Initialize Database and Activate Advanced Features ### Initialize Database and Activate Advanced Features
......
# Rake tasks # Rake tasks
- [Backup restore](backup_restore.md) - [Backup restore](backup_restore.md)
- [Check](check.md)
- [Cleanup](cleanup.md) - [Cleanup](cleanup.md)
- [Features](features.md) - [Features](features.md)
- [Maintenance](maintenance.md) and self-checks - [Maintenance](maintenance.md) and self-checks
- [User management](user_management.md) - [User management](user_management.md)
- [Web hooks](web_hooks.md) - [Web hooks](web_hooks.md)
- [Import](import.md) of git repositories in bulk - [Import](import.md) of git repositories in bulk
- [Rebuild authorized_keys file](http://doc.gitlab.com/ce/raketasks/maintenance.html#rebuild-authorized_keys-file) task for administrators - [Rebuild authorized_keys file](http://doc.gitlab.com/ce/raketasks/maintenance.html#rebuild-authorized_keys-file) task for administrators
\ No newline at end of file
# Check Rake Tasks
## Repository Integrity
Even though Git is very resilient and tries to prevent data integrity issues,
there are times when things go wrong. The following Rake tasks intend to
help GitLab administrators diagnose problem repositories so they can be fixed.
There are 3 things that are checked to determine integrity.
1. Git repository file system check ([git fsck](https://git-scm.com/docs/git-fsck)).
This step verifies the connectivity and validity of objects in the repository.
1. Check for `config.lock` in the repository directory.
1. Check for any branch/references lock files in `refs/heads`.
It's important to note that the existence of `config.lock` or reference locks
alone do not necessarily indicate a problem. Lock files are routinely created
and removed as Git and GitLab perform operations on the repository. They serve
to prevent data integrity issues. However, if a Git operation is interrupted these
locks may not be cleaned up properly.
The following symptoms may indicate a problem with repository integrity. If users
experience these symptoms you may use the rake tasks described below to determine
exactly which repositories are causing the trouble.
- Receiving an error when trying to push code - `remote: error: cannot lock ref`
- A 500 error when viewing the GitLab dashboard or when accessing a specific project.
### Check all GitLab repositories
This task loops through all repositories on the GitLab server and runs the
3 integrity checks described previously.
```
# omnibus-gitlab
sudo gitlab-rake gitlab:repo:check
# installation from source
bundle exec rake gitlab:repo:check RAILS_ENV=production
```
### Check repositories for a specific user
This task checks all repositories that a specific user has access to. This is important
because sometimes you know which user is experiencing trouble but you don't know
which project might be the cause.
If the rake task is executed without brackets at the end, you will be prompted
to enter a username.
```bash
# omnibus-gitlab
sudo gitlab-rake gitlab:user:check_repos
sudo gitlab-rake gitlab:user:check_repos[<username>]
# installation from source
bundle exec rake gitlab:user:check_repos RAILS_ENV=production
bundle exec rake gitlab:user:check_repos[<username>] RAILS_ENV=production
```
Example output:
![gitlab:user:check_repos output](check_repos_output.png)
...@@ -67,7 +67,7 @@ sudo -u git -H git checkout 8-3-stable-ee ...@@ -67,7 +67,7 @@ sudo -u git -H git checkout 8-3-stable-ee
```bash ```bash
cd /home/git/gitlab-shell cd /home/git/gitlab-shell
sudo -u git -H git fetch --all sudo -u git -H git fetch --all
sudo -u git -H git checkout v2.6.8 sudo -u git -H git checkout v2.6.9
``` ```
### 5. Update gitlab-workhorse ### 5. Update gitlab-workhorse
...@@ -78,7 +78,7 @@ which should already be on your system from GitLab 8.1. ...@@ -78,7 +78,7 @@ which should already be on your system from GitLab 8.1.
```bash ```bash
cd /home/git/gitlab-workhorse cd /home/git/gitlab-workhorse
sudo -u git -H git fetch --all sudo -u git -H git fetch --all
sudo -u git -H git checkout 0.4.2 sudo -u git -H git checkout 0.5.1
sudo -u git -H make sudo -u git -H make
``` ```
...@@ -115,6 +115,12 @@ git diff origin/8-2-stable:config/gitlab.yml.example origin/8-3-stable:config/gi ...@@ -115,6 +115,12 @@ git diff origin/8-2-stable:config/gitlab.yml.example origin/8-3-stable:config/gi
#### Nginx configuration #### Nginx configuration
GitLab 8.3 introduces major changes in the NGINX configuration.
Because all HTTP requests pass through gitlab-workhorse now a lot of
directives need to be removed from NGINX. During future upgrades there
should be much less changes in the NGINX configuration because of
this.
View changes between the previous recommended Nginx configuration and the View changes between the previous recommended Nginx configuration and the
current one: current one:
...@@ -134,6 +140,18 @@ via [/etc/default/gitlab]. ...@@ -134,6 +140,18 @@ via [/etc/default/gitlab].
[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache [Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-3-stable/lib/support/init.d/gitlab.default.example#L34 [/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-3-stable/lib/support/init.d/gitlab.default.example#L34
#### Init script
We updated the init script for GitLab in order to pass new
configuration options to gitlab-workhorse. We let gitlab-workhorse
connect to the Rails application via a Unix domain socket and we tell
it where the 'public' directory of GitLab is.
```
cd /home/git/gitlab
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
```
### 8. Use Redis v2.8.0+ ### 8. Use Redis v2.8.0+
Previous versions of GitLab allowed Redis versions >= 2.0 to be used, but Previous versions of GitLab allowed Redis versions >= 2.0 to be used, but
......
...@@ -28,4 +28,4 @@ ...@@ -28,4 +28,4 @@
- [Repository Mirroring](repository_mirroring.md) - [Repository Mirroring](repository_mirroring.md)
- [Merge When Build Succeeds](merge_when_build_succeeds.md) - [Merge When Build Succeeds](merge_when_build_succeeds.md)
- [Manage large binaries with Git LFS](lfs/manage_large_binaries_with_git_lfs.md) - [Manage large binaries with Git LFS](lfs/manage_large_binaries_with_git_lfs.md)
- [Importing from SVN, GitHub, BitBucket, etc](importing/README.md)
# Migrating projects to a GitLab instance # Migrating projects to a GitLab instance
1. [Bitbucket](import_projects_from_bitbucket.md) 1. [Bitbucket](import_projects_from_bitbucket.md)
2. [GitHub](import_projects_from_github.md) 1. [GitHub](import_projects_from_github.md)
3. [GitLab.com](import_projects_from_gitlab_com.md) 1. [GitLab.com](import_projects_from_gitlab_com.md)
4. [FogBugz](import_projects_from_fogbugz.md) 1. [FogBugz](import_projects_from_fogbugz.md)
4. [SVN](migrating_from_svn.md) 1. [SVN](migrating_from_svn.md)
### Note In addition to the specific migration documentation above, you can import any
* If you'd like to migrate from a self-hosted GitLab instance to GitLab.com, you can copy your repos by changing the remote and pushing to the new server; but issues and merge requests can't be imported. Git repository via HTTP from the New Project page. Be aware that if the
repository is too large the import can timeout.
### Migrating from self-hosted GitLab to GitLab.com
You can copy your repos by changing the remote and pushing to the new server;
but issues and merge requests can't be imported.
* You can import any Git repository via HTTP from the New Project page.
If the repository is too large, it can timeout.
# Migrating from SVN to GitLab # Migrating from SVN to GitLab
SVN stands for Subversion and is a version control system (VCS). Subversion (SVN) is a central version control system (VCS) while
Git is a distributed version control system. Git is a distributed version control system. There are some major differences
between the two, for more information consult your favorite search engine.
There are some major differences between the two, for more information consult your favorite search engine. If you are currently using an SVN repository, you can migrate the repository
to Git and GitLab. We recommend a hard cut over - run the migration command once
and then have all developers start using the new GitLab repository immediately.
Otherwise, it's hard to keep changing in sync in both directions. The conversion
process should be run on a local workstation.
Git has tools for migrating SVN repositories to git, namely `git svn`. You can read more about this at Install `svn2git`. On all systems you can install as a Ruby gem if you already
[git documentation pages](https://git-scm.com/book/en/Git-and-Other-Systems-Git-and-Subversion). have Ruby and Git installed.
Apart from the [official git documentation](https://git-scm.com/book/en/Git-and-Other-Systems-Migrating-to-Git) there is also ```bash
user created step by step guide for migrating from SVN to GitLab. sudo gem install svn2git
```
[Benjamin New](https://github.com/leftclickben) wrote [a guide that shows how to do a migration](https://gist.github.com/leftclickben/322b7a3042cbe97ed2af). Mirrors can be found [here](https://gitlab.com/snippets/2168) and [here](https://gist.github.com/maxlazio/f1b593b0d00aa966e9ca). On Debian-based Linux distributions you can install the native packages:
```bash
sudo apt-get install git-core git-svn ruby
```
Optionally, prepare an authors file so `svn2git` can map SVN authors to Git authors.
If you choose not to create the authors file then commits will not be attributed
to the correct GitLab user. Some users may not consider this a big issue while
others will want to ensure they complete this step. If you choose to map authors
you will be required to map every author that is present on changes in the SVN
repository. If you don't, the conversion will fail and you will have to update
the author file accordingly. The following command will search through the
repository and output a list of authors.
```bash
svn log --quiet | grep -E "r[0-9]+ \| .+ \|" | cut -d'|' -f2 | sed 's/ //g' | sort | uniq
```
Use the output from the last command to construct the authors file.
Create a file called `authors.txt` and add one mapping per line.
```
janedoe = Jane Doe <janedoe@example.com>
johndoe = John Doe <johndoe@example.com>
```
If your SVN repository is in the standard format (trunk, branches, tags,
not nested) the conversion is simple. For a non-standard repository see
[svn2git documentation](https://github.com/nirvdrum/svn2git). The following
command will checkout the repository and do the conversion in the current
working directory. Be sure to create a new directory for each repository before
running the `svn2git` command. The conversion process will take some time.
```bash
svn2git https://svn.example.com/path/to/repo --authors /path/to/authors.txt
```
If your SVN repository requires a username and password add the
`--username <username>` and `--password <password` flags to the above command.
`svn2git` also supports excluding certain file paths, branches, tags, etc. See
[svn2git documentation](https://github.com/nirvdrum/svn2git) or run
`svn2git --help` for full documentation on all of the available options.
Create a new GitLab project, where you will eventually push your converted code.
Copy the SSH or HTTP(S) repository URL from the project page. Add the GitLab
repository as a Git remote and push all the changes. This will push all commits,
branches and tags.
```bash
git remote add origin git@gitlab.com:<group>/<project>.git
git push --all origin
```
## Contribute to this guide ## Contribute to this guide
We welcome all contributions that would expand this guide with instructions on how to migrate from SVN and other version control systems. We welcome all contributions that would expand this guide with instructions on
how to migrate from SVN and other version control systems.
...@@ -75,18 +75,18 @@ class Spinach::Features::ExploreGroups < Spinach::FeatureSteps ...@@ -75,18 +75,18 @@ class Spinach::Features::ExploreGroups < Spinach::FeatureSteps
name: projectname, name: projectname,
path: "#{groupname}-#{projectname}", path: "#{groupname}-#{projectname}",
visibility_level: visibility_level visibility_level: visibility_level
) )
create(:issue, create(:issue,
title: "#{projectname} feature", title: "#{projectname} feature",
project: project project: project
) )
create(:merge_request, create(:merge_request,
title: "#{projectname} feature implemented", title: "#{projectname} feature implemented",
source_project: project, source_project: project,
target_project: project target_project: project
) )
create(:closed_issue_event, create(:closed_issue_event,
project: project project: project
) )
end end
end end
...@@ -61,11 +61,11 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps ...@@ -61,11 +61,11 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps
create(:issue, create(:issue,
title: "Bug", title: "Bug",
project: public_project project: public_project
) )
create(:issue, create(:issue,
title: "New feature", title: "New feature",
project: public_project project: public_project
) )
visit namespace_project_issues_path(public_project.namespace, public_project) visit namespace_project_issues_path(public_project.namespace, public_project)
end end
...@@ -80,11 +80,11 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps ...@@ -80,11 +80,11 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps
create(:issue, create(:issue,
title: "Internal Bug", title: "Internal Bug",
project: internal_project project: internal_project
) )
create(:issue, create(:issue,
title: "New internal feature", title: "New internal feature",
project: internal_project project: internal_project
) )
visit namespace_project_issues_path(internal_project.namespace, internal_project) visit namespace_project_issues_path(internal_project.namespace, internal_project)
end end
...@@ -104,7 +104,7 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps ...@@ -104,7 +104,7 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps
title: "Bug fix for public project", title: "Bug fix for public project",
source_project: public_project, source_project: public_project,
target_project: public_project, target_project: public_project,
) )
end end
step 'I should see list of merge requests for "Community" project' do step 'I should see list of merge requests for "Community" project' do
...@@ -121,7 +121,7 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps ...@@ -121,7 +121,7 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps
title: "Feature implemented", title: "Feature implemented",
source_project: internal_project, source_project: internal_project,
target_project: internal_project target_project: internal_project
) )
end end
step 'I should see list of merge requests for "Internal" project' do step 'I should see list of merge requests for "Internal" project' do
......
...@@ -131,7 +131,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps ...@@ -131,7 +131,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
step 'I should see new group "Owned" avatar' do step 'I should see new group "Owned" avatar' do
expect(owned_group.avatar).to be_instance_of AvatarUploader expect(owned_group.avatar).to be_instance_of AvatarUploader
expect(owned_group.avatar.url).to eq "/uploads/group/avatar/#{ Group.find_by(name:"Owned").id }/banana_sample.gif" expect(owned_group.avatar.url).to eq "/uploads/group/avatar/#{Group.find_by(name:"Owned").id}/banana_sample.gif"
end end
step 'I should see the "Remove avatar" button' do step 'I should see the "Remove avatar" button' do
......
...@@ -34,7 +34,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps ...@@ -34,7 +34,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
step 'I should see new avatar' do step 'I should see new avatar' do
expect(@user.avatar).to be_instance_of AvatarUploader expect(@user.avatar).to be_instance_of AvatarUploader
expect(@user.avatar.url).to eq "/uploads/user/avatar/#{ @user.id }/banana_sample.gif" expect(@user.avatar.url).to eq "/uploads/user/avatar/#{@user.id}/banana_sample.gif"
end end
step 'I should see the "Remove avatar" button' do step 'I should see the "Remove avatar" button' do
......
...@@ -41,7 +41,8 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps ...@@ -41,7 +41,8 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps
click_button "Compare branches and continue" click_button "Compare branches and continue"
expect(page).to have_content "New Merge Request" expect(page).to have_css("h3.page-title", text: "New Merge Request")
fill_in "merge_request_title", with: "Merge Request On Forked Project" fill_in "merge_request_title", with: "Merge Request On Forked Project"
end end
......
...@@ -273,7 +273,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps ...@@ -273,7 +273,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
end end
step 'I should see merged request' do step 'I should see merged request' do
page.within '.issue-box' do page.within '.status-box' do
expect(page).to have_content "Merged" expect(page).to have_content "Merged"
end end
end end
...@@ -283,7 +283,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps ...@@ -283,7 +283,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
end end
step 'I should see reopened merge request "Bug NS-04"' do step 'I should see reopened merge request "Bug NS-04"' do
page.within '.issue-box' do page.within '.status-box' do
expect(page).to have_content "Open" expect(page).to have_content "Open"
end end
end end
......
...@@ -40,7 +40,7 @@ class Spinach::Features::Project < Spinach::FeatureSteps ...@@ -40,7 +40,7 @@ class Spinach::Features::Project < Spinach::FeatureSteps
step 'I should see new project avatar' do step 'I should see new project avatar' do
expect(@project.avatar).to be_instance_of AvatarUploader expect(@project.avatar).to be_instance_of AvatarUploader
url = @project.avatar.url url = @project.avatar.url
expect(url).to eq "/uploads/project/avatar/#{ @project.id }/banana_sample.gif" expect(url).to eq "/uploads/project/avatar/#{@project.id}/banana_sample.gif"
end end
step 'I should see the "Remove avatar" button' do step 'I should see the "Remove avatar" button' do
......
...@@ -42,7 +42,7 @@ class Spinach::Features::ProjectSnippets < Spinach::FeatureSteps ...@@ -42,7 +42,7 @@ class Spinach::Features::ProjectSnippets < Spinach::FeatureSteps
end end
step 'I click link "Edit"' do step 'I click link "Edit"' do
page.within ".page-title" do page.within ".detail-page-header" do
click_link "Edit" click_link "Edit"
end end
end end
......
...@@ -238,13 +238,13 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps ...@@ -238,13 +238,13 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
end end
step 'I am redirected to the new file' do step 'I am redirected to the new file' do
expect(current_path).to eq(namespace_project_blob_path( expect(current_path).to eq(
@project.namespace, @project, 'master/' + new_file_name)) namespace_project_blob_path(@project.namespace, @project, 'master/' + new_file_name))
end end
step 'I am redirected to the new file with directory' do step 'I am redirected to the new file with directory' do
expect(current_path).to eq(namespace_project_blob_path( expect(current_path).to eq(
@project.namespace, @project, 'master/' + new_file_name_with_directory)) namespace_project_blob_path(@project.namespace, @project, 'master/' + new_file_name_with_directory))
end end
step 'I am redirected to the new merge request page' do step 'I am redirected to the new merge request page' do
...@@ -252,8 +252,8 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps ...@@ -252,8 +252,8 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
end end
step 'I am redirected to the root directory' do step 'I am redirected to the root directory' do
expect(current_path).to eq(namespace_project_tree_path( expect(current_path).to eq(
@project.namespace, @project, 'master/')) namespace_project_tree_path(@project.namespace, @project, 'master/'))
end end
step "I don't see the permalink link" do step "I don't see the permalink link" do
......
...@@ -166,7 +166,7 @@ module SharedDiffNote ...@@ -166,7 +166,7 @@ module SharedDiffNote
end end
step 'I should see add a diff comment button' do step 'I should see add a diff comment button' do
expect(page).to have_css('.js-add-diff-note-button', visible: true) expect(page).to have_css('.js-add-diff-note-button')
end end
step 'I should see an empty diff comment form' do step 'I should see an empty diff comment form' do
......
...@@ -240,8 +240,8 @@ module SharedPaths ...@@ -240,8 +240,8 @@ module SharedPaths
end end
step 'I visit a binary file in the repo' do step 'I visit a binary file in the repo' do
visit namespace_project_blob_path(@project.namespace, @project, File.join( visit namespace_project_blob_path(@project.namespace, @project,
root_ref, 'files/images/logo-black.png')) File.join(root_ref, 'files/images/logo-black.png'))
end end
step "I visit my project's commits page" do step "I visit my project's commits page" do
...@@ -352,8 +352,8 @@ module SharedPaths ...@@ -352,8 +352,8 @@ module SharedPaths
end end
step 'I am on the ".gitignore" edit file page' do step 'I am on the ".gitignore" edit file page' do
expect(current_path).to eq(namespace_project_edit_blob_path( expect(current_path).to eq(
@project.namespace, @project, File.join(root_ref, '.gitignore'))) namespace_project_edit_blob_path(@project.namespace, @project, File.join(root_ref, '.gitignore')))
end end
step 'I visit project source page for "6d39438"' do step 'I visit project source page for "6d39438"' do
......
...@@ -13,7 +13,7 @@ class Spinach::Features::Snippets < Spinach::FeatureSteps ...@@ -13,7 +13,7 @@ class Spinach::Features::Snippets < Spinach::FeatureSteps
end end
step 'I click link "Edit"' do step 'I click link "Edit"' do
page.within ".page-title" do page.within ".detail-page-header" do
click_link "Edit" click_link "Edit"
end end
end end
......
...@@ -72,9 +72,10 @@ module API ...@@ -72,9 +72,10 @@ module API
expose :shared_runners_enabled expose :shared_runners_enabled
expose :creator_id expose :creator_id
expose :namespace expose :namespace
expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda{ | project, options | project.forked? } expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda{ |project, options| project.forked? }
expose :avatar_url expose :avatar_url
expose :star_count, :forks_count expose :star_count, :forks_count
expose :open_issues_count, if: lambda { |project, options| project.issues_enabled? && project.default_issues_tracker? }
end end
class ProjectMember < UserBasic class ProjectMember < UserBasic
......
...@@ -39,6 +39,17 @@ module API ...@@ -39,6 +39,17 @@ module API
present @projects, with: Entities::Project present @projects, with: Entities::Project
end end
# Gets starred project for the authenticated user
#
# Example Request:
# GET /projects/starred
get '/starred' do
@projects = current_user.starred_projects
@projects = filter_projects(@projects)
@projects = paginate @projects
present @projects, with: Entities::Project
end
# Get all projects for admin user # Get all projects for admin user
# #
# Example Request: # Example Request:
......
module Banzai
def self.render(text, context = {})
Renderer.render(text, context)
end
def self.render_result(text, context = {})
Renderer.render_result(text, context)
end
def self.post_process(html, context)
Renderer.post_process(html, context)
end
end
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment