Commit 539de0dd authored by Douwe Maan's avatar Douwe Maan

Merge branch 'master' into rs-redactor-filter

parents b093cb35 0b9273a2
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.1.0 (unreleased) v 8.1.0 (unreleased)
- Make diff file view easier to use on mobile screens (Stan Hu)
- Add support for creating directories from Files page (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)
- Improved performance of the trending projects page
- Improved performance of finding projects by their namespace
- Fix bug where transferring a project would result in stale commit links (Stan Hu) - Fix bug where transferring a project would result in stale commit links (Stan Hu)
- Include full path of source and target branch names in New Merge Request page (Stan Hu) - Include full path of source and target branch names in New Merge Request page (Stan Hu)
- Add user preference to view activities as default dashboard (Stan Hu) - Add user preference to view activities as default dashboard (Stan Hu)
...@@ -10,6 +16,7 @@ v 8.1.0 (unreleased) ...@@ -10,6 +16,7 @@ v 8.1.0 (unreleased)
- Move CI charts to project graphs area - Move CI charts to project graphs area
- 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
- Show CI status on commit page - Show CI status on commit page
- Show CI status on Your projects page and Starred projects page - Show CI status on Your projects page and Starred projects page
- Remove "Continuous Integration" page from dashboard - Remove "Continuous Integration" page from dashboard
...@@ -33,6 +40,20 @@ v 8.1.0 (unreleased) ...@@ -33,6 +40,20 @@ v 8.1.0 (unreleased)
- 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 preffered 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
- Add "Quick Submit" behavior to input fields throughout the application. Use
Cmd+Enter on Mac and Ctrl+Enter on Windows/Linux.
- Fix position of hamburger in header for smaller screens (Han Loong Liauw)
- Fix bug where Emojis in Markdown would truncate remaining text (Sakata Sinji)
- Persist filters when sorting on admin user page (Jerry Lukins)
- Add spellcheck=false to certain input fields
- 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
- Apply new design for Files page
- Add "New Page" button to Wiki Pages tab (Stan Hu)
- Only render 404 page from /public
- Hide passwords from services API (Alex Lossent)
- Fix: Images cannot show when projects' path was changed
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)
...@@ -41,11 +62,13 @@ v 8.0.4 ...@@ -41,11 +62,13 @@ v 8.0.4
- Remove CI token from build traces - Remove CI token from build traces
- Fix "Assign All" button on Runner admin page - Fix "Assign All" button on Runner admin page
- Fix search in Files - Fix search in Files
- Add full project namespace to payload of system webhooks (Ricardo Band)
v 8.0.3 v 8.0.3
- Fix URL shown in Slack notifications - Fix URL shown in Slack notifications
- Fix bug where projects would appear to be stuck in the forked import state (Stan Hu) - Fix bug where projects would appear to be stuck in the forked import state (Stan Hu)
- Fix Error 500 in creating merge requests with > 1000 diffs (Stan Hu) - Fix Error 500 in creating merge requests with > 1000 diffs (Stan Hu)
- Add work_in_progress key to MR web hooks (Ben Boeckel)
v 8.0.2 v 8.0.2
- Fix default avatar not rendering in network graph (Stan Hu) - Fix default avatar not rendering in network graph (Stan Hu)
......
...@@ -22,20 +22,20 @@ gem "mysql2", '~> 0.3.16', group: :mysql ...@@ -22,20 +22,20 @@ gem "mysql2", '~> 0.3.16', group: :mysql
gem "pg", '~> 0.18.2', group: :postgres gem "pg", '~> 0.18.2', group: :postgres
# Authentication libraries # Authentication libraries
gem "devise", '~> 3.5.2' gem 'devise', '~> 3.5.2'
gem "devise-async", '~> 0.9.0' gem 'devise-async', '~> 0.9.0'
gem 'omniauth', "~> 1.2.2" gem 'doorkeeper', '~> 2.1.3'
gem 'omniauth-google-oauth2', '~> 0.2.5' gem 'omniauth', '~> 1.2.2'
gem 'omniauth-twitter', '~> 1.0.1' gem 'omniauth-bitbucket', '~> 0.0.2'
gem 'omniauth-github', '~> 1.1.1' gem 'omniauth-github', '~> 1.1.1'
gem 'omniauth-shibboleth', '~> 1.1.1' gem 'omniauth-gitlab', '~> 1.0.0'
gem 'omniauth-kerberos', '~> 0.2.0', group: :kerberos gem 'omniauth-google-oauth2', '~> 0.2.0'
gem 'omniauth-gitlab', '~> 1.0.0' gem 'omniauth-kerberos', '~> 0.3.0', group: :kerberos
gem 'omniauth-bitbucket', '~> 0.0.2' gem 'omniauth-saml', '~> 1.4.0'
gem 'omniauth-saml', '~> 1.4.0' gem 'omniauth-shibboleth', '~> 1.2.0'
gem 'doorkeeper', '~> 2.1.3' gem 'omniauth-twitter', '~> 1.2.0'
gem 'omniauth_crowd' gem 'omniauth_crowd'
gem "rack-oauth2", "~> 1.0.5" gem 'rack-oauth2', '~> 1.0.5'
# Two-factor authentication # Two-factor authentication
gem 'devise-two-factor', '~> 2.0.0' gem 'devise-two-factor', '~> 2.0.0'
...@@ -47,7 +47,7 @@ gem "browser", '~> 1.0.0' ...@@ -47,7 +47,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.17' gem "gitlab_git", '~> 7.2.18'
# 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
...@@ -65,9 +65,9 @@ gem 'gollum-lib', '~> 4.0.2' ...@@ -65,9 +65,9 @@ gem 'gollum-lib', '~> 4.0.2'
gem "gitlab-linguist", "~> 3.0.1", require: "linguist" gem "gitlab-linguist", "~> 3.0.1", require: "linguist"
# API # API
gem "grape", "~> 0.6.1" gem 'grape', '~> 0.6.1'
gem "grape-entity", "~> 0.4.2" gem 'grape-entity', '~> 0.4.2'
gem 'rack-cors', '~> 0.2.9', require: 'rack/cors' gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
# Format dates and times # Format dates and times
# based on human-friendly examples # based on human-friendly examples
...@@ -80,7 +80,7 @@ gem 'enumerize', '~> 0.7.0' ...@@ -80,7 +80,7 @@ gem 'enumerize', '~> 0.7.0'
gem "kaminari", "~> 0.16.3" gem "kaminari", "~> 0.16.3"
# HAML # HAML
gem "haml-rails", '~> 0.5.3' gem "haml-rails", '~> 0.9.0'
# Files attachments # Files attachments
gem "carrierwave", '~> 0.9.0' gem "carrierwave", '~> 0.9.0'
...@@ -128,7 +128,6 @@ gem 'after_commit_queue' ...@@ -128,7 +128,6 @@ gem 'after_commit_queue'
gem 'acts-as-taggable-on', '~> 3.4' gem 'acts-as-taggable-on', '~> 3.4'
# Background jobs # Background jobs
gem 'slim', '~> 2.0.2'
gem 'sinatra', '~> 1.4.4', require: nil gem 'sinatra', '~> 1.4.4', require: nil
gem 'sidekiq', '3.3.0' gem 'sidekiq', '3.3.0'
gem 'sidetiq', '~> 0.6.3' gem 'sidetiq', '~> 0.6.3'
...@@ -151,7 +150,7 @@ gem 'version_sorter', '~> 2.0.0' ...@@ -151,7 +150,7 @@ gem 'version_sorter', '~> 2.0.0'
gem "redis-rails", '~> 4.0.0' gem "redis-rails", '~> 4.0.0'
# Campfire integration # Campfire integration
gem 'tinder', '~> 1.9.2' gem 'tinder', '~> 1.10.0'
# HipChat integration # HipChat integration
gem 'hipchat', '~> 1.5.0' gem 'hipchat', '~> 1.5.0'
...@@ -163,7 +162,7 @@ gem "gitlab-flowdock-git-hook", "~> 1.0.1" ...@@ -163,7 +162,7 @@ gem "gitlab-flowdock-git-hook", "~> 1.0.1"
gem "gemnasium-gitlab-service", "~> 0.2" gem "gemnasium-gitlab-service", "~> 0.2"
# Slack integration # Slack integration
gem "slack-notifier", "~> 1.0.0" gem "slack-notifier", "~> 1.2.0"
# Asana integration # Asana integration
gem 'asana', '~> 0.0.6' gem 'asana', '~> 0.0.6'
...@@ -291,7 +290,7 @@ gem 'newrelic-grape' ...@@ -291,7 +290,7 @@ gem 'newrelic-grape'
gem 'octokit', '~> 3.7.0' gem 'octokit', '~> 3.7.0'
gem "mail_room", "~> 0.5.2" gem "mail_room", "~> 0.6.0"
gem 'email_reply_parser', '~> 0.5.8' gem 'email_reply_parser', '~> 0.5.8'
...@@ -300,9 +299,6 @@ gem 'activerecord-deprecated_finders', '~> 1.0.3' ...@@ -300,9 +299,6 @@ gem 'activerecord-deprecated_finders', '~> 1.0.3'
gem 'activerecord-session_store', '~> 0.1.0' gem 'activerecord-session_store', '~> 0.1.0'
gem "nested_form", '~> 0.3.2' gem "nested_form", '~> 0.3.2'
# Scheduled
gem 'whenever', '~> 0.8.4', require: false
# OAuth # OAuth
gem 'oauth2', '~> 1.0.0' gem 'oauth2', '~> 1.0.0'
......
...@@ -105,7 +105,6 @@ GEM ...@@ -105,7 +105,6 @@ GEM
celluloid (0.16.0) celluloid (0.16.0)
timers (~> 4.0.0) timers (~> 4.0.0)
charlock_holmes (0.6.9.4) charlock_holmes (0.6.9.4)
chronic (0.10.2)
chunky_png (1.3.4) chunky_png (1.3.4)
cliver (0.3.2) cliver (0.3.2)
coderay (1.1.0) coderay (1.1.0)
...@@ -182,8 +181,8 @@ GEM ...@@ -182,8 +181,8 @@ GEM
factory_girl_rails (4.3.0) factory_girl_rails (4.3.0)
factory_girl (~> 4.3.0) factory_girl (~> 4.3.0)
railties (>= 3.0.0) railties (>= 3.0.0)
faraday (0.8.10) faraday (0.9.2)
multipart-post (~> 1.2.0) multipart-post (>= 1.2, < 3)
faraday_middleware (0.10.0) faraday_middleware (0.10.0)
faraday (>= 0.7.4, < 0.10) faraday (>= 0.7.4, < 0.10)
fastercsv (1.5.5) fastercsv (1.5.5)
...@@ -279,7 +278,7 @@ GEM ...@@ -279,7 +278,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.17) gitlab_git (7.2.18)
activesupport (~> 4.0) activesupport (~> 4.0)
charlock_holmes (~> 0.6) charlock_holmes (~> 0.6)
gitlab-linguist (~> 3.0) gitlab-linguist (~> 3.0)
...@@ -330,12 +329,13 @@ GEM ...@@ -330,12 +329,13 @@ GEM
rspec (>= 2.14, < 4.0) rspec (>= 2.14, < 4.0)
haml (4.0.7) haml (4.0.7)
tilt tilt
haml-rails (0.5.3) haml-rails (0.9.0)
actionpack (>= 4.0.1) actionpack (>= 4.0.1)
activesupport (>= 4.0.1) activesupport (>= 4.0.1)
haml (>= 3.1, < 5.0) haml (>= 4.0.6, < 5.0)
html2haml (>= 1.0.1)
railties (>= 4.0.1) railties (>= 4.0.1)
hashie (2.1.2) hashie (3.4.2)
highline (1.6.21) highline (1.6.21)
hike (1.2.3) hike (1.2.3)
hipchat (1.5.2) hipchat (1.5.2)
...@@ -345,6 +345,11 @@ GEM ...@@ -345,6 +345,11 @@ GEM
html-pipeline (1.11.0) html-pipeline (1.11.0)
activesupport (>= 2) activesupport (>= 2)
nokogiri (~> 1.4) nokogiri (~> 1.4)
html2haml (2.0.0)
erubis (~> 2.7.0)
haml (~> 4.0.0)
nokogiri (~> 1.6.0)
ruby_parser (~> 3.5)
http-cookie (1.0.2) http-cookie (1.0.2)
domain_name (~> 0.5) domain_name (~> 0.5)
http_parser.rb (0.5.3) http_parser.rb (0.5.3)
...@@ -387,7 +392,7 @@ GEM ...@@ -387,7 +392,7 @@ GEM
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.5.2) mail_room (0.6.0)
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)
...@@ -396,7 +401,7 @@ GEM ...@@ -396,7 +401,7 @@ GEM
mousetrap-rails (1.4.6) mousetrap-rails (1.4.6)
multi_json (1.11.2) multi_json (1.11.2)
multi_xml (0.5.5) multi_xml (0.5.5)
multipart-post (1.2.0) multipart-post (2.0.0)
mysql2 (0.3.20) mysql2 (0.3.20)
nenv (0.2.0) nenv (0.2.0)
nested_form (0.3.2) nested_form (0.3.2)
...@@ -440,7 +445,7 @@ GEM ...@@ -440,7 +445,7 @@ GEM
omniauth-google-oauth2 (0.2.6) omniauth-google-oauth2 (0.2.6)
omniauth (> 1.0) omniauth (> 1.0)
omniauth-oauth2 (~> 1.1) omniauth-oauth2 (~> 1.1)
omniauth-kerberos (0.2.0) omniauth-kerberos (0.3.0)
omniauth-multipassword omniauth-multipassword
timfel-krb5-auth (~> 0.8) timfel-krb5-auth (~> 0.8)
omniauth-multipassword (0.4.2) omniauth-multipassword (0.4.2)
...@@ -454,11 +459,11 @@ GEM ...@@ -454,11 +459,11 @@ GEM
omniauth-saml (1.4.1) omniauth-saml (1.4.1)
omniauth (~> 1.1) omniauth (~> 1.1)
ruby-saml (~> 1.0.0) ruby-saml (~> 1.0.0)
omniauth-shibboleth (1.1.2) omniauth-shibboleth (1.2.1)
omniauth (>= 1.0.0) omniauth (>= 1.0.0)
omniauth-twitter (1.0.1) omniauth-twitter (1.2.1)
multi_json (~> 1.3) json (~> 1.3)
omniauth-oauth (~> 1.0) omniauth-oauth (~> 1.1)
omniauth_crowd (2.2.3) omniauth_crowd (2.2.3)
activesupport activesupport
nokogiri (>= 1.4.4) nokogiri (>= 1.4.4)
...@@ -496,7 +501,7 @@ GEM ...@@ -496,7 +501,7 @@ GEM
rack (>= 0.4) rack (>= 0.4)
rack-attack (4.3.0) rack-attack (4.3.0)
rack rack
rack-cors (0.2.9) rack-cors (0.4.0)
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)
...@@ -666,10 +671,7 @@ GEM ...@@ -666,10 +671,7 @@ GEM
rack-protection (~> 1.4) rack-protection (~> 1.4)
tilt (>= 1.3, < 3) tilt (>= 1.3, < 3)
six (0.2.0) six (0.2.0)
slack-notifier (1.0.0) slack-notifier (1.2.1)
slim (2.0.3)
temple (~> 0.6.6)
tilt (>= 1.3.3, < 2.1)
slop (3.6.0) slop (3.6.0)
spinach (0.8.10) spinach (0.8.10)
colorize colorize
...@@ -705,7 +707,6 @@ GEM ...@@ -705,7 +707,6 @@ GEM
railties (>= 3.2.5, < 5) railties (>= 3.2.5, < 5)
teaspoon-jasmine (2.2.0) teaspoon-jasmine (2.2.0)
teaspoon (>= 1.0.0) teaspoon (>= 1.0.0)
temple (0.6.10)
term-ansicolor (1.3.2) term-ansicolor (1.3.2)
tins (~> 1.0) tins (~> 1.0)
terminal-table (1.5.2) terminal-table (1.5.2)
...@@ -721,13 +722,13 @@ GEM ...@@ -721,13 +722,13 @@ GEM
timers (4.0.4) timers (4.0.4)
hitimes hitimes
timfel-krb5-auth (0.8.3) timfel-krb5-auth (0.8.3)
tinder (1.9.4) tinder (1.10.1)
eventmachine (~> 1.0) eventmachine (~> 1.0)
faraday (~> 0.8.9) faraday (~> 0.9.0)
faraday_middleware (~> 0.9) faraday_middleware (~> 0.9)
hashie (>= 1.0, < 3) hashie (>= 1.0)
json (~> 1.8.0) json (~> 1.8.0)
mime-types (~> 1.19) mime-types
multi_json (~> 1.7) multi_json (~> 1.7)
twitter-stream (~> 0.1) twitter-stream (~> 0.1)
tins (1.6.0) tins (1.6.0)
...@@ -770,9 +771,6 @@ GEM ...@@ -770,9 +771,6 @@ GEM
websocket-driver (0.6.2) websocket-driver (0.6.2)
websocket-extensions (>= 0.1.0) websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2) websocket-extensions (0.1.2)
whenever (0.8.4)
activesupport (>= 2.3.4)
chronic (>= 0.6.3)
wikicloth (0.8.1) wikicloth (0.8.1)
builder builder
expression_parser expression_parser
...@@ -836,7 +834,7 @@ DEPENDENCIES ...@@ -836,7 +834,7 @@ 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.17) gitlab_git (~> 7.2.18)
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)
...@@ -845,7 +843,7 @@ DEPENDENCIES ...@@ -845,7 +843,7 @@ DEPENDENCIES
grape-entity (~> 0.4.2) grape-entity (~> 0.4.2)
growl growl
guard-rspec (~> 4.2.0) guard-rspec (~> 4.2.0)
haml-rails (~> 0.5.3) haml-rails (~> 0.9.0)
hipchat (~> 1.5.0) hipchat (~> 1.5.0)
html-pipeline (~> 1.11.0) html-pipeline (~> 1.11.0)
httparty (~> 0.13.3) httparty (~> 0.13.3)
...@@ -856,7 +854,7 @@ DEPENDENCIES ...@@ -856,7 +854,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.5.2) mail_room (~> 0.6.0)
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)
...@@ -870,11 +868,11 @@ DEPENDENCIES ...@@ -870,11 +868,11 @@ DEPENDENCIES
omniauth-bitbucket (~> 0.0.2) omniauth-bitbucket (~> 0.0.2)
omniauth-github (~> 1.1.1) omniauth-github (~> 1.1.1)
omniauth-gitlab (~> 1.0.0) omniauth-gitlab (~> 1.0.0)
omniauth-google-oauth2 (~> 0.2.5) omniauth-google-oauth2 (~> 0.2.0)
omniauth-kerberos (~> 0.2.0) omniauth-kerberos (~> 0.3.0)
omniauth-saml (~> 1.4.0) omniauth-saml (~> 1.4.0)
omniauth-shibboleth (~> 1.1.1) omniauth-shibboleth (~> 1.2.0)
omniauth-twitter (~> 1.0.1) omniauth-twitter (~> 1.2.0)
omniauth_crowd omniauth_crowd
org-ruby (~> 0.9.12) org-ruby (~> 0.9.12)
paranoia (~> 2.0) paranoia (~> 2.0)
...@@ -883,7 +881,7 @@ DEPENDENCIES ...@@ -883,7 +881,7 @@ DEPENDENCIES
pry-rails pry-rails
quiet_assets (~> 1.0.2) quiet_assets (~> 1.0.2)
rack-attack (~> 4.3.0) rack-attack (~> 4.3.0)
rack-cors (~> 0.2.9) rack-cors (~> 0.4.0)
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)
...@@ -912,8 +910,7 @@ DEPENDENCIES ...@@ -912,8 +910,7 @@ DEPENDENCIES
simplecov (~> 0.10.0) simplecov (~> 0.10.0)
sinatra (~> 1.4.4) sinatra (~> 1.4.4)
six (~> 0.2.0) six (~> 0.2.0)
slack-notifier (~> 1.0.0) slack-notifier (~> 1.2.0)
slim (~> 2.0.2)
spinach-rails (~> 0.2.1) spinach-rails (~> 0.2.1)
spring (~> 1.3.6) spring (~> 1.3.6)
spring-commands-rspec (~> 1.0.4) spring-commands-rspec (~> 1.0.4)
...@@ -927,7 +924,7 @@ DEPENDENCIES ...@@ -927,7 +924,7 @@ DEPENDENCIES
teaspoon-jasmine (~> 2.2.0) teaspoon-jasmine (~> 2.2.0)
test_after_commit (~> 0.2.2) test_after_commit (~> 0.2.2)
thin (~> 1.6.1) thin (~> 1.6.1)
tinder (~> 1.9.2) tinder (~> 1.10.0)
turbolinks (~> 2.5.0) turbolinks (~> 2.5.0)
uglifier (~> 2.3.2) uglifier (~> 2.3.2)
underscore-rails (~> 1.4.4) underscore-rails (~> 1.4.4)
...@@ -937,7 +934,6 @@ DEPENDENCIES ...@@ -937,7 +934,6 @@ DEPENDENCIES
version_sorter (~> 2.0.0) version_sorter (~> 2.0.0)
virtus (~> 1.0.1) virtus (~> 1.0.1)
webmock (~> 1.21.0) webmock (~> 1.21.0)
whenever (~> 0.8.4)
wikicloth (= 0.8.1) wikicloth (= 0.8.1)
BUNDLED WITH BUNDLED WITH
......
...@@ -79,7 +79,11 @@ Thanks for the issue report but we only support issues for the latest stable ver ...@@ -79,7 +79,11 @@ Thanks for the issue report but we only support issues for the latest stable ver
### Support requests and configuration questions ### Support requests and configuration questions
Thanks for your interest in GitLab. We don't use the issue tracker for support requests and configuration questions. Please use the \[support forum\]\(https://groups.google.com/forum/#!forum/gitlabhq), \[Stack Overflow\]\(http://stackoverflow.com/questions/tagged/gitlab), the #gitlab IRC channel on Freenode or the http://about.gitlab.com paid services for this purpose. Have a look at the \[contribution guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) for more information. Thanks for your interest in GitLab. We don't use the issue tracker for support
requests and configuration questions. Please check our
\[getting help\]\(https://about.gitlab.com/getting-help/) page to see all of the available
support options. Also, have a look at the \[contribution guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md)
for more information.
### Code format ### Code format
......
...@@ -71,7 +71,7 @@ GitLab is a Ruby on Rails application that runs on the following software: ...@@ -71,7 +71,7 @@ GitLab is a Ruby on Rails application that runs on the following software:
- Ubuntu/Debian/CentOS/RHEL - Ubuntu/Debian/CentOS/RHEL
- Ruby (MRI) 2.1 - Ruby (MRI) 2.1
- Git 1.7.10+ - Git 1.7.10+
- Redis 2.0+ - Redis 2.4+
- MySQL or PostgreSQL - MySQL or PostgreSQL
For more information please see the [architecture documentation](http://doc.gitlab.com/ce/development/architecture.html). For more information please see the [architecture documentation](http://doc.gitlab.com/ce/development/architecture.html).
......
...@@ -180,6 +180,7 @@ $ -> ...@@ -180,6 +180,7 @@ $ ->
$('.navbar-toggle').on 'click', -> $('.navbar-toggle').on 'click', ->
$('.header-content .title').toggle() $('.header-content .title').toggle()
$('.header-content .navbar-collapse').toggle() $('.header-content .navbar-collapse').toggle()
$('.navbar-toggle').toggleClass('active')
# Show/hide comments on diff # Show/hide comments on diff
$("body").on "click", ".js-toggle-diff-comments", (e) -> $("body").on "click", ".js-toggle-diff-comments", (e) ->
......
# Quick Submit behavior
#
# When an input field with the `js-quick-submit` class receives a "Meta+Enter"
# (Mac) or "Ctrl+Enter" (Linux/Windows) key combination, its parent form is
# submitted.
#
#= require extensions/jquery
#
# ### Example Markup
#
# <form action="/foo">
# <input type="text" class="js-quick-submit" />
# <textarea class="js-quick-submit"></textarea>
# </form>
#
$(document).on 'keydown.quick_submit', '.js-quick-submit', (e) ->
return if (e.originalEvent && e.originalEvent.repeat) || e.repeat
return unless e.keyCode == 13 # Enter
if navigator.userAgent.match(/Macintosh/)
return unless (e.metaKey && !e.altKey && !e.ctrlKey && !e.shiftKey)
else
return unless (e.ctrlKey && !e.altKey && !e.metaKey && !e.shiftKey)
e.preventDefault()
$form = $(e.target).closest('form')
$form.find('input[type=submit], button[type=submit]').disable()
$form.submit()
...@@ -34,6 +34,5 @@ $.fn.requiresInput = -> ...@@ -34,6 +34,5 @@ $.fn.requiresInput = ->
$form.on 'change input', fieldSelector, requireInput $form.on 'change input', fieldSelector, requireInput
# Triggered on standard document `ready` and on Turbolinks `page:load` events $ ->
$(document).on 'ready page:load', ->
$('form.js-requires-input').requiresInput() $('form.js-requires-input').requiresInput()
...@@ -47,6 +47,7 @@ class @BlobFileDropzone ...@@ -47,6 +47,7 @@ class @BlobFileDropzone
return return
this.on 'sending', (file, xhr, formData) -> this.on 'sending', (file, xhr, formData) ->
formData.append('new_branch', form.find('#new_branch').val())
formData.append('commit_message', form.find('#commit_message').val()) formData.append('commit_message', form.find('#commit_message').val())
return return
......
This diff is collapsed.
$(document).on 'click', '.badge-codes-toggle', -> $(document).on 'click', '.badge-codes-toggle', ->
$('.badge-codes-block').toggleClass("hide") $('.badge-codes-block').toggleClass("hide")
return false return false
$(document).on 'click', '.sync-now', ->
$(this).find('i').addClass('fa-spin')
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
# #
# ### Example Markup # ### Example Markup
# #
# <div id="tree-content-holder"> # <div id="blob-content-holder">
# <div class="file-content"> # <div class="file-content">
# <div class="line-numbers"> # <div class="line-numbers">
# <a href="#L1" id="L1" data-line-number="1">1</a> # <a href="#L1" id="L1" data-line-number="1">1</a>
...@@ -53,7 +53,7 @@ class @LineHighlighter ...@@ -53,7 +53,7 @@ class @LineHighlighter
$.scrollTo("#L#{range[0]}", offset: -150) $.scrollTo("#L#{range[0]}", offset: -150)
bindEvents: -> bindEvents: ->
$('#tree-content-holder').on 'mousedown', 'a[data-line-number]', @clickHandler $('#blob-content-holder').on 'mousedown', 'a[data-line-number]', @clickHandler
# While it may seem odd to bind to the mousedown event and then throw away # While it may seem odd to bind to the mousedown event and then throw away
# the click event, there is a method to our madness. # the click event, there is a method to our madness.
...@@ -62,7 +62,7 @@ class @LineHighlighter ...@@ -62,7 +62,7 @@ class @LineHighlighter
# active state even when the event is cancelled, resulting in an ugly border # active state even when the event is cancelled, resulting in an ugly border
# around the link and/or a persisted underline text decoration. # around the link and/or a persisted underline text decoration.
$('#tree-content-holder').on 'click', 'a[data-line-number]', (event) -> $('#blob-content-holder').on 'click', 'a[data-line-number]', (event) ->
event.preventDefault() event.preventDefault()
clickHandler: (event) => clickHandler: (event) =>
......
...@@ -69,7 +69,7 @@ class @MergeRequestTabs ...@@ -69,7 +69,7 @@ class @MergeRequestTabs
scrollToElement: (container) -> scrollToElement: (container) ->
if window.location.hash if window.location.hash
top = $(container + " " + window.location.hash).offset().top top = $(container + " " + window.location.hash).offset().top
$('body').scrollTo(top); $('body').scrollTo(top)
# Activate a tab based on the current action # Activate a tab based on the current action
activateTab: (action) -> activateTab: (action) ->
...@@ -139,13 +139,16 @@ class @MergeRequestTabs ...@@ -139,13 +139,16 @@ class @MergeRequestTabs
@diffsLoaded = true @diffsLoaded = true
@scrollToElement(".diffs") @scrollToElement(".diffs")
toggleLoading: -> # Show or hide the loading spinner
$('.mr-loading-status .loading').toggle() #
# status - Boolean, true to show, false to hide
toggleLoading: (status) ->
$('.mr-loading-status .loading').toggle(status)
_get: (options) -> _get: (options) ->
defaults = { defaults = {
beforeSend: @toggleLoading beforeSend: => @toggleLoading(true)
complete: @toggleLoading complete: => @toggleLoading(false)
dataType: 'json' dataType: 'json'
type: 'GET' type: 'GET'
} }
......
...@@ -63,12 +63,6 @@ class @Notes ...@@ -63,12 +63,6 @@ class @Notes
# fetch notes when tab becomes visible # fetch notes when tab becomes visible
$(document).on "visibilitychange", @visibilityChange $(document).on "visibilitychange", @visibilityChange
# Chrome doesn't fire keypress or keyup for Command+Enter, so we need keydown.
$(document).on 'keydown', '.js-note-text', (e) ->
return if e.originalEvent.repeat
if e.keyCode == 10 || ((e.metaKey || e.ctrlKey) && e.keyCode == 13)
$(@).closest('form').submit()
cleanBinding: -> cleanBinding: ->
$(document).off "ajax:success", ".js-main-target-form" $(document).off "ajax:success", ".js-main-target-form"
$(document).off "ajax:success", ".js-discussion-note-form" $(document).off "ajax:success", ".js-discussion-note-form"
...@@ -82,7 +76,6 @@ class @Notes ...@@ -82,7 +76,6 @@ class @Notes
$(document).off "click", ".js-discussion-reply-button" $(document).off "click", ".js-discussion-reply-button"
$(document).off "click", ".js-add-diff-note-button" $(document).off "click", ".js-add-diff-note-button"
$(document).off "visibilitychange" $(document).off "visibilitychange"
$(document).off "keydown", ".js-note-text"
$(document).off "keyup", ".js-note-text" $(document).off "keyup", ".js-note-text"
$(document).off "click", ".js-note-target-reopen" $(document).off "click", ".js-note-target-reopen"
$(document).off "click", ".js-note-target-close" $(document).off "click", ".js-note-target-close"
......
...@@ -11,59 +11,41 @@ ...@@ -11,59 +11,41 @@
*= require cal-heatmap *= require cal-heatmap
*/ */
/*
* Welcome to GitLab css!
* If you need to add or modify UI component that is common for many pages
* like a table or typography then make changes in the framework/ directory.
* If you need to add unique style that should affect only one page - use pages/
* directory.
*/
@import "base/fonts"; /*
@import "base/variables"; * GitLab UI framework
@import "base/mixins";
@import "base/layout";
/**
* Customized Twitter bootstrap
*/ */
@import 'base/gl_variables'; @import "framework";
@import 'base/gl_bootstrap';
/** /*
* NProgress load bar css * NProgress load bar css
*/ */
@import 'nprogress'; @import 'nprogress';
@import 'nprogress-bootstrap'; @import 'nprogress-bootstrap';
/** /*
* Font icons * Font icons
*
*/ */
@import "font-awesome"; @import "font-awesome";
/** /*
* UI themes:
*/
@import "themes/**/*";
/**
* Generic css (forms, nav etc):
*/
@import "generic/**/*";
/**
* Page specific styles (issues, projects etc): * Page specific styles (issues, projects etc):
*/ */
@import "pages/**/*"; @import "pages/**/*";
/** /*
* Code highlight * Code highlight
*/ */
@import "highlight/**/*"; @import "highlight/**/*";
/** /*
* Styles for JS behaviors. * Styles for JS behaviors.
*/ */
@import "behaviors.scss"; @import "behaviors.scss";
\ No newline at end of file
/**
* CI specific styles:
*/
@import "ci/**/*";
@import "framework/fonts";
@import "framework/variables";
@import "framework/mixins";
@import "framework/layout";
@import 'framework/tw_bootstrap_variables';
@import 'framework/tw_bootstrap';
@import "framework/avatar.scss";
@import "framework/blocks.scss";
@import "framework/buttons.scss";
@import "framework/calendar.scss";
@import "framework/callout.scss";
@import "framework/common.scss";
@import "framework/files.scss";
@import "framework/filters.scss";
@import "framework/flash.scss";
@import "framework/forms.scss";
@import "framework/gfm.scss";
@import "framework/gitlab-theme.scss";
@import "framework/header.scss";
@import "framework/highlight.scss";
@import "framework/issue_box.scss";
@import "framework/jquery.scss";
@import "framework/lists.scss";
@import "framework/markdown_area.scss";
@import "framework/mobile.scss";
@import "framework/pagination.scss";
@import "framework/selects.scss";
@import "framework/sidebar.scss";
@import "framework/tables.scss";
@import "framework/timeline.scss";
@import "framework/typography.scss";
@import "framework/zen.scss";
body { @mixin btn-default {
text-rendering: geometricPrecision; @include border-radius(2px);
border-width: 1px;
border-style: solid;
text-transform: uppercase;
font-size: 13px;
font-weight: 600;
line-height: 18px;
padding: 11px $gl-padding;
letter-spacing: .4px;
&:focus,
&:active {
outline: none;
@include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
}
}
@mixin btn-middle {
@include btn-default;
@include border-radius(2px);
padding: 11px 24px;
}
@mixin btn-color($light, $border-light, $normal, $border-normal, $dark, $border-dark, $color) {
background-color: $light;
border-color: $border-light;
color: $color;
&:hover,
&:focus {
background-color: $normal;
border-color: $border-normal;
color: $color;
}
&:active {
@include box-shadow (inset 0 0 4px rgba(0, 0, 0, 0.12));
background-color: $dark;
border-color: $border-dark;
color: $color;
}
} }
@mixin btn-green {
@include btn-color($green-light, $border-green-light, $green-normal, $border-green-normal, $green-dark, $border-green-dark, #FFFFFF);
}
@mixin btn-blue {
@include btn-color($blue-light, $border-blue-light, $blue-normal, $border-blue-normal, $blue-dark, $border-blue-dark, #FFFFFF);
}
@mixin btn-orange {
@include btn-color($orange-light, $border-orange-light, $orange-normal, $border-orange-normal, $orange-dark, $border-orange-dark, #FFFFFF);
}
@mixin btn-red {
@include btn-color($red-light, $border-red-light, $red-normal, $border-red-normal, $red-dark, $border-red-dark, #FFFFFF);
}
@mixin btn-gray {
@include btn-color($gray-light, $border-gray-light, $gray-normal, $border-gray-normal, $gray-dark, $border-gray-dark, #313236);
}
@mixin btn-white {
@include btn-color($white-light, $border-white-light, $white-normal, $border-white-normal, $white-dark, $border-white-dark, #313236);
}
.btn { .btn {
@extend .btn-default; @include btn-default;
@include btn-white;
&.btn-sm {
padding: 5px 10px;
}
&.btn-xs {
padding: 1px 5px;
}
&.btn-success,
&.btn-new,
&.btn-create,
&.btn-save,
&.btn-green {
@include btn-green;
}
&.btn-new { &.btn-gray {
@extend .btn-success; @include btn-gray;
} }
&.btn-create { &.btn-primary,
@extend .btn-success; &.btn-info {
@include btn-blue;
} }
&.btn-save { &.btn-warning {
@extend .btn-success; @include btn-orange;
} }
&.btn-remove { &.btn-danger,
@extend .btn-danger; &.btn-remove,
&.btn-red {
@include btn-red;
} }
&.btn-cancel { &.btn-cancel {
...@@ -47,14 +133,6 @@ body { ...@@ -47,14 +133,6 @@ body {
margin-right: 0px; margin-right: 0px;
} }
} }
&.btn-save {
@extend .btn-primary;
}
&.btn-new, &.btn-create {
@extend .btn-success;
}
} }
.btn-block { .btn-block {
...@@ -91,138 +169,3 @@ body { ...@@ -91,138 +169,3 @@ body {
} }
} }
} }
@mixin btn-info {
@include border-radius(2px);
border-width: 1px;
border-style: solid;
text-transform: uppercase;
font-size: 13px;
font-weight: 600;
line-height: 18px;
padding: 11px 16px;
letter-spacing: .4px;
&:hover {
border-width: 1px;
border-style: solid;
}
&:focus {
border-width: 1px;
border-style: solid;
}
&:active {
@include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
border-width: 1px;
border-style: solid;
}
}
@mixin btn-middle {
@include border-radius(2px);
border-width: 1px;
border-style: solid;
text-transform: uppercase;
font-size: 13px;
font-weight: 600;
line-height: 18px;
padding: 11px 24px;
letter-spacing: .4px;
&:hover {
border-width: 1px;
border-style: solid;
}
&:focus {
border-width: 1px;
border-style: solid;
}
&:active {
@include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
border-width: 1px;
border-style: solid;
}
}
@mixin btn-green {
background-color: #28b061;
border: 1px solid #26a65c;
color: #fff;
&:hover {
background-color: #26ab5d;
border: 1px solid #229954;
color: #fff;
}
&:focus {
background-color: #26ab5d;
border: 1px solid #229954;
color: #fff;
}
&:active {
@include box-shadow (inset 0 0 4px rgba(0, 0, 0, 0.12));
background-color: #23a158 !important;
border: 1px solid #229954 !important;
color: #fff !important;
}
}
/*Butons*/
@mixin bnt-project {
background-color: #f0f2f5;
border-color: #dce0e5;
color: #313236;
&:hover {
border-color:#dce0e5;
background-color: #ebeef2;
color: #313236;
}
&:focus {
border-color: #dce0e5;
background-color: #ebeef2;
color: #313236;
}
&:active {
@include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
color: #313236 !important;
border-color: #c6cacf !important;
background-color: #e4e7ed !important;
}
}
@mixin btn-remove {
background-color: #f72e60;
border-color: #ee295a;
&:hover {
background-color: #e82757;
border-color: #e32555;
}
&:focus {
background-color: #e82757;
border-color: #e32555;
}
&:active {
@include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
background-color: #d42450 !important;
border-color: #e12554 !important;
}
}
\ No newline at end of file
...@@ -394,3 +394,7 @@ table { ...@@ -394,3 +394,7 @@ table {
.dropzone .dz-preview .dz-progress .dz-upload { .dropzone .dz-preview .dz-progress .dz-upload {
background: $gl-success !important; background: $gl-success !important;
} }
.space-right {
margin-right: 10px;
}
...@@ -29,12 +29,6 @@ input[type='text'].danger { ...@@ -29,12 +29,6 @@ input[type='text'].danger {
border-top: 1px solid $border-color; border-top: 1px solid $border-color;
} }
@media (min-width: $screen-sm-min) {
.form-actions {
padding-left: 17%;
}
}
label { label {
&.control-label { &.control-label {
@extend .col-sm-2; @extend .col-sm-2;
...@@ -84,3 +78,17 @@ label { ...@@ -84,3 +78,17 @@ label {
.wiki-content { .wiki-content {
margin-top: 35px; margin-top: 35px;
} }
.form-group .control-label {
font-weight: normal;
}
.form-control::-webkit-input-placeholder {
color: #7f8fa4;
}
.input-group {
.input-group-addon {
background-color: #f7f8fa;
}
}
...@@ -22,4 +22,5 @@ ...@@ -22,4 +22,5 @@
.gfm-commit, .gfm-commit_range { .gfm-commit, .gfm-commit_range {
font-family: $monospace_font; font-family: $monospace_font;
font-size: 90%;
} }
...@@ -50,15 +50,17 @@ header { ...@@ -50,15 +50,17 @@ header {
.navbar-toggle { .navbar-toggle {
color: #666; color: #666;
margin: 0; margin: 6px 0;
border-radius: 0; border-radius: 0;
position: absolute; position: absolute;
right: 2px; right: 2px;
top: 15px;
&:hover { &:hover {
background-color: #EEE; background-color: #EEE;
} }
&.active {
color: #7f8fa4;
}
} }
} }
} }
...@@ -87,6 +89,7 @@ header { ...@@ -87,6 +89,7 @@ header {
.navbar-collapse { .navbar-collapse {
float: right; float: right;
border-top: none;
} }
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
*/ */
.issue-box { .issue-box {
@include border-radius(3px); @include border-radius(2px);
display: inline-block; display: inline-block;
padding: 10px $gl-padding; padding: 10px $gl-padding;
......
...@@ -5,6 +5,7 @@ html { ...@@ -5,6 +5,7 @@ html {
body { body {
padding-top: $header-height; padding-top: $header-height;
text-rendering: geometricPrecision;
} }
} }
......
...@@ -117,8 +117,12 @@ ul.content-list { ...@@ -117,8 +117,12 @@ ul.content-list {
} }
.controls { .controls {
padding-top: 10px; padding-top: 4px;
float: right; float: right;
.btn {
padding: 10px 14px;
}
} }
} }
} }
......
...@@ -54,147 +54,6 @@ ...@@ -54,147 +54,6 @@
@include box-shadow(0 0 0 3px #f1f1f1); @include box-shadow(0 0 0 3px #f1f1f1);
} }
@mixin md-typography {
color: $md-text-color;
a {
color: $md-link-color;
}
img {
max-width: 100%;
}
*:first-child {
margin-top: 0;
}
code {
font-family: $monospace_font;
white-space: pre;
word-wrap: normal;
padding: 1px 2px;
}
kbd {
display: inline-block;
padding: 3px 5px;
font-size: 11px;
line-height: 10px;
color: #555;
vertical-align: middle;
background-color: #FCFCFC;
border-width: 1px;
border-style: solid;
border-color: #CCC #CCC #BBB;
border-image: none;
border-radius: 3px;
box-shadow: 0px -1px 0px #BBB inset;
}
h1 {
font-size: 1.3em;
font-weight: 600;
margin: 24px 0 12px 0;
padding: 0 0 10px 0;
border-bottom: 1px solid #e7e9ed;
color: #313236;
}
h2 {
font-size: 1.2em;
font-weight: 600;
margin: 24px 0 12px 0;
color: #313236;
}
h3 {
margin: 24px 0 12px 0;
font-size: 1.25em;
}
h4 {
margin: 24px 0 12px 0;
font-size: 1.1em;
}
h5 {
margin: 24px 0 12px 0;
font-size: 1em;
}
h6 {
margin: 24px 0 12px 0;
font-size: 0.90em;
}
blockquote {
padding: 8px 21px;
margin: 12px 0 12px;
border-left: 3px solid #e7e9ed;
}
blockquote p {
color: #7f8fa4 !important;
font-size: 15px;
line-height: 1.5;
}
p {
color:#5c5d5e;
margin:6px 0 0 0;
}
table {
@extend .table;
@extend .table-bordered;
margin: 12px 0 12px 0;
color: #5c5d5e;
th {
background: #f8fafc;
}
}
pre {
margin: 12px 0 12px 0 !important;
background-color: #f8fafc !important;
font-size: 13px !important;
color: #5b6169 !important;
line-height: 1.6em !important;
@include border-radius(2px);
}
p > code {
font-weight: inherit;
}
ul {
color: #5c5d5e;
}
li {
line-height: 1.6em;
}
a[href*="/uploads/"], a[href*="storage.googleapis.com/google-code-attachments/"] {
&:before {
margin-right: 4px;
font: normal normal normal 14px/1 FontAwesome;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
content: "\f0c6";
}
&:hover:before {
text-decoration: none;
}
}
}
@mixin str-truncated($max_width: 82%) { @mixin str-truncated($max_width: 82%) {
display: inline-block; display: inline-block;
overflow: hidden; overflow: hidden;
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
margin-right: 0; margin-right: 0;
} }
.issues-filters, .issues-details-filters,
.dash-projects-filters, .dash-projects-filters,
.check-all-holder { .check-all-holder {
display: none; display: none;
...@@ -83,6 +83,7 @@ ...@@ -83,6 +83,7 @@
.center-top-menu { .center-top-menu {
height: 45px; height: 45px;
margin-bottom: 30px;
li a { li a {
font-size: 14px; font-size: 14px;
...@@ -90,9 +91,11 @@ ...@@ -90,9 +91,11 @@
} }
} }
.projects-search-form { .activity-filter-block {
margin: 0 -5px !important; display: none;
}
.projects-search-form {
.btn { .btn {
display: none; display: none;
} }
...@@ -100,6 +103,11 @@ ...@@ -100,6 +103,11 @@
} }
@media (max-width: $screen-sm-max) { @media (max-width: $screen-sm-max) {
.page-with-sidebar .content-wrapper {
padding: 0;
padding-top: 1px;
}
.issues-filters { .issues-filters {
.milestone-filter, .labels-filter { .milestone-filter, .labels-filter {
display: none; display: none;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
font-size: $gl-font-size; font-size: $gl-font-size;
line-height: 1.42857143; line-height: 1.42857143;
@include border-radius(4px); @include border-radius(2px);
.select2-arrow { .select2-arrow {
background: #FFF; background: #FFF;
...@@ -18,8 +18,39 @@ ...@@ -18,8 +18,39 @@
} }
} }
.select2-container .select2-choice, .select2-container.select2-drop-above .select2-choice{
color: #7f8fa4;
border: 1px solid #e7e9ed;
}
.select2-drop {
@include box-shadow(rgba(76, 86, 103, 0.247059) 0px 0px 1px 0px, rgba(31, 37, 50, 0.317647) 0px 2px 18px 0px);
@include border-radius (0px);
padding: 16px;
border: none !important;
}
.select2-results .select2-result-label {
padding: 16px;
}
.select2-drop{
color: #7f8fa4;
}
.select2-highlighted {
background: #3084bb !important;
}
.select2-results li.select2-result-with-children > .select2-result-label {
font-weight: 600;
color: #313236;
}
.select2-container-multi .select2-choices { .select2-container-multi .select2-choices {
@include border-radius(4px); @include border-radius(2px);
border-color: #CCC; border-color: #CCC;
} }
...@@ -63,7 +94,7 @@ ...@@ -63,7 +94,7 @@
.ajax-users-dropdown, .ajax-project-users-dropdown { .ajax-users-dropdown, .ajax-project-users-dropdown {
.select2-search { .select2-search {
padding-top: 4px; padding-top: 2px;
} }
} }
...@@ -97,9 +128,6 @@ ...@@ -97,9 +128,6 @@
} }
.user-name { .user-name {
} }
.user-username {
color: #999;
}
} }
.namespace-result { .namespace-result {
...@@ -114,5 +142,5 @@ ...@@ -114,5 +142,5 @@
} }
.ajax-users-dropdown { .ajax-users-dropdown {
min-width: 225px !important; min-width: 250px !important;
} }
table { table {
&.table { &.table {
.dropdown-menu a {
text-decoration: none;
}
.success,
.warning,
.danger,
.info {
color: #fff;
a:not(.btn) {
text-decoration: underline;
color: #fff;
}
}
tr { tr {
td, th { td, th {
padding: 8px 10px; padding: 8px 10px;
...@@ -12,7 +28,7 @@ table { ...@@ -12,7 +28,7 @@ table {
border-bottom: 1px solid $border-color !important; border-bottom: 1px solid $border-color !important;
} }
td { td {
border-color: #F1F1F1 !important; border-color: $table-border-color !important;
border-bottom: 1px solid; border-bottom: 1px solid;
} }
} }
......
...@@ -10,8 +10,8 @@ ...@@ -10,8 +10,8 @@
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 #f1f2f4; border-bottom: 1px solid #ECEEF1;
border-right: 1px solid #f1f2f4; border-right: 1px solid #ECEEF1;
&:last-child { &:last-child {
border-bottom: none; border-bottom: none;
......
...@@ -32,8 +32,6 @@ ...@@ -32,8 +32,6 @@
@import "bootstrap/pager"; @import "bootstrap/pager";
@import "bootstrap/labels"; @import "bootstrap/labels";
@import "bootstrap/badges"; @import "bootstrap/badges";
@import "bootstrap/jumbotron";
@import "bootstrap/thumbnails";
@import "bootstrap/alerts"; @import "bootstrap/alerts";
@import "bootstrap/progress-bars"; @import "bootstrap/progress-bars";
@import "bootstrap/list-group"; @import "bootstrap/list-group";
...@@ -251,23 +249,3 @@ ...@@ -251,23 +249,3 @@
.text-info:hover { .text-info:hover {
color: $brand-info; color: $brand-info;
} }
// Tables =====================================================================
table.table {
.dropdown-menu a {
text-decoration: none;
}
.success,
.warning,
.danger,
.info {
color: #fff;
a:not(.btn) {
text-decoration: underline;
color: #fff;
}
}
}
...@@ -22,8 +22,8 @@ $brand-info: $gl-info; ...@@ -22,8 +22,8 @@ $brand-info: $gl-info;
$brand-warning: $gl-warning; $brand-warning: $gl-warning;
$brand-danger: $gl-danger; $brand-danger: $gl-danger;
$border-radius-base: 3px !default; $border-radius-base: 2px !default;
$border-radius-large: 5px !default; $border-radius-large: 2px !default;
$border-radius-small: 2px !default; $border-radius-small: 2px !default;
...@@ -156,3 +156,5 @@ $nav-link-padding: 13px $gl-padding; ...@@ -156,3 +156,5 @@ $nav-link-padding: 13px $gl-padding;
$pre-bg: #f8fafc !default; $pre-bg: #f8fafc !default;
$pre-color: $gl-gray !default; $pre-color: $gl-gray !default;
$pre-border-color: #e7e9ed; $pre-border-color: #e7e9ed;
$table-bg-accent: $background-color;
@mixin md-typography {
color: $md-text-color;
a {
color: $md-link-color;
}
img {
max-width: 100%;
}
*:first-child {
margin-top: 0;
}
code {
font-family: $monospace_font;
white-space: pre;
word-wrap: normal;
padding: 1px 2px;
}
kbd {
display: inline-block;
padding: 3px 5px;
font-size: 11px;
line-height: 10px;
color: #555;
vertical-align: middle;
background-color: #FCFCFC;
border-width: 1px;
border-style: solid;
border-color: #CCC #CCC #BBB;
border-image: none;
border-radius: 3px;
box-shadow: 0px -1px 0px #BBB inset;
}
h1 {
font-size: 1.3em;
font-weight: 600;
margin: 24px 0 12px 0;
padding: 0 0 10px 0;
border-bottom: 1px solid #e7e9ed;
color: #313236;
}
h2 {
font-size: 1.2em;
font-weight: 600;
margin: 24px 0 12px 0;
color: #313236;
}
h3 {
margin: 24px 0 12px 0;
font-size: 1.25em;
}
h4 {
margin: 24px 0 12px 0;
font-size: 1.1em;
}
h5 {
margin: 24px 0 12px 0;
font-size: 1em;
}
h6 {
margin: 24px 0 12px 0;
font-size: 0.90em;
}
blockquote {
padding: 8px 21px;
margin: 12px 0 12px;
border-left: 3px solid #e7e9ed;
}
blockquote p {
color: #7f8fa4 !important;
font-size: 15px;
line-height: 1.5;
}
p {
color:#5c5d5e;
margin:6px 0 0 0;
}
table {
@extend .table;
@extend .table-bordered;
margin: 12px 0 12px 0;
color: #5c5d5e;
th {
background: #f8fafc;
}
}
pre {
margin: 12px 0 12px 0 !important;
background-color: #f8fafc !important;
font-size: 13px !important;
color: #5b6169 !important;
line-height: 1.6em !important;
@include border-radius(2px);
}
p > code {
font-weight: inherit;
}
ul {
color: #5c5d5e;
}
li {
line-height: 1.6em;
}
a[href*="/uploads/"], a[href*="storage.googleapis.com/google-code-attachments/"] {
&:before {
margin-right: 4px;
font: normal normal normal 14px/1 FontAwesome;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
content: "\f0c6";
}
&:hover:before {
text-decoration: none;
}
}
}
/** /**
* Headers * Headers
* *
...@@ -6,7 +147,7 @@ body { ...@@ -6,7 +147,7 @@ body {
text-rendering:optimizeLegibility; text-rendering:optimizeLegibility;
-webkit-text-shadow: rgba(255,255,255,0.01) 0 0 1px; -webkit-text-shadow: rgba(255,255,255,0.01) 0 0 1px;
} }
.page-title { .page-title {
margin-top: 0px; margin-top: 0px;
line-height: 1.3; line-height: 1.3;
...@@ -127,4 +268,4 @@ textarea.js-gfm-input { ...@@ -127,4 +268,4 @@ textarea.js-gfm-input {
.strikethrough { .strikethrough {
text-decoration: line-through; text-decoration: line-through;
} }
\ No newline at end of file
...@@ -16,6 +16,7 @@ $avatar_radius: 50%; ...@@ -16,6 +16,7 @@ $avatar_radius: 50%;
$code_font_size: 13px; $code_font_size: 13px;
$code_line_height: 1.5; $code_line_height: 1.5;
$border-color: #dce0e6; $border-color: #dce0e6;
$table-border-color: #eef0f2;
$background-color: #F7F8FA; $background-color: #F7F8FA;
$header-height: 58px; $header-height: 58px;
$fixed-layout-width: 1200px; $fixed-layout-width: 1200px;
...@@ -23,15 +24,67 @@ $gl-gray: #7f8fa4; ...@@ -23,15 +24,67 @@ $gl-gray: #7f8fa4;
$gl-padding: 16px; $gl-padding: 16px;
$gl-avatar-size: 46px; $gl-avatar-size: 46px;
/*
* Color schema
*/
$white-light: #FFFFFF;
$white-normal: #DCE0E5;
$white-dark: #E4E7ED;
$gray-light: #F0F2F5;
$gray-normal: #DCE0E5;
$gray-dark: #E4E7ED;
$green-light: #31AF64;
$green-normal: #2FAA60;
$green-dark: #2CA05B;
$blue-light: #2EA8E5;
$blue-normal: #2D9FD8;
$blue-dark: #2897CE;
$orange-light: #FC6443;
$orange-normal: #E75E40;
$orange-dark: #CE5237;
$red-light: #F43263;
$red-normal: #E52C5A;
$red-dark: #D22852;
$border-white-light: #E3E7EC;
$border-white-normal: #D6DAE2;
$border-white-dark: #C6CACF;
$border-gray-light: #DCE0E5;
$border-gray-normal: #D6DAE2;
$border-gray-dark: #C6CACF;
$border-green-light: #2FAA60;
$border-green-normal: #2CA05B;
$border-green-dark: #279654;
$border-blue-light: #2D9FD8;
$border-blue-normal: #2897CE;
$border-blue-dark: #258DC1;
$border-orange-light: #ED5C3D;
$border-orange-normal: #CE5237;
$border-orange-dark: #C14E35;
$border-red-light: #E52C5A;
$border-red-normal: #D22852;
$border-red-dark: #CA264F;
/* /*
* State colors: * State colors:
*/ */
$gl-primary: #446e9b; $gl-primary: $blue-normal;
$gl-success: #44c679; $gl-success: $green-normal;
$gl-info: #00aaff; $gl-info: $blue-normal;
$gl-warning: #EB9532; $gl-warning: $orange-normal;
$gl-danger: #d9534f; $gl-danger: $red-normal;
/* /*
* Commit Diff Colors * Commit Diff Colors
......
...@@ -73,4 +73,3 @@ ...@@ -73,4 +73,3 @@
margin-bottom: 2px; margin-bottom: 2px;
} }
} }
.commits-compare-switch{ .commits-compare-switch{
@extend .btn; @include btn-default;
@include btn-white;
background: image-url("switch_icon.png") no-repeat center center; background: image-url("switch_icon.png") no-repeat center center;
text-indent: -9999px; text-indent: -9999px;
float: left; float: left;
......
// Common
.diff-file { .diff-file {
margin-left: -$gl-padding; margin-left: -$gl-padding;
margin-right: -$gl-padding; margin-right: -$gl-padding;
...@@ -12,24 +13,17 @@ ...@@ -12,24 +13,17 @@
color: #555; color: #555;
z-index: 10; z-index: 10;
> span { .diff-title {
font-family: $monospace_font; font-family: $monospace_font;
word-break: break-all; word-break: break-all;
margin-right: 200px;
display: block; display: block;
.file-mode { .file-mode {
margin-left: 10px;
color: #777; color: #777;
} }
} }
.diff-btn-group { .diff-controls {
float: right;
position: absolute;
top: 5px;
right: 15px;
.btn { .btn {
padding: 0px 10px; padding: 0px 10px;
font-size: 13px; font-size: 13px;
...@@ -90,12 +84,12 @@ ...@@ -90,12 +84,12 @@
} }
} }
tr.line_holder.parallel{ tr.line_holder.parallel {
.old_line, .new_line, .diff_line { .old_line, .new_line, .diff_line {
min-width: 50px; min-width: 50px;
} }
td.line_content.parallel{ td.line_content.parallel {
width: 50%; width: 50%;
} }
} }
...@@ -105,7 +99,7 @@ ...@@ -105,7 +99,7 @@
padding: 0px; padding: 0px;
border: none; border: none;
background: $background-color; background: $background-color;
color: rgba(0,0,0,0.3); color: rgba(0, 0, 0, 0.3);
padding: 0px 5px; padding: 0px 5px;
border-right: 1px solid $border-color; border-right: 1px solid $border-color;
text-align: right; text-align: right;
...@@ -117,7 +111,7 @@ ...@@ -117,7 +111,7 @@
float: left; float: left;
width: 35px; width: 35px;
font-weight: normal; font-weight: normal;
color: rgba(0,0,0,0.3); color: rgba(0, 0, 0, 0.3);
&:hover { &:hover {
text-decoration: underline; text-decoration: underline;
} }
...@@ -168,7 +162,7 @@ ...@@ -168,7 +162,7 @@
background: #ddd; background: #ddd;
text-align: center; text-align: center;
padding: 30px; padding: 30px;
.wrap{ .wrap {
display: inline-block; display: inline-block;
} }
...@@ -176,7 +170,7 @@ ...@@ -176,7 +170,7 @@
display: inline-block; display: inline-block;
background-color: #fff; background-color: #fff;
line-height: 0; line-height: 0;
img{ img {
border: 1px solid #FFF; border: 1px solid #FFF;
background: image-url('trans_bg.gif'); background: image-url('trans_bg.gif');
max-width: 100%; max-width: 100%;
...@@ -189,21 +183,21 @@ ...@@ -189,21 +183,21 @@
border: 1px solid $added; border: 1px solid $added;
} }
} }
.image-info{ .image-info {
font-size: 12px; font-size: 12px;
margin: 5px 0 0 0; margin: 5px 0 0 0;
color: grey; color: grey;
} }
.view.swipe{ .view.swipe {
position: relative; position: relative;
.swipe-frame{ .swipe-frame {
display: block; display: block;
margin: auto; margin: auto;
position: relative; position: relative;
} }
.swipe-wrap{ .swipe-wrap {
overflow: hidden; overflow: hidden;
border-left: 1px solid #999; border-left: 1px solid #999;
position: absolute; position: absolute;
...@@ -211,33 +205,33 @@ ...@@ -211,33 +205,33 @@
top: 13px; top: 13px;
right: 7px; right: 7px;
} }
.frame{ .frame {
top: 0; top: 0;
right: 0; right: 0;
position: absolute; position: absolute;
&.deleted{ &.deleted {
margin: 0; margin: 0;
display: block; display: block;
top: 13px; top: 13px;
right: 7px; right: 7px;
} }
} }
.swipe-bar{ .swipe-bar {
display: block; display: block;
height: 100%; height: 100%;
width: 15px; width: 15px;
z-index: 100; z-index: 100;
position: absolute; position: absolute;
cursor: pointer; cursor: pointer;
&:hover{ &:hover {
.top-handle{ .top-handle {
background-position: -15px 3px; background-position: -15px 3px;
} }
.bottom-handle{ .bottom-handle {
background-position: -15px -11px; background-position: -15px -11px;
} }
}; }
.top-handle{ .top-handle {
display: block; display: block;
height: 14px; height: 14px;
width: 15px; width: 15px;
...@@ -245,7 +239,7 @@ ...@@ -245,7 +239,7 @@
top: 0px; top: 0px;
background: image-url('swipemode_sprites.gif') 0 3px no-repeat; background: image-url('swipemode_sprites.gif') 0 3px no-repeat;
} }
.bottom-handle{ .bottom-handle {
display: block; display: block;
height: 14px; height: 14px;
width: 15px; width: 15px;
...@@ -254,9 +248,10 @@ ...@@ -254,9 +248,10 @@
background: image-url('swipemode_sprites.gif') 0 -11px no-repeat; background: image-url('swipemode_sprites.gif') 0 -11px no-repeat;
} }
} }
} //.view.swipe }
.view.onion-skin{ //.view.swipe
.onion-skin-frame{ .view.onion-skin {
.onion-skin-frame {
display: block; display: block;
margin: auto; margin: auto;
position: relative; position: relative;
...@@ -267,7 +262,7 @@ ...@@ -267,7 +262,7 @@
top: 0px; top: 0px;
left: 0px; left: 0px;
} }
.controls{ .controls {
display: block; display: block;
height: 14px; height: 14px;
width: 300px; width: 300px;
...@@ -277,7 +272,7 @@ ...@@ -277,7 +272,7 @@
left: 50%; left: 50%;
margin-left: -150px; margin-left: -150px;
.drag-track{ .drag-track {
display: block; display: block;
position: absolute; position: absolute;
left: 12px; left: 12px;
...@@ -317,39 +312,40 @@ ...@@ -317,39 +312,40 @@
background: image-url('onion_skin_sprites.gif') -2px -10px no-repeat; background: image-url('onion_skin_sprites.gif') -2px -10px no-repeat;
} }
} }
} //.view.onion-skin }
//.view.onion-skin
} }
.view-modes{ .view-modes {
padding: 10px; padding: 10px;
text-align: center; text-align: center;
background: #EEE; background: #EEE;
ul, li{ ul, li {
list-style: none; list-style: none;
margin: 0; margin: 0;
padding: 0; padding: 0;
display: inline-block; display: inline-block;
} }
li{ li {
color: grey; color: grey;
border-left: 1px solid #c1c1c1; border-left: 1px solid #c1c1c1;
padding: 0 12px 0 16px; padding: 0 12px 0 16px;
cursor: pointer; cursor: pointer;
&:first-child{ &:first-child {
border-left: none; border-left: none;
} }
&:hover{ &:hover {
text-decoration: underline; text-decoration: underline;
} }
&.active{ &.active {
&:hover{ &:hover {
text-decoration: none; text-decoration: none;
} }
cursor: default; cursor: default;
color: #333; color: #333;
} }
&.disabled{ &.disabled {
display: none; display: none;
} }
} }
...@@ -373,3 +369,37 @@ ...@@ -373,3 +369,37 @@
float: right; float: right;
margin-top: -5px; margin-top: -5px;
} }
// Mobile
@media (max-width: 480px) {
.diff-title {
margin: 0;
.file-mode {
display: none;
}
}
.diff-controls {
position: static;
text-align: center;
}
}
// Bigger screens
@media (min-width: 481px) {
.diff-title {
margin-right: 200px;
.file-mode {
margin-left: 10px;
}
}
.diff-controls {
float: right;
position: absolute;
top: 5px;
right: 15px;
}
}
...@@ -54,21 +54,22 @@ ...@@ -54,21 +54,22 @@
margin-top: -15px; margin-top: -15px;
padding: 10px 0; padding: 10px 0;
margin-bottom: 0; margin-bottom: 0;
color: $gl-gray; color: #5c5d5e;
font-size: 16px; font-size: 16px;
.author { .author {
color: $gl-gray; color: #5c5d5e;
} }
.issue-id { .issue-id {
font-size: 19px; color: #5c5d5e;
color: $gl-text-color;
} }
} }
.issue-title { .issue-title {
margin: 0; margin: 0;
font-size: 23px;
color: #313236;
} }
.description { .description {
......
...@@ -3,12 +3,11 @@ ...@@ -3,12 +3,11 @@
* *
*/ */
.mr-state-widget { .mr-state-widget {
background: #f8fafc; background: #F7F8FA;
margin-bottom: 20px; margin-bottom: 20px;
color: $gl-gray; color: $gl-gray;
border: 1px solid #eef0f2; border: 1px solid #dce0e6;
@include box-shadow(0 1px 1px rgba(0, 0, 0, 0.05)); @include border-radius(2px);
@include border-radius(3px);
form { form {
margin-bottom: 0; margin-bottom: 0;
...@@ -77,10 +76,16 @@ ...@@ -77,10 +76,16 @@
padding: 15px; padding: 15px;
} }
.normal {
color: #5c5d5e;
}
.mr-widget-body { .mr-widget-body {
h4 { h4 {
font-weight: bold; font-weight: 600;
font-size: 17px;
margin: 5px 0; margin: 5px 0;
color: #313236;
} }
p:last-child { p:last-child {
...@@ -97,14 +102,26 @@ ...@@ -97,14 +102,26 @@
} }
} }
.merge-request .merge-request-tabs{ .merge-request .merge-request-tabs {
@include nav-menu; @include nav-menu;
margin: -$gl-padding; margin: -$gl-padding;
padding: $gl-padding; padding: $gl-padding;
text-align: center; text-align: center;
border-top: 1px solid #e7e9ed; margin-bottom: 1px;
margin-top: 18px; }
margin-bottom: 3px;
// Mobile
@media (max-width: 480px) {
.merge-request .merge-request-tabs {
margin: 0;
padding: 0;
li {
a {
padding: 0;
}
}
}
} }
.mr_source_commit, .mr_source_commit,
...@@ -120,10 +137,12 @@ ...@@ -120,10 +137,12 @@
} }
.label-branch { .label-branch {
color: #222; color: #313236;
font-family: $monospace_font; font-family: $monospace_font;
font-weight: bold; font-weight: bold;
overflow: hidden; overflow: hidden;
font-size: 14px;
margin: 0 3px;
} }
.mr-list { .mr-list {
......
...@@ -65,19 +65,18 @@ ...@@ -65,19 +65,18 @@
.note-image-attach { .note-image-attach {
@extend .col-md-4; @extend .col-md-4;
@extend .thumbnail;
margin-left: 45px; margin-left: 45px;
float: none; float: none;
} }
.common-note-form { .common-note-form {
margin: 0; margin: 0;
background: #f8fafc; background: #F7F8FA;
padding: $gl-padding; padding: $gl-padding;
margin-left: -$gl-padding; margin-left: -$gl-padding;
margin-right: -$gl-padding; margin-right: -$gl-padding;
border-right: 1px solid #f1f2f4; border-right: 1px solid #ECEEF1;
border-top: 1px solid #f1f2f4; border-top: 1px solid #ECEEF1;
margin-bottom: -$gl-padding; margin-bottom: -$gl-padding;
} }
...@@ -168,7 +167,7 @@ ...@@ -168,7 +167,7 @@
.comment-hints { .comment-hints {
color: #999; color: #999;
background: #FFF; background: #FFF;
padding: 5px; padding: 7px;
margin-top: -11px; margin-top: -11px;
border: 1px solid $border-color; border: 1px solid $border-color;
font-size: 13px; font-size: 13px;
......
...@@ -18,7 +18,7 @@ ul.notes { ...@@ -18,7 +18,7 @@ ul.notes {
font-size: 14px; font-size: 14px;
padding-top: 10px; padding-top: 10px;
padding-bottom: 10px; padding-bottom: 10px;
background: #f8fafc; background: #FDFDFD;
.timeline-icon { .timeline-icon {
.avatar { .avatar {
......
...@@ -13,11 +13,15 @@ ...@@ -13,11 +13,15 @@
.edit_project { .edit_project {
fieldset.features { fieldset.features {
.control-label { .control-label {
font-weight: bold; font-weight: normal;
} }
} }
} }
.project-edit-content {
padding: 7px;
}
.project-name-holder { .project-name-holder {
.help-inline { .help-inline {
vertical-align: top; vertical-align: top;
...@@ -59,6 +63,7 @@ ...@@ -59,6 +63,7 @@
} }
p { p {
padding: 0 $gl-padding;
color: #5c5d5e; color: #5c5d5e;
} }
} }
...@@ -92,8 +97,7 @@ ...@@ -92,8 +97,7 @@
margin-bottom: 0px; margin-bottom: 0px;
.btn { .btn {
@include bnt-project; @include btn-gray;
@include btn-info;
.count { .count {
display: inline-block; display: inline-block;
...@@ -149,7 +153,7 @@ ...@@ -149,7 +153,7 @@
.input-group-btn { .input-group-btn {
.btn { .btn {
@include bnt-project; @include btn-gray;
@include btn-middle; @include btn-middle;
&:hover { &:hover {
...@@ -183,8 +187,8 @@ ...@@ -183,8 +187,8 @@
margin: 0 12px 0 12px; margin: 0 12px 0 12px;
.btn{ .btn{
@include bnt-project; @include btn-gray;
@include btn-info; @include btn-default;
} }
.dropdown-toggle { .dropdown-toggle {
...@@ -251,18 +255,19 @@ ...@@ -251,18 +255,19 @@
margin-bottom: 10px; margin-bottom: 10px;
i { i {
margin: 0 3px; margin: 2px 0;
font-size: 20px; font-size: 20px;
} }
.option-title { .option-title {
font-weight: bold; font-weight: normal;
display: inline-block; display: inline-block;
color: #313236;
} }
.option-descr { .option-descr {
margin-left: 36px; margin-left: 29px;
color: $gray; color: #54565b;
} }
} }
} }
...@@ -376,8 +381,8 @@ table.table.protected-branches-list tr.no-border { ...@@ -376,8 +381,8 @@ table.table.protected-branches-list tr.no-border {
} }
.nav > li > a { .nav > li > a {
@include btn-info; @include btn-default;
@include bnt-project; @include btn-gray;
background-color: transparent; background-color: transparent;
border: 1px solid #f7f8fa; border: 1px solid #f7f8fa;
...@@ -437,7 +442,7 @@ pre.light-well { ...@@ -437,7 +442,7 @@ pre.light-well {
.btn-remove { .btn-remove {
@include btn-middle; @include btn-middle;
@include btn-remove; @include btn-red;
float: left !important; float: left !important;
} }
...@@ -506,8 +511,3 @@ pre.light-well { ...@@ -506,8 +511,3 @@ pre.light-well {
margin-top: -1px; margin-top: -1px;
} }
} }
.inline-form {
display: inline-block;
}
.tree-holder { .tree-holder {
.tree-content-holder { .tree-table-holder {
float: left; margin-left: -$gl-padding;
width: 100%; margin-right: -$gl-padding;
} }
.tree_progress { .tree_progress {
...@@ -13,10 +13,15 @@ ...@@ -13,10 +13,15 @@
} }
.tree-table { .tree-table {
@extend .table; margin-bottom: 0;
@include border-radius(0);
tr { tr {
> td, > th {
padding: 10px $gl-padding;
line-height: 32px;
border-color: $table-border-color !important;
}
&:hover { &:hover {
td { td {
background: $hover; background: $hover;
...@@ -27,9 +32,9 @@ ...@@ -27,9 +32,9 @@
} }
&.selected { &.selected {
td { td {
background: $background-color; background: $gray-dark;
border-top: 1px solid #EEE; border-top: 1px solid $border-gray-dark;
border-bottom: 1px solid #EEE; border-bottom: 1px solid $border-gray-dark;
} }
} }
} }
...@@ -85,19 +90,6 @@ ...@@ -85,19 +90,6 @@
margin-right: 15px; margin-right: 15px;
} }
.readme-holder {
margin: 0 auto;
.readme-file-title {
font-size: 14px;
font-weight: bold;
margin-bottom: 20px;
color: #777;
border-bottom: 1px solid #DDD;
padding: 10px 0;
}
}
.blob-commit-info { .blob-commit-info {
list-style: none; list-style: none;
margin: 0; margin: 0;
......
.ci-body { .build-page {
// color codes are based on http://en.wikipedia.org/wiki/File:Xterm_256color_chart.svg // color codes are based on http://en.wikipedia.org/wiki/File:Xterm_256color_chart.svg
// see also: https://gist.github.com/jasonm23/2868981 // see also: https://gist.github.com/jasonm23/2868981
......
...@@ -30,7 +30,7 @@ class ApplicationController < ActionController::Base ...@@ -30,7 +30,7 @@ class ApplicationController < ActionController::Base
rescue_from ActiveRecord::RecordNotFound do |exception| rescue_from ActiveRecord::RecordNotFound do |exception|
log_exception(exception) log_exception(exception)
render "errors/not_found", layout: "errors", status: 404 render_404
end end
protected protected
...@@ -149,10 +149,6 @@ class ApplicationController < ActionController::Base ...@@ -149,10 +149,6 @@ class ApplicationController < ActionController::Base
render "errors/access_denied", layout: "errors", status: 404 render "errors/access_denied", layout: "errors", status: 404
end end
def not_found!
render "errors/not_found", layout: "errors", status: 404
end
def git_not_found! def git_not_found!
render "errors/git_not_found", layout: "errors", status: 404 render "errors/git_not_found", layout: "errors", status: 404
end end
......
module Ci
class BuildsController < Ci::ApplicationController
before_action :authenticate_user!, except: [:status]
before_action :project
before_action :authorize_access_project!, except: [:status]
before_action :authorize_manage_project!, except: [:status, :retry, :cancel]
before_action :authorize_manage_builds!, only: [:retry, :cancel]
before_action :build
def retry
if @build.commands.blank?
return page_404
end
build = Ci::Build.retry(@build)
if params[:return_to]
redirect_to URI.parse(params[:return_to]).path
else
redirect_to build_path(build)
end
end
def status
render json: @build.to_json(only: [:status, :id, :sha, :coverage], methods: :sha)
end
def cancel
@build.cancel
redirect_to build_path(@build)
end
protected
def project
@project = Ci::Project.find(params[:project_id])
end
def build
@build ||= project.builds.unscoped.find_by!(id: params[:id])
end
def commit_by_sha
@project.commits.find_by(sha: params[:id])
end
def build_path(build)
namespace_project_build_path(build.gl_project.namespace, build.gl_project, build)
end
end
end
module Ci
class CommitsController < Ci::ApplicationController
before_action :authenticate_user!, except: [:status, :show]
before_action :authenticate_public_page!, only: :show
before_action :project
before_action :authorize_access_project!, except: [:status, :show, :cancel]
before_action :authorize_manage_builds!, only: [:cancel]
def status
commit = Ci::Project.find(params[:project_id]).commits.find_by_sha!(params[:id])
render json: commit.to_json(only: [:id, :sha], methods: [:status, :coverage])
rescue ActiveRecord::RecordNotFound
render json: { status: "not_found" }
end
def cancel
commit.builds.running_or_pending.each(&:cancel)
redirect_to namespace_project_commit_path(commit.gl_project.namespace, commit.gl_project, commit.sha)
end
private
def project
@project ||= Ci::Project.find(params[:project_id])
end
def commit
@commit ||= Ci::Project.find(params[:project_id]).commits.find_by_sha!(params[:id])
end
end
end
module Ci module Ci
class ProjectsController < Ci::ApplicationController class ProjectsController < Ci::ApplicationController
before_action :authenticate_user!, except: [:build, :badge, :show] before_action :project
before_action :authenticate_public_page!, only: :show before_action :authenticate_user!, except: [:build, :badge]
before_action :project, only: [:build, :show, :badge, :toggle_shared_runners, :dumped_yaml] before_action :authorize_access_project!, except: [:badge]
before_action :authorize_access_project!, except: [:build, :badge, :show, :new]
before_action :authorize_manage_project!, only: [:toggle_shared_runners, :dumped_yaml] before_action :authorize_manage_project!, only: [:toggle_shared_runners, :dumped_yaml]
before_action :authenticate_token!, only: [:build]
before_action :no_cache, only: [:badge] before_action :no_cache, only: [:badge]
protect_from_forgery except: :build protect_from_forgery
layout 'ci/project', except: [:index]
def show
@ref = params[:ref]
@commits = @project.commits.reverse_order
if @ref
# unscope is required, because of default_scope defined in Ci::Build
builds = @project.builds.unscope(:select, :order).where(ref: @ref).select(:commit_id).distinct
@commits = @commits.where(id: builds)
end
@commits = @commits.page(params[:page]).per(20)
end
# Project status badge # Project status badge
# Image with build status for sha or ref # Image with build status for sha or ref
......
module Ci
class ServicesController < Ci::ApplicationController
before_action :authenticate_user!
before_action :project
before_action :authorize_access_project!
before_action :authorize_manage_project!
before_action :service, only: [:edit, :update, :test]
respond_to :html
layout 'ci/project'
def index
@project.build_missing_services
@services = @project.services.reload
end
def edit
end
def update
if @service.update_attributes(service_params)
redirect_to edit_ci_project_service_path(@project, @service.to_param)
else
render 'edit'
end
end
def test
last_build = @project.builds.last
if @service.execute(last_build)
message = { notice: 'We successfully tested the service' }
else
message = { alert: 'We tried to test the service but error occurred' }
end
redirect_to :back, message
end
private
def project
@project = Ci::Project.find(params[:project_id])
end
def service
@service ||= @project.services.find { |service| service.to_param == params[:id] }
end
def service_params
params.require(:service).permit(
:type, :active, :webhook, :notify_only_broken_builds,
:email_recipients, :email_only_broken_builds, :email_add_pusher,
:hipchat_token, :hipchat_room, :hipchat_server
)
end
end
end
...@@ -88,7 +88,7 @@ class GroupsController < Groups::ApplicationController ...@@ -88,7 +88,7 @@ class GroupsController < Groups::ApplicationController
def destroy def destroy
DestroyGroupService.new(@group, current_user).execute DestroyGroupService.new(@group, current_user).execute
redirect_to root_path, alert: "Group '#{@group.name} was deleted." redirect_to root_path, alert: "Group '#{@group.name}' was successfully deleted."
end end
protected protected
......
...@@ -62,7 +62,7 @@ class Import::BitbucketController < Import::BaseController ...@@ -62,7 +62,7 @@ class Import::BitbucketController < Import::BaseController
end end
def verify_bitbucket_import_enabled def verify_bitbucket_import_enabled
not_found! unless bitbucket_import_enabled? render_404 unless bitbucket_import_enabled?
end end
def bitbucket_auth def bitbucket_auth
......
...@@ -99,6 +99,6 @@ class Import::FogbugzController < Import::BaseController ...@@ -99,6 +99,6 @@ class Import::FogbugzController < Import::BaseController
end end
def verify_fogbugz_import_enabled def verify_fogbugz_import_enabled
not_found! unless fogbugz_import_enabled? render_404 unless fogbugz_import_enabled?
end end
end end
...@@ -47,7 +47,7 @@ class Import::GithubController < Import::BaseController ...@@ -47,7 +47,7 @@ class Import::GithubController < Import::BaseController
end end
def verify_github_import_enabled def verify_github_import_enabled
not_found! unless github_import_enabled? render_404 unless github_import_enabled?
end end
def github_auth def github_auth
......
...@@ -44,7 +44,7 @@ class Import::GitlabController < Import::BaseController ...@@ -44,7 +44,7 @@ class Import::GitlabController < Import::BaseController
end end
def verify_gitlab_import_enabled def verify_gitlab_import_enabled
not_found! unless gitlab_import_enabled? render_404 unless gitlab_import_enabled?
end end
def gitlab_auth def gitlab_auth
......
...@@ -42,7 +42,7 @@ class Import::GitoriousController < Import::BaseController ...@@ -42,7 +42,7 @@ class Import::GitoriousController < Import::BaseController
end end
def verify_gitorious_import_enabled def verify_gitorious_import_enabled
not_found! unless gitorious_import_enabled? render_404 unless gitorious_import_enabled?
end end
end end
...@@ -106,7 +106,7 @@ class Import::GoogleCodeController < Import::BaseController ...@@ -106,7 +106,7 @@ class Import::GoogleCodeController < Import::BaseController
end end
def verify_google_code_import_enabled def verify_google_code_import_enabled
not_found! unless google_code_import_enabled? render_404 unless google_code_import_enabled?
end end
def user_map def user_map
......
...@@ -12,7 +12,7 @@ class Projects::AvatarsController < Projects::ApplicationController ...@@ -12,7 +12,7 @@ class Projects::AvatarsController < Projects::ApplicationController
filename: @blob.name filename: @blob.name
) )
else else
not_found! render_404
end end
end end
......
...@@ -8,7 +8,7 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -8,7 +8,7 @@ class Projects::BlobController < Projects::ApplicationController
before_action :require_non_empty_project, except: [:new, :create] before_action :require_non_empty_project, except: [:new, :create]
before_action :authorize_download_code! before_action :authorize_download_code!
before_action :authorize_push_code!, only: [:destroy] before_action :authorize_push_code!, only: [:destroy, :create]
before_action :assign_blob_vars before_action :assign_blob_vars
before_action :commit, except: [:new, :create] before_action :commit, except: [:new, :create]
before_action :blob, except: [:new, :create] before_action :blob, except: [:new, :create]
...@@ -25,7 +25,7 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -25,7 +25,7 @@ class Projects::BlobController < Projects::ApplicationController
result = Files::CreateService.new(@project, current_user, @commit_params).execute result = Files::CreateService.new(@project, current_user, @commit_params).execute
if result[:status] == :success if result[:status] == :success
flash[:notice] = "Your changes have been successfully committed" flash[:notice] = "The changes have been successfully committed"
respond_to do |format| respond_to do |format|
format.html { redirect_to namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @file_path)) } format.html { redirect_to namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @file_path)) }
format.json { render json: { message: "success", filePath: namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @file_path)) } } format.json { render json: { message: "success", filePath: namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @file_path)) } }
...@@ -34,7 +34,7 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -34,7 +34,7 @@ class Projects::BlobController < Projects::ApplicationController
flash[:alert] = result[:message] flash[:alert] = result[:message]
respond_to do |format| respond_to do |format|
format.html { render :new } format.html { render :new }
format.json { render json: { message: "failed", filePath: namespace_project_new_blob_path(@project.namespace, @project, @id) } } format.json { render json: { message: "failed", filePath: namespace_project_blob_path(@project.namespace, @project, @id) } }
end end
end end
end end
...@@ -113,14 +113,14 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -113,14 +113,14 @@ class Projects::BlobController < Projects::ApplicationController
end end
end end
return not_found! return render_404
end end
end end
def commit def commit
@commit = @repository.commit(@ref) @commit = @repository.commit(@ref)
return not_found! unless @commit return render_404 unless @commit
end end
def assign_blob_vars def assign_blob_vars
...@@ -128,7 +128,7 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -128,7 +128,7 @@ class Projects::BlobController < Projects::ApplicationController
@ref, @path = extract_ref(@id) @ref, @path = extract_ref(@id)
rescue InvalidPathError rescue InvalidPathError
not_found! render_404
end end
def after_edit_path def after_edit_path
...@@ -154,7 +154,7 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -154,7 +154,7 @@ class Projects::BlobController < Projects::ApplicationController
def editor_variables def editor_variables
@current_branch = @ref @current_branch = @ref
@target_branch = (sanitized_new_branch_name || @ref) @target_branch = params[:new_branch].present? ? sanitized_new_branch_name : @ref
@file_path = @file_path =
if action_name.to_s == 'create' if action_name.to_s == 'create'
......
...@@ -2,6 +2,8 @@ class Projects::BuildsController < Projects::ApplicationController ...@@ -2,6 +2,8 @@ class Projects::BuildsController < Projects::ApplicationController
before_action :ci_project before_action :ci_project
before_action :build before_action :build
before_action :authorize_admin_project!, except: [:show, :status]
layout "project" layout "project"
def show def show
...@@ -17,9 +19,37 @@ class Projects::BuildsController < Projects::ApplicationController ...@@ -17,9 +19,37 @@ class Projects::BuildsController < Projects::ApplicationController
end end
end end
def retry
if @build.commands.blank?
return page_404
end
build = Ci::Build.retry(@build)
if params[:return_to]
redirect_to URI.parse(params[:return_to]).path
else
redirect_to build_path(build)
end
end
def status
render json: @build.to_json(only: [:status, :id, :sha, :coverage], methods: :sha)
end
def cancel
@build.cancel
redirect_to build_path(@build)
end
private private
def build def build
@build ||= ci_project.builds.unscoped.find_by!(id: params[:id]) @build ||= ci_project.builds.unscoped.find_by!(id: params[:id])
end end
def build_path(build)
namespace_project_build_path(build.gl_project.namespace, build.gl_project, build)
end
end end
class Projects::CiServicesController < Projects::ApplicationController
before_action :ci_project
before_action :authorize_admin_project!
layout "project_settings"
def index
@ci_project.build_missing_services
@services = @ci_project.services.reload
end
def edit
service
end
def update
if @service.update_attributes(service_params)
redirect_to edit_namespace_project_ci_service_path(@project, @project.namespace, @service.to_param)
else
render 'edit'
end
end
def test
last_build = @project.builds.last
if @service.execute(last_build)
message = { notice: 'We successfully tested the service' }
else
message = { alert: 'We tried to test the service but error occurred' }
end
redirect_to :back, message
end
private
def service
@service ||= @ci_project.services.find { |service| service.to_param == params[:id] }
end
def service_params
params.require(:service).permit(
:type, :active, :webhook, :notify_only_broken_builds,
:email_recipients, :email_only_broken_builds, :email_add_pusher,
:hipchat_token, :hipchat_room, :hipchat_server
)
end
end
...@@ -38,6 +38,14 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -38,6 +38,14 @@ class Projects::CommitController < Projects::ApplicationController
@ci_project = @project.gitlab_ci_project @ci_project = @project.gitlab_ci_project
end end
def cancel_builds
@ci_commit = @project.ci_commit(@commit.sha)
@ci_commit.builds.running_or_pending.each(&:cancel)
redirect_to ci_namespace_project_commit_path(project.namespace, project, commit.sha)
end
def branches def branches
@branches = @project.repository.branch_names_contains(commit.id) @branches = @project.repository.branch_names_contains(commit.id)
@tags = @project.repository.tag_names_contains(commit.id) @tags = @project.repository.tag_names_contains(commit.id)
......
...@@ -20,7 +20,7 @@ class Projects::RawController < Projects::ApplicationController ...@@ -20,7 +20,7 @@ class Projects::RawController < Projects::ApplicationController
disposition: 'inline' disposition: 'inline'
) )
else else
not_found! render_404
end end
end end
......
# Controller for viewing a repository's file structure # Controller for viewing a repository's file structure
class Projects::TreeController < Projects::ApplicationController class Projects::TreeController < Projects::ApplicationController
include ExtractsPath include ExtractsPath
include ActionView::Helpers::SanitizeHelper
before_action :require_non_empty_project, except: [:new, :create] before_action :require_non_empty_project, except: [:new, :create]
before_action :assign_ref_vars before_action :assign_ref_vars
before_action :assign_dir_vars, only: [:create_dir]
before_action :authorize_download_code! before_action :authorize_download_code!
before_action :authorize_push_code!, only: [:create_dir]
def show def show
return not_found! unless @repository.commit(@ref) return render_404 unless @repository.commit(@ref)
if tree.entries.empty? if tree.entries.empty?
if @repository.blob_at(@commit.id, @path) if @repository.blob_at(@commit.id, @path)
...@@ -16,7 +19,7 @@ class Projects::TreeController < Projects::ApplicationController ...@@ -16,7 +19,7 @@ class Projects::TreeController < Projects::ApplicationController
File.join(@ref, @path)) File.join(@ref, @path))
) and return ) and return
elsif @path.present? elsif @path.present?
return not_found! return render_404
end end
end end
...@@ -26,4 +29,38 @@ class Projects::TreeController < Projects::ApplicationController ...@@ -26,4 +29,38 @@ class Projects::TreeController < Projects::ApplicationController
format.js { no_cache_headers } format.js { no_cache_headers }
end end
end end
def create_dir
return render_404 unless @commit_params.values.all?
begin
result = Files::CreateDirService.new(@project, current_user, @commit_params).execute
message = result[:message]
rescue => e
message = e.to_s
end
if result && result[:status] == :success
flash[:notice] = "The directory has been successfully created"
respond_to do |format|
format.html { redirect_to namespace_project_blob_path(@project.namespace, @project, File.join(@new_branch, @dir_name)) }
end
else
flash[:alert] = message
respond_to do |format|
format.html { redirect_to namespace_project_blob_path(@project.namespace, @project, @new_branch) }
end
end
end
def assign_dir_vars
@new_branch = params[:new_branch].present? ? sanitize(strip_tags(params[:new_branch])) : @ref
@dir_name = File.join(@path, params[:dir_name])
@commit_params = {
file_path: @dir_name,
current_branch: @ref,
target_branch: @new_branch,
commit_message: params[:commit_message],
}
end
end end
...@@ -20,7 +20,7 @@ class Projects::UploadsController < Projects::ApplicationController ...@@ -20,7 +20,7 @@ class Projects::UploadsController < Projects::ApplicationController
end end
def show def show
return not_found! if uploader.nil? || !uploader.file.exists? return render_404 if uploader.nil? || !uploader.file.exists?
disposition = uploader.image? ? 'inline' : 'attachment' disposition = uploader.image? ? 'inline' : 'attachment'
send_file uploader.file.path, disposition: disposition send_file uploader.file.path, disposition: disposition
......
...@@ -10,7 +10,7 @@ class UploadsController < ApplicationController ...@@ -10,7 +10,7 @@ class UploadsController < ApplicationController
end end
unless uploader.file && uploader.file.exists? unless uploader.file && uploader.file.exists?
return not_found! return render_404
end end
disposition = uploader.image? ? 'inline' : 'attachment' disposition = uploader.image? ? 'inline' : 'attachment'
...@@ -21,7 +21,7 @@ class UploadsController < ApplicationController ...@@ -21,7 +21,7 @@ class UploadsController < ApplicationController
def find_model def find_model
unless upload_model && upload_mount unless upload_model && upload_mount
return not_found! return render_404
end end
@model = upload_model.find(params[:id]) @model = upload_model.find(params[:id])
...@@ -44,7 +44,7 @@ class UploadsController < ApplicationController ...@@ -44,7 +44,7 @@ class UploadsController < ApplicationController
return if authorized return if authorized
if current_user if current_user
not_found! render_404
else else
authenticate_user! authenticate_user!
end end
......
...@@ -72,11 +72,15 @@ class IssuableFinder ...@@ -72,11 +72,15 @@ class IssuableFinder
params[:milestone_title].present? params[:milestone_title].present?
end end
def no_milestones?
milestones? && params[:milestone_title] == Milestone::None.title
end
def milestones def milestones
return @milestones if defined?(@milestones) return @milestones if defined?(@milestones)
@milestones = @milestones =
if milestones? && params[:milestone_title] != Milestone::None.title if milestones?
Milestone.where(title: params[:milestone_title]) Milestone.where(title: params[:milestone_title])
else else
nil nil
...@@ -183,7 +187,11 @@ class IssuableFinder ...@@ -183,7 +187,11 @@ class IssuableFinder
def by_milestone(items) def by_milestone(items)
if milestones? if milestones?
items = items.where(milestone_id: milestones.try(:pluck, :id)) if no_milestones?
items = items.where(milestone_id: [-1, nil])
else
items = items.where(milestone_id: milestones.try(:pluck, :id))
end
end end
items items
...@@ -207,13 +215,19 @@ class IssuableFinder ...@@ -207,13 +215,19 @@ class IssuableFinder
def by_label(items) def by_label(items)
if params[:label_name].present? if params[:label_name].present?
label_names = params[:label_name].split(",") if params[:label_name] == Label::None.title
item_ids = LabelLink.where(target_type: klass.name).pluck(:target_id)
item_ids = LabelLink.joins(:label). items = items.where('id NOT IN (?)', item_ids)
where('labels.title in (?)', label_names). else
where(target_type: klass.name).pluck(:target_id) label_names = params[:label_name].split(",")
item_ids = LabelLink.joins(:label).
where('labels.title in (?)', label_names).
where(target_type: klass.name).pluck(:target_id)
items = items.where(id: item_ids) items = items.where(id: item_ids)
end
end end
items items
......
class TrendingProjectsFinder class TrendingProjectsFinder
def execute(current_user, start_date = nil) def execute(current_user, start_date = 1.month.ago)
start_date ||= Date.today - 1.month projects_for(current_user).trending(start_date)
projects = projects_for(current_user)
# Determine trending projects based on comments count
# for period of time - ex. month
projects.joins(:notes).where('notes.created_at > ?', start_date).
group("projects.id").reorder("count(notes.id) DESC")
end end
private private
......
...@@ -93,7 +93,10 @@ module LabelsHelper ...@@ -93,7 +93,10 @@ module LabelsHelper
end end
def project_labels_options(project) def project_labels_options(project)
options_from_collection_for_select(project.labels, 'name', 'name', params[:label_name]) labels = project.labels.to_a
labels.unshift(Label::None)
labels.unshift(Label::Any)
options_from_collection_for_select(labels, 'name', 'title', params[:label_name])
end end
# Required for Gitlab::Markdown::LabelReferenceFilter # Required for Gitlab::Markdown::LabelReferenceFilter
......
...@@ -30,7 +30,8 @@ module MilestonesHelper ...@@ -30,7 +30,8 @@ module MilestonesHelper
grouped_milestones = Milestones::GroupService.new(milestones).execute grouped_milestones = Milestones::GroupService.new(milestones).execute
grouped_milestones.unshift(Milestone::None) grouped_milestones.unshift(Milestone::None)
grouped_milestones.unshift(Milestone::Any)
options_from_collection_for_select(grouped_milestones, 'title', 'title', params[:milestone_title]) options_from_collection_for_select(grouped_milestones, 'name', 'title', params[:milestone_title])
end end
end end
...@@ -135,6 +135,8 @@ class Ability ...@@ -135,6 +135,8 @@ class Ability
def project_report_rules def project_report_rules
project_guest_rules + [ project_guest_rules + [
:create_commit_status,
:read_commit_statuses,
:download_code, :download_code,
:fork_project, :fork_project,
:create_project_snippet, :create_project_snippet,
......
...@@ -24,32 +24,19 @@ ...@@ -24,32 +24,19 @@
# #
module Ci module Ci
class Build < ActiveRecord::Base class Build < CommitStatus
extend Ci::Model
LAZY_ATTRIBUTES = ['trace'] LAZY_ATTRIBUTES = ['trace']
belongs_to :commit, class_name: 'Ci::Commit'
belongs_to :runner, class_name: 'Ci::Runner' belongs_to :runner, class_name: 'Ci::Runner'
belongs_to :trigger_request, class_name: 'Ci::TriggerRequest' belongs_to :trigger_request, class_name: 'Ci::TriggerRequest'
belongs_to :user
serialize :options serialize :options
validates :commit, presence: true
validates :status, presence: true
validates :coverage, numericality: true, allow_blank: true validates :coverage, numericality: true, allow_blank: true
validates_presence_of :ref validates_presence_of :ref
scope :running, ->() { where(status: "running") }
scope :pending, ->() { where(status: "pending") }
scope :success, ->() { where(status: "success") }
scope :failed, ->() { where(status: "failed") }
scope :unstarted, ->() { where(runner_id: nil) } scope :unstarted, ->() { where(runner_id: nil) }
scope :running_or_pending, ->() { where(status:[:running, :pending]) }
scope :latest, ->() { where(id: unscope(:select).select('max(id)').group(:name, :ref)).order(stage_idx: :asc) }
scope :ignore_failures, ->() { where(allow_failure: false) } scope :ignore_failures, ->() { where(allow_failure: false) }
scope :for_ref, ->(ref) { where(ref: ref) }
scope :similar, ->(build) { where(ref: build.ref, tag: build.tag, trigger_request_id: build.trigger_request_id) } scope :similar, ->(build) { where(ref: build.ref, tag: build.tag, trigger_request_id: build.trigger_request_id) }
acts_as_taggable acts_as_taggable
...@@ -74,13 +61,14 @@ module Ci ...@@ -74,13 +61,14 @@ module Ci
def create_from(build) def create_from(build)
new_build = build.dup new_build = build.dup
new_build.status = :pending new_build.status = 'pending'
new_build.runner_id = nil new_build.runner_id = nil
new_build.trigger_request_id = nil
new_build.save new_build.save
end end
def retry(build) def retry(build)
new_build = Ci::Build.new(status: :pending) new_build = Ci::Build.new(status: 'pending')
new_build.ref = build.ref new_build.ref = build.ref
new_build.tag = build.tag new_build.tag = build.tag
new_build.options = build.options new_build.options = build.options
...@@ -98,28 +86,7 @@ module Ci ...@@ -98,28 +86,7 @@ module Ci
end end
state_machine :status, initial: :pending do state_machine :status, initial: :pending do
event :run do
transition pending: :running
end
event :drop do
transition running: :failed
end
event :success do
transition running: :success
end
event :cancel do
transition [:pending, :running] => :canceled
end
after_transition pending: :running do |build, transition|
build.update_attributes started_at: Time.now
end
after_transition any => [:success, :failed, :canceled] do |build, transition| after_transition any => [:success, :failed, :canceled] do |build, transition|
build.update_attributes finished_at: Time.now
project = build.project project = build.project
if project.web_hooks? if project.web_hooks?
...@@ -136,19 +103,10 @@ module Ci ...@@ -136,19 +103,10 @@ module Ci
build.update_coverage build.update_coverage
end end
end end
state :pending, value: 'pending'
state :running, value: 'running'
state :failed, value: 'failed'
state :success, value: 'success'
state :canceled, value: 'canceled'
end end
delegate :sha, :short_sha, :project, :gl_project, def ignored?
to: :commit, prefix: false failed? && allow_failure?
def before_sha
Gitlab::Git::BLANK_SHA
end end
def trace_html def trace_html
...@@ -156,22 +114,6 @@ module Ci ...@@ -156,22 +114,6 @@ module Ci
html || '' html || ''
end end
def started?
!pending? && !canceled? && started_at
end
def active?
running? || pending?
end
def complete?
canceled? || success? || failed?
end
def ignored?
failed? && allow_failure?
end
def timeout def timeout
project.timeout project.timeout
end end
...@@ -180,14 +122,6 @@ module Ci ...@@ -180,14 +122,6 @@ module Ci
yaml_variables + project_variables + trigger_variables yaml_variables + project_variables + trigger_variables
end end
def duration
if started_at && finished_at
finished_at - started_at
elsif started_at
Time.now - started_at
end
end
def project def project
commit.project commit.project
end end
...@@ -278,6 +212,25 @@ module Ci ...@@ -278,6 +212,25 @@ module Ci
"#{dir_to_trace}/#{id}.log" "#{dir_to_trace}/#{id}.log"
end end
def target_url
Gitlab::Application.routes.url_helpers.
namespace_project_build_url(gl_project.namespace, gl_project, self)
end
def cancel_url
if active?
Gitlab::Application.routes.url_helpers.
cancel_namespace_project_build_path(gl_project.namespace, gl_project, self)
end
end
def retry_url
if commands.present?
Gitlab::Application.routes.url_helpers.
retry_namespace_project_build_path(gl_project.namespace, gl_project, self)
end
end
private private
def yaml_variables def yaml_variables
......
...@@ -20,7 +20,8 @@ module Ci ...@@ -20,7 +20,8 @@ module Ci
extend Ci::Model extend Ci::Model
belongs_to :gl_project, class_name: '::Project', foreign_key: :gl_project_id belongs_to :gl_project, class_name: '::Project', foreign_key: :gl_project_id
has_many :builds, dependent: :destroy, class_name: 'Ci::Build' has_many :statuses, dependent: :destroy, class_name: 'CommitStatus'
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'
validates_presence_of :sha validates_presence_of :sha
...@@ -47,7 +48,7 @@ module Ci ...@@ -47,7 +48,7 @@ module Ci
end end
def retry def retry
builds_without_retry.each do |build| latest_builds.each do |build|
Ci::Build.retry(build) Ci::Build.retry(build)
end end
end end
...@@ -81,12 +82,11 @@ module Ci ...@@ -81,12 +82,11 @@ module Ci
end end
def stage def stage
running_or_pending = builds_without_retry.running_or_pending running_or_pending = statuses.latest.running_or_pending.ordered
running_or_pending.limit(1).pluck(:stage).first running_or_pending.first.try(:stage)
end end
def create_builds(ref, tag, user, trigger_request = nil) def create_builds(ref, tag, user, trigger_request = nil)
return if skip_ci? && trigger_request.blank?
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).present?
...@@ -94,7 +94,6 @@ module Ci ...@@ -94,7 +94,6 @@ module Ci
end end
def create_next_builds(ref, tag, user, trigger_request) def create_next_builds(ref, tag, user, trigger_request)
return if skip_ci? && trigger_request.blank?
return unless config_processor return unless config_processor
stages = builds.where(ref: ref, tag: tag, trigger_request: trigger_request).group_by(&:stage) stages = builds.where(ref: ref, tag: tag, trigger_request: trigger_request).group_by(&:stage)
...@@ -107,61 +106,60 @@ module Ci ...@@ -107,61 +106,60 @@ module Ci
end end
def refs def refs
builds.group(:ref).pluck(:ref) statuses.order(:ref).pluck(:ref).uniq
end end
def last_ref def latest_statuses
builds.latest.first.try(:ref) @latest_statuses ||= statuses.latest.to_a
end end
def builds_without_retry def latest_builds
builds.latest @latest_builds ||= builds.latest.to_a
end end
def builds_without_retry_for_ref(ref) def latest_builds_for_ref(ref)
builds.for_ref(ref).latest latest_builds.select { |build| build.ref == ref }
end end
def retried_builds def retried
@retried_builds ||= (builds.order(id: :desc) - builds_without_retry) @retried ||= (statuses.order(id: :desc) - statuses.latest)
end end
def status def status
if skip_ci? if yaml_errors.present?
return 'skipped'
elsif yaml_errors.present?
return 'failed' return 'failed'
elsif builds.none? end
return 'skipped'
elsif success? @status ||= begin
'success' latest = latest_statuses
elsif pending? latest.reject! { |status| status.try(&:allow_failure?) }
'pending'
elsif running? if latest.none?
'running' 'skipped'
elsif canceled? elsif latest.all?(&:success?)
'canceled' 'success'
else elsif latest.all?(&:pending?)
'failed' 'pending'
elsif latest.any?(&:running?) || latest.any?(&:pending?)
'running'
elsif latest.all?(&:canceled?)
'canceled'
else
'failed'
end
end end
end end
def pending? def pending?
builds_without_retry.all? do |build| status == 'pending'
build.pending?
end
end end
def running? def running?
builds_without_retry.any? do |build| status == 'running'
build.running? || build.pending?
end
end end
def success? def success?
builds_without_retry.all? do |build| status == 'success'
build.success? || build.ignored?
end
end end
def failed? def failed?
...@@ -169,26 +167,21 @@ module Ci ...@@ -169,26 +167,21 @@ module Ci
end end
def canceled? def canceled?
builds_without_retry.all? do |build| status == 'canceled'
build.canceled?
end
end end
def duration def duration
@duration ||= builds_without_retry.select(&:duration).sum(&:duration).to_i duration_array = latest_statuses.map(&:duration).compact
end duration_array.reduce(:+).to_i
def duration_for_ref(ref)
builds_without_retry_for_ref(ref).select(&:duration).sum(&:duration).to_i
end end
def finished_at def finished_at
@finished_at ||= builds.order('finished_at DESC').first.try(:finished_at) @finished_at ||= statuses.order('finished_at DESC').first.try(:finished_at)
end end
def coverage def coverage
if project.coverage_enabled? if project.coverage_enabled?
coverage_array = builds_without_retry.map(&:coverage).compact coverage_array = latest_builds.map(&:coverage).compact
if coverage_array.size >= 1 if coverage_array.size >= 1
'%.2f' % (coverage_array.reduce(:+) / coverage_array.size) '%.2f' % (coverage_array.reduce(:+) / coverage_array.size)
end end
...@@ -196,7 +189,7 @@ module Ci ...@@ -196,7 +189,7 @@ module Ci
end end
def matrix_for_ref?(ref) def matrix_for_ref?(ref)
builds_without_retry_for_ref(ref).pluck(:id).size > 1 latest_builds_for_ref(ref).size > 1
end end
def config_processor def config_processor
...@@ -217,7 +210,6 @@ module Ci ...@@ -217,7 +210,6 @@ module Ci
end end
def skip_ci? def skip_ci?
return false if builds.any?
git_commit_message =~ /(\[ci skip\])/ if git_commit_message git_commit_message =~ /(\[ci skip\])/ if git_commit_message
end end
......
...@@ -184,4 +184,12 @@ class Commit ...@@ -184,4 +184,12 @@ class Commit
def parents def parents
@parents ||= Commit.decorate(super, project) @parents ||= Commit.decorate(super, project)
end end
def ci_commit
project.ci_commit(sha)
end
def status
ci_commit.try(:status) || :not_found
end
end end
class CommitStatus < ActiveRecord::Base
self.table_name = 'ci_builds'
belongs_to :commit, class_name: 'Ci::Commit'
belongs_to :user
validates :commit, presence: true
validates :status, inclusion: { in: %w(pending running failed success canceled) }
validates_presence_of :name
alias_attribute :author, :user
scope :running, -> { where(status: 'running') }
scope :pending, -> { where(status: 'pending') }
scope :success, -> { where(status: 'success') }
scope :failed, -> { where(status: 'failed') }
scope :running_or_pending, -> { where(status:[:running, :pending]) }
scope :latest, -> { where(id: unscope(:select).select('max(id)').group(:name, :ref)) }
scope :ordered, -> { order(:ref, :stage_idx, :name) }
scope :for_ref, ->(ref) { where(ref: ref) }
scope :running_or_pending, -> { where(status: [:running, :pending]) }
state_machine :status, initial: :pending do
event :run do
transition pending: :running
end
event :drop do
transition running: :failed
end
event :success do
transition [:pending, :running] => :success
end
event :cancel do
transition [:pending, :running] => :canceled
end
after_transition pending: :running do |build, transition|
build.update_attributes started_at: Time.now
end
after_transition any => [:success, :failed, :canceled] do |build, transition|
build.update_attributes finished_at: Time.now
end
state :pending, value: 'pending'
state :running, value: 'running'
state :failed, value: 'failed'
state :success, value: 'success'
state :canceled, value: 'canceled'
end
delegate :sha, :short_sha, :gl_project,
to: :commit, prefix: false
# TODO: this should be removed with all references
def before_sha
Gitlab::Git::BLANK_SHA
end
def started?
!pending? && !canceled? && started_at
end
def active?
running? || pending?
end
def complete?
canceled? || success? || failed?
end
def duration
if started_at && finished_at
finished_at - started_at
elsif started_at
Time.now - started_at
end
end
def cancel_url
nil
end
def retry_url
nil
end
end
# Concern for querying columns with specific case sensitivity handling.
module CaseSensitivity
extend ActiveSupport::Concern
module ClassMethods
# Queries the given columns regardless of the casing used.
#
# Unlike other ActiveRecord methods this method only operates on a Hash.
def iwhere(params)
criteria = self
cast_lower = Gitlab::Database.postgresql?
params.each do |key, value|
column = ActiveRecord::Base.connection.quote_table_name(key)
if cast_lower
condition = "LOWER(#{column}) = LOWER(:value)"
else
condition = "#{column} = :value"
end
criteria = criteria.where(condition, value: value)
end
criteria
end
end
end
class GenericCommitStatus < CommitStatus
before_validation :set_default_values
# GitHub compatible API
alias_attribute :context, :name
def set_default_values
self.context ||= 'default'
self.stage ||= 'external'
end
def tags
[:external]
end
end
class GroupMilestone class GroupMilestone
alias_attribute :name, :title
def initialize(title, milestones) def initialize(title, milestones)
@title = title @title = title
@milestones = milestones @milestones = milestones
......
...@@ -12,6 +12,11 @@ ...@@ -12,6 +12,11 @@
class Label < ActiveRecord::Base class Label < ActiveRecord::Base
include Referable include Referable
# Represents a "No Label" state used for filtering Issues and Merge
# Requests that have no label assigned.
LabelStruct = Struct.new(:title, :name)
None = LabelStruct.new('No Label', 'No Label')
Any = LabelStruct.new('Any', '')
DEFAULT_COLOR = '#428BCA' DEFAULT_COLOR = '#428BCA'
......
...@@ -227,7 +227,7 @@ class MergeRequest < ActiveRecord::Base ...@@ -227,7 +227,7 @@ class MergeRequest < ActiveRecord::Base
end end
def work_in_progress? def work_in_progress?
title =~ /\A\[?WIP\]?:? /i !!(title =~ /\A\[?WIP\]?:? /i)
end end
def mergeable? def mergeable?
...@@ -275,7 +275,8 @@ class MergeRequest < ActiveRecord::Base ...@@ -275,7 +275,8 @@ class MergeRequest < ActiveRecord::Base
attrs = { attrs = {
source: source_project.hook_attrs, source: source_project.hook_attrs,
target: target_project.hook_attrs, target: target_project.hook_attrs,
last_commit: nil last_commit: nil,
work_in_progress: work_in_progress?
} }
unless last_commit.nil? unless last_commit.nil?
......
...@@ -16,7 +16,9 @@ ...@@ -16,7 +16,9 @@
class Milestone < ActiveRecord::Base class Milestone < ActiveRecord::Base
# Represents a "No Milestone" state used for filtering Issues and Merge # Represents a "No Milestone" state used for filtering Issues and Merge
# Requests that have no milestone assigned. # Requests that have no milestone assigned.
None = Struct.new(:title).new('No Milestone') MilestoneStruct = Struct.new(:title, :name)
None = MilestoneStruct.new('No Milestone', 'No Milestone')
Any = MilestoneStruct.new('Any', '')
include InternalId include InternalId
include Sortable include Sortable
...@@ -47,6 +49,8 @@ class Milestone < ActiveRecord::Base ...@@ -47,6 +49,8 @@ class Milestone < ActiveRecord::Base
state :active state :active
end end
alias_attribute :name, :title
class << self class << self
def search(query) def search(query)
query = "%#{query}%" query = "%#{query}%"
......
...@@ -118,6 +118,8 @@ class Namespace < ActiveRecord::Base ...@@ -118,6 +118,8 @@ class Namespace < ActiveRecord::Base
gitlab_shell.add_namespace(path_was) gitlab_shell.add_namespace(path_was)
if gitlab_shell.mv_namespace(path_was, path) if gitlab_shell.mv_namespace(path_was, path)
Gitlab::UploadsTransfer.new.rename_namespace(path_was, path)
# If repositories moved successfully we need to # If repositories moved successfully we need to
# send update instructions to users. # send update instructions to users.
# However we cannot allow rollback since we moved namespace dir # However we cannot allow rollback since we moved namespace dir
......
...@@ -40,6 +40,7 @@ class Project < ActiveRecord::Base ...@@ -40,6 +40,7 @@ class Project < ActiveRecord::Base
include Referable include Referable
include Sortable include Sortable
include AfterCommitQueue include AfterCommitQueue
include CaseSensitivity
extend Gitlab::ConfigHelper extend Gitlab::ConfigHelper
extend Enumerize extend Enumerize
...@@ -235,13 +236,18 @@ class Project < ActiveRecord::Base ...@@ -235,13 +236,18 @@ class Project < ActiveRecord::Base
end end
def find_with_namespace(id) def find_with_namespace(id)
return nil unless id.include?('/') namespace_path, project_path = id.split('/')
id = id.split('/') return nil if !namespace_path || !project_path
namespace = Namespace.by_path(id.first)
return nil unless namespace # Use of unscoped ensures we're not secretly adding any ORDER BYs, which
# have a negative impact on performance (and aren't needed for this
where(namespace_id: namespace.id).where("LOWER(projects.path) = :path", path: id.second.downcase).first # query).
unscoped.
joins(:namespace).
iwhere('namespaces.path' => namespace_path).
iwhere('projects.path' => project_path).
take
end end
def visibility_levels def visibility_levels
...@@ -260,6 +266,20 @@ class Project < ActiveRecord::Base ...@@ -260,6 +266,20 @@ class Project < ActiveRecord::Base
name_pattern = Gitlab::Regex::NAMESPACE_REGEX_STR name_pattern = Gitlab::Regex::NAMESPACE_REGEX_STR
%r{(?<project>#{name_pattern}/#{name_pattern})} %r{(?<project>#{name_pattern}/#{name_pattern})}
end end
def trending(since = 1.month.ago)
# By counting in the JOIN we don't expose the GROUP BY to the outer query.
# This means that calls such as "any?" and "count" just return a number of
# the total count, instead of the counts grouped per project as a Hash.
join_body = "INNER JOIN (
SELECT project_id, COUNT(*) AS amount
FROM notes
WHERE created_at >= #{sanitize(since)}
GROUP BY project_id
) join_note_counts ON projects.id = join_note_counts.project_id"
joins(join_body).reorder('join_note_counts.amount DESC')
end
end end
def team def team
...@@ -636,6 +656,8 @@ class Project < ActiveRecord::Base ...@@ -636,6 +656,8 @@ class Project < ActiveRecord::Base
# db changes in order to prevent out of sync between db and fs # db changes in order to prevent out of sync between db and fs
raise Exception.new('repository cannot be renamed') raise Exception.new('repository cannot be renamed')
end end
Gitlab::UploadsTransfer.new.rename_project(path_was, path, namespace.path)
end end
def hook_attrs def hook_attrs
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment