Merge branch 'master' into reference-pipeline-and-caching
This commit is contained in:
commit
de0acf3cf7
|
|
@ -25,7 +25,6 @@ config/initializers/rack_attack.rb
|
||||||
config/initializers/smtp_settings.rb
|
config/initializers/smtp_settings.rb
|
||||||
config/resque.yml
|
config/resque.yml
|
||||||
config/unicorn.rb
|
config/unicorn.rb
|
||||||
config/mail_room.yml
|
|
||||||
config/secrets.yml
|
config/secrets.yml
|
||||||
coverage/*
|
coverage/*
|
||||||
db/*.sqlite3
|
db/*.sqlite3
|
||||||
|
|
|
||||||
34
CHANGELOG
34
CHANGELOG
|
|
@ -1,7 +1,28 @@
|
||||||
Please view this file on the master branch, on stable branches it's out of date.
|
Please view this file on the master branch, on stable branches it's out of date.
|
||||||
|
|
||||||
|
v 8.2.0 (unreleased)
|
||||||
|
- Ensure MySQL CI limits DB migrations occur after the fields have been created (Stan Hu)
|
||||||
|
- Improved performance of replacing references in comments
|
||||||
|
- Fix duplicate repositories in GitHub import page (Stan Hu)
|
||||||
|
- Redirect to a default path if HTTP_REFERER is not set (Stan Hu)
|
||||||
|
- Show last project commit to default branch on project home page
|
||||||
|
- Highlight comment based on anchor in URL
|
||||||
|
- Adds ability to remove the forked relationship from project settings screen. (Han Loong Liauw)
|
||||||
|
- Improved performance of sorting milestone issues
|
||||||
|
- Allow users to select the Files view as default project view (Cristian Bica)
|
||||||
|
|
||||||
v 8.1.0 (unreleased)
|
v 8.1.0 (unreleased)
|
||||||
|
- Send an email to admin email when a user is reported for spam (Jonathan Rochkind)
|
||||||
|
- Show notifications button when user is member of group rather than project (Grzegorz Bizon)
|
||||||
|
- Fix bug preventing mentioned issued from being closed when MR is merged using fast-forward merge.
|
||||||
|
- Fix nonatomic database update potentially causing project star counts to go negative (Stan Hu)
|
||||||
|
- Fix error preventing displaying of commit data for a directory with a leading dot (Stan Hu)
|
||||||
|
- Speed up load times of issue detail pages by roughly 1.5x
|
||||||
|
- If a merge request is to close an issue, show this on the issue page (Zeger-Jan van de Weg)
|
||||||
|
- Add a system note and update relevant merge requests when a branch is deleted or re-added (Stan Hu)
|
||||||
- Make diff file view easier to use on mobile screens (Stan Hu)
|
- Make diff file view easier to use on mobile screens (Stan Hu)
|
||||||
|
- Improved performance of finding users by username or Email address
|
||||||
|
- Fix bug where merge request comments created by API would not trigger notifications (Stan Hu)
|
||||||
- Add support for creating directories from Files page (Stan Hu)
|
- Add support for creating directories from Files page (Stan Hu)
|
||||||
- Allow removing of project without confirmation when JavaScript is disabled (Stan Hu)
|
- Allow removing of project without confirmation when JavaScript is disabled (Stan Hu)
|
||||||
- Support filtering by "Any" milestone or issue and fix "No Milestone" and "No Label" filters (Stan Hu)
|
- Support filtering by "Any" milestone or issue and fix "No Milestone" and "No Label" filters (Stan Hu)
|
||||||
|
|
@ -17,6 +38,8 @@ v 8.1.0 (unreleased)
|
||||||
- Fix cases where Markdown did not render links in activity feed (Stan Hu)
|
- Fix cases where Markdown did not render links in activity feed (Stan Hu)
|
||||||
- Add first and last to pagination (Zeger-Jan van de Weg)
|
- Add first and last to pagination (Zeger-Jan van de Weg)
|
||||||
- Added Commit Status API
|
- Added Commit Status API
|
||||||
|
- Added Builds View
|
||||||
|
- Added when to .gitlab-ci.yml
|
||||||
- Show CI status on commit page
|
- Show CI status on commit page
|
||||||
- Added CI_BUILD_TAG, _STAGE, _NAME and _TRIGGERED to CI builds
|
- Added CI_BUILD_TAG, _STAGE, _NAME and _TRIGGERED to CI builds
|
||||||
- Show CI status on Your projects page and Starred projects page
|
- Show CI status on Your projects page and Starred projects page
|
||||||
|
|
@ -40,7 +63,7 @@ v 8.1.0 (unreleased)
|
||||||
- Move CI web hooks page to project settings area
|
- Move CI web hooks page to project settings area
|
||||||
- Fix User Identities API. It now allows you to properly create or update user's identities.
|
- Fix User Identities API. It now allows you to properly create or update user's identities.
|
||||||
- Add user preference to change layout width (Peter Göbel)
|
- Add user preference to change layout width (Peter Göbel)
|
||||||
- Use commit status in merge request widget as preffered source of CI status
|
- Use commit status in merge request widget as preferred source of CI status
|
||||||
- Integrate CI commit and build pages into project pages
|
- Integrate CI commit and build pages into project pages
|
||||||
- Move CI services page to project settings area
|
- Move CI services page to project settings area
|
||||||
- Add "Quick Submit" behavior to input fields throughout the application. Use
|
- Add "Quick Submit" behavior to input fields throughout the application. Use
|
||||||
|
|
@ -48,6 +71,7 @@ v 8.1.0 (unreleased)
|
||||||
- Fix position of hamburger in header for smaller screens (Han Loong Liauw)
|
- Fix position of hamburger in header for smaller screens (Han Loong Liauw)
|
||||||
- Fix bug where Emojis in Markdown would truncate remaining text (Sakata Sinji)
|
- Fix bug where Emojis in Markdown would truncate remaining text (Sakata Sinji)
|
||||||
- Persist filters when sorting on admin user page (Jerry Lukins)
|
- Persist filters when sorting on admin user page (Jerry Lukins)
|
||||||
|
- Allow dashboard and group issues/MRs to be filtered by label
|
||||||
- Add spellcheck=false to certain input fields
|
- Add spellcheck=false to certain input fields
|
||||||
- Invalidate stored service password if the endpoint URL is changed
|
- Invalidate stored service password if the endpoint URL is changed
|
||||||
- Project names are not fully shown if group name is too big, even on group page view
|
- Project names are not fully shown if group name is too big, even on group page view
|
||||||
|
|
@ -56,6 +80,14 @@ v 8.1.0 (unreleased)
|
||||||
- Only render 404 page from /public
|
- Only render 404 page from /public
|
||||||
- Hide passwords from services API (Alex Lossent)
|
- Hide passwords from services API (Alex Lossent)
|
||||||
- Fix: Images cannot show when projects' path was changed
|
- Fix: Images cannot show when projects' path was changed
|
||||||
|
- Let gitlab-git-http-server generate and serve 'git archive' downloads
|
||||||
|
- Optimize query when filtering on issuables (Zeger-Jan van de Weg)
|
||||||
|
- Fix padding of outdated discussion item.
|
||||||
|
|
||||||
|
v 8.0.5
|
||||||
|
- Correct lookup-by-email for LDAP logins
|
||||||
|
- Fix loading spinner sometimes not being hidden on Merge Request tab switches
|
||||||
|
- Animate the logo on hover
|
||||||
|
|
||||||
v 8.0.4
|
v 8.0.4
|
||||||
- Fix Message-ID header to be RFC 2111-compliant to prevent e-mails being dropped (Stan Hu)
|
- Fix Message-ID header to be RFC 2111-compliant to prevent e-mails being dropped (Stan Hu)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
0.3.0
|
||||||
27
Gemfile
27
Gemfile
|
|
@ -1,13 +1,5 @@
|
||||||
source "https://rubygems.org"
|
source "https://rubygems.org"
|
||||||
|
|
||||||
def darwin_only(require_as)
|
|
||||||
RUBY_PLATFORM.include?('darwin') && require_as
|
|
||||||
end
|
|
||||||
|
|
||||||
def linux_only(require_as)
|
|
||||||
RUBY_PLATFORM.include?('linux') && require_as
|
|
||||||
end
|
|
||||||
|
|
||||||
gem 'rails', '4.1.12'
|
gem 'rails', '4.1.12'
|
||||||
|
|
||||||
# Specify a sprockets version due to security issue
|
# Specify a sprockets version due to security issue
|
||||||
|
|
@ -47,7 +39,7 @@ gem "browser", '~> 1.0.0'
|
||||||
|
|
||||||
# Extracting information from a git repository
|
# Extracting information from a git repository
|
||||||
# Provide access to Gitlab::Git library
|
# Provide access to Gitlab::Git library
|
||||||
gem "gitlab_git", '~> 7.2.18'
|
gem "gitlab_git", '~> 7.2.19'
|
||||||
|
|
||||||
# LDAP Auth
|
# LDAP Auth
|
||||||
# GitLab fork with several improvements to original library. For full list of changes
|
# GitLab fork with several improvements to original library. For full list of changes
|
||||||
|
|
@ -102,7 +94,7 @@ gem "seed-fu", '~> 2.3.5'
|
||||||
gem 'html-pipeline', '~> 1.11.0'
|
gem 'html-pipeline', '~> 1.11.0'
|
||||||
gem 'task_list', '~> 1.0.2', require: 'task_list/railtie'
|
gem 'task_list', '~> 1.0.2', require: 'task_list/railtie'
|
||||||
gem 'github-markup', '~> 1.3.1'
|
gem 'github-markup', '~> 1.3.1'
|
||||||
gem 'redcarpet', '~> 3.3.2'
|
gem 'redcarpet', '~> 3.3.3'
|
||||||
gem 'RedCloth', '~> 4.2.9'
|
gem 'RedCloth', '~> 4.2.9'
|
||||||
gem 'rdoc', '~>3.6'
|
gem 'rdoc', '~>3.6'
|
||||||
gem 'org-ruby', '~> 0.9.12'
|
gem 'org-ruby', '~> 0.9.12'
|
||||||
|
|
@ -196,7 +188,7 @@ gem 'charlock_holmes', '~> 0.6.9.4'
|
||||||
|
|
||||||
gem "sass-rails", '~> 4.0.5'
|
gem "sass-rails", '~> 4.0.5'
|
||||||
gem "coffee-rails", '~> 4.1.0'
|
gem "coffee-rails", '~> 4.1.0'
|
||||||
gem "uglifier", '~> 2.3.2'
|
gem "uglifier", '~> 2.7.2'
|
||||||
gem 'turbolinks', '~> 2.5.0'
|
gem 'turbolinks', '~> 2.5.0'
|
||||||
gem 'jquery-turbolinks', '~> 2.0.1'
|
gem 'jquery-turbolinks', '~> 2.0.1'
|
||||||
|
|
||||||
|
|
@ -224,6 +216,9 @@ group :development do
|
||||||
gem 'quiet_assets', '~> 1.0.2'
|
gem 'quiet_assets', '~> 1.0.2'
|
||||||
gem 'rack-mini-profiler', '~> 0.9.0', require: false
|
gem 'rack-mini-profiler', '~> 0.9.0', require: false
|
||||||
gem 'rerun', '~> 0.10.0'
|
gem 'rerun', '~> 0.10.0'
|
||||||
|
gem 'bullet', require: false
|
||||||
|
gem 'active_record_query_trace', require: false
|
||||||
|
gem 'rack-lineprof', platform: :mri
|
||||||
|
|
||||||
# Better errors handler
|
# Better errors handler
|
||||||
gem 'better_errors', '~> 1.0.1'
|
gem 'better_errors', '~> 1.0.1'
|
||||||
|
|
@ -290,7 +285,7 @@ gem 'newrelic-grape'
|
||||||
|
|
||||||
gem 'octokit', '~> 3.7.0'
|
gem 'octokit', '~> 3.7.0'
|
||||||
|
|
||||||
gem "mail_room", "~> 0.6.0"
|
gem "mail_room", "~> 0.6.1"
|
||||||
|
|
||||||
gem 'email_reply_parser', '~> 0.5.8'
|
gem 'email_reply_parser', '~> 0.5.8'
|
||||||
|
|
||||||
|
|
@ -304,11 +299,3 @@ gem 'oauth2', '~> 1.0.0'
|
||||||
|
|
||||||
# Soft deletion
|
# Soft deletion
|
||||||
gem "paranoia", "~> 2.0"
|
gem "paranoia", "~> 2.0"
|
||||||
|
|
||||||
group :development, :test do
|
|
||||||
gem 'guard-rspec', '~> 4.2.0'
|
|
||||||
|
|
||||||
gem 'rb-fsevent', require: darwin_only('rb-fsevent')
|
|
||||||
gem 'growl', require: darwin_only('growl')
|
|
||||||
gem 'rb-inotify', require: linux_only('rb-inotify')
|
|
||||||
end
|
|
||||||
|
|
|
||||||
54
Gemfile.lock
54
Gemfile.lock
|
|
@ -17,6 +17,7 @@ GEM
|
||||||
activesupport (= 4.1.12)
|
activesupport (= 4.1.12)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
erubis (~> 2.7.0)
|
erubis (~> 2.7.0)
|
||||||
|
active_record_query_trace (1.5)
|
||||||
activemodel (4.1.12)
|
activemodel (4.1.12)
|
||||||
activesupport (= 4.1.12)
|
activesupport (= 4.1.12)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
|
|
@ -87,6 +88,9 @@ GEM
|
||||||
terminal-table (~> 1.4)
|
terminal-table (~> 1.4)
|
||||||
browser (1.0.0)
|
browser (1.0.0)
|
||||||
builder (3.2.2)
|
builder (3.2.2)
|
||||||
|
bullet (4.14.9)
|
||||||
|
activesupport (>= 3.0.0)
|
||||||
|
uniform_notifier (~> 1.9.0)
|
||||||
byebug (6.0.2)
|
byebug (6.0.2)
|
||||||
cal-heatmap-rails (0.0.1)
|
cal-heatmap-rails (0.0.1)
|
||||||
capybara (2.4.4)
|
capybara (2.4.4)
|
||||||
|
|
@ -134,6 +138,7 @@ GEM
|
||||||
daemons (1.2.3)
|
daemons (1.2.3)
|
||||||
database_cleaner (1.4.1)
|
database_cleaner (1.4.1)
|
||||||
debug_inspector (0.0.2)
|
debug_inspector (0.0.2)
|
||||||
|
debugger-ruby_core_source (1.3.8)
|
||||||
default_value_for (3.0.1)
|
default_value_for (3.0.1)
|
||||||
activerecord (>= 3.2.0, < 5.0)
|
activerecord (>= 3.2.0, < 5.0)
|
||||||
descendants_tracker (0.0.4)
|
descendants_tracker (0.0.4)
|
||||||
|
|
@ -278,7 +283,7 @@ GEM
|
||||||
mime-types (~> 1.19)
|
mime-types (~> 1.19)
|
||||||
gitlab_emoji (0.1.1)
|
gitlab_emoji (0.1.1)
|
||||||
gemojione (~> 2.0)
|
gemojione (~> 2.0)
|
||||||
gitlab_git (7.2.18)
|
gitlab_git (7.2.19)
|
||||||
activesupport (~> 4.0)
|
activesupport (~> 4.0)
|
||||||
charlock_holmes (~> 0.6)
|
charlock_holmes (~> 0.6)
|
||||||
gitlab-linguist (~> 3.0)
|
gitlab-linguist (~> 3.0)
|
||||||
|
|
@ -314,19 +319,6 @@ GEM
|
||||||
grape-entity (0.4.8)
|
grape-entity (0.4.8)
|
||||||
activesupport
|
activesupport
|
||||||
multi_json (>= 1.3.2)
|
multi_json (>= 1.3.2)
|
||||||
growl (1.0.3)
|
|
||||||
guard (2.13.0)
|
|
||||||
formatador (>= 0.2.4)
|
|
||||||
listen (>= 2.7, <= 4.0)
|
|
||||||
lumberjack (~> 1.0)
|
|
||||||
nenv (~> 0.1)
|
|
||||||
notiffany (~> 0.0)
|
|
||||||
pry (>= 0.9.12)
|
|
||||||
shellany (~> 0.0)
|
|
||||||
thor (>= 0.18.1)
|
|
||||||
guard-rspec (4.2.10)
|
|
||||||
guard (~> 2.1)
|
|
||||||
rspec (>= 2.14, < 4.0)
|
|
||||||
haml (4.0.7)
|
haml (4.0.7)
|
||||||
tilt
|
tilt
|
||||||
haml-rails (0.9.0)
|
haml-rails (0.9.0)
|
||||||
|
|
@ -387,12 +379,11 @@ GEM
|
||||||
celluloid (~> 0.16.0)
|
celluloid (~> 0.16.0)
|
||||||
rb-fsevent (>= 0.9.3)
|
rb-fsevent (>= 0.9.3)
|
||||||
rb-inotify (>= 0.9)
|
rb-inotify (>= 0.9)
|
||||||
lumberjack (1.0.9)
|
|
||||||
macaddr (1.7.1)
|
macaddr (1.7.1)
|
||||||
systemu (~> 2.6.2)
|
systemu (~> 2.6.2)
|
||||||
mail (2.6.3)
|
mail (2.6.3)
|
||||||
mime-types (>= 1.16, < 3)
|
mime-types (>= 1.16, < 3)
|
||||||
mail_room (0.6.0)
|
mail_room (0.6.1)
|
||||||
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)
|
||||||
|
|
@ -403,7 +394,6 @@ GEM
|
||||||
multi_xml (0.5.5)
|
multi_xml (0.5.5)
|
||||||
multipart-post (2.0.0)
|
multipart-post (2.0.0)
|
||||||
mysql2 (0.3.20)
|
mysql2 (0.3.20)
|
||||||
nenv (0.2.0)
|
|
||||||
nested_form (0.3.2)
|
nested_form (0.3.2)
|
||||||
net-ldap (0.11)
|
net-ldap (0.11)
|
||||||
net-scp (1.2.1)
|
net-scp (1.2.1)
|
||||||
|
|
@ -416,9 +406,6 @@ GEM
|
||||||
newrelic_rpm (3.9.4.245)
|
newrelic_rpm (3.9.4.245)
|
||||||
nokogiri (1.6.6.2)
|
nokogiri (1.6.6.2)
|
||||||
mini_portile (~> 0.6.0)
|
mini_portile (~> 0.6.0)
|
||||||
notiffany (0.0.7)
|
|
||||||
nenv (~> 0.1)
|
|
||||||
shellany (~> 0.0)
|
|
||||||
nprogress-rails (0.1.2.3)
|
nprogress-rails (0.1.2.3)
|
||||||
oauth (0.4.7)
|
oauth (0.4.7)
|
||||||
oauth2 (1.0.0)
|
oauth2 (1.0.0)
|
||||||
|
|
@ -502,6 +489,10 @@ GEM
|
||||||
rack-attack (4.3.0)
|
rack-attack (4.3.0)
|
||||||
rack
|
rack
|
||||||
rack-cors (0.4.0)
|
rack-cors (0.4.0)
|
||||||
|
rack-lineprof (0.0.3)
|
||||||
|
rack (~> 1.5)
|
||||||
|
rblineprof (~> 0.3.6)
|
||||||
|
term-ansicolor (~> 1.3)
|
||||||
rack-mini-profiler (0.9.7)
|
rack-mini-profiler (0.9.7)
|
||||||
rack (>= 1.1.3)
|
rack (>= 1.1.3)
|
||||||
rack-mount (0.8.3)
|
rack-mount (0.8.3)
|
||||||
|
|
@ -540,13 +531,15 @@ GEM
|
||||||
rb-fsevent (0.9.5)
|
rb-fsevent (0.9.5)
|
||||||
rb-inotify (0.9.5)
|
rb-inotify (0.9.5)
|
||||||
ffi (>= 0.5.0)
|
ffi (>= 0.5.0)
|
||||||
|
rblineprof (0.3.6)
|
||||||
|
debugger-ruby_core_source (~> 1.3)
|
||||||
rbvmomi (1.8.2)
|
rbvmomi (1.8.2)
|
||||||
builder
|
builder
|
||||||
nokogiri (>= 1.4.1)
|
nokogiri (>= 1.4.1)
|
||||||
trollop
|
trollop
|
||||||
rdoc (3.12.2)
|
rdoc (3.12.2)
|
||||||
json (~> 1.4)
|
json (~> 1.4)
|
||||||
redcarpet (3.3.2)
|
redcarpet (3.3.3)
|
||||||
redis (3.2.1)
|
redis (3.2.1)
|
||||||
redis-actionpack (4.0.0)
|
redis-actionpack (4.0.0)
|
||||||
actionpack (~> 4)
|
actionpack (~> 4)
|
||||||
|
|
@ -647,7 +640,6 @@ GEM
|
||||||
sexp_processor (4.6.0)
|
sexp_processor (4.6.0)
|
||||||
sham_rack (1.3.6)
|
sham_rack (1.3.6)
|
||||||
rack
|
rack
|
||||||
shellany (0.0.1)
|
|
||||||
shoulda-matchers (2.8.0)
|
shoulda-matchers (2.8.0)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
sidekiq (3.3.0)
|
sidekiq (3.3.0)
|
||||||
|
|
@ -741,7 +733,7 @@ GEM
|
||||||
simple_oauth (~> 0.1.4)
|
simple_oauth (~> 0.1.4)
|
||||||
tzinfo (1.2.2)
|
tzinfo (1.2.2)
|
||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
uglifier (2.3.3)
|
uglifier (2.7.2)
|
||||||
execjs (>= 0.3.0)
|
execjs (>= 0.3.0)
|
||||||
json (>= 1.8.0)
|
json (>= 1.8.0)
|
||||||
underscore-rails (1.4.4)
|
underscore-rails (1.4.4)
|
||||||
|
|
@ -755,6 +747,7 @@ GEM
|
||||||
unicorn-worker-killer (0.4.3)
|
unicorn-worker-killer (0.4.3)
|
||||||
get_process_mem (~> 0)
|
get_process_mem (~> 0)
|
||||||
unicorn (~> 4)
|
unicorn (~> 4)
|
||||||
|
uniform_notifier (1.9.0)
|
||||||
uuid (2.3.8)
|
uuid (2.3.8)
|
||||||
macaddr (~> 1.0)
|
macaddr (~> 1.0)
|
||||||
version_sorter (2.0.0)
|
version_sorter (2.0.0)
|
||||||
|
|
@ -784,6 +777,7 @@ PLATFORMS
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
RedCloth (~> 4.2.9)
|
RedCloth (~> 4.2.9)
|
||||||
ace-rails-ap (~> 2.0.1)
|
ace-rails-ap (~> 2.0.1)
|
||||||
|
active_record_query_trace
|
||||||
activerecord-deprecated_finders (~> 1.0.3)
|
activerecord-deprecated_finders (~> 1.0.3)
|
||||||
activerecord-session_store (~> 0.1.0)
|
activerecord-session_store (~> 0.1.0)
|
||||||
acts-as-taggable-on (~> 3.4)
|
acts-as-taggable-on (~> 3.4)
|
||||||
|
|
@ -800,6 +794,7 @@ DEPENDENCIES
|
||||||
bootstrap-sass (~> 3.0)
|
bootstrap-sass (~> 3.0)
|
||||||
brakeman (= 3.0.1)
|
brakeman (= 3.0.1)
|
||||||
browser (~> 1.0.0)
|
browser (~> 1.0.0)
|
||||||
|
bullet
|
||||||
byebug
|
byebug
|
||||||
cal-heatmap-rails (~> 0.0.1)
|
cal-heatmap-rails (~> 0.0.1)
|
||||||
capybara (~> 2.4.0)
|
capybara (~> 2.4.0)
|
||||||
|
|
@ -834,15 +829,13 @@ DEPENDENCIES
|
||||||
gitlab-flowdock-git-hook (~> 1.0.1)
|
gitlab-flowdock-git-hook (~> 1.0.1)
|
||||||
gitlab-linguist (~> 3.0.1)
|
gitlab-linguist (~> 3.0.1)
|
||||||
gitlab_emoji (~> 0.1)
|
gitlab_emoji (~> 0.1)
|
||||||
gitlab_git (~> 7.2.18)
|
gitlab_git (~> 7.2.19)
|
||||||
gitlab_meta (= 7.0)
|
gitlab_meta (= 7.0)
|
||||||
gitlab_omniauth-ldap (~> 1.2.1)
|
gitlab_omniauth-ldap (~> 1.2.1)
|
||||||
gollum-lib (~> 4.0.2)
|
gollum-lib (~> 4.0.2)
|
||||||
gon (~> 5.0.0)
|
gon (~> 5.0.0)
|
||||||
grape (~> 0.6.1)
|
grape (~> 0.6.1)
|
||||||
grape-entity (~> 0.4.2)
|
grape-entity (~> 0.4.2)
|
||||||
growl
|
|
||||||
guard-rspec (~> 4.2.0)
|
|
||||||
haml-rails (~> 0.9.0)
|
haml-rails (~> 0.9.0)
|
||||||
hipchat (~> 1.5.0)
|
hipchat (~> 1.5.0)
|
||||||
html-pipeline (~> 1.11.0)
|
html-pipeline (~> 1.11.0)
|
||||||
|
|
@ -854,7 +847,7 @@ DEPENDENCIES
|
||||||
jquery-ui-rails (~> 4.2.1)
|
jquery-ui-rails (~> 4.2.1)
|
||||||
kaminari (~> 0.16.3)
|
kaminari (~> 0.16.3)
|
||||||
letter_opener (~> 1.1.2)
|
letter_opener (~> 1.1.2)
|
||||||
mail_room (~> 0.6.0)
|
mail_room (~> 0.6.1)
|
||||||
minitest (~> 5.7.0)
|
minitest (~> 5.7.0)
|
||||||
mousetrap-rails (~> 1.4.6)
|
mousetrap-rails (~> 1.4.6)
|
||||||
mysql2 (~> 0.3.16)
|
mysql2 (~> 0.3.16)
|
||||||
|
|
@ -882,14 +875,13 @@ DEPENDENCIES
|
||||||
quiet_assets (~> 1.0.2)
|
quiet_assets (~> 1.0.2)
|
||||||
rack-attack (~> 4.3.0)
|
rack-attack (~> 4.3.0)
|
||||||
rack-cors (~> 0.4.0)
|
rack-cors (~> 0.4.0)
|
||||||
|
rack-lineprof
|
||||||
rack-mini-profiler (~> 0.9.0)
|
rack-mini-profiler (~> 0.9.0)
|
||||||
rack-oauth2 (~> 1.0.5)
|
rack-oauth2 (~> 1.0.5)
|
||||||
rails (= 4.1.12)
|
rails (= 4.1.12)
|
||||||
raphael-rails (~> 2.1.2)
|
raphael-rails (~> 2.1.2)
|
||||||
rb-fsevent
|
|
||||||
rb-inotify
|
|
||||||
rdoc (~> 3.6)
|
rdoc (~> 3.6)
|
||||||
redcarpet (~> 3.3.2)
|
redcarpet (~> 3.3.3)
|
||||||
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.10.0)
|
||||||
|
|
@ -926,7 +918,7 @@ DEPENDENCIES
|
||||||
thin (~> 1.6.1)
|
thin (~> 1.6.1)
|
||||||
tinder (~> 1.10.0)
|
tinder (~> 1.10.0)
|
||||||
turbolinks (~> 2.5.0)
|
turbolinks (~> 2.5.0)
|
||||||
uglifier (~> 2.3.2)
|
uglifier (~> 2.7.2)
|
||||||
underscore-rails (~> 1.4.4)
|
underscore-rails (~> 1.4.4)
|
||||||
unf (~> 0.1.4)
|
unf (~> 0.1.4)
|
||||||
unicorn (~> 4.8.2)
|
unicorn (~> 4.8.2)
|
||||||
|
|
|
||||||
|
|
@ -10,17 +10,17 @@
|
||||||
<g id="Fill-1-+-Group-24">
|
<g id="Fill-1-+-Group-24">
|
||||||
<g id="Group-24">
|
<g id="Group-24">
|
||||||
<g id="Group">
|
<g id="Group">
|
||||||
<path d="M105.0614,193.655 L105.0614,193.655 L143.7014,74.734 L66.4214,74.734 L105.0614,193.655 L105.0614,193.655 Z" id="Fill-4" fill="#E24329"></path>
|
<path d="M105.0614,193.655 L105.0614,193.655 L143.7014,74.734 L66.4214,74.734 L105.0614,193.655 L105.0614,193.655 Z" id="Fill-4" fill="#E24329" class="tanuki-shape"></path>
|
||||||
<path d="M105.0614,193.6548 L66.4214,74.7338 L12.2684,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" id="Fill-8" fill="#FC6D26"></path>
|
<path d="M105.0614,193.6548 L66.4214,74.7338 L12.2684,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" id="Fill-8" fill="#FC6D26" class="tanuki-shape"></path>
|
||||||
<path d="M12.2685,74.7341 L12.2685,74.7341 L0.5265,110.8731 C-0.5445,114.1691 0.6285,117.7801 3.4325,119.8171 L105.0615,193.6551 L12.2685,74.7341 L12.2685,74.7341 Z" id="Fill-12" fill="#FCA326"></path>
|
<path d="M12.2685,74.7341 L12.2685,74.7341 L0.5265,110.8731 C-0.5445,114.1691 0.6285,117.7801 3.4325,119.8171 L105.0615,193.6551 L12.2685,74.7341 L12.2685,74.7341 Z" id="Fill-12" fill="#FCA326" class="tanuki-shape"></path>
|
||||||
<path d="M12.2685,74.7342 L66.4215,74.7342 L43.1485,3.1092 C41.9515,-0.5768 36.7375,-0.5758 35.5405,3.1092 L12.2685,74.7342 L12.2685,74.7342 Z" id="Fill-16" fill="#E24329"></path>
|
<path d="M12.2685,74.7342 L66.4215,74.7342 L43.1485,3.1092 C41.9515,-0.5768 36.7375,-0.5758 35.5405,3.1092 L12.2685,74.7342 L12.2685,74.7342 Z" id="Fill-16" fill="#E24329" class="tanuki-shape"></path>
|
||||||
<path d="M105.0614,193.6548 L143.7014,74.7338 L197.8544,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" id="Fill-18" fill="#FC6D26"></path>
|
<path d="M105.0614,193.6548 L143.7014,74.7338 L197.8544,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" id="Fill-18" fill="#FC6D26" class="tanuki-shape"></path>
|
||||||
<path d="M197.8544,74.7341 L197.8544,74.7341 L209.5964,110.8731 C210.6674,114.1691 209.4944,117.7801 206.6904,119.8171 L105.0614,193.6551 L197.8544,74.7341 L197.8544,74.7341 Z" id="Fill-20" fill="#FCA326"></path>
|
<path d="M197.8544,74.7341 L197.8544,74.7341 L209.5964,110.8731 C210.6674,114.1691 209.4944,117.7801 206.6904,119.8171 L105.0614,193.6551 L197.8544,74.7341 L197.8544,74.7341 Z" id="Fill-20" fill="#FCA326" class="tanuki-shape"></path>
|
||||||
<path d="M197.8544,74.7342 L143.7014,74.7342 L166.9744,3.1092 C168.1714,-0.5768 173.3854,-0.5758 174.5824,3.1092 L197.8544,74.7342 L197.8544,74.7342 Z" id="Fill-22" fill="#E24329"></path>
|
<path d="M197.8544,74.7342 L143.7014,74.7342 L166.9744,3.1092 C168.1714,-0.5768 173.3854,-0.5758 174.5824,3.1092 L197.8544,74.7342 L197.8544,74.7342 Z" id="Fill-22" fill="#E24329" class="tanuki-shape"></path>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.4 KiB |
|
|
@ -68,8 +68,8 @@ class @MergeRequestTabs
|
||||||
|
|
||||||
scrollToElement: (container) ->
|
scrollToElement: (container) ->
|
||||||
if window.location.hash
|
if window.location.hash
|
||||||
top = $(container + " " + window.location.hash).offset().top
|
$el = $("#{container} #{window.location.hash}")
|
||||||
$('body').scrollTo(top)
|
$('body').scrollTo($el.offset().top) if $el.length
|
||||||
|
|
||||||
# Activate a tab based on the current action
|
# Activate a tab based on the current action
|
||||||
activateTab: (action) ->
|
activateTab: (action) ->
|
||||||
|
|
@ -127,7 +127,7 @@ class @MergeRequestTabs
|
||||||
document.getElementById('commits').innerHTML = data.html
|
document.getElementById('commits').innerHTML = data.html
|
||||||
$('.js-timeago').timeago()
|
$('.js-timeago').timeago()
|
||||||
@commitsLoaded = true
|
@commitsLoaded = true
|
||||||
@scrollToElement(".commits")
|
@scrollToElement("#commits")
|
||||||
|
|
||||||
loadDiff: (source) ->
|
loadDiff: (source) ->
|
||||||
return if @diffsLoaded
|
return if @diffsLoaded
|
||||||
|
|
@ -137,7 +137,7 @@ class @MergeRequestTabs
|
||||||
success: (data) =>
|
success: (data) =>
|
||||||
document.getElementById('diffs').innerHTML = data.html
|
document.getElementById('diffs').innerHTML = data.html
|
||||||
@diffsLoaded = true
|
@diffsLoaded = true
|
||||||
@scrollToElement(".diffs")
|
@scrollToElement("#diffs")
|
||||||
|
|
||||||
# Show or hide the loading spinner
|
# Show or hide the loading spinner
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ class @ShortcutsNavigation extends Shortcuts
|
||||||
Mousetrap.bind('g e', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-project-activity'))
|
Mousetrap.bind('g e', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-project-activity'))
|
||||||
Mousetrap.bind('g f', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-tree'))
|
Mousetrap.bind('g f', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-tree'))
|
||||||
Mousetrap.bind('g c', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-commits'))
|
Mousetrap.bind('g c', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-commits'))
|
||||||
|
Mousetrap.bind('g b', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-builds'))
|
||||||
Mousetrap.bind('g n', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-network'))
|
Mousetrap.bind('g n', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-network'))
|
||||||
Mousetrap.bind('g g', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-graphs'))
|
Mousetrap.bind('g g', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-graphs'))
|
||||||
Mousetrap.bind('g i', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-issues'))
|
Mousetrap.bind('g i', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-issues'))
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
line-height: 36px;
|
line-height: 36px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content-block,
|
||||||
.gray-content-block {
|
.gray-content-block {
|
||||||
margin: -$gl-padding;
|
margin: -$gl-padding;
|
||||||
background-color: $background-color;
|
background-color: $background-color;
|
||||||
|
|
@ -27,6 +28,10 @@
|
||||||
border-bottom: 1px solid $border-color;
|
border-bottom: 1px solid $border-color;
|
||||||
color: $gl-gray;
|
color: $gl-gray;
|
||||||
|
|
||||||
|
&.white {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
&.top-block {
|
&.top-block {
|
||||||
border-top: none;
|
border-top: none;
|
||||||
}
|
}
|
||||||
|
|
@ -60,3 +65,48 @@
|
||||||
line-height: 42px;
|
line-height: 42px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cover-block {
|
||||||
|
text-align: center;
|
||||||
|
background: #f7f8fa;
|
||||||
|
margin: -$gl-padding;
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding: 44px $gl-padding;
|
||||||
|
border-bottom: 1px solid $border-color;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.avatar-holder {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.avatar, .identicon {
|
||||||
|
margin: 0 auto;
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.identicon {
|
||||||
|
@include border-radius(50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cover-title {
|
||||||
|
color: $gl-header-color;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 23px;
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 16px 0 5px 0;
|
||||||
|
color: #4c4e54;
|
||||||
|
font-size: 23px;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cover-desc {
|
||||||
|
padding: 0 $gl-padding;
|
||||||
|
color: $gl-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cover-controls {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,10 @@
|
||||||
border-bottom: 1px solid #E7E9EE;
|
border-bottom: 1px solid #E7E9EE;
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
|
|
||||||
|
&.readme-holder {
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
@extend .table;
|
@extend .table;
|
||||||
}
|
}
|
||||||
|
|
@ -94,7 +98,6 @@
|
||||||
border-right: none;
|
border-right: none;
|
||||||
}
|
}
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 10px $gl-padding;
|
|
||||||
}
|
}
|
||||||
.lines {
|
.lines {
|
||||||
pre {
|
pre {
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ ul.content-list {
|
||||||
|
|
||||||
> li {
|
> li {
|
||||||
padding: $gl-padding;
|
padding: $gl-padding;
|
||||||
border-color: #f1f2f4;
|
border-color: $table-border-color;
|
||||||
margin-left: -$gl-padding;
|
margin-left: -$gl-padding;
|
||||||
margin-right: -$gl-padding;
|
margin-right: -$gl-padding;
|
||||||
color: $gl-gray;
|
color: $gl-gray;
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.select2-results .select2-result-label {
|
.select2-results .select2-result-label {
|
||||||
padding: 16px;
|
padding: 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.select2-drop{
|
.select2-drop{
|
||||||
|
|
@ -143,4 +143,4 @@
|
||||||
|
|
||||||
.ajax-users-dropdown {
|
.ajax-users-dropdown {
|
||||||
min-width: 250px !important;
|
min-width: 250px !important;
|
||||||
}
|
}
|
||||||
|
|
@ -242,6 +242,9 @@
|
||||||
img {
|
img {
|
||||||
width: 36px;
|
width: 36px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tanuki-logo, img {
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -265,3 +268,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.tanuki-shape {
|
||||||
|
transition: all 0.8s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
fill: rgb(255, 255, 255);
|
||||||
|
transition: all 0.1s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
|
.table-holder {
|
||||||
|
margin: -$gl-padding;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
&.table {
|
&.table {
|
||||||
.dropdown-menu a {
|
.dropdown-menu a {
|
||||||
|
|
@ -18,15 +24,17 @@ table {
|
||||||
|
|
||||||
tr {
|
tr {
|
||||||
td, th {
|
td, th {
|
||||||
padding: 8px 10px;
|
padding: 10px $gl-padding;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
th {
|
th {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
border-bottom: 1px solid $border-color !important;
|
border-bottom: 1px solid $border-color !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
td {
|
td {
|
||||||
border-color: $table-border-color !important;
|
border-color: $table-border-color !important;
|
||||||
border-bottom: 1px solid;
|
border-bottom: 1px solid;
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,17 @@
|
||||||
|
|
||||||
.timeline-entry {
|
.timeline-entry {
|
||||||
padding: $gl-padding;
|
padding: $gl-padding;
|
||||||
border-color: #f1f2f4;
|
border-color: $table-border-color;
|
||||||
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 #ECEEF1;
|
||||||
border-right: 1px solid #ECEEF1;
|
border-right: 1px solid #ECEEF1;
|
||||||
|
|
||||||
|
&:target {
|
||||||
|
background: $hover;
|
||||||
|
}
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
@mixin md-typography {
|
@mixin md-typography {
|
||||||
color: $md-text-color;
|
color: $md-text-color;
|
||||||
|
word-wrap: break-word;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: $md-link-color;
|
color: $md-link-color;
|
||||||
|
|
@ -17,7 +18,6 @@
|
||||||
font-family: $monospace_font;
|
font-family: $monospace_font;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
word-wrap: normal;
|
word-wrap: normal;
|
||||||
padding: 1px 2px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kbd {
|
kbd {
|
||||||
|
|
@ -73,6 +73,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
color: #7f8fa4;
|
||||||
|
font-size: inherit;
|
||||||
padding: 8px 21px;
|
padding: 8px 21px;
|
||||||
margin: 12px 0 12px;
|
margin: 12px 0 12px;
|
||||||
border-left: 3px solid #e7e9ed;
|
border-left: 3px solid #e7e9ed;
|
||||||
|
|
@ -80,7 +82,7 @@
|
||||||
|
|
||||||
blockquote p {
|
blockquote p {
|
||||||
color: #7f8fa4 !important;
|
color: #7f8fa4 !important;
|
||||||
font-size: 15px;
|
font-size: inherit;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,9 +103,9 @@
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
margin: 12px 0 12px 0 !important;
|
margin: 12px 0 12px 0 !important;
|
||||||
background-color: #f8fafc !important;
|
background-color: #f8fafc;
|
||||||
font-size: 13px !important;
|
font-size: 13px !important;
|
||||||
color: #5b6169 !important;
|
color: #5b6169;
|
||||||
line-height: 1.6em !important;
|
line-height: 1.6em !important;
|
||||||
@include border-radius(2px);
|
@include border-radius(2px);
|
||||||
}
|
}
|
||||||
|
|
@ -112,9 +114,9 @@
|
||||||
font-weight: inherit;
|
font-weight: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ul, ol {
|
||||||
ul {
|
padding: 0;
|
||||||
color: #5c5d5e;
|
margin: 6px 0 6px 18px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
|
|
@ -136,6 +138,33 @@
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Link to current header. */
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
a.anchor {
|
||||||
|
// Setting `display: none` would prevent the anchor being scrolled to, so
|
||||||
|
// instead we set the height to 0 and it gets updated on hover.
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover > a.anchor {
|
||||||
|
$size: 16px;
|
||||||
|
position: absolute;
|
||||||
|
right: 100%;
|
||||||
|
top: 50%;
|
||||||
|
margin-top: -$size/2;
|
||||||
|
margin-right: 0px;
|
||||||
|
padding-right: 20px;
|
||||||
|
display: inline-block;
|
||||||
|
width: $size;
|
||||||
|
height: $size;
|
||||||
|
background-image: image-url("icon-link.png");
|
||||||
|
background-size: contain;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -202,53 +231,11 @@ a > code {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wiki typography
|
* Apply Markdown typography
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
.wiki {
|
.wiki {
|
||||||
@include md-typography;
|
@include md-typography;
|
||||||
|
|
||||||
word-wrap: break-word;
|
|
||||||
padding: 7px;
|
|
||||||
|
|
||||||
/* Link to current header. */
|
|
||||||
h1, h2, h3, h4, h5, h6 {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
a.anchor {
|
|
||||||
// Setting `display: none` would prevent the anchor being scrolled to, so
|
|
||||||
// instead we set the height to 0 and it gets updated on hover.
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover > a.anchor {
|
|
||||||
$size: 16px;
|
|
||||||
position: absolute;
|
|
||||||
right: 100%;
|
|
||||||
top: 50%;
|
|
||||||
margin-top: -$size/2;
|
|
||||||
margin-right: 0px;
|
|
||||||
padding-right: 20px;
|
|
||||||
display: inline-block;
|
|
||||||
width: $size;
|
|
||||||
height: $size;
|
|
||||||
background-image: image-url("icon-link.png");
|
|
||||||
background-size: contain;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ul,ol {
|
|
||||||
padding: 0;
|
|
||||||
margin: 6px 0 6px 18px !important;
|
|
||||||
}
|
|
||||||
ol {
|
|
||||||
color: #5c5d5e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.md-area {
|
|
||||||
@include md-typography;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.md {
|
.md {
|
||||||
|
|
@ -261,6 +248,7 @@ a > code {
|
||||||
*/
|
*/
|
||||||
textarea.js-gfm-input {
|
textarea.js-gfm-input {
|
||||||
font-family: $monospace_font;
|
font-family: $monospace_font;
|
||||||
|
color: $gl-text-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.md-preview {
|
.md-preview {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
/* https://github.com/MozMorris/tomorrow-pygments */
|
/* https://github.com/MozMorris/tomorrow-pygments */
|
||||||
pre.code.highlight.dark,
|
|
||||||
.code.dark {
|
.code.dark {
|
||||||
|
|
||||||
background-color: #1d1f21;
|
background-color: #1d1f21 !important;
|
||||||
color: #c5c8c6;
|
color: #c5c8c6 !important;
|
||||||
|
|
||||||
pre.code,
|
pre.highlight,
|
||||||
.line-numbers,
|
.line-numbers,
|
||||||
.line-numbers a {
|
.line-numbers a {
|
||||||
background-color: #1d1f21 !important;
|
background-color: #1d1f21 !important;
|
||||||
|
|
@ -23,8 +22,8 @@ pre.code.highlight.dark,
|
||||||
|
|
||||||
// Search result highlight
|
// Search result highlight
|
||||||
span.highlight_word {
|
span.highlight_word {
|
||||||
background: #ffe792;
|
background-color: #ffe792 !important;
|
||||||
color: #000000;
|
color: #000000 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hll { background-color: #373b41 }
|
.hll { background-color: #373b41 }
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
/* https://github.com/richleland/pygments-css/blob/master/monokai.css */
|
/* https://github.com/richleland/pygments-css/blob/master/monokai.css */
|
||||||
pre.code.monokai,
|
|
||||||
.code.monokai {
|
.code.monokai {
|
||||||
|
|
||||||
background: #272822;
|
background-color: #272822 !important;
|
||||||
color: #f8f8f2;
|
color: #f8f8f2 !important;
|
||||||
|
|
||||||
pre.highlight,
|
pre.highlight,
|
||||||
.line-numbers,
|
.line-numbers,
|
||||||
.line-numbers a {
|
.line-numbers a {
|
||||||
background:#272822 !important;
|
background-color :#272822 !important;
|
||||||
color:#f8f8f2 !important;
|
color: #f8f8f2 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre.code {
|
pre.code {
|
||||||
|
|
@ -23,8 +22,8 @@ pre.code.monokai,
|
||||||
|
|
||||||
// Search result highlight
|
// Search result highlight
|
||||||
span.highlight_word {
|
span.highlight_word {
|
||||||
background: #ffe792;
|
background-color: #ffe792 !important;
|
||||||
color: #000000;
|
color: #000000 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hll { background-color: #49483e }
|
.hll { background-color: #49483e }
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
/* https://gist.github.com/qguv/7936275 */
|
/* https://gist.github.com/qguv/7936275 */
|
||||||
pre.code.highlight.solarized-dark,
|
|
||||||
.code.solarized-dark {
|
.code.solarized-dark {
|
||||||
|
|
||||||
background-color: #002b36;
|
background-color: #002b36 !important;
|
||||||
color: #93a1a1;
|
color: #93a1a1 !important;
|
||||||
|
|
||||||
pre.code,
|
pre.highlight,
|
||||||
.line-numbers,
|
.line-numbers,
|
||||||
.line-numbers a {
|
.line-numbers a {
|
||||||
background-color: #002b36 !important;
|
background-color: #002b36 !important;
|
||||||
|
|
@ -23,7 +22,7 @@ pre.code.highlight.solarized-dark,
|
||||||
|
|
||||||
// Search result highlight
|
// Search result highlight
|
||||||
span.highlight_word {
|
span.highlight_word {
|
||||||
background: #094554;
|
background-color: #094554 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Solarized Dark
|
/* Solarized Dark
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
/* https://gist.github.com/qguv/7936275 */
|
/* https://gist.github.com/qguv/7936275 */
|
||||||
pre.code.highlight.solarized-light,
|
|
||||||
.code.solarized-light {
|
.code.solarized-light {
|
||||||
|
|
||||||
background-color: #fdf6e3;
|
background-color: #fdf6e3 !important;
|
||||||
color: #586e75;
|
color: #586e75 !important;
|
||||||
|
|
||||||
pre.code,
|
pre.highlight,
|
||||||
.line-numbers,
|
.line-numbers,
|
||||||
.line-numbers a {
|
.line-numbers a {
|
||||||
background-color: #fdf6e3 !important;
|
background-color: #fdf6e3 !important;
|
||||||
|
|
@ -23,7 +22,7 @@ pre.code.highlight.solarized-light,
|
||||||
|
|
||||||
// Search result highlight
|
// Search result highlight
|
||||||
span.highlight_word {
|
span.highlight_word {
|
||||||
background: #eee8d5;
|
background-color: #eee8d5 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Solarized Light
|
/* Solarized Light
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,20 @@
|
||||||
/* https://github.com/aahan/pygments-github-style */
|
/* https://github.com/aahan/pygments-github-style */
|
||||||
pre.code.highlight.white,
|
|
||||||
.code.white {
|
.code.white {
|
||||||
background-color: #f8fafc;
|
|
||||||
font-size: 13px;
|
|
||||||
color: #5b6169;
|
|
||||||
line-height: 1.6em;
|
|
||||||
|
|
||||||
|
background-color: #f8fafc !important;
|
||||||
|
color: #5b6169 !important;
|
||||||
|
|
||||||
|
pre.highlight,
|
||||||
.line-numbers,
|
.line-numbers,
|
||||||
.line-numbers a {
|
.line-numbers a {
|
||||||
background-color: $background-color !important;
|
background-color: $background-color !important;
|
||||||
color: $gl-gray !important;
|
color: $gl-gray !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre.highlight {
|
|
||||||
background-color: #fff !important;
|
|
||||||
color: #333 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre.code {
|
pre.code {
|
||||||
border-left: 1px solid $border-color;
|
border-left: 1px solid $border-color;
|
||||||
|
background-color: #fff !important;
|
||||||
|
color: #333 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
// highlight line via anchor
|
// highlight line via anchor
|
||||||
|
|
@ -28,7 +24,7 @@ pre.code.highlight.white,
|
||||||
|
|
||||||
// Search result highlight
|
// Search result highlight
|
||||||
span.highlight_word {
|
span.highlight_word {
|
||||||
background: #fafe3d;
|
background-color: #fafe3d !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hll { background-color: #f8f8f8 }
|
.hll { background-color: #f8f8f8 }
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,6 @@
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wide-table-holder {
|
|
||||||
margin-left: -$gl-padding;
|
|
||||||
margin-right: -$gl-padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
.builds,
|
.builds,
|
||||||
.projects-table {
|
.projects-table {
|
||||||
.light {
|
.light {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
padding: $gl-padding;
|
padding: $gl-padding;
|
||||||
margin-left: -$gl-padding;
|
margin-left: -$gl-padding;
|
||||||
margin-right: -$gl-padding;
|
margin-right: -$gl-padding;
|
||||||
border-bottom: 1px solid #f1f2f4;
|
border-bottom: 1px solid $table-border-color;
|
||||||
color: #7f8fa4;
|
color: #7f8fa4;
|
||||||
|
|
||||||
&.event-inline {
|
&.event-inline {
|
||||||
|
|
|
||||||
|
|
@ -68,3 +68,7 @@ body.modal-open {
|
||||||
.modal .modal-dialog {
|
.modal .modal-dialog {
|
||||||
width: 860px;
|
width: 860px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.documentation {
|
||||||
|
padding: 7px;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,11 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ ul.notes {
|
||||||
.discussion-header,
|
.discussion-header,
|
||||||
.note-header {
|
.note-header {
|
||||||
@extend .cgray;
|
@extend .cgray;
|
||||||
padding-bottom: 15px;
|
|
||||||
|
|
||||||
a:hover {
|
a:hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
@ -75,6 +74,10 @@ ul.notes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.discussion-body {
|
||||||
|
padding-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
.discussion {
|
.discussion {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: block;
|
display: block;
|
||||||
|
|
|
||||||
|
|
@ -47,3 +47,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.calendar-hint {
|
||||||
|
margin-top: -12px;
|
||||||
|
float: right;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -457,7 +457,7 @@ pre.light-well {
|
||||||
|
|
||||||
.project-row {
|
.project-row {
|
||||||
padding: $gl-padding;
|
padding: $gl-padding;
|
||||||
border-color: #f1f2f4;
|
border-color: $table-border-color;
|
||||||
margin-left: -$gl-padding;
|
margin-left: -$gl-padding;
|
||||||
margin-right: -$gl-padding;
|
margin-right: -$gl-padding;
|
||||||
|
|
||||||
|
|
@ -511,3 +511,38 @@ pre.light-well {
|
||||||
margin-top: -1px;
|
margin-top: -1px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.project-last-commit {
|
||||||
|
margin: 0 7px;
|
||||||
|
|
||||||
|
.ci-status {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.commit-row-message {
|
||||||
|
color: $gl-gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.commit_short_id {
|
||||||
|
margin-right: 5px;
|
||||||
|
color: $gl-link-color;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.commit-author-link {
|
||||||
|
margin-left: 7px;
|
||||||
|
text-decoration: none;
|
||||||
|
.avatar {
|
||||||
|
float: none;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.commit-author-name {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-show-readme .readme-holder {
|
||||||
|
border-top: 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,11 @@
|
||||||
.tree-holder {
|
.tree-holder {
|
||||||
.tree-table-holder {
|
|
||||||
margin-left: -$gl-padding;
|
|
||||||
margin-right: -$gl-padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tree_progress {
|
|
||||||
display: none;
|
|
||||||
margin: 20px;
|
|
||||||
&.loading {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tree-table {
|
.tree-table {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
|
||||||
tr {
|
tr {
|
||||||
> td, > th {
|
> td, > th {
|
||||||
padding: 10px $gl-padding;
|
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
border-color: $table-border-color !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,10 @@ class AbuseReportsController < ApplicationController
|
||||||
@abuse_report.reporter = current_user
|
@abuse_report.reporter = current_user
|
||||||
|
|
||||||
if @abuse_report.save
|
if @abuse_report.save
|
||||||
|
if current_application_settings.admin_notification_email.present?
|
||||||
|
AbuseReportMailer.delay.notify(@abuse_report.id)
|
||||||
|
end
|
||||||
|
|
||||||
message = "Thank you for your report. A GitLab administrator will look into it shortly."
|
message = "Thank you for your report. A GitLab administrator will look into it shortly."
|
||||||
redirect_to root_path, notice: message
|
redirect_to root_path, notice: message
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
|
||||||
:default_snippet_visibility,
|
:default_snippet_visibility,
|
||||||
:restricted_signup_domains_raw,
|
:restricted_signup_domains_raw,
|
||||||
:version_check_enabled,
|
:version_check_enabled,
|
||||||
|
:admin_notification_email,
|
||||||
:user_oauth_applications,
|
:user_oauth_applications,
|
||||||
restricted_visibility_levels: [],
|
restricted_visibility_levels: [],
|
||||||
import_sources: []
|
import_sources: []
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController
|
||||||
BroadcastMessage.find(params[:id]).destroy
|
BroadcastMessage.find(params[:id]).destroy
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_to :back }
|
format.html { redirect_back_or_default(default: { action: 'index' }) }
|
||||||
format.js { render nothing: true }
|
format.js { render nothing: true }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ class Admin::HooksController < Admin::ApplicationController
|
||||||
}
|
}
|
||||||
@hook.execute(data, 'system_hooks')
|
@hook.execute(data, 'system_hooks')
|
||||||
|
|
||||||
redirect_to :back
|
redirect_back_or_default
|
||||||
end
|
end
|
||||||
|
|
||||||
def hook_params
|
def hook_params
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,13 @@ class Admin::ServicesController < Admin::ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def application_services_params
|
def application_services_params
|
||||||
params.permit(:id,
|
application_services_params = params.permit(:id,
|
||||||
service: Projects::ServicesController::ALLOWED_PARAMS)
|
service: Projects::ServicesController::ALLOWED_PARAMS)
|
||||||
|
if application_services_params[:service].is_a?(Hash)
|
||||||
|
Projects::ServicesController::FILTER_BLANK_PARAMS.each do |param|
|
||||||
|
application_services_params[:service].delete(param) if application_services_params[:service][param].blank?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
application_services_params
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -33,33 +33,33 @@ class Admin::UsersController < Admin::ApplicationController
|
||||||
|
|
||||||
def block
|
def block
|
||||||
if user.block
|
if user.block
|
||||||
redirect_to :back, notice: "Successfully blocked"
|
redirect_back_or_admin_user(notice: "Successfully blocked")
|
||||||
else
|
else
|
||||||
redirect_to :back, alert: "Error occurred. User was not blocked"
|
redirect_back_or_admin_user(alert: "Error occurred. User was not blocked")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def unblock
|
def unblock
|
||||||
if user.activate
|
if user.activate
|
||||||
redirect_to :back, notice: "Successfully unblocked"
|
redirect_back_or_admin_user(notice: "Successfully unblocked")
|
||||||
else
|
else
|
||||||
redirect_to :back, alert: "Error occurred. User was not unblocked"
|
redirect_back_or_admin_user(alert: "Error occurred. User was not unblocked")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def unlock
|
def unlock
|
||||||
if user.unlock_access!
|
if user.unlock_access!
|
||||||
redirect_to :back, alert: "Successfully unlocked"
|
redirect_back_or_admin_user(alert: "Successfully unlocked")
|
||||||
else
|
else
|
||||||
redirect_to :back, alert: "Error occurred. User was not unlocked"
|
redirect_back_or_admin_user(alert: "Error occurred. User was not unlocked")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def confirm
|
def confirm
|
||||||
if user.confirm
|
if user.confirm
|
||||||
redirect_to :back, notice: "Successfully confirmed"
|
redirect_back_or_admin_user(notice: "Successfully confirmed")
|
||||||
else
|
else
|
||||||
redirect_to :back, alert: "Error occurred. User was not confirmed"
|
redirect_back_or_admin_user(alert: "Error occurred. User was not confirmed")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -138,7 +138,7 @@ class Admin::UsersController < Admin::ApplicationController
|
||||||
user.update_secondary_emails!
|
user.update_secondary_emails!
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_to :back, notice: "Successfully removed email." }
|
format.html { redirect_back_or_admin_user(notice: "Successfully removed email.") }
|
||||||
format.js { render nothing: true }
|
format.js { render nothing: true }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -157,4 +157,12 @@ class Admin::UsersController < Admin::ApplicationController
|
||||||
:projects_limit, :can_create_group, :admin, :key_id
|
:projects_limit, :can_create_group, :admin, :key_id
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def redirect_back_or_admin_user(options = {})
|
||||||
|
redirect_back_or_default(default: default_route, options: options)
|
||||||
|
end
|
||||||
|
|
||||||
|
def default_route
|
||||||
|
[:admin, @user]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,10 @@ class ApplicationController < ActionController::Base
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def redirect_back_or_default(default: root_path, options: {})
|
||||||
|
redirect_to request.referer.present? ? :back : default, options
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
# From https://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example
|
# From https://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example
|
||||||
|
|
@ -150,7 +154,7 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def git_not_found!
|
def git_not_found!
|
||||||
render "errors/git_not_found", layout: "errors", status: 404
|
render html: "errors/git_not_found", layout: "errors", status: 404
|
||||||
end
|
end
|
||||||
|
|
||||||
def method_missing(method_sym, *arguments, &block)
|
def method_missing(method_sym, *arguments, &block)
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,17 @@
|
||||||
module Ci
|
module Ci
|
||||||
class ProjectsController < Ci::ApplicationController
|
class ProjectsController < Ci::ApplicationController
|
||||||
before_action :project
|
before_action :project, except: [:index]
|
||||||
before_action :authenticate_user!, except: [:build, :badge]
|
before_action :authenticate_user!, except: [:index, :build, :badge]
|
||||||
before_action :authorize_access_project!, except: [:badge]
|
before_action :authorize_access_project!, except: [:index, :badge]
|
||||||
before_action :authorize_manage_project!, only: [:toggle_shared_runners, :dumped_yaml]
|
before_action :authorize_manage_project!, only: [:toggle_shared_runners, :dumped_yaml]
|
||||||
before_action :no_cache, only: [:badge]
|
before_action :no_cache, only: [:badge]
|
||||||
protect_from_forgery
|
protect_from_forgery
|
||||||
|
|
||||||
|
def show
|
||||||
|
# Temporary compatibility with CI badges pointing to CI project page
|
||||||
|
redirect_to namespace_project_path(project.gl_project.namespace, project.gl_project)
|
||||||
|
end
|
||||||
|
|
||||||
# Project status badge
|
# Project status badge
|
||||||
# Image with build status for sha or ref
|
# Image with build status for sha or ref
|
||||||
def badge
|
def badge
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,6 @@ class Import::GithubController < Import::BaseController
|
||||||
|
|
||||||
def status
|
def status
|
||||||
@repos = client.repos
|
@repos = client.repos
|
||||||
client.orgs.each do |org|
|
|
||||||
@repos += client.org_repos(org.login)
|
|
||||||
end
|
|
||||||
|
|
||||||
@already_added_projects = current_user.created_projects.where(import_type: "github")
|
@already_added_projects = current_user.created_projects.where(import_type: "github")
|
||||||
already_added_projects_names = @already_added_projects.pluck(:import_source)
|
already_added_projects_names = @already_added_projects.pluck(:import_source)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,18 +10,18 @@ class Import::GoogleCodeController < Import::BaseController
|
||||||
dump_file = params[:dump_file]
|
dump_file = params[:dump_file]
|
||||||
|
|
||||||
unless dump_file.respond_to?(:read)
|
unless dump_file.respond_to?(:read)
|
||||||
return redirect_to :back, alert: "You need to upload a Google Takeout archive."
|
return redirect_back_or_default(options: { alert: "You need to upload a Google Takeout archive." })
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
dump = JSON.parse(dump_file.read)
|
dump = JSON.parse(dump_file.read)
|
||||||
rescue
|
rescue
|
||||||
return redirect_to :back, alert: "The uploaded file is not a valid Google Takeout archive."
|
return redirect_back_or_default(options: { alert: "The uploaded file is not a valid Google Takeout archive." })
|
||||||
end
|
end
|
||||||
|
|
||||||
client = Gitlab::GoogleCodeImport::Client.new(dump)
|
client = Gitlab::GoogleCodeImport::Client.new(dump)
|
||||||
unless client.valid?
|
unless client.valid?
|
||||||
return redirect_to :back, alert: "The uploaded file is not a valid Google Takeout archive."
|
return redirect_back_or_default(options: { alert: "The uploaded file is not a valid Google Takeout archive." })
|
||||||
end
|
end
|
||||||
|
|
||||||
session[:google_code_dump] = dump
|
session[:google_code_dump] = dump
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ class InvitesController < ApplicationController
|
||||||
|
|
||||||
redirect_to path, notice: "You have been granted #{member.human_access} access to #{label}."
|
redirect_to path, notice: "You have been granted #{member.human_access} access to #{label}."
|
||||||
else
|
else
|
||||||
redirect_to :back, alert: "The invitation could not be accepted."
|
redirect_back_or_default(options: { alert: "The invitation could not be accepted." })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -31,7 +31,7 @@ class InvitesController < ApplicationController
|
||||||
|
|
||||||
redirect_to path, notice: "You have declined the invitation to join #{label}."
|
redirect_to path, notice: "You have declined the invitation to join #{label}."
|
||||||
else
|
else
|
||||||
redirect_to :back, alert: "The invitation could not be declined."
|
redirect_back_or_default(options: { alert: "The invitation could not be declined." })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ class Profiles::NotificationsController < Profiles::ApplicationController
|
||||||
flash[:alert] = "Failed to save new settings"
|
flash[:alert] = "Failed to save new settings"
|
||||||
end
|
end
|
||||||
|
|
||||||
redirect_to :back
|
redirect_back_or_default(default: profile_notifications_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
format.js
|
format.js
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ class ProfilesController < Profiles::ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_to :back }
|
format.html { redirect_back_or_default(default: { action: 'show' }) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,32 @@
|
||||||
class Projects::BuildsController < Projects::ApplicationController
|
class Projects::BuildsController < Projects::ApplicationController
|
||||||
before_action :ci_project
|
before_action :ci_project
|
||||||
before_action :build
|
before_action :build, except: [:index, :cancel_all]
|
||||||
|
|
||||||
before_action :authorize_admin_project!, except: [:show, :status]
|
before_action :authorize_admin_project!, except: [:index, :show, :status]
|
||||||
|
|
||||||
layout "project"
|
layout "project"
|
||||||
|
|
||||||
|
def index
|
||||||
|
@scope = params[:scope]
|
||||||
|
@all_builds = project.ci_builds
|
||||||
|
@builds =
|
||||||
|
case @scope
|
||||||
|
when 'all'
|
||||||
|
@all_builds
|
||||||
|
when 'finished'
|
||||||
|
@all_builds.finished
|
||||||
|
else
|
||||||
|
@all_builds.running_or_pending
|
||||||
|
end
|
||||||
|
@builds = @builds.order('created_at DESC').page(params[:page]).per(30)
|
||||||
|
end
|
||||||
|
|
||||||
|
def cancel_all
|
||||||
|
@project.ci_builds.running_or_pending.each(&:cancel)
|
||||||
|
|
||||||
|
redirect_to namespace_project_builds_path(project.namespace, project)
|
||||||
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@builds = @ci_project.commits.find_by_sha(@build.sha).builds.order('id DESC')
|
@builds = @ci_project.commits.find_by_sha(@build.sha).builds.order('id DESC')
|
||||||
@builds = @builds.where("id not in (?)", @build.id).page(params[:page]).per(20)
|
@builds = @builds.where("id not in (?)", @build.id).page(params[:page]).per(20)
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ class Projects::CiServicesController < Projects::ApplicationController
|
||||||
message = { alert: 'We tried to test the service but error occurred' }
|
message = { alert: 'We tried to test the service but error occurred' }
|
||||||
end
|
end
|
||||||
|
|
||||||
redirect_to :back, message
|
redirect_back_or_default(options: message)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ class Projects::CiWebHooksController < Projects::ApplicationController
|
||||||
def test
|
def test
|
||||||
Ci::TestHookService.new.execute(hook, current_user)
|
Ci::TestHookService.new.execute(hook, current_user)
|
||||||
|
|
||||||
redirect_to :back
|
redirect_back_or_default(default: { action: 'index' })
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,10 @@ class Projects::CompareController < Projects::ApplicationController
|
||||||
execute(@project, head_ref, @project, base_ref)
|
execute(@project, head_ref, @project, base_ref)
|
||||||
|
|
||||||
if compare_result
|
if compare_result
|
||||||
@commits = compare_result.commits
|
@commits = Commit.decorate(compare_result.commits, @project)
|
||||||
@diffs = compare_result.diffs
|
@diffs = compare_result.diffs
|
||||||
@commit = @commits.last
|
@commit = @commits.last
|
||||||
|
@first_commit = @commits.first
|
||||||
@line_notes = []
|
@line_notes = []
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ class Projects::DeployKeysController < Projects::ApplicationController
|
||||||
def disable
|
def disable
|
||||||
@project.deploy_keys_projects.find_by(deploy_key_id: params[:id]).destroy
|
@project.deploy_keys_projects.find_by(deploy_key_id: params[:id]).destroy
|
||||||
|
|
||||||
redirect_to :back
|
redirect_back_or_default(default: { action: 'index' })
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ class Projects::HooksController < Projects::ApplicationController
|
||||||
flash[:alert] = 'Hook execution failed. Ensure the project has commits.'
|
flash[:alert] = 'Hook execution failed. Ensure the project has commits.'
|
||||||
end
|
end
|
||||||
|
|
||||||
redirect_to :back
|
redirect_back_or_default(default: { action: 'index' })
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,9 @@ class Projects::IssuesController < Projects::ApplicationController
|
||||||
# Allow issues bulk update
|
# Allow issues bulk update
|
||||||
before_action :authorize_admin_issues!, only: [:bulk_update]
|
before_action :authorize_admin_issues!, only: [:bulk_update]
|
||||||
|
|
||||||
|
# Cross-reference merge requests
|
||||||
|
before_action :closed_by_merge_requests, only: [:show]
|
||||||
|
|
||||||
respond_to :html
|
respond_to :html
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
|
@ -57,7 +60,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
||||||
def show
|
def show
|
||||||
@participants = @issue.participants(current_user)
|
@participants = @issue.participants(current_user)
|
||||||
@note = @project.notes.new(noteable: @issue)
|
@note = @project.notes.new(noteable: @issue)
|
||||||
@notes = @issue.notes.inc_author.fresh
|
@notes = @issue.notes.with_associations.fresh
|
||||||
@noteable = @issue
|
@noteable = @issue
|
||||||
|
|
||||||
respond_with(@issue)
|
respond_with(@issue)
|
||||||
|
|
@ -103,7 +106,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
||||||
|
|
||||||
def bulk_update
|
def bulk_update
|
||||||
result = Issues::BulkUpdateService.new(project, current_user, bulk_update_params).execute
|
result = Issues::BulkUpdateService.new(project, current_user, bulk_update_params).execute
|
||||||
redirect_to :back, notice: "#{result[:count]} issues updated"
|
redirect_back_or_default(default: { action: 'index' }, options: { notice: "#{result[:count]} issues updated" })
|
||||||
end
|
end
|
||||||
|
|
||||||
def toggle_subscription
|
def toggle_subscription
|
||||||
|
|
@ -112,6 +115,10 @@ class Projects::IssuesController < Projects::ApplicationController
|
||||||
render nothing: true
|
render nothing: true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def closed_by_merge_requests
|
||||||
|
@closed_by_merge_requests ||= @issue.closed_by_merge_requests(current_user)
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def issue
|
def issue
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
||||||
|
|
||||||
def diffs
|
def diffs
|
||||||
@commit = @merge_request.last_commit
|
@commit = @merge_request.last_commit
|
||||||
|
@first_commit = @merge_request.first_commit
|
||||||
|
|
||||||
@comments_allowed = @reply_allowed = true
|
@comments_allowed = @reply_allowed = true
|
||||||
@comments_target = {
|
@comments_target = {
|
||||||
noteable_type: 'MergeRequest',
|
noteable_type: 'MergeRequest',
|
||||||
|
|
@ -89,7 +91,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
||||||
@target_project = merge_request.target_project
|
@target_project = merge_request.target_project
|
||||||
@source_project = merge_request.source_project
|
@source_project = merge_request.source_project
|
||||||
@commits = @merge_request.compare_commits
|
@commits = @merge_request.compare_commits
|
||||||
@commit = @merge_request.compare_commits.last
|
@commit = @merge_request.last_commit
|
||||||
|
@first_commit = @merge_request.first_commit
|
||||||
@diffs = @merge_request.compare_diffs
|
@diffs = @merge_request.compare_diffs
|
||||||
@note_counts = Note.where(commit_id: @commits.map(&:id)).
|
@note_counts = Note.where(commit_id: @commits.map(&:id)).
|
||||||
group(:commit_id).count
|
group(:commit_id).count
|
||||||
|
|
@ -259,7 +262,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
||||||
@commits = @merge_request.commits
|
@commits = @merge_request.commits
|
||||||
|
|
||||||
@merge_request_diff = @merge_request.merge_request_diff
|
@merge_request_diff = @merge_request.merge_request_diff
|
||||||
|
|
||||||
if @merge_request.locked_long_ago?
|
if @merge_request.locked_long_ago?
|
||||||
@merge_request.unlock_mr
|
@merge_request.unlock_mr
|
||||||
@merge_request.close
|
@merge_request.close
|
||||||
|
|
|
||||||
|
|
@ -75,11 +75,7 @@ class Projects::MilestonesController < Projects::ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def sort_issues
|
def sort_issues
|
||||||
@issues = @milestone.issues.where(id: params['sortable_issue'])
|
@milestone.sort_issues(params['sortable_issue'].map(&:to_i))
|
||||||
@issues.each do |issue|
|
|
||||||
issue.position = params['sortable_issue'].index(issue.id.to_s) + 1
|
|
||||||
issue.save
|
|
||||||
end
|
|
||||||
|
|
||||||
render json: { saved: true }
|
render json: { saved: true }
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ class Projects::NotesController < Projects::ApplicationController
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.json { render_note_json(@note) }
|
format.json { render_note_json(@note) }
|
||||||
format.html { redirect_to :back }
|
format.html { redirect_back_or_default }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -34,7 +34,7 @@ class Projects::NotesController < Projects::ApplicationController
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.json { render_note_json(@note) }
|
format.json { render_note_json(@note) }
|
||||||
format.html { redirect_to :back }
|
format.html { redirect_back_or_default }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,8 @@ class Projects::ProjectMembersController < Projects::ApplicationController
|
||||||
|
|
||||||
def leave
|
def leave
|
||||||
if @project.namespace == current_user.namespace
|
if @project.namespace == current_user.namespace
|
||||||
return redirect_to(:back, alert: 'You can not leave your own project. Transfer or delete the project.')
|
message = 'You can not leave your own project. Transfer or delete the project.'
|
||||||
|
return redirect_back_or_default(default: { action: 'index' }, options: { alert: message })
|
||||||
end
|
end
|
||||||
|
|
||||||
@project.project_members.find_by(user_id: current_user).destroy
|
@project.project_members.find_by(user_id: current_user).destroy
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ class Projects::RefsController < Projects::ApplicationController
|
||||||
include TreeHelper
|
include TreeHelper
|
||||||
|
|
||||||
before_action :require_non_empty_project
|
before_action :require_non_empty_project
|
||||||
|
before_action :validate_ref_id
|
||||||
before_action :assign_ref_vars
|
before_action :assign_ref_vars
|
||||||
before_action :authorize_download_code!
|
before_action :authorize_download_code!
|
||||||
|
|
||||||
|
|
@ -71,4 +72,10 @@ class Projects::RefsController < Projects::ApplicationController
|
||||||
format.js
|
format.js
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def validate_ref_id
|
||||||
|
return not_found! if params[:id].present? && params[:id] !~ Gitlab::Regex.git_reference_regex
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -11,18 +11,9 @@ class Projects::RepositoriesController < Projects::ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def archive
|
def archive
|
||||||
begin
|
render json: ArchiveRepositoryService.new(@project, params[:ref], params[:format]).execute
|
||||||
file_path = ArchiveRepositoryService.new(@project, params[:ref], params[:format]).execute
|
rescue => ex
|
||||||
rescue
|
logger.error("#{self.class.name}: #{ex}")
|
||||||
return head :not_found
|
return git_not_found!
|
||||||
end
|
|
||||||
|
|
||||||
if file_path
|
|
||||||
# Send file to user
|
|
||||||
response.headers["Content-Length"] = File.open(file_path).size.to_s
|
|
||||||
send_file file_path
|
|
||||||
else
|
|
||||||
redirect_to request.fullpath
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,10 @@ class Projects::ServicesController < Projects::ApplicationController
|
||||||
:note_events, :send_from_committer_email, :disable_diffs, :external_wiki_url,
|
:note_events, :send_from_committer_email, :disable_diffs, :external_wiki_url,
|
||||||
:notify, :color,
|
:notify, :color,
|
||||||
:server_host, :server_port, :default_irc_uri, :enable_ssl_verification]
|
:server_host, :server_port, :default_irc_uri, :enable_ssl_verification]
|
||||||
|
|
||||||
|
# Parameters to ignore if no value is specified
|
||||||
|
FILTER_BLANK_PARAMS = [:password]
|
||||||
|
|
||||||
# Authorize
|
# Authorize
|
||||||
before_action :authorize_admin_project!
|
before_action :authorize_admin_project!
|
||||||
before_action :service, only: [:edit, :update, :test]
|
before_action :service, only: [:edit, :update, :test]
|
||||||
|
|
@ -48,7 +52,7 @@ class Projects::ServicesController < Projects::ApplicationController
|
||||||
message = { alert: error_message }
|
message = { alert: error_message }
|
||||||
end
|
end
|
||||||
|
|
||||||
redirect_to :back, message
|
redirect_back_or_default(options: message)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
@ -59,7 +63,9 @@ class Projects::ServicesController < Projects::ApplicationController
|
||||||
|
|
||||||
def service_params
|
def service_params
|
||||||
service_params = params.require(:service).permit(ALLOWED_PARAMS)
|
service_params = params.require(:service).permit(ALLOWED_PARAMS)
|
||||||
service_params.delete("password") if service_params["password"].blank?
|
FILTER_BLANK_PARAMS.each do |param|
|
||||||
|
service_params.delete(param) if service_params[param].blank?
|
||||||
|
end
|
||||||
service_params
|
service_params
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
class ProjectsController < ApplicationController
|
class ProjectsController < ApplicationController
|
||||||
|
include ExtractsPath
|
||||||
|
|
||||||
prepend_before_filter :render_go_import, only: [:show]
|
prepend_before_filter :render_go_import, only: [:show]
|
||||||
skip_before_action :authenticate_user!, only: [:show, :activity]
|
skip_before_action :authenticate_user!, only: [:show, :activity]
|
||||||
before_action :project, except: [:new, :create]
|
before_action :project, except: [:new, :create]
|
||||||
before_action :repository, except: [:new, :create]
|
before_action :repository, except: [:new, :create]
|
||||||
|
before_action :assign_ref_vars, :tree, only: [:show], if: :repo_exists?
|
||||||
|
|
||||||
# Authorize
|
# Authorize
|
||||||
before_action :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive]
|
before_action :authorize_admin_project!, only: [:edit, :update]
|
||||||
before_action :event_filter, only: [:show, :activity]
|
before_action :event_filter, only: [:show, :activity]
|
||||||
|
|
||||||
layout :determine_layout
|
layout :determine_layout
|
||||||
|
|
@ -56,6 +59,8 @@ class ProjectsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def transfer
|
def transfer
|
||||||
|
return access_denied! unless can?(current_user, :change_namespace, @project)
|
||||||
|
|
||||||
namespace = Namespace.find_by(id: params[:new_namespace_id])
|
namespace = Namespace.find_by(id: params[:new_namespace_id])
|
||||||
::Projects::TransferService.new(project, current_user).execute(namespace)
|
::Projects::TransferService.new(project, current_user).execute(namespace)
|
||||||
|
|
||||||
|
|
@ -64,6 +69,15 @@ class ProjectsController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def remove_fork
|
||||||
|
return access_denied! unless can?(current_user, :remove_fork_project, @project)
|
||||||
|
|
||||||
|
if @project.forked?
|
||||||
|
@project.forked_project_link.destroy
|
||||||
|
flash[:notice] = 'The fork relationship has been removed.'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def activity
|
def activity
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html
|
format.html
|
||||||
|
|
@ -87,7 +101,7 @@ class ProjectsController < ApplicationController
|
||||||
render 'projects/empty'
|
render 'projects/empty'
|
||||||
else
|
else
|
||||||
if current_user
|
if current_user
|
||||||
@membership = @project.project_member_by_id(current_user.id)
|
@membership = @project.team.find_member(current_user.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
render :show
|
render :show
|
||||||
|
|
@ -139,6 +153,7 @@ class ProjectsController < ApplicationController
|
||||||
|
|
||||||
def archive
|
def archive
|
||||||
return access_denied! unless can?(current_user, :archive_project, @project)
|
return access_denied! unless can?(current_user, :archive_project, @project)
|
||||||
|
|
||||||
@project.archive!
|
@project.archive!
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
|
|
@ -148,6 +163,7 @@ class ProjectsController < ApplicationController
|
||||||
|
|
||||||
def unarchive
|
def unarchive
|
||||||
return access_denied! unless can?(current_user, :archive_project, @project)
|
return access_denied! unless can?(current_user, :archive_project, @project)
|
||||||
|
|
||||||
@project.unarchive!
|
@project.unarchive!
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
|
|
@ -225,4 +241,14 @@ class ProjectsController < ApplicationController
|
||||||
|
|
||||||
render "go_import", layout: false
|
render "go_import", layout: false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def repo_exists?
|
||||||
|
project.repository_exists? && !project.empty_repo?
|
||||||
|
end
|
||||||
|
|
||||||
|
# Override get_id from ExtractsPath, which returns the branch and file path
|
||||||
|
# for the blob/tree, which in this case is just the root of the default branch.
|
||||||
|
def get_id
|
||||||
|
project.repository.root_ref
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -53,15 +53,36 @@ class IssuableFinder
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def project?
|
||||||
|
params[:project_id].present?
|
||||||
|
end
|
||||||
|
|
||||||
def project
|
def project
|
||||||
return @project if defined?(@project)
|
return @project if defined?(@project)
|
||||||
|
|
||||||
@project =
|
if project?
|
||||||
if params[:project_id].present?
|
@project = Project.find(params[:project_id])
|
||||||
Project.find(params[:project_id])
|
|
||||||
else
|
unless Ability.abilities.allowed?(current_user, :read_project, @project)
|
||||||
nil
|
@project = nil
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
@project = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
@project
|
||||||
|
end
|
||||||
|
|
||||||
|
def projects
|
||||||
|
return @projects if defined?(@projects)
|
||||||
|
|
||||||
|
if project?
|
||||||
|
project
|
||||||
|
elsif current_user && params[:authorized_only].presence && !current_user_related?
|
||||||
|
current_user.authorized_projects
|
||||||
|
else
|
||||||
|
ProjectsFinder.new.execute(current_user)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def search
|
def search
|
||||||
|
|
@ -72,7 +93,7 @@ class IssuableFinder
|
||||||
params[:milestone_title].present?
|
params[:milestone_title].present?
|
||||||
end
|
end
|
||||||
|
|
||||||
def no_milestones?
|
def filter_by_no_milestone?
|
||||||
milestones? && params[:milestone_title] == Milestone::None.title
|
milestones? && params[:milestone_title] == Milestone::None.title
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -81,12 +102,22 @@ class IssuableFinder
|
||||||
|
|
||||||
@milestones =
|
@milestones =
|
||||||
if milestones?
|
if milestones?
|
||||||
Milestone.where(title: params[:milestone_title])
|
scope = Milestone.where(project_id: projects)
|
||||||
|
|
||||||
|
scope.where(title: params[:milestone_title])
|
||||||
else
|
else
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def labels?
|
||||||
|
params[:label_name].present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def filter_by_no_label?
|
||||||
|
labels? && params[:label_name] == Label::None.title
|
||||||
|
end
|
||||||
|
|
||||||
def assignee?
|
def assignee?
|
||||||
params[:assignee_id].present?
|
params[:assignee_id].present?
|
||||||
end
|
end
|
||||||
|
|
@ -120,19 +151,7 @@ class IssuableFinder
|
||||||
private
|
private
|
||||||
|
|
||||||
def init_collection
|
def init_collection
|
||||||
table_name = klass.table_name
|
klass.all
|
||||||
|
|
||||||
if project
|
|
||||||
if Ability.abilities.allowed?(current_user, :read_project, project)
|
|
||||||
project.send(table_name)
|
|
||||||
else
|
|
||||||
[]
|
|
||||||
end
|
|
||||||
elsif current_user && params[:authorized_only].presence && !current_user_related?
|
|
||||||
klass.of_projects(current_user.authorized_projects).references(:project)
|
|
||||||
else
|
|
||||||
klass.of_projects(ProjectsFinder.new.execute(current_user)).references(:project)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def by_scope(items)
|
def by_scope(items)
|
||||||
|
|
@ -170,7 +189,12 @@ class IssuableFinder
|
||||||
end
|
end
|
||||||
|
|
||||||
def by_project(items)
|
def by_project(items)
|
||||||
items = items.of_projects(project.id) if project
|
items =
|
||||||
|
if projects
|
||||||
|
items.of_projects(projects).references(:project)
|
||||||
|
else
|
||||||
|
items.none
|
||||||
|
end
|
||||||
|
|
||||||
items
|
items
|
||||||
end
|
end
|
||||||
|
|
@ -185,18 +209,6 @@ class IssuableFinder
|
||||||
items.sort(params[:sort])
|
items.sort(params[:sort])
|
||||||
end
|
end
|
||||||
|
|
||||||
def by_milestone(items)
|
|
||||||
if milestones?
|
|
||||||
if no_milestones?
|
|
||||||
items = items.where(milestone_id: [-1, nil])
|
|
||||||
else
|
|
||||||
items = items.where(milestone_id: milestones.try(:pluck, :id))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
items
|
|
||||||
end
|
|
||||||
|
|
||||||
def by_assignee(items)
|
def by_assignee(items)
|
||||||
if assignee?
|
if assignee?
|
||||||
items = items.where(assignee_id: assignee.try(:id))
|
items = items.where(assignee_id: assignee.try(:id))
|
||||||
|
|
@ -213,20 +225,36 @@ class IssuableFinder
|
||||||
items
|
items
|
||||||
end
|
end
|
||||||
|
|
||||||
def by_label(items)
|
def by_milestone(items)
|
||||||
if params[:label_name].present?
|
if milestones?
|
||||||
if params[:label_name] == Label::None.title
|
if filter_by_no_milestone?
|
||||||
item_ids = LabelLink.where(target_type: klass.name).pluck(:target_id)
|
items = items.where(milestone_id: [-1, nil])
|
||||||
|
else
|
||||||
|
items = items.joins(:milestone).where(milestones: { title: params[:milestone_title] })
|
||||||
|
|
||||||
items = items.where('id NOT IN (?)', item_ids)
|
if projects
|
||||||
|
items = items.where(milestones: { project_id: projects })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
items
|
||||||
|
end
|
||||||
|
|
||||||
|
def by_label(items)
|
||||||
|
if labels?
|
||||||
|
if filter_by_no_label?
|
||||||
|
items = items.
|
||||||
|
joins("LEFT OUTER JOIN label_links ON label_links.target_type = '#{klass.name}' AND label_links.target_id = #{klass.table_name}.id").
|
||||||
|
where(label_links: { id: nil })
|
||||||
else
|
else
|
||||||
label_names = params[:label_name].split(",")
|
label_names = params[:label_name].split(",")
|
||||||
|
|
||||||
item_ids = LabelLink.joins(:label).
|
items = items.joins(:labels).where(labels: { title: label_names })
|
||||||
where('labels.title in (?)', label_names).
|
|
||||||
where(target_type: klass.name).pluck(:target_id)
|
|
||||||
|
|
||||||
items = items.where(id: item_ids)
|
if projects
|
||||||
|
items = items.where(labels: { project_id: projects })
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,6 @@ module AppearancesHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def brand_header_logo
|
def brand_header_logo
|
||||||
image_tag 'logo.svg'
|
render 'shared/logo.svg'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -68,13 +68,17 @@ module ApplicationHelper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def avatar_icon(user_email = '', size = nil)
|
def avatar_icon(user_or_email = nil, size = nil)
|
||||||
user = User.find_by(email: user_email)
|
if user_or_email.is_a?(User)
|
||||||
|
user = user_or_email
|
||||||
|
else
|
||||||
|
user = User.find_by(email: user_or_email)
|
||||||
|
end
|
||||||
|
|
||||||
if user
|
if user
|
||||||
user.avatar_url(size) || default_avatar
|
user.avatar_url(size) || default_avatar
|
||||||
else
|
else
|
||||||
gravatar_icon(user_email, size)
|
gravatar_icon(user_or_email, size)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,8 @@ module DiffHelper
|
||||||
|
|
||||||
def commit_for_diff(diff)
|
def commit_for_diff(diff)
|
||||||
if diff.deleted_file
|
if diff.deleted_file
|
||||||
@merge_request ? @merge_request.commits.last : @commit.parents.first
|
first_commit = @first_commit || @commit
|
||||||
|
first_commit.parent
|
||||||
else
|
else
|
||||||
@commit
|
@commit
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,10 @@ module GitlabRoutingHelper
|
||||||
namespace_project_commits_path(project.namespace, project, @ref || project.repository.root_ref)
|
namespace_project_commits_path(project.namespace, project, @ref || project.repository.root_ref)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def project_builds_path(project, *args)
|
||||||
|
namespace_project_builds_path(project.namespace, project, *args)
|
||||||
|
end
|
||||||
|
|
||||||
def activity_project_path(project, *args)
|
def activity_project_path(project, *args)
|
||||||
activity_namespace_project_path(project.namespace, project, *args)
|
activity_namespace_project_path(project.namespace, project, *args)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,10 @@ module IssuesHelper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def merge_requests_sentence(merge_requests)
|
||||||
|
merge_requests.map(&:to_reference).to_sentence(last_word_connector: ', or ')
|
||||||
|
end
|
||||||
|
|
||||||
# Required for Gitlab::Markdown::IssueReferenceFilter
|
# Required for Gitlab::Markdown::IssueReferenceFilter
|
||||||
module_function :url_for_issue
|
module_function :url_for_issue
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -92,11 +92,19 @@ module LabelsHelper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def project_labels_options(project)
|
def projects_labels_options
|
||||||
labels = project.labels.to_a
|
labels =
|
||||||
labels.unshift(Label::None)
|
if @project
|
||||||
labels.unshift(Label::Any)
|
@project.labels
|
||||||
options_from_collection_for_select(labels, 'name', 'title', params[:label_name])
|
else
|
||||||
|
Label.where(project_id: @projects)
|
||||||
|
end
|
||||||
|
|
||||||
|
grouped_labels = Labels::GroupService.new(labels).execute
|
||||||
|
grouped_labels.unshift(Label::None)
|
||||||
|
grouped_labels.unshift(Label::Any)
|
||||||
|
|
||||||
|
options_from_collection_for_select(grouped_labels, 'name', 'title', params[:label_name])
|
||||||
end
|
end
|
||||||
|
|
||||||
# Required for Gitlab::Markdown::LabelReferenceFilter
|
# Required for Gitlab::Markdown::LabelReferenceFilter
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ module MergeRequestsHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def issues_sentence(issues)
|
def issues_sentence(issues)
|
||||||
issues.map { |i| "##{i.iid}" }.to_sentence
|
issues.map(&:to_reference).to_sentence
|
||||||
end
|
end
|
||||||
|
|
||||||
def mr_change_branches_path(merge_request)
|
def mr_change_branches_path(merge_request)
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,8 @@ module PreferencesHelper
|
||||||
def project_view_choices
|
def project_view_choices
|
||||||
[
|
[
|
||||||
['Readme (default)', :readme],
|
['Readme (default)', :readme],
|
||||||
['Activity view', :activity]
|
['Activity view', :activity],
|
||||||
|
['Files view', :files]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -46,8 +47,7 @@ module PreferencesHelper
|
||||||
Gitlab::ColorSchemes.for_user(current_user).css_class
|
Gitlab::ColorSchemes.for_user(current_user).css_class
|
||||||
end
|
end
|
||||||
|
|
||||||
def prefer_readme?
|
def default_project_view
|
||||||
!current_user ||
|
current_user ? current_user.project_view : 'readme'
|
||||||
current_user.project_view == 'readme'
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ module ProjectsHelper
|
||||||
author_html = ""
|
author_html = ""
|
||||||
|
|
||||||
# Build avatar image tag
|
# Build avatar image tag
|
||||||
author_html << image_tag(avatar_icon(author.try(:email), opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}", alt:'') if opts[:avatar]
|
author_html << image_tag(avatar_icon(author, opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}", alt:'') if opts[:avatar]
|
||||||
|
|
||||||
# Build name span tag
|
# Build name span tag
|
||||||
author_html << content_tag(:span, sanitize(author.name), class: opts[:author_class]) if opts[:name]
|
author_html << content_tag(:span, sanitize(author.name), class: opts[:author_class]) if opts[:name]
|
||||||
|
|
@ -70,6 +70,10 @@ module ProjectsHelper
|
||||||
"You are going to transfer #{project.name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
|
"You are going to transfer #{project.name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def remove_fork_project_message(project)
|
||||||
|
"You are going to remove the fork relationship to source project #{@project.forked_from_project.name_with_namespace}. Are you ABSOLUTELY sure?"
|
||||||
|
end
|
||||||
|
|
||||||
def project_nav_tabs
|
def project_nav_tabs
|
||||||
@nav_tabs ||= get_project_nav_tabs(@project, current_user)
|
@nav_tabs ||= get_project_nav_tabs(@project, current_user)
|
||||||
end
|
end
|
||||||
|
|
@ -113,6 +117,10 @@ module ProjectsHelper
|
||||||
nav_tabs << :merge_requests
|
nav_tabs << :merge_requests
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if project.gitlab_ci? && can?(current_user, :read_build, project)
|
||||||
|
nav_tabs << :builds
|
||||||
|
end
|
||||||
|
|
||||||
if can?(current_user, :admin_project, project)
|
if can?(current_user, :admin_project, project)
|
||||||
nav_tabs << :settings
|
nav_tabs << :settings
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -13,4 +13,17 @@ module RunnersHelper
|
||||||
title: "Runner is #{status}, last contact was #{time_ago_in_words(runner.contacted_at)} ago"
|
title: "Runner is #{status}, last contact was #{time_ago_in_words(runner.contacted_at)} ago"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def runner_link(runner)
|
||||||
|
display_name = truncate(runner.display_name, length: 15)
|
||||||
|
id = "\##{runner.id}"
|
||||||
|
|
||||||
|
if current_user && current_user.admin
|
||||||
|
link_to ci_admin_runner_path(runner) do
|
||||||
|
display_name + id
|
||||||
|
end
|
||||||
|
else
|
||||||
|
display_name + id
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
class AbuseReportMailer < BaseMailer
|
||||||
|
include Gitlab::CurrentSettings
|
||||||
|
|
||||||
|
def notify(abuse_report_id)
|
||||||
|
@abuse_report = AbuseReport.find(abuse_report_id)
|
||||||
|
|
||||||
|
mail(
|
||||||
|
to: current_application_settings.admin_notification_email,
|
||||||
|
subject: "#{@abuse_report.user.name} (#{@abuse_report.user.username}) was reported for abuse"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -41,6 +41,7 @@ class Ability
|
||||||
:read_project_member,
|
:read_project_member,
|
||||||
:read_merge_request,
|
:read_merge_request,
|
||||||
:read_note,
|
:read_note,
|
||||||
|
:read_build,
|
||||||
:download_code
|
:download_code
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -127,6 +128,7 @@ class Ability
|
||||||
:read_project_member,
|
:read_project_member,
|
||||||
:read_merge_request,
|
:read_merge_request,
|
||||||
:read_note,
|
:read_note,
|
||||||
|
:read_build,
|
||||||
:create_project,
|
:create_project,
|
||||||
:create_issue,
|
:create_issue,
|
||||||
:create_note
|
:create_note
|
||||||
|
|
@ -187,7 +189,8 @@ class Ability
|
||||||
:change_visibility_level,
|
:change_visibility_level,
|
||||||
:rename_project,
|
:rename_project,
|
||||||
:remove_project,
|
:remove_project,
|
||||||
:archive_project
|
:archive_project,
|
||||||
|
:remove_fork_project
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,10 @@ class ApplicationSetting < ActiveRecord::Base
|
||||||
allow_blank: true,
|
allow_blank: true,
|
||||||
format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" }
|
format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" }
|
||||||
|
|
||||||
|
validates :admin_notification_email,
|
||||||
|
allow_blank: true,
|
||||||
|
email: true
|
||||||
|
|
||||||
validates_each :restricted_visibility_levels do |record, attr, value|
|
validates_each :restricted_visibility_levels do |record, attr, value|
|
||||||
unless value.nil?
|
unless value.nil?
|
||||||
value.each do |level|
|
value.each do |level|
|
||||||
|
|
|
||||||
|
|
@ -93,10 +93,7 @@ module Ci
|
||||||
Ci::WebHookService.new.build_end(build)
|
Ci::WebHookService.new.build_end(build)
|
||||||
end
|
end
|
||||||
|
|
||||||
if build.commit.should_create_next_builds?(build)
|
build.commit.create_next_builds(build)
|
||||||
build.commit.create_next_builds(build.ref, build.tag, build.user, build.trigger_request)
|
|
||||||
end
|
|
||||||
|
|
||||||
project.execute_services(build)
|
project.execute_services(build)
|
||||||
|
|
||||||
if project.coverage_enabled?
|
if project.coverage_enabled?
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ module Ci
|
||||||
has_many :builds, class_name: 'Ci::Build'
|
has_many :builds, class_name: 'Ci::Build'
|
||||||
has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest'
|
has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest'
|
||||||
|
|
||||||
|
scope :ordered, -> { order('CASE WHEN ci_commits.committed_at IS NULL THEN 0 ELSE 1 END', :committed_at, :id) }
|
||||||
|
|
||||||
validates_presence_of :sha
|
validates_presence_of :sha
|
||||||
validate :valid_commit_sha
|
validate :valid_commit_sha
|
||||||
|
|
||||||
|
|
@ -89,19 +91,28 @@ module Ci
|
||||||
def create_builds(ref, tag, user, trigger_request = nil)
|
def create_builds(ref, tag, user, trigger_request = nil)
|
||||||
return unless config_processor
|
return unless config_processor
|
||||||
config_processor.stages.any? do |stage|
|
config_processor.stages.any? do |stage|
|
||||||
CreateBuildsService.new.execute(self, stage, ref, tag, user, trigger_request).present?
|
CreateBuildsService.new.execute(self, stage, ref, tag, user, trigger_request, 'success').present?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_next_builds(ref, tag, user, trigger_request)
|
def create_next_builds(build)
|
||||||
return unless config_processor
|
return unless config_processor
|
||||||
|
|
||||||
stages = builds.where(ref: ref, tag: tag, trigger_request: trigger_request).group_by(&:stage)
|
# don't create other builds if this one is retried
|
||||||
|
latest_builds = builds.similar(build).latest
|
||||||
|
return unless latest_builds.exists?(build.id)
|
||||||
|
|
||||||
config_processor.stages.any? do |stage|
|
# get list of stages after this build
|
||||||
unless stages.include?(stage)
|
next_stages = config_processor.stages.drop_while { |stage| stage != build.stage }
|
||||||
CreateBuildsService.new.execute(self, stage, ref, tag, user, trigger_request).present?
|
next_stages.delete(build.stage)
|
||||||
end
|
|
||||||
|
# get status for all prior builds
|
||||||
|
prior_builds = latest_builds.reject { |other_build| next_stages.include?(other_build.stage) }
|
||||||
|
status = Ci::Status.get_status(prior_builds)
|
||||||
|
|
||||||
|
# create builds for next stages based
|
||||||
|
next_stages.any? do |stage|
|
||||||
|
CreateBuildsService.new.execute(self, stage, build.ref, build.tag, build.user, build.trigger_request, status).present?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -130,24 +141,7 @@ module Ci
|
||||||
return 'failed'
|
return 'failed'
|
||||||
end
|
end
|
||||||
|
|
||||||
@status ||= begin
|
@status ||= Ci::Status.get_status(latest_statuses)
|
||||||
latest = latest_statuses
|
|
||||||
latest.reject! { |status| status.try(&:allow_failure?) }
|
|
||||||
|
|
||||||
if latest.none?
|
|
||||||
'skipped'
|
|
||||||
elsif latest.all?(&:success?)
|
|
||||||
'success'
|
|
||||||
elsif latest.all?(&:pending?)
|
|
||||||
'pending'
|
|
||||||
elsif latest.any?(&:running?) || latest.any?(&:pending?)
|
|
||||||
'running'
|
|
||||||
elsif latest.all?(&:canceled?)
|
|
||||||
'canceled'
|
|
||||||
else
|
|
||||||
'failed'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def pending?
|
def pending?
|
||||||
|
|
@ -217,16 +211,6 @@ module Ci
|
||||||
update!(committed_at: DateTime.now)
|
update!(committed_at: DateTime.now)
|
||||||
end
|
end
|
||||||
|
|
||||||
def should_create_next_builds?(build)
|
|
||||||
# don't create other builds if this one is retried
|
|
||||||
other_builds = builds.similar(build).latest
|
|
||||||
return false unless other_builds.include?(build)
|
|
||||||
|
|
||||||
other_builds.all? do |build|
|
|
||||||
build.success? || build.ignored?
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def save_yaml_error(error)
|
def save_yaml_error(error)
|
||||||
|
|
|
||||||
|
|
@ -205,7 +205,7 @@ module Ci
|
||||||
end
|
end
|
||||||
|
|
||||||
def commits
|
def commits
|
||||||
gl_project.ci_commits
|
gl_project.ci_commits.ordered
|
||||||
end
|
end
|
||||||
|
|
||||||
def builds
|
def builds
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ module Ci
|
||||||
end
|
end
|
||||||
|
|
||||||
def display_name
|
def display_name
|
||||||
return token unless !description.blank?
|
return short_sha unless !description.blank?
|
||||||
|
|
||||||
description
|
description
|
||||||
end
|
end
|
||||||
|
|
@ -95,7 +95,7 @@ module Ci
|
||||||
end
|
end
|
||||||
|
|
||||||
def short_sha
|
def short_sha
|
||||||
token[0...10]
|
token[0...8] if token
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,14 @@ class Commit
|
||||||
@committer ||= User.find_by_any_email(committer_email)
|
@committer ||= User.find_by_any_email(committer_email)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def parents
|
||||||
|
@parents ||= parent_ids.map { |id| project.commit(id) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def parent
|
||||||
|
@parent ||= project.commit(self.parent_id) if self.parent_id
|
||||||
|
end
|
||||||
|
|
||||||
def notes
|
def notes
|
||||||
project.notes.for_commit_id(self.id)
|
project.notes.for_commit_id(self.id)
|
||||||
end
|
end
|
||||||
|
|
@ -181,10 +189,6 @@ class Commit
|
||||||
@raw.short_id(7)
|
@raw.short_id(7)
|
||||||
end
|
end
|
||||||
|
|
||||||
def parents
|
|
||||||
@parents ||= Commit.decorate(super, project)
|
|
||||||
end
|
|
||||||
|
|
||||||
def ci_commit
|
def ci_commit
|
||||||
project.ci_commit(sha)
|
project.ci_commit(sha)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ class CommitStatus < ActiveRecord::Base
|
||||||
scope :success, -> { where(status: 'success') }
|
scope :success, -> { where(status: 'success') }
|
||||||
scope :failed, -> { where(status: 'failed') }
|
scope :failed, -> { where(status: 'failed') }
|
||||||
scope :running_or_pending, -> { where(status:[:running, :pending]) }
|
scope :running_or_pending, -> { where(status:[:running, :pending]) }
|
||||||
|
scope :finished, -> { where(status:[:success, :failed, :canceled]) }
|
||||||
scope :latest, -> { where(id: unscope(:select).select('max(id)').group(:name, :ref)) }
|
scope :latest, -> { where(id: unscope(:select).select('max(id)').group(:name, :ref)) }
|
||||||
scope :ordered, -> { order(:ref, :stage_idx, :name) }
|
scope :ordered, -> { order(:ref, :stage_idx, :name) }
|
||||||
scope :for_ref, ->(ref) { where(ref: ref) }
|
scope :for_ref, ->(ref) { where(ref: ref) }
|
||||||
|
|
@ -27,7 +28,7 @@ class CommitStatus < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
event :drop do
|
event :drop do
|
||||||
transition running: :failed
|
transition [:pending, :running] => :failed
|
||||||
end
|
end
|
||||||
|
|
||||||
event :success do
|
event :success do
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ module Issuable
|
||||||
|
|
||||||
attr_mentionable :title
|
attr_mentionable :title
|
||||||
attr_mentionable :description, cache: true
|
attr_mentionable :description, cache: true
|
||||||
participant :author, :assignee, :notes
|
participant :author, :assignee, :notes_with_associations
|
||||||
end
|
end
|
||||||
|
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
|
|
@ -86,6 +86,10 @@ module Issuable
|
||||||
assignee_id_changed?
|
assignee_id_changed?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def open?
|
||||||
|
opened? || reopened?
|
||||||
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Votes
|
# Votes
|
||||||
#
|
#
|
||||||
|
|
@ -177,6 +181,10 @@ module Issuable
|
||||||
self.class.to_s.underscore
|
self.class.to_s.underscore
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def notes_with_associations
|
||||||
|
notes.includes(:author, :project)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def filter_superceded_votes(votes, notes)
|
def filter_superceded_votes(votes, notes)
|
||||||
|
|
|
||||||
|
|
@ -60,12 +60,12 @@ module Mentionable
|
||||||
end
|
end
|
||||||
|
|
||||||
def mentioned_users(current_user = nil, load_lazy_references: true)
|
def mentioned_users(current_user = nil, load_lazy_references: true)
|
||||||
all_references(current_user).users
|
all_references(current_user, load_lazy_references: load_lazy_references).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)
|
def referenced_mentionables(current_user = self.author, text = nil, load_lazy_references: true)
|
||||||
refs = all_references(current_user, text)
|
refs = all_references(current_user, text, load_lazy_references: load_lazy_references)
|
||||||
(refs.issues + refs.merge_requests + refs.commits) - [local_reference]
|
(refs.issues + refs.merge_requests + refs.commits) - [local_reference]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ class Group < Namespace
|
||||||
end
|
end
|
||||||
|
|
||||||
def owners
|
def owners
|
||||||
@owners ||= group_members.owners.map(&:user)
|
@owners ||= group_members.owners.includes(:user).map(&:user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_users(user_ids, access_level, current_user = nil)
|
def add_users(user_ids, access_level, current_user = nil)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
class GroupLabel
|
||||||
|
attr_accessor :title, :labels
|
||||||
|
alias_attribute :name, :title
|
||||||
|
|
||||||
|
def initialize(title, labels)
|
||||||
|
@title = title
|
||||||
|
@labels = labels
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
class GroupMilestone
|
class GroupMilestone
|
||||||
|
attr_accessor :title, :milestones
|
||||||
alias_attribute :name, :title
|
alias_attribute :name, :title
|
||||||
|
|
||||||
def initialize(title, milestones)
|
def initialize(title, milestones)
|
||||||
|
|
@ -7,18 +7,10 @@ class GroupMilestone
|
||||||
@milestones = milestones
|
@milestones = milestones
|
||||||
end
|
end
|
||||||
|
|
||||||
def title
|
|
||||||
@title
|
|
||||||
end
|
|
||||||
|
|
||||||
def safe_title
|
def safe_title
|
||||||
@title.parameterize
|
@title.parameterize
|
||||||
end
|
end
|
||||||
|
|
||||||
def milestones
|
|
||||||
@milestones
|
|
||||||
end
|
|
||||||
|
|
||||||
def projects
|
def projects
|
||||||
milestones.map { |milestone| milestone.project }
|
milestones.map { |milestone| milestone.project }
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -95,4 +95,14 @@ class Issue < ActiveRecord::Base
|
||||||
def source_project
|
def source_project
|
||||||
project
|
project
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# From all notes on this issue, we'll select the system notes about linked
|
||||||
|
# merge requests. Of those, the MRs closing `self` are returned.
|
||||||
|
def closed_by_merge_requests(current_user = nil)
|
||||||
|
return [] unless open?
|
||||||
|
|
||||||
|
notes.system.flat_map do |note|
|
||||||
|
note.all_references(current_user).merge_requests
|
||||||
|
end.uniq.select { |mr| mr.open? && mr.closes_issue?(self) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ class MergeRequest < ActiveRecord::Base
|
||||||
after_create :create_merge_request_diff
|
after_create :create_merge_request_diff
|
||||||
after_update :update_merge_request_diff
|
after_update :update_merge_request_diff
|
||||||
|
|
||||||
delegate :commits, :diffs, :last_commit, :last_commit_short_sha, to: :merge_request_diff, prefix: nil
|
delegate :commits, :diffs, to: :merge_request_diff, prefix: nil
|
||||||
|
|
||||||
# When this attribute is true some MR validation is ignored
|
# When this attribute is true some MR validation is ignored
|
||||||
# It allows us to close or modify broken merge requests
|
# It allows us to close or modify broken merge requests
|
||||||
|
|
@ -157,6 +157,18 @@ class MergeRequest < ActiveRecord::Base
|
||||||
reference
|
reference
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def last_commit
|
||||||
|
merge_request_diff ? merge_request_diff.last_commit : compare_commits.last
|
||||||
|
end
|
||||||
|
|
||||||
|
def first_commit
|
||||||
|
merge_request_diff ? merge_request_diff.first_commit : compare_commits.first
|
||||||
|
end
|
||||||
|
|
||||||
|
def last_commit_short_sha
|
||||||
|
last_commit.short_id
|
||||||
|
end
|
||||||
|
|
||||||
def validate_branches
|
def validate_branches
|
||||||
if target_project == source_project && target_branch == source_branch
|
if target_project == source_project && target_branch == source_branch
|
||||||
errors.add :branch_conflict, "You can not use same project/branch for source and target"
|
errors.add :branch_conflict, "You can not use same project/branch for source and target"
|
||||||
|
|
@ -222,10 +234,6 @@ class MergeRequest < ActiveRecord::Base
|
||||||
self.target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::CLOSED).last
|
self.target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::CLOSED).last
|
||||||
end
|
end
|
||||||
|
|
||||||
def open?
|
|
||||||
opened? || reopened?
|
|
||||||
end
|
|
||||||
|
|
||||||
def work_in_progress?
|
def work_in_progress?
|
||||||
!!(title =~ /\A\[?WIP\]?:? /i)
|
!!(title =~ /\A\[?WIP\]?:? /i)
|
||||||
end
|
end
|
||||||
|
|
@ -294,6 +302,10 @@ class MergeRequest < ActiveRecord::Base
|
||||||
target_project
|
target_project
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def closes_issue?(issue)
|
||||||
|
closes_issues.include?(issue)
|
||||||
|
end
|
||||||
|
|
||||||
# Return the set of issues that will be closed if this merge request is accepted.
|
# Return the set of issues that will be closed if this merge request is accepted.
|
||||||
def closes_issues(current_user = self.author)
|
def closes_issues(current_user = self.author)
|
||||||
if target_branch == project.default_branch
|
if target_branch == project.default_branch
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,10 @@ class MergeRequestDiff < ActiveRecord::Base
|
||||||
commits.first
|
commits.first
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def first_commit
|
||||||
|
commits.last
|
||||||
|
end
|
||||||
|
|
||||||
def last_commit_short_sha
|
def last_commit_short_sha
|
||||||
@last_commit_short_sha ||= last_commit.short_id
|
@last_commit_short_sha ||= last_commit.short_id
|
||||||
end
|
end
|
||||||
|
|
@ -163,7 +167,8 @@ class MergeRequestDiff < ActiveRecord::Base
|
||||||
merge_request.fetch_ref
|
merge_request.fetch_ref
|
||||||
|
|
||||||
# Get latest sha of branch from source project
|
# Get latest sha of branch from source project
|
||||||
source_sha = merge_request.source_project.commit(source_branch).sha
|
source_commit = merge_request.source_project.commit(source_branch)
|
||||||
|
source_sha = source_commit.try(:sha)
|
||||||
|
|
||||||
Gitlab::CompareResult.new(
|
Gitlab::CompareResult.new(
|
||||||
Gitlab::Git::Compare.new(
|
Gitlab::Git::Compare.new(
|
||||||
|
|
|
||||||
|
|
@ -105,4 +105,36 @@ class Milestone < ActiveRecord::Base
|
||||||
def author_id
|
def author_id
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Sorts the issues for the given IDs.
|
||||||
|
#
|
||||||
|
# This method runs a single SQL query using a CASE statement to update the
|
||||||
|
# position of all issues in the current milestone (scoped to the list of IDs).
|
||||||
|
#
|
||||||
|
# Given the ids [10, 20, 30] this method produces a SQL query something like
|
||||||
|
# the following:
|
||||||
|
#
|
||||||
|
# UPDATE issues
|
||||||
|
# SET position = CASE
|
||||||
|
# WHEN id = 10 THEN 1
|
||||||
|
# WHEN id = 20 THEN 2
|
||||||
|
# WHEN id = 30 THEN 3
|
||||||
|
# ELSE position
|
||||||
|
# END
|
||||||
|
# WHERE id IN (10, 20, 30);
|
||||||
|
#
|
||||||
|
# This method expects that the IDs given in `ids` are already Fixnums.
|
||||||
|
def sort_issues(ids)
|
||||||
|
pairs = []
|
||||||
|
|
||||||
|
ids.each_with_index do |id, index|
|
||||||
|
pairs << id
|
||||||
|
pairs << index + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
conditions = 'WHEN id = ? THEN ? ' * ids.length
|
||||||
|
|
||||||
|
issues.where(id: ids).
|
||||||
|
update_all(["position = CASE #{conditions} ELSE position END", *pairs])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,11 @@ class Note < ActiveRecord::Base
|
||||||
scope :inc_author_project, ->{ includes(:project, :author) }
|
scope :inc_author_project, ->{ includes(:project, :author) }
|
||||||
scope :inc_author, ->{ includes(:author) }
|
scope :inc_author, ->{ includes(:author) }
|
||||||
|
|
||||||
|
scope :with_associations, -> do
|
||||||
|
includes(:author, :noteable, :updated_by,
|
||||||
|
project: [:project_members, { group: [:group_members] }])
|
||||||
|
end
|
||||||
|
|
||||||
serialize :st_diff
|
serialize :st_diff
|
||||||
before_create :set_diff, if: ->(n) { n.line_code.present? }
|
before_create :set_diff, if: ->(n) { n.line_code.present? }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ class Project < ActiveRecord::Base
|
||||||
has_many :deploy_keys, through: :deploy_keys_projects
|
has_many :deploy_keys, through: :deploy_keys_projects
|
||||||
has_many :users_star_projects, dependent: :destroy
|
has_many :users_star_projects, dependent: :destroy
|
||||||
has_many :starrers, through: :users_star_projects, source: :user
|
has_many :starrers, through: :users_star_projects, source: :user
|
||||||
has_many :ci_commits, ->() { order('CASE WHEN ci_commits.committed_at IS NULL THEN 0 ELSE 1 END', :committed_at, :id) }, dependent: :destroy, class_name: 'Ci::Commit', foreign_key: :gl_project_id
|
has_many :ci_commits, dependent: :destroy, class_name: 'Ci::Commit', foreign_key: :gl_project_id
|
||||||
has_many :ci_builds, through: :ci_commits, source: :builds, dependent: :destroy, class_name: 'Ci::Build'
|
has_many :ci_builds, through: :ci_commits, source: :builds, dependent: :destroy, class_name: 'Ci::Build'
|
||||||
|
|
||||||
has_one :import_data, dependent: :destroy, class_name: "ProjectImportData"
|
has_one :import_data, dependent: :destroy, class_name: "ProjectImportData"
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ class BambooService < CiService
|
||||||
end
|
end
|
||||||
|
|
||||||
def reset_password
|
def reset_password
|
||||||
if prop_updated?(:bamboo_url)
|
if bamboo_url_changed? && !password_touched?
|
||||||
self.password = nil
|
self.password = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ class TeamcityService < CiService
|
||||||
end
|
end
|
||||||
|
|
||||||
def reset_password
|
def reset_password
|
||||||
if prop_updated?(:teamcity_url)
|
if teamcity_url_changed? && !password_touched?
|
||||||
self.password = nil
|
self.password = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -139,15 +139,28 @@ class ProjectTeam
|
||||||
Gitlab::Access.options.key max_member_access(user_id)
|
Gitlab::Access.options.key max_member_access(user_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# This method assumes project and group members are eager loaded for optimal
|
||||||
|
# performance.
|
||||||
def max_member_access(user_id)
|
def max_member_access(user_id)
|
||||||
access = []
|
access = []
|
||||||
access << project.project_members.find_by(user_id: user_id).try(:access_field)
|
|
||||||
|
|
||||||
if group
|
project.project_members.each do |member|
|
||||||
access << group.group_members.find_by(user_id: user_id).try(:access_field)
|
if member.user_id == user_id
|
||||||
|
access << member.access_field if member.access_field
|
||||||
|
break
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
access.compact.max
|
if group
|
||||||
|
group.group_members.each do |member|
|
||||||
|
if member.user_id == user_id
|
||||||
|
access << member.access_field if member.access_field
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
access.max
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,14 @@ class Repository
|
||||||
|
|
||||||
attr_accessor :raw_repository, :path_with_namespace, :project
|
attr_accessor :raw_repository, :path_with_namespace, :project
|
||||||
|
|
||||||
|
def self.clean_old_archives
|
||||||
|
repository_downloads_path = Gitlab.config.gitlab.repository_downloads_path
|
||||||
|
|
||||||
|
return unless File.directory?(repository_downloads_path)
|
||||||
|
|
||||||
|
Gitlab::Popen.popen(%W(find #{repository_downloads_path} -not -path #{repository_downloads_path} -mmin +120 -delete))
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(path_with_namespace, default_branch = nil, project = nil)
|
def initialize(path_with_namespace, default_branch = nil, project = nil)
|
||||||
@path_with_namespace = path_with_namespace
|
@path_with_namespace = path_with_namespace
|
||||||
@project = project
|
@project = project
|
||||||
|
|
@ -269,14 +277,6 @@ class Repository
|
||||||
end
|
end
|
||||||
|
|
||||||
# Remove archives older than 2 hours
|
# Remove archives older than 2 hours
|
||||||
def clean_old_archives
|
|
||||||
repository_downloads_path = Gitlab.config.gitlab.repository_downloads_path
|
|
||||||
|
|
||||||
return unless File.directory?(repository_downloads_path)
|
|
||||||
|
|
||||||
Gitlab::Popen.popen(%W(find #{repository_downloads_path} -not -path #{repository_downloads_path} -mmin +120 -delete))
|
|
||||||
end
|
|
||||||
|
|
||||||
def branches_sorted_by(value)
|
def branches_sorted_by(value)
|
||||||
case value
|
case value
|
||||||
when 'recently_updated'
|
when 'recently_updated'
|
||||||
|
|
@ -312,13 +312,7 @@ class Repository
|
||||||
end
|
end
|
||||||
|
|
||||||
def blob_for_diff(commit, diff)
|
def blob_for_diff(commit, diff)
|
||||||
file = blob_at(commit.id, diff.new_path)
|
blob_at(commit.id, diff.file_path)
|
||||||
|
|
||||||
unless file
|
|
||||||
file = prev_blob_for_diff(commit, diff)
|
|
||||||
end
|
|
||||||
|
|
||||||
file
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def prev_blob_for_diff(commit, diff)
|
def prev_blob_for_diff(commit, diff)
|
||||||
|
|
@ -480,6 +474,10 @@ class Repository
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def merge_base(first_commit_id, second_commit_id)
|
||||||
|
rugged.merge_base(first_commit_id, second_commit_id)
|
||||||
|
end
|
||||||
|
|
||||||
def search_files(query, ref)
|
def search_files(query, ref)
|
||||||
offset = 2
|
offset = 2
|
||||||
args = %W(git grep -i -n --before-context #{offset} --after-context #{offset} #{query} #{ref || root_ref})
|
args = %W(git grep -i -n --before-context #{offset} --after-context #{offset} #{query} #{ref || root_ref})
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@ class Service < ActiveRecord::Base
|
||||||
|
|
||||||
after_initialize :initialize_properties
|
after_initialize :initialize_properties
|
||||||
|
|
||||||
|
after_commit :reset_updated_properties
|
||||||
|
|
||||||
belongs_to :project
|
belongs_to :project
|
||||||
has_one :service_hook
|
has_one :service_hook
|
||||||
|
|
||||||
|
|
@ -103,6 +105,7 @@ class Service < ActiveRecord::Base
|
||||||
|
|
||||||
# Provide convenient accessor methods
|
# Provide convenient accessor methods
|
||||||
# for each serialized property.
|
# for each serialized property.
|
||||||
|
# Also keep track of updated properties in a similar way as ActiveModel::Dirty
|
||||||
def self.prop_accessor(*args)
|
def self.prop_accessor(*args)
|
||||||
args.each do |arg|
|
args.each do |arg|
|
||||||
class_eval %{
|
class_eval %{
|
||||||
|
|
@ -111,21 +114,39 @@ class Service < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def #{arg}=(value)
|
def #{arg}=(value)
|
||||||
|
updated_properties['#{arg}'] = #{arg} unless #{arg}_changed?
|
||||||
self.properties['#{arg}'] = value
|
self.properties['#{arg}'] = value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def #{arg}_changed?
|
||||||
|
#{arg}_touched? && #{arg} != #{arg}_was
|
||||||
|
end
|
||||||
|
|
||||||
|
def #{arg}_touched?
|
||||||
|
updated_properties.include?('#{arg}')
|
||||||
|
end
|
||||||
|
|
||||||
|
def #{arg}_was
|
||||||
|
updated_properties['#{arg}']
|
||||||
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# ActiveRecord does not provide a mechanism to track changes in serialized keys.
|
# Returns a hash of the properties that have been assigned a new value since last save,
|
||||||
# This is why we need to perform extra query to do it mannually.
|
# indicating their original values (attr => original value).
|
||||||
def prop_updated?(prop_name)
|
# ActiveRecord does not provide a mechanism to track changes in serialized keys,
|
||||||
relation_name = self.type.underscore
|
# so we need a specific implementation for service properties.
|
||||||
previous_value = project.send(relation_name).send(prop_name)
|
# This allows to track changes to properties set with the accessor methods,
|
||||||
return false if previous_value.nil?
|
# but not direct manipulation of properties hash.
|
||||||
previous_value != send(prop_name)
|
def updated_properties
|
||||||
|
@updated_properties ||= ActiveSupport::HashWithIndifferentAccess.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reset_updated_properties
|
||||||
|
@updated_properties = nil
|
||||||
|
end
|
||||||
|
|
||||||
def async_execute(data)
|
def async_execute(data)
|
||||||
return unless supported_events.include?(data[:object_kind])
|
return unless supported_events.include?(data[:object_kind])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ class User < ActiveRecord::Base
|
||||||
include Referable
|
include Referable
|
||||||
include Sortable
|
include Sortable
|
||||||
include TokenAuthenticatable
|
include TokenAuthenticatable
|
||||||
|
include CaseSensitivity
|
||||||
|
|
||||||
default_value_for :admin, false
|
default_value_for :admin, false
|
||||||
default_value_for :can_create_group, gitlab_config.default_can_create_group
|
default_value_for :can_create_group, gitlab_config.default_can_create_group
|
||||||
|
|
@ -182,7 +183,7 @@ class User < ActiveRecord::Base
|
||||||
|
|
||||||
# User's Project preference
|
# User's Project preference
|
||||||
# Note: When adding an option, it MUST go on the end of the array.
|
# Note: When adding an option, it MUST go on the end of the array.
|
||||||
enum project_view: [:readme, :activity]
|
enum project_view: [:readme, :activity, :files]
|
||||||
|
|
||||||
alias_attribute :private_token, :authentication_token
|
alias_attribute :private_token, :authentication_token
|
||||||
|
|
||||||
|
|
@ -273,8 +274,13 @@ class User < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def by_login(login)
|
def by_login(login)
|
||||||
where('lower(username) = :value OR lower(email) = :value',
|
return nil unless login
|
||||||
value: login.to_s.downcase).first
|
|
||||||
|
if login.include?('@'.freeze)
|
||||||
|
unscoped.iwhere(email: login).take
|
||||||
|
else
|
||||||
|
unscoped.iwhere(username: login).take
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_by_username!(username)
|
def find_by_username!(username)
|
||||||
|
|
@ -700,12 +706,15 @@ class User < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def toggle_star(project)
|
def toggle_star(project)
|
||||||
user_star_project = users_star_projects.
|
UsersStarProject.transaction do
|
||||||
where(project: project, user: self).take
|
user_star_project = users_star_projects.
|
||||||
if user_star_project
|
where(project: project, user: self).lock(true).first
|
||||||
user_star_project.destroy
|
|
||||||
else
|
if user_star_project
|
||||||
UsersStarProject.create!(project: project, user: self)
|
user_star_project.destroy
|
||||||
|
else
|
||||||
|
UsersStarProject.create!(project: project, user: self)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,19 +7,12 @@ class ArchiveRepositoryService
|
||||||
end
|
end
|
||||||
|
|
||||||
def execute(options = {})
|
def execute(options = {})
|
||||||
project.repository.clean_old_archives
|
RepositoryArchiveCacheWorker.perform_async
|
||||||
|
|
||||||
raise "No archive file path" unless file_path
|
metadata = project.repository.archive_metadata(ref, storage_path, format)
|
||||||
|
raise "Repository or ref not found" if metadata.empty?
|
||||||
|
|
||||||
return file_path if archived?
|
metadata
|
||||||
|
|
||||||
unless archiving?
|
|
||||||
RepositoryArchiveWorker.perform_async(project.id, ref, format)
|
|
||||||
end
|
|
||||||
|
|
||||||
archived = wait_until_archived(options[:timeout] || 5.0)
|
|
||||||
|
|
||||||
file_path if archived
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
@ -27,36 +20,4 @@ class ArchiveRepositoryService
|
||||||
def storage_path
|
def storage_path
|
||||||
Gitlab.config.gitlab.repository_downloads_path
|
Gitlab.config.gitlab.repository_downloads_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_path
|
|
||||||
@file_path ||= project.repository.archive_file_path(ref, storage_path, format)
|
|
||||||
end
|
|
||||||
|
|
||||||
def pid_file_path
|
|
||||||
@pid_file_path ||= project.repository.archive_pid_file_path(ref, storage_path, format)
|
|
||||||
end
|
|
||||||
|
|
||||||
def archived?
|
|
||||||
File.exist?(file_path)
|
|
||||||
end
|
|
||||||
|
|
||||||
def archiving?
|
|
||||||
File.exist?(pid_file_path)
|
|
||||||
end
|
|
||||||
|
|
||||||
def wait_until_archived(timeout = 5.0)
|
|
||||||
return archived? if timeout == 0.0
|
|
||||||
|
|
||||||
t1 = Time.now
|
|
||||||
|
|
||||||
begin
|
|
||||||
sleep 0.1
|
|
||||||
|
|
||||||
success = archived?
|
|
||||||
|
|
||||||
t2 = Time.now
|
|
||||||
end until success || t2 - t1 >= timeout
|
|
||||||
|
|
||||||
success
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,20 @@
|
||||||
module Ci
|
module Ci
|
||||||
class CreateBuildsService
|
class CreateBuildsService
|
||||||
def execute(commit, stage, ref, tag, user, trigger_request)
|
def execute(commit, stage, ref, tag, user, trigger_request, status)
|
||||||
builds_attrs = commit.config_processor.builds_for_stage_and_ref(stage, ref, tag)
|
builds_attrs = commit.config_processor.builds_for_stage_and_ref(stage, ref, tag)
|
||||||
|
|
||||||
|
# check when to create next build
|
||||||
|
builds_attrs = builds_attrs.select do |build_attrs|
|
||||||
|
case build_attrs[:when]
|
||||||
|
when 'on_success'
|
||||||
|
status == 'success'
|
||||||
|
when 'on_failure'
|
||||||
|
status == 'failed'
|
||||||
|
when 'always'
|
||||||
|
%w(success failed).include?(status)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
builds_attrs.map do |build_attrs|
|
builds_attrs.map do |build_attrs|
|
||||||
# don't create the same build twice
|
# don't create the same build twice
|
||||||
unless commit.builds.find_by(ref: ref, tag: tag, trigger_request: trigger_request, name: build_attrs[:name])
|
unless commit.builds.find_by(ref: ref, tag: tag, trigger_request: trigger_request, name: build_attrs[:name])
|
||||||
|
|
|
||||||
|
|
@ -49,10 +49,13 @@ class GitPushService
|
||||||
elsif push_to_existing_branch?(ref, oldrev)
|
elsif push_to_existing_branch?(ref, oldrev)
|
||||||
# Collect data for this git push
|
# Collect data for this git push
|
||||||
@push_commits = project.repository.commits_between(oldrev, newrev)
|
@push_commits = project.repository.commits_between(oldrev, newrev)
|
||||||
project.update_merge_requests(oldrev, newrev, ref, @user)
|
|
||||||
process_commit_messages(ref)
|
process_commit_messages(ref)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Update merge requests that may be affected by this push. A new branch
|
||||||
|
# could cause the last commit of a merge request to change.
|
||||||
|
project.update_merge_requests(oldrev, newrev, ref, @user)
|
||||||
|
|
||||||
@push_data = build_push_data(oldrev, newrev, ref)
|
@push_data = build_push_data(oldrev, newrev, ref)
|
||||||
|
|
||||||
# If CI was disabled but .gitlab-ci.yml file was pushed
|
# If CI was disabled but .gitlab-ci.yml file was pushed
|
||||||
|
|
@ -76,7 +79,7 @@ class GitPushService
|
||||||
|
|
||||||
authors = Hash.new do |hash, commit|
|
authors = Hash.new do |hash, commit|
|
||||||
email = commit.author_email
|
email = commit.author_email
|
||||||
return hash[email] if hash.has_key?(email)
|
next hash[email] if hash.has_key?(email)
|
||||||
|
|
||||||
hash[email] = commit_user(commit)
|
hash[email] = commit_user(commit)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
module Labels
|
||||||
|
class GroupService < ::BaseService
|
||||||
|
def initialize(project_labels)
|
||||||
|
@project_labels = project_labels.group_by(&:title)
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute
|
||||||
|
build(@project_labels)
|
||||||
|
end
|
||||||
|
|
||||||
|
def label(title)
|
||||||
|
if title
|
||||||
|
group_label = @project_labels[title].group_by(&:title)
|
||||||
|
build(group_label).first
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def build(label)
|
||||||
|
label.map { |title, labels| GroupLabel.new(title, labels) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -6,6 +6,7 @@ module MergeRequests
|
||||||
#
|
#
|
||||||
class PostMergeService < MergeRequests::BaseService
|
class PostMergeService < MergeRequests::BaseService
|
||||||
def execute(merge_request)
|
def execute(merge_request)
|
||||||
|
close_issues(merge_request)
|
||||||
merge_request.mark_as_merged
|
merge_request.mark_as_merged
|
||||||
create_merge_event(merge_request, current_user)
|
create_merge_event(merge_request, current_user)
|
||||||
create_note(merge_request)
|
create_note(merge_request)
|
||||||
|
|
@ -15,6 +16,15 @@ module MergeRequests
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def close_issues(merge_request)
|
||||||
|
return unless merge_request.target_branch == project.default_branch
|
||||||
|
|
||||||
|
closed_issues = merge_request.closes_issues(current_user)
|
||||||
|
closed_issues.each do |issue|
|
||||||
|
Issues::CloseService.new(project, current_user, {}).execute(issue, merge_request)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def create_merge_event(merge_request, current_user)
|
def create_merge_event(merge_request, current_user)
|
||||||
EventCreateService.new.merge_mr(merge_request, current_user)
|
EventCreateService.new.merge_mr(merge_request, current_user)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,20 @@ module MergeRequests
|
||||||
@oldrev, @newrev = oldrev, newrev
|
@oldrev, @newrev = oldrev, newrev
|
||||||
@branch_name = Gitlab::Git.ref_name(ref)
|
@branch_name = Gitlab::Git.ref_name(ref)
|
||||||
@fork_merge_requests = @project.fork_merge_requests.opened
|
@fork_merge_requests = @project.fork_merge_requests.opened
|
||||||
@commits = @project.repository.commits_between(oldrev, newrev)
|
@commits = []
|
||||||
|
|
||||||
|
# Leave a system note if a branch were deleted/added
|
||||||
|
if Gitlab::Git.blank_ref?(oldrev) || Gitlab::Git.blank_ref?(newrev)
|
||||||
|
comment_mr_branch_presence_changed
|
||||||
|
comment_mr_with_commits if @commits.present?
|
||||||
|
else
|
||||||
|
@commits = @project.repository.commits_between(oldrev, newrev)
|
||||||
|
comment_mr_with_commits
|
||||||
|
close_merge_requests
|
||||||
|
end
|
||||||
|
|
||||||
close_merge_requests
|
|
||||||
reload_merge_requests
|
reload_merge_requests
|
||||||
execute_mr_web_hooks
|
execute_mr_web_hooks
|
||||||
comment_mr_with_commits
|
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
@ -31,7 +39,6 @@ module MergeRequests
|
||||||
commit_ids.include?(merge_request.last_commit.id)
|
commit_ids.include?(merge_request.last_commit.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
merge_requests.uniq.select(&:source_project).each do |merge_request|
|
merge_requests.uniq.select(&:source_project).each do |merge_request|
|
||||||
MergeRequests::PostMergeService.
|
MergeRequests::PostMergeService.
|
||||||
new(merge_request.target_project, @current_user).
|
new(merge_request.target_project, @current_user).
|
||||||
|
|
@ -70,13 +77,38 @@ module MergeRequests
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Add comment about branches being deleted or added to merge requests
|
||||||
|
def comment_mr_branch_presence_changed
|
||||||
|
presence = Gitlab::Git.blank_ref?(@oldrev) ? :add : :delete
|
||||||
|
|
||||||
|
merge_requests_for_source_branch.each do |merge_request|
|
||||||
|
last_commit = merge_request.last_commit
|
||||||
|
|
||||||
|
# Only look at changed commits in restore branch case
|
||||||
|
unless Gitlab::Git.blank_ref?(@newrev)
|
||||||
|
begin
|
||||||
|
# Since any number of commits could have been made to the restored branch,
|
||||||
|
# find the common root to see what has been added.
|
||||||
|
common_ref = @project.repository.merge_base(last_commit.id, @newrev)
|
||||||
|
# If the a commit no longer exists in this repo, gitlab_git throws
|
||||||
|
# a Rugged::OdbError. This is fixed in https://gitlab.com/gitlab-org/gitlab_git/merge_requests/52
|
||||||
|
@commits = @project.repository.commits_between(common_ref, @newrev) if common_ref
|
||||||
|
rescue
|
||||||
|
end
|
||||||
|
|
||||||
|
# Prevent system notes from seeing a blank SHA
|
||||||
|
@oldrev = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
SystemNoteService.change_branch_presence(
|
||||||
|
merge_request, merge_request.project, @current_user,
|
||||||
|
:source, @branch_name, presence)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Add comment about pushing new commits to merge requests
|
# Add comment about pushing new commits to merge requests
|
||||||
def comment_mr_with_commits
|
def comment_mr_with_commits
|
||||||
merge_requests = @project.origin_merge_requests.opened.where(source_branch: @branch_name).to_a
|
merge_requests_for_source_branch.each do |merge_request|
|
||||||
merge_requests += @fork_merge_requests.where(source_branch: @branch_name).to_a
|
|
||||||
merge_requests = filter_merge_requests(merge_requests)
|
|
||||||
|
|
||||||
merge_requests.each do |merge_request|
|
|
||||||
mr_commit_ids = Set.new(merge_request.commits.map(&:id))
|
mr_commit_ids = Set.new(merge_request.commits.map(&:id))
|
||||||
|
|
||||||
new_commits, existing_commits = @commits.partition do |commit|
|
new_commits, existing_commits = @commits.partition do |commit|
|
||||||
|
|
@ -91,14 +123,7 @@ module MergeRequests
|
||||||
|
|
||||||
# Call merge request webhook with update branches
|
# Call merge request webhook with update branches
|
||||||
def execute_mr_web_hooks
|
def execute_mr_web_hooks
|
||||||
merge_requests = @project.origin_merge_requests.opened
|
merge_requests_for_source_branch.each do |merge_request|
|
||||||
.where(source_branch: @branch_name)
|
|
||||||
.to_a
|
|
||||||
merge_requests += @fork_merge_requests.where(source_branch: @branch_name)
|
|
||||||
.to_a
|
|
||||||
merge_requests = filter_merge_requests(merge_requests)
|
|
||||||
|
|
||||||
merge_requests.each do |merge_request|
|
|
||||||
execute_hooks(merge_request, 'update')
|
execute_hooks(merge_request, 'update')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -106,5 +131,13 @@ module MergeRequests
|
||||||
def filter_merge_requests(merge_requests)
|
def filter_merge_requests(merge_requests)
|
||||||
merge_requests.uniq.select(&:source_project)
|
merge_requests.uniq.select(&:source_project)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def merge_requests_for_source_branch
|
||||||
|
@source_merge_requests ||= begin
|
||||||
|
merge_requests = @project.origin_merge_requests.opened.where(source_branch: @branch_name).to_a
|
||||||
|
merge_requests += @fork_merge_requests.where(source_branch: @branch_name).to_a
|
||||||
|
filter_merge_requests(merge_requests)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue