Commit 0452e0a5 authored by Jacob Schatz's avatar Jacob Schatz

Merge branch 'master' into faster-diffs

parents 76905134 f7659638
...@@ -284,7 +284,7 @@ Style/IfWithSemicolon: ...@@ -284,7 +284,7 @@ Style/IfWithSemicolon:
# Checks that conditional statements do not have an identical line at the # Checks that conditional statements do not have an identical line at the
# end of each branch, which can validly be moved out of the conditional. # end of each branch, which can validly be moved out of the conditional.
Style/IdenticalConditionalBranches: Style/IdenticalConditionalBranches:
Enabled: false Enabled: true
# Checks the indentation of the first line of the right-hand-side of a # Checks the indentation of the first line of the right-hand-side of a
# multi-line assignment. # multi-line assignment.
......
...@@ -5,6 +5,7 @@ v 8.10.0 (unreleased) ...@@ -5,6 +5,7 @@ v 8.10.0 (unreleased)
- Replace Haml with Hamlit to make view rendering faster. !3666 - Replace Haml with Hamlit to make view rendering faster. !3666
- Refactor repository paths handling to allow multiple git mount points - Refactor repository paths handling to allow multiple git mount points
- Add Application Setting to configure default Repository Path for new projects - Add Application Setting to configure default Repository Path for new projects
- Remove pinTo from Flash and make inline flash messages look nicer !4854 (winniehell)
- Wrap code blocks on Activies and Todos page. !4783 (winniehell) - Wrap code blocks on Activies and Todos page. !4783 (winniehell)
- Align flash messages with left side of page content !4959 (winniehell) - Align flash messages with left side of page content !4959 (winniehell)
- Display last commit of deleted branch in push events !4699 (winniehell) - Display last commit of deleted branch in push events !4699 (winniehell)
...@@ -18,27 +19,35 @@ v 8.10.0 (unreleased) ...@@ -18,27 +19,35 @@ v 8.10.0 (unreleased)
- Fix MR-auto-close text added to description. !4836 - Fix MR-auto-close text added to description. !4836
- Fix issue, preventing users w/o push access to sort tags !5105 (redetection) - Fix issue, preventing users w/o push access to sort tags !5105 (redetection)
- Add Spring EmojiOne updates. - Add Spring EmojiOne updates.
- Add syntax for multiline blockquote using `>>>` fence !3954
- Fix viewing notification settings when a project is pending deletion - Fix viewing notification settings when a project is pending deletion
- Fix pagination when sorting by columns with lots of ties (like priority) - Fix pagination when sorting by columns with lots of ties (like priority)
- The Markdown reference parsers now re-use query results to prevent running the same queries multiple times !5020
- Updated project header design - Updated project header design
- Exclude email check from the standard health check - Exclude email check from the standard health check
- Updated layout for Projects, Groups, Users on Admin area !4424 - Updated layout for Projects, Groups, Users on Admin area !4424
- Fix changing issue state columns in milestone view - Fix changing issue state columns in milestone view
- Add notification settings dropdown for groups - Add notification settings dropdown for groups
- Wildcards for protected branches. !4665
- Allow importing from Github using Personal Access Tokens. (Eric K Idema) - Allow importing from Github using Personal Access Tokens. (Eric K Idema)
- API: Todos !3188 (Robert Schilling) - API: Todos !3188 (Robert Schilling)
- API: Expose shared groups for projects and shared projects for groups !5050 (Robert Schilling)
- Add "Enabled Git access protocols" to Application Settings - Add "Enabled Git access protocols" to Application Settings
- Diffs will create button/diff form on demand no on server side - Diffs will create button/diff form on demand no on server side
- Reduce size of HTML used by diff comment forms - Reduce size of HTML used by diff comment forms
- Fix user creation with stronger minimum password requirements !4054 (nathan-pmt) - Fix user creation with stronger minimum password requirements !4054 (nathan-pmt)
- Only show New Snippet button to users that can create snippets.
- PipelinesFinder uses git cache data - PipelinesFinder uses git cache data
- Throttle the update of `project.pushes_since_gc` to 1 minute. - Throttle the update of `project.pushes_since_gc` to 1 minute.
- Allow expanding and collapsing files in diff view (!4990)
- Collapse large diffs by default (!4990)
- Check for conflicts with existing Project's wiki path when creating a new project. - Check for conflicts with existing Project's wiki path when creating a new project.
- Show last push widget in upstream after push to fork - Show last push widget in upstream after push to fork
- Don't instantiate a git tree on Projects show default view - Don't instantiate a git tree on Projects show default view
- Bump Rinku to 2.0.0 - Bump Rinku to 2.0.0
- Remove unused front-end variable -> default_issues_tracker - Remove unused front-end variable -> default_issues_tracker
- Better caching of git calls on ProjectsController#show. - Better caching of git calls on ProjectsController#show.
- Avoid to retrieve MR closes_issues as much as possible.
- Add API endpoint for a group issues !4520 (mahcsig) - Add API endpoint for a group issues !4520 (mahcsig)
- Add Bugzilla integration !4930 (iamtjg) - Add Bugzilla integration !4930 (iamtjg)
- Instrument Rinku usage - Instrument Rinku usage
...@@ -46,6 +55,8 @@ v 8.10.0 (unreleased) ...@@ -46,6 +55,8 @@ v 8.10.0 (unreleased)
- RailsCache metris now includes fetch_hit/fetch_miss and read_hit/read_miss info. - RailsCache metris now includes fetch_hit/fetch_miss and read_hit/read_miss info.
- Allow [ci skip] to be in any case and allow [skip ci]. !4785 (simon_w) - Allow [ci skip] to be in any case and allow [skip ci]. !4785 (simon_w)
- Set import_url validation to be more strict - Set import_url validation to be more strict
- Memoize MR merged/closed events retrieval
- Don't render discussion notes when requesting diff tab through AJAX
- Add basic system information like memory and disk usage to the admin panel - Add basic system information like memory and disk usage to the admin panel
- Don't garbage collect commits that have related DB records like comments - Don't garbage collect commits that have related DB records like comments
- More descriptive message for git hooks and file locks - More descriptive message for git hooks and file locks
...@@ -54,6 +65,14 @@ v 8.10.0 (unreleased) ...@@ -54,6 +65,14 @@ v 8.10.0 (unreleased)
- Fix importer for GitHub Pull Requests when a branch was reused across Pull Requests - Fix importer for GitHub Pull Requests when a branch was reused across Pull Requests
- Add date when user joined the team on the member page - Add date when user joined the team on the member page
- Fix 404 redirect after validation fails importing a GitLab project - Fix 404 redirect after validation fails importing a GitLab project
- Fix 404 redirect after validation fails importing a GitLab project
- Added setting to set new users by default as external !4545 (Dravere)
- Add min value for project limit field on user's form !3622 (jastkand)
- Add reminder to not paste private SSH keys !4399 (Ingo Blechschmidt)
- Remove duplicate `description` field in `MergeRequest` entities (Ben Boeckel)
v 8.9.6 (unreleased)
- Fix importing of events under notes for GitLab projects
v 8.9.5 v 8.9.5
- Add more debug info to import/export and memory killer. !5108 - Add more debug info to import/export and memory killer. !5108
...@@ -98,7 +117,7 @@ v 8.9.3 ...@@ -98,7 +117,7 @@ v 8.9.3
- Removed fade when filtering results. !4932 - Removed fade when filtering results. !4932
- Fix missing avatar on system notes. !4954 - Fix missing avatar on system notes. !4954
- Reduce overhead and optimize ProjectTeam#max_member_access performance. !4973 - Reduce overhead and optimize ProjectTeam#max_member_access performance. !4973
- Use update_columns to by_pass all the dirty code on active_record. !4985 - Use update_columns to bypass all the dirty code on active_record. !4985
- Fix restore Rake task warning message output !4980 - Fix restore Rake task warning message output !4980
v 8.9.2 v 8.9.2
...@@ -2602,13 +2621,13 @@ v 6.5.0 ...@@ -2602,13 +2621,13 @@ v 6.5.0
- Files API supports base64 encoded content (sponsored by O'Reilly Media) - Files API supports base64 encoded content (sponsored by O'Reilly Media)
- Added support for Go's repository retrieval (Bruno Albuquerque) - Added support for Go's repository retrieval (Bruno Albuquerque)
v6.4.3 v 6.4.3
- Don't use unicorn worker killer if PhusionPassenger is defined - Don't use unicorn worker killer if PhusionPassenger is defined
v6.4.2 v 6.4.2
- Fixed wrong behaviour of script/upgrade.rb - Fixed wrong behaviour of script/upgrade.rb
v6.4.1 v 6.4.1
- Fixed bug with repository rename - Fixed bug with repository rename
- Fixed bug with project transfer - Fixed bug with project transfer
......
source "https://rubygems.org" source 'https://rubygems.org'
gem 'rails', '4.2.6' gem 'rails', '4.2.6'
gem 'rails-deprecated_sanitizer', '~> 1.0.3' gem 'rails-deprecated_sanitizer', '~> 1.0.3'
...@@ -11,11 +11,11 @@ gem 'responders', '~> 2.0' ...@@ -11,11 +11,11 @@ gem 'responders', '~> 2.0'
gem 'sprockets', '~> 3.6.0' gem 'sprockets', '~> 3.6.0'
# Default values for AR models # Default values for AR models
gem "default_value_for", "~> 3.0.0" gem 'default_value_for', '~> 3.0.0'
# Supported DBs # Supported DBs
gem "mysql2", '~> 0.3.16', group: :mysql 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', '~> 4.0' gem 'devise', '~> 4.0'
...@@ -28,7 +28,7 @@ gem 'omniauth-cas3', '~> 1.1.2' ...@@ -28,7 +28,7 @@ gem 'omniauth-cas3', '~> 1.1.2'
gem 'omniauth-facebook', '~> 3.0.0' gem 'omniauth-facebook', '~> 3.0.0'
gem 'omniauth-github', '~> 1.1.1' gem 'omniauth-github', '~> 1.1.1'
gem 'omniauth-gitlab', '~> 1.0.0' gem 'omniauth-gitlab', '~> 1.0.0'
gem 'omniauth-google-oauth2', '~> 0.2.0' gem 'omniauth-google-oauth2', '~> 0.4.1'
gem 'omniauth-kerberos', '~> 0.3.0', group: :kerberos gem 'omniauth-kerberos', '~> 0.3.0', group: :kerberos
gem 'omniauth-saml', '~> 1.6.0' gem 'omniauth-saml', '~> 1.6.0'
gem 'omniauth-shibboleth', '~> 1.2.0' gem 'omniauth-shibboleth', '~> 1.2.0'
...@@ -48,16 +48,16 @@ gem 'attr_encrypted', '~> 3.0.0' ...@@ -48,16 +48,16 @@ gem 'attr_encrypted', '~> 3.0.0'
gem 'u2f', '~> 0.2.1' gem 'u2f', '~> 0.2.1'
# Browser detection # Browser detection
gem "browser", '~> 2.2' gem 'browser', '~> 2.2'
# 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", '~> 10.2' gem 'gitlab_git', '~> 10.2'
# 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
# see https://github.com/intridea/omniauth-ldap/compare/master...gitlabhq:master # see https://github.com/intridea/omniauth-ldap/compare/master...gitlabhq:master
gem 'gitlab_omniauth-ldap', '~> 1.2.1', require: "omniauth-ldap" gem 'gitlab_omniauth-ldap', '~> 1.2.1', require: 'omniauth-ldap'
# Git Wiki # Git Wiki
# Required manually in config/initializers/gollum.rb to control load order # Required manually in config/initializers/gollum.rb to control load order
...@@ -65,7 +65,7 @@ gem 'gollum-lib', '~> 4.1.0', require: false ...@@ -65,7 +65,7 @@ gem 'gollum-lib', '~> 4.1.0', require: false
gem 'gollum-rugged_adapter', '~> 0.4.2', require: false gem 'gollum-rugged_adapter', '~> 0.4.2', require: false
# Language detection # Language detection
gem "github-linguist", "~> 4.7.0", require: "linguist" gem 'github-linguist', '~> 4.7.0', require: 'linguist'
# API # API
gem 'grape', '~> 0.13.0' gem 'grape', '~> 0.13.0'
...@@ -73,13 +73,13 @@ gem 'grape-entity', '~> 0.4.2' ...@@ -73,13 +73,13 @@ gem 'grape-entity', '~> 0.4.2'
gem 'rack-cors', '~> 0.4.0', require: 'rack/cors' gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
# Pagination # Pagination
gem "kaminari", "~> 0.17.0" gem 'kaminari', '~> 0.17.0'
# HAML # HAML
gem 'hamlit', '~> 2.5' gem 'hamlit', '~> 2.5'
# Files attachments # Files attachments
gem "carrierwave", '~> 0.10.0' gem 'carrierwave', '~> 0.10.0'
# Drag and Drop UI # Drag and Drop UI
gem 'dropzonejs-rails', '~> 0.7.1' gem 'dropzonejs-rails', '~> 0.7.1'
...@@ -94,13 +94,13 @@ gem 'fog-openstack', '~> 0.1' ...@@ -94,13 +94,13 @@ gem 'fog-openstack', '~> 0.1'
gem 'fog-rackspace', '~> 0.1.1' gem 'fog-rackspace', '~> 0.1.1'
# for aws storage # for aws storage
gem "unf", '~> 0.1.4' gem 'unf', '~> 0.1.4'
# Authorization # Authorization
gem "six", '~> 0.2.0' gem 'six', '~> 0.2.0'
# Seed data # Seed data
gem "seed-fu", '~> 2.3.5' gem 'seed-fu', '~> 2.3.5'
# Markdown and HTML processing # Markdown and HTML processing
gem 'html-pipeline', '~> 1.11.0' gem 'html-pipeline', '~> 1.11.0'
...@@ -124,29 +124,29 @@ gem 'diffy', '~> 3.0.3' ...@@ -124,29 +124,29 @@ gem 'diffy', '~> 3.0.3'
# Application server # Application server
group :unicorn do group :unicorn do
gem "unicorn", '~> 4.9.0' gem 'unicorn', '~> 4.9.0'
gem 'unicorn-worker-killer', '~> 0.4.2' gem 'unicorn-worker-killer', '~> 0.4.2'
end end
# State machine # State machine
gem "state_machines-activerecord", '~> 0.4.0' gem 'state_machines-activerecord', '~> 0.4.0'
# Run events after state machine commits # Run events after state machine commits
gem 'after_commit_queue' gem 'after_commit_queue', '~> 1.3.0'
# Issue tags # Issue tags
gem 'acts-as-taggable-on', '~> 3.4' gem 'acts-as-taggable-on', '~> 3.4'
# Background jobs # Background jobs
gem 'sinatra', '~> 1.4.4', require: nil gem 'sinatra', '~> 1.4.4', require: false
gem 'sidekiq', '~> 4.0' gem 'sidekiq', '~> 4.0'
gem 'sidekiq-cron', '~> 0.4.0' gem 'sidekiq-cron', '~> 0.4.0'
gem 'redis-namespace' gem 'redis-namespace', '~> 1.5.2'
# HTTP requests # HTTP requests
gem "httparty", '~> 0.13.3' gem 'httparty', '~> 0.13.3'
# Colored output to console # Colored output to console
gem "rainbow", '~> 2.1.0' gem 'rainbow', '~> 2.1.0'
# GitLab settings # GitLab settings
gem 'settingslogic', '~> 2.0.9' gem 'settingslogic', '~> 2.0.9'
...@@ -156,7 +156,7 @@ gem 'settingslogic', '~> 2.0.9' ...@@ -156,7 +156,7 @@ gem 'settingslogic', '~> 2.0.9'
gem 'version_sorter', '~> 2.0.0' gem 'version_sorter', '~> 2.0.0'
# Cache # Cache
gem "redis-rails", '~> 4.0.0' gem 'redis-rails', '~> 4.0.0'
# Redis # Redis
gem 'redis', '~> 3.2' gem 'redis', '~> 3.2'
...@@ -169,13 +169,13 @@ gem 'tinder', '~> 1.10.0' ...@@ -169,13 +169,13 @@ gem 'tinder', '~> 1.10.0'
gem 'hipchat', '~> 1.5.0' gem 'hipchat', '~> 1.5.0'
# Flowdock integration # Flowdock integration
gem "gitlab-flowdock-git-hook", "~> 1.0.1" gem 'gitlab-flowdock-git-hook', '~> 1.0.1'
# Gemnasium integration # Gemnasium integration
gem "gemnasium-gitlab-service", "~> 0.2" gem 'gemnasium-gitlab-service', '~> 0.2'
# Slack integration # Slack integration
gem "slack-notifier", "~> 1.2.0" gem 'slack-notifier', '~> 1.2.0'
# Asana integration # Asana integration
gem 'asana', '~> 0.4.0' gem 'asana', '~> 0.4.0'
...@@ -187,20 +187,20 @@ gem 'ruby-fogbugz', '~> 0.2.1' ...@@ -187,20 +187,20 @@ gem 'ruby-fogbugz', '~> 0.2.1'
gem 'd3_rails', '~> 3.5.0' gem 'd3_rails', '~> 3.5.0'
# underscore-rails # underscore-rails
gem "underscore-rails", "~> 1.8.0" gem 'underscore-rails', '~> 1.8.0'
# Sanitize user input # Sanitize user input
gem "sanitize", '~> 2.0' gem 'sanitize', '~> 2.0'
gem 'babosa', '~> 1.0.2' gem 'babosa', '~> 1.0.2'
# Sanitizes SVG input # Sanitizes SVG input
gem "loofah", "~> 2.0.3" gem 'loofah', '~> 2.0.3'
# Working with license # Working with license
gem 'licensee', '~> 8.0.0' gem 'licensee', '~> 8.0.0'
# Protect against bruteforcing # Protect against bruteforcing
gem "rack-attack", '~> 4.3.1' gem 'rack-attack', '~> 4.3.1'
# Ace editor # Ace editor
gem 'ace-rails-ap', '~> 4.0.2' gem 'ace-rails-ap', '~> 4.0.2'
...@@ -214,9 +214,9 @@ gem 'charlock_holmes', '~> 0.7.3' ...@@ -214,9 +214,9 @@ gem 'charlock_holmes', '~> 0.7.3'
# Parse duration # Parse duration
gem 'chronic_duration', '~> 0.10.6' gem 'chronic_duration', '~> 0.10.6'
gem "sass-rails", '~> 5.0.0' gem 'sass-rails', '~> 5.0.0'
gem "coffee-rails", '~> 4.1.0' gem 'coffee-rails', '~> 4.1.0'
gem "uglifier", '~> 2.7.2' gem 'uglifier', '~> 2.7.2'
gem 'turbolinks', '~> 2.5.0' gem 'turbolinks', '~> 2.5.0'
gem 'jquery-turbolinks', '~> 2.1.0' gem 'jquery-turbolinks', '~> 2.1.0'
...@@ -247,13 +247,13 @@ group :metrics do ...@@ -247,13 +247,13 @@ group :metrics do
end end
group :development do group :development do
gem "foreman" gem 'foreman', '~> 0.78.0'
gem 'brakeman', '~> 3.3.0', require: false gem 'brakeman', '~> 3.3.0', require: false
gem 'letter_opener_web', '~> 1.3.0' gem 'letter_opener_web', '~> 1.3.0'
gem 'rerun', '~> 0.11.0' gem 'rerun', '~> 0.11.0'
gem 'bullet', require: false gem 'bullet', '~> 5.0.0', require: false
gem 'rblineprof', platform: :mri, require: false gem 'rblineprof', '~> 0.3.6', platform: :mri, require: false
gem 'web-console', '~> 2.0' gem 'web-console', '~> 2.0'
# Better errors handler # Better errors handler
...@@ -261,15 +261,15 @@ group :development do ...@@ -261,15 +261,15 @@ group :development do
gem 'binding_of_caller', '~> 0.7.2' gem 'binding_of_caller', '~> 0.7.2'
# Docs generator # Docs generator
gem "sdoc", '~> 0.3.20' gem 'sdoc', '~> 0.3.20'
# thin instead webrick # thin instead webrick
gem 'thin', '~> 1.7.0' gem 'thin', '~> 1.7.0'
end end
group :development, :test do group :development, :test do
gem 'byebug', platform: :mri gem 'byebug', '~> 8.2.1', platform: :mri
gem 'pry-rails' gem 'pry-rails', '~> 0.3.4'
gem 'awesome_print', '~> 1.2.0', require: false gem 'awesome_print', '~> 1.2.0', require: false
gem 'fuubar', '~> 2.0.0' gem 'fuubar', '~> 2.0.0'
...@@ -277,7 +277,7 @@ group :development, :test do ...@@ -277,7 +277,7 @@ group :development, :test do
gem 'database_cleaner', '~> 1.4.0' gem 'database_cleaner', '~> 1.4.0'
gem 'factory_girl_rails', '~> 4.6.0' gem 'factory_girl_rails', '~> 4.6.0'
gem 'rspec-rails', '~> 3.5.0' gem 'rspec-rails', '~> 3.5.0'
gem 'rspec-retry' gem 'rspec-retry', '~> 0.4.5'
gem 'spinach-rails', '~> 0.2.1' gem 'spinach-rails', '~> 0.2.1'
gem 'spinach-rerun-reporter', '~> 0.0.2' gem 'spinach-rerun-reporter', '~> 0.0.2'
...@@ -303,14 +303,14 @@ group :development, :test do ...@@ -303,14 +303,14 @@ group :development, :test do
gem 'rubocop-rspec', '~> 1.5.0', require: false gem 'rubocop-rspec', '~> 1.5.0', require: false
gem 'scss_lint', '~> 0.47.0', require: false gem 'scss_lint', '~> 0.47.0', require: false
gem 'simplecov', '~> 0.11.0', require: false gem 'simplecov', '~> 0.11.0', require: false
gem 'flog', require: false gem 'flog', '~> 4.3.2', require: false
gem 'flay', require: false gem 'flay', '~> 2.6.1', require: false
gem 'bundler-audit', require: false gem 'bundler-audit', '~> 0.5.0', require: false
gem 'benchmark-ips', require: false gem 'benchmark-ips', '~> 2.3.0', require: false
gem "license_finder", require: false gem 'license_finder', '~> 2.1.0', require: false
gem 'knapsack' gem 'knapsack', '~> 1.11.0'
end end
group :test do group :test do
...@@ -318,30 +318,30 @@ group :test do ...@@ -318,30 +318,30 @@ group :test do
gem 'email_spec', '~> 1.6.0' gem 'email_spec', '~> 1.6.0'
gem 'webmock', '~> 1.21.0' gem 'webmock', '~> 1.21.0'
gem 'test_after_commit', '~> 0.4.2' gem 'test_after_commit', '~> 0.4.2'
gem 'sham_rack' gem 'sham_rack', '~> 1.3.6'
end end
group :production do group :production do
gem "gitlab_meta", '7.0' gem 'gitlab_meta', '7.0'
end end
gem "newrelic_rpm", '~> 3.14' gem 'newrelic_rpm', '~> 3.14'
gem 'octokit', '~> 4.3.0' gem 'octokit', '~> 4.3.0'
gem "mail_room", "~> 0.8" gem 'mail_room', '~> 0.8'
gem 'email_reply_parser', '~> 0.5.8' gem 'email_reply_parser', '~> 0.5.8'
## CI ## CI
gem 'activerecord-session_store', '~> 1.0.0' gem 'activerecord-session_store', '~> 1.0.0'
gem "nested_form", '~> 0.3.2' gem 'nested_form', '~> 0.3.2'
# OAuth # OAuth
gem 'oauth2', '~> 1.0.0' gem 'oauth2', '~> 1.2.0'
# Soft deletion # Soft deletion
gem "paranoia", "~> 2.0" gem 'paranoia', '~> 2.0'
# Health check # Health check
gem 'health_check', '~> 1.5.1' gem 'health_check', '~> 1.5.1'
......
...@@ -353,7 +353,7 @@ GEM ...@@ -353,7 +353,7 @@ GEM
jquery-ui-rails (5.0.5) jquery-ui-rails (5.0.5)
railties (>= 3.2.16) railties (>= 3.2.16)
json (1.8.3) json (1.8.3)
jwt (1.5.2) jwt (1.5.4)
kaminari (0.17.0) kaminari (0.17.0)
actionpack (>= 3.0.0) actionpack (>= 3.0.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
...@@ -393,7 +393,7 @@ GEM ...@@ -393,7 +393,7 @@ GEM
mini_portile2 (2.1.0) mini_portile2 (2.1.0)
minitest (5.7.0) minitest (5.7.0)
mousetrap-rails (1.4.6) mousetrap-rails (1.4.6)
multi_json (1.11.2) multi_json (1.12.1)
multi_xml (0.5.5) multi_xml (0.5.5)
multipart-post (2.0.0) multipart-post (2.0.0)
mysql2 (0.3.20) mysql2 (0.3.20)
...@@ -406,12 +406,12 @@ GEM ...@@ -406,12 +406,12 @@ GEM
pkg-config (~> 1.1.7) pkg-config (~> 1.1.7)
numerizer (0.1.1) numerizer (0.1.1)
oauth (0.4.7) oauth (0.4.7)
oauth2 (1.0.0) oauth2 (1.2.0)
faraday (>= 0.8, < 0.10) faraday (>= 0.8, < 0.10)
jwt (~> 1.0) jwt (~> 1.0)
multi_json (~> 1.3) multi_json (~> 1.3)
multi_xml (~> 0.5) multi_xml (~> 0.5)
rack (~> 1.2) rack (>= 1.2, < 3)
octokit (4.3.0) octokit (4.3.0)
sawyer (~> 0.7.0, >= 0.5.3) sawyer (~> 0.7.0, >= 0.5.3)
omniauth (1.3.1) omniauth (1.3.1)
...@@ -439,7 +439,7 @@ GEM ...@@ -439,7 +439,7 @@ GEM
omniauth-gitlab (1.0.1) omniauth-gitlab (1.0.1)
omniauth (~> 1.0) omniauth (~> 1.0)
omniauth-oauth2 (~> 1.0) omniauth-oauth2 (~> 1.0)
omniauth-google-oauth2 (0.2.10) omniauth-google-oauth2 (0.4.1)
addressable (~> 2.3) addressable (~> 2.3)
jwt (~> 1.0) jwt (~> 1.0)
multi_json (~> 1.3) multi_json (~> 1.3)
...@@ -806,7 +806,7 @@ DEPENDENCIES ...@@ -806,7 +806,7 @@ DEPENDENCIES
activerecord-session_store (~> 1.0.0) activerecord-session_store (~> 1.0.0)
acts-as-taggable-on (~> 3.4) acts-as-taggable-on (~> 3.4)
addressable (~> 2.3.8) addressable (~> 2.3.8)
after_commit_queue after_commit_queue (~> 1.3.0)
akismet (~> 2.0) akismet (~> 2.0)
allocations (~> 1.0) allocations (~> 1.0)
asana (~> 0.4.0) asana (~> 0.4.0)
...@@ -815,15 +815,15 @@ DEPENDENCIES ...@@ -815,15 +815,15 @@ DEPENDENCIES
awesome_print (~> 1.2.0) awesome_print (~> 1.2.0)
babosa (~> 1.0.2) babosa (~> 1.0.2)
base32 (~> 0.3.0) base32 (~> 0.3.0)
benchmark-ips benchmark-ips (~> 2.3.0)
better_errors (~> 1.0.1) better_errors (~> 1.0.1)
binding_of_caller (~> 0.7.2) binding_of_caller (~> 0.7.2)
bootstrap-sass (~> 3.3.0) bootstrap-sass (~> 3.3.0)
brakeman (~> 3.3.0) brakeman (~> 3.3.0)
browser (~> 2.2) browser (~> 2.2)
bullet bullet (~> 5.0.0)
bundler-audit bundler-audit (~> 0.5.0)
byebug byebug (~> 8.2.1)
capybara (~> 2.6.2) capybara (~> 2.6.2)
capybara-screenshot (~> 1.0.0) capybara-screenshot (~> 1.0.0)
carrierwave (~> 0.10.0) carrierwave (~> 0.10.0)
...@@ -844,8 +844,8 @@ DEPENDENCIES ...@@ -844,8 +844,8 @@ DEPENDENCIES
email_spec (~> 1.6.0) email_spec (~> 1.6.0)
factory_girl_rails (~> 4.6.0) factory_girl_rails (~> 4.6.0)
ffaker (~> 2.0.0) ffaker (~> 2.0.0)
flay flay (~> 2.6.1)
flog flog (~> 4.3.2)
fog-aws (~> 0.9) fog-aws (~> 0.9)
fog-azure (~> 0.0) fog-azure (~> 0.0)
fog-core (~> 1.40) fog-core (~> 1.40)
...@@ -854,7 +854,7 @@ DEPENDENCIES ...@@ -854,7 +854,7 @@ DEPENDENCIES
fog-openstack (~> 0.1) fog-openstack (~> 0.1)
fog-rackspace (~> 0.1.1) fog-rackspace (~> 0.1.1)
font-awesome-rails (~> 4.6.1) font-awesome-rails (~> 4.6.1)
foreman foreman (~> 0.78.0)
fuubar (~> 2.0.0) fuubar (~> 2.0.0)
gemnasium-gitlab-service (~> 0.2) gemnasium-gitlab-service (~> 0.2)
gemojione (~> 2.6) gemojione (~> 2.6)
...@@ -881,9 +881,9 @@ DEPENDENCIES ...@@ -881,9 +881,9 @@ DEPENDENCIES
jquery-ui-rails (~> 5.0.0) jquery-ui-rails (~> 5.0.0)
jwt jwt
kaminari (~> 0.17.0) kaminari (~> 0.17.0)
knapsack knapsack (~> 1.11.0)
letter_opener_web (~> 1.3.0) letter_opener_web (~> 1.3.0)
license_finder license_finder (~> 2.1.0)
licensee (~> 8.0.0) licensee (~> 8.0.0)
loofah (~> 2.0.3) loofah (~> 2.0.3)
mail_room (~> 0.8) mail_room (~> 0.8)
...@@ -895,7 +895,7 @@ DEPENDENCIES ...@@ -895,7 +895,7 @@ DEPENDENCIES
net-ssh (~> 3.0.1) net-ssh (~> 3.0.1)
newrelic_rpm (~> 3.14) newrelic_rpm (~> 3.14)
nokogiri (~> 1.6.7, >= 1.6.7.2) nokogiri (~> 1.6.7, >= 1.6.7.2)
oauth2 (~> 1.0.0) oauth2 (~> 1.2.0)
octokit (~> 4.3.0) octokit (~> 4.3.0)
omniauth (~> 1.3.1) omniauth (~> 1.3.1)
omniauth-auth0 (~> 1.4.1) omniauth-auth0 (~> 1.4.1)
...@@ -905,7 +905,7 @@ DEPENDENCIES ...@@ -905,7 +905,7 @@ DEPENDENCIES
omniauth-facebook (~> 3.0.0) omniauth-facebook (~> 3.0.0)
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.0) omniauth-google-oauth2 (~> 0.4.1)
omniauth-kerberos (~> 0.3.0) omniauth-kerberos (~> 0.3.0)
omniauth-saml (~> 1.6.0) omniauth-saml (~> 1.6.0)
omniauth-shibboleth (~> 1.2.0) omniauth-shibboleth (~> 1.2.0)
...@@ -916,19 +916,19 @@ DEPENDENCIES ...@@ -916,19 +916,19 @@ DEPENDENCIES
pg (~> 0.18.2) pg (~> 0.18.2)
poltergeist (~> 1.9.0) poltergeist (~> 1.9.0)
premailer-rails (~> 1.9.0) premailer-rails (~> 1.9.0)
pry-rails pry-rails (~> 0.3.4)
rack-attack (~> 4.3.1) rack-attack (~> 4.3.1)
rack-cors (~> 0.4.0) rack-cors (~> 0.4.0)
rack-oauth2 (~> 1.2.1) rack-oauth2 (~> 1.2.1)
rails (= 4.2.6) rails (= 4.2.6)
rails-deprecated_sanitizer (~> 1.0.3) rails-deprecated_sanitizer (~> 1.0.3)
rainbow (~> 2.1.0) rainbow (~> 2.1.0)
rblineprof rblineprof (~> 0.3.6)
rdoc (~> 3.6) rdoc (~> 3.6)
recaptcha (~> 3.0) recaptcha (~> 3.0)
redcarpet (~> 3.3.3) redcarpet (~> 3.3.3)
redis (~> 3.2) redis (~> 3.2)
redis-namespace redis-namespace (~> 1.5.2)
redis-rails (~> 4.0.0) redis-rails (~> 4.0.0)
request_store (~> 1.3.0) request_store (~> 1.3.0)
rerun (~> 0.11.0) rerun (~> 0.11.0)
...@@ -936,7 +936,7 @@ DEPENDENCIES ...@@ -936,7 +936,7 @@ DEPENDENCIES
rouge (~> 1.11) rouge (~> 1.11)
rqrcode-rails3 (~> 0.1.7) rqrcode-rails3 (~> 0.1.7)
rspec-rails (~> 3.5.0) rspec-rails (~> 3.5.0)
rspec-retry rspec-retry (~> 0.4.5)
rubocop (~> 0.40.0) rubocop (~> 0.40.0)
rubocop-rspec (~> 1.5.0) rubocop-rspec (~> 1.5.0)
ruby-fogbugz (~> 0.2.1) ruby-fogbugz (~> 0.2.1)
...@@ -948,7 +948,7 @@ DEPENDENCIES ...@@ -948,7 +948,7 @@ DEPENDENCIES
select2-rails (~> 3.5.9) select2-rails (~> 3.5.9)
sentry-raven (~> 1.1.0) sentry-raven (~> 1.1.0)
settingslogic (~> 2.0.9) settingslogic (~> 2.0.9)
sham_rack sham_rack (~> 1.3.6)
shoulda-matchers (~> 2.8.0) shoulda-matchers (~> 2.8.0)
sidekiq (~> 4.0) sidekiq (~> 4.0)
sidekiq-cron (~> 0.4.0) sidekiq-cron (~> 0.4.0)
......
...@@ -47,14 +47,12 @@ ...@@ -47,14 +47,12 @@
#= require date.format #= require date.format
#= require_directory ./behaviors #= require_directory ./behaviors
#= require_directory ./blob #= require_directory ./blob
#= require_directory ./ci
#= require_directory ./commit #= require_directory ./commit
#= require_directory ./extensions #= require_directory ./extensions
#= require_directory ./lib/utils #= require_directory ./lib/utils
#= require_directory ./u2f #= require_directory ./u2f
#= require_directory . #= require_directory .
#= require fuzzaldrin-plus #= require fuzzaldrin-plus
#= require cropper
#= require u2f #= require u2f
window.slugify = (text) -> window.slugify = (text) ->
......
class @CiBuild class @Build
@interval: null @interval: null
@state: null @state: null
constructor: (@page_url, @build_url, @build_status, @state) -> constructor: (@page_url, @build_url, @build_status, @state) ->
clearInterval(CiBuild.interval) clearInterval(Build.interval)
# Init breakpoint checker # Init breakpoint checker
@bp = Breakpoints.get() @bp = Breakpoints.get()
...@@ -40,7 +40,7 @@ class @CiBuild ...@@ -40,7 +40,7 @@ class @CiBuild
# Check for new build output if user still watching build page # Check for new build output if user still watching build page
# Only valid for runnig build when output changes during time # Only valid for runnig build when output changes during time
# #
CiBuild.interval = setInterval => Build.interval = setInterval =>
if window.location.href.split("#").first() is @page_url if window.location.href.split("#").first() is @page_url
@getBuildTrace() @getBuildTrace()
, 4000 , 4000
......
#= require pager
#= require jquery_nested_form
#= require_tree .
$(document).on 'click', '.assign-all-runner', ->
$(this).replaceWith('<i class="fa fa-refresh fa-spin"></i> Assign in progress..')
window.unbindEvents = ->
$(document).unbind('scroll')
$(document).off('scroll')
document.addEventListener("page:fetch", unbindEvents)
$(document).on 'click', '.badge-codes-toggle', ->
$('.badge-codes-block').toggleClass("hide")
return false
...@@ -131,7 +131,6 @@ class Dispatcher ...@@ -131,7 +131,6 @@ class Dispatcher
when 'dashboard', 'root' when 'dashboard', 'root'
shortcut_handler = new ShortcutsDashboardNavigation() shortcut_handler = new ShortcutsDashboardNavigation()
when 'profiles' when 'profiles'
new Profile()
new NotificationsForm() new NotificationsForm()
new NotificationsDropdown() new NotificationsDropdown()
when 'projects' when 'projects'
......
class @Flash class @Flash
constructor: (message, type = 'alert')-> hideFlash = -> $(@).fadeOut()
@flash = $(".flash-container")
@flash.html("")
innerDiv = $('<div/>', constructor: (message, type = 'alert', parent = null)->
if parent
@flashContainer = parent.find('.flash-container')
else
@flashContainer = $('.flash-container-page')
@flashContainer.html('')
flash = $('<div/>',
class: "flash-#{type}" class: "flash-#{type}"
) )
innerDiv.appendTo(".flash-container") flash.on 'click', hideFlash
textDiv = $("<div/>", textDiv = $('<div/>',
class: "flash-text", class: 'flash-text',
text: message text: message
) )
textDiv.appendTo(innerDiv) textDiv.appendTo(flash)
if @flash.parent().hasClass('content-wrapper') if @flashContainer.parent().hasClass('content-wrapper')
textDiv.addClass('container-fluid container-limited') textDiv.addClass('container-fluid container-limited')
@flash.click -> $(@).fadeOut() flash.appendTo(@flashContainer)
@flash.show() @flashContainer.show()
pinTo: (selector) ->
@flash.detach().appendTo(selector)
...@@ -56,6 +56,7 @@ class GitLabDropdownFilter ...@@ -56,6 +56,7 @@ class GitLabDropdownFilter
return BLUR_KEYCODES.indexOf(keyCode) >= 0 return BLUR_KEYCODES.indexOf(keyCode) >= 0
filter: (search_text) -> filter: (search_text) ->
@options.onFilter(search_text) if @options.onFilter
data = @options.data() data = @options.data()
if data? and not @options.filterByText if data? and not @options.filterByText
...@@ -195,6 +196,7 @@ class GitLabDropdown ...@@ -195,6 +196,7 @@ class GitLabDropdown
@filter = new GitLabDropdownFilter @filterInput, @filter = new GitLabDropdownFilter @filterInput,
filterInputBlur: @filterInputBlur filterInputBlur: @filterInputBlur
filterByText: @options.filterByText filterByText: @options.filterByText
onFilter: @options.onFilter
remote: @options.filterRemote remote: @options.filterRemote
query: @options.data query: @options.data
keys: searchFields keys: searchFields
...@@ -530,7 +532,7 @@ class GitLabDropdown ...@@ -530,7 +532,7 @@ class GitLabDropdown
if $el.length if $el.length
e.preventDefault() e.preventDefault()
e.stopImmediatePropagation() e.stopImmediatePropagation()
$(selector, @dropdown)[0].click() $el.first().trigger('click')
addArrowKeyEvent: -> addArrowKeyEvent: ->
ARROW_KEY_CODES = [38, 40] ARROW_KEY_CODES = [38, 40]
......
...@@ -5,12 +5,12 @@ ...@@ -5,12 +5,12 @@
w.gl.utils.isInGroupsPage = -> w.gl.utils.isInGroupsPage = ->
return $('body').data('page').split(':')[0] is 'groups' return gl.utils.getPagePath() is 'groups'
w.gl.utils.isInProjectPage = -> w.gl.utils.isInProjectPage = ->
return $('body').data('page').split(':')[0] is 'projects' return gl.utils.getPagePath() is 'projects'
w.gl.utils.getProjectSlug = -> w.gl.utils.getProjectSlug = ->
...@@ -40,6 +40,9 @@ ...@@ -40,6 +40,9 @@
e.stopImmediatePropagation() e.stopImmediatePropagation()
return false return false
gl.utils.getPagePath = ->
return $('body').data('page').split(':')[0]
jQuery.timefor = (time, suffix, expiredLabel) -> jQuery.timefor = (time, suffix, expiredLabel) ->
......
...@@ -159,6 +159,7 @@ class @MergeRequestTabs ...@@ -159,6 +159,7 @@ class @MergeRequestTabs
$('#diffs').html data.html $('#diffs').html data.html
gl.utils.localTimeAgo($('.js-timeago', 'div#diffs')) gl.utils.localTimeAgo($('.js-timeago', 'div#diffs'))
$('#diffs .js-syntax-highlight').syntaxHighlight() $('#diffs .js-syntax-highlight').syntaxHighlight()
$('#diffs .diff-file').singleFileDiff()
@expandViewContainer() if @diffViewType() is 'parallel' @expandViewContainer() if @diffViewType() is 'parallel'
@diffsLoaded = true @diffsLoaded = true
@scrollToElement("#diffs") @scrollToElement("#diffs")
......
...@@ -194,8 +194,7 @@ class @Notes ...@@ -194,8 +194,7 @@ class @Notes
renderNote: (note) -> renderNote: (note) ->
unless note.valid unless note.valid
if note.award if note.award
flash = new Flash('You have already awarded this emoji!', 'alert') new Flash('You have already awarded this emoji!', 'alert')
flash.pinTo('.header-content')
return return
if note.award if note.award
...@@ -325,6 +324,8 @@ class @Notes ...@@ -325,6 +324,8 @@ class @Notes
form.find("#note_position").remove() form.find("#note_position").remove()
form.find("#note_type").remove() form.find("#note_type").remove()
@parentTimeline = form.parents('.timeline')
### ###
General note form setup. General note form setup.
...@@ -357,8 +358,7 @@ class @Notes ...@@ -357,8 +358,7 @@ class @Notes
@renderNote(note) @renderNote(note)
addNoteError: (xhr, note, status) => addNoteError: (xhr, note, status) =>
flash = new Flash('Your comment could not be submitted! Please check your network connection and try again.', 'alert') new Flash('Your comment could not be submitted! Please check your network connection and try again.', 'alert', @parentTimeline)
flash.pinTo('.md-area')
### ###
Called in response to the new note form being submitted Called in response to the new note form being submitted
......
...@@ -78,3 +78,6 @@ $ -> ...@@ -78,3 +78,6 @@ $ ->
if comment && comment.length > 1 && $title.val() == '' if comment && comment.length > 1 && $title.val() == ''
$title.val(comment[1]).change() $title.val(comment[1]).change()
if gl.utils.getPagePath() == 'profiles'
new Profile()
class @ProtectedBranchSelect
constructor: (currentProject) ->
$('.dropdown-footer').hide();
@dropdown = $('.js-protected-branch-select').glDropdown(
data: @getProtectedBranches
filterable: true
remote: false
search:
fields: ['title']
selectable: true
toggleLabel: (selected) -> if (selected and 'id' of selected) then selected.title else 'Protected Branch'
fieldName: 'protected_branch[name]'
text: (protected_branch) -> _.escape(protected_branch.title)
id: (protected_branch) -> _.escape(protected_branch.id)
onFilter: @toggleCreateNewButton
clicked: () -> $('.protect-branch-btn').attr('disabled', false)
)
$('.create-new-protected-branch').on 'click', (event) =>
# Refresh the dropdown's data, which ends up calling `getProtectedBranches`
@dropdown.data('glDropdown').remote.execute()
@dropdown.data('glDropdown').selectRowAtIndex(event, 0)
getProtectedBranches: (term, callback) =>
if @selectedBranch
callback(gon.open_branches.concat(@selectedBranch))
else
callback(gon.open_branches)
toggleCreateNewButton: (branchName) =>
@selectedBranch = { title: branchName, id: branchName, text: branchName }
if branchName is ''
$('.protected-branch-select-footer-list').addClass('hidden')
$('.dropdown-footer').hide();
else
$('.create-new-protected-branch').text("Create Protected Branch: #{branchName}")
$('.protected-branch-select-footer-list').removeClass('hidden')
$('.dropdown-footer').show();
...@@ -11,7 +11,8 @@ $ -> ...@@ -11,7 +11,8 @@ $ ->
dataType: "json" dataType: "json"
data: data:
id: id id: id
developers_can_push: checked protected_branch:
developers_can_push: checked
success: -> success: ->
row = $(e.target) row = $(e.target)
......
class @SingleFileDiff
WRAPPER = '<div class="diff-content diff-wrap-lines"></div>'
LOADING_HTML = '<i class="fa fa-spinner fa-spin"></i>'
ERROR_HTML = '<div class="nothing-here-block"><i class="fa fa-warning"></i> Could not load diff</div>'
COLLAPSED_HTML = '<div class="nothing-here-block diff-collapsed">This diff is collapsed. Click to expand it.</div>'
constructor: (@file) ->
@content = $('.diff-content', @file)
@diffForPath = @content.find('[data-diff-for-path]').data 'diff-for-path'
@isOpen = !@diffForPath
if @diffForPath
@collapsedContent = @content
@loadingContent = $(WRAPPER).addClass('loading').html(LOADING_HTML).hide()
@content = null
@collapsedContent.after(@loadingContent)
else
@collapsedContent = $(WRAPPER).html(COLLAPSED_HTML).hide()
@content.after(@collapsedContent)
@collapsedContent.on 'click', @toggleDiff
$('.file-title > a', @file).on 'click', @toggleDiff
toggleDiff: (e) =>
@isOpen = !@isOpen
if not @isOpen and not @hasError
@content.hide()
@collapsedContent.show()
else if @content
@collapsedContent.hide()
@content.show()
else
@getContentHTML()
getContentHTML: ->
@collapsedContent.hide()
@loadingContent.show()
$.get @diffForPath, (data) =>
@loadingContent.hide()
if data.html
@content = $(data.html)
@content.syntaxHighlight()
else
@hasError = true
@content = $(ERROR_HTML)
@collapsedContent.after(@content)
return
$.fn.singleFileDiff = ->
return @each ->
if not $.data this, 'singleFileDiff'
$.data this, 'singleFileDiff', new SingleFileDiff this
.blank-state-welcome {
text-align: center;
border-bottom: 1px solid $border-color;
.blank-state-text {
margin-bottom: 0;
}
}
.blank-state { .blank-state {
padding-top: 20px; padding-top: 20px;
padding-bottom: 20px; padding-bottom: 20px;
...@@ -6,7 +15,15 @@ ...@@ -6,7 +15,15 @@
.blank-state-no-icon { .blank-state-no-icon {
padding-top: 40px; padding-top: 40px;
padding-bottom: 40px; padding-bottom: 40px;
}
.blank-state-icon {
padding-bottom: 20px;
path {
fill: $gray-darkest;
}
} }
.blank-state-title { .blank-state-title {
...@@ -21,3 +38,7 @@ ...@@ -21,3 +38,7 @@
margin-bottom: $gl-padding; margin-bottom: $gl-padding;
font-size: 15px; font-size: 15px;
} }
.blank-state-welcome-title {
font-size: 24px;
}
...@@ -16,6 +16,9 @@ ...@@ -16,6 +16,9 @@
font-weight: normal; font-weight: normal;
font-size: 16px; font-size: 16px;
line-height: 36px; line-height: 36px;
&.diff-collapsed {
cursor: pointer;
}
} }
.row-content-block { .row-content-block {
......
.flash-container { .flash-container {
cursor: pointer; cursor: pointer;
margin: 0; margin: 0;
margin-bottom: $gl-padding;
font-size: 14px; font-size: 14px;
width: 100%;
z-index: 100; z-index: 100;
.flash-notice { .flash-notice {
...@@ -18,9 +18,27 @@ ...@@ -18,9 +18,27 @@
} }
.flash-notice, .flash-alert { .flash-notice, .flash-alert {
.container-fluid.flash-text { border-radius: $border-radius-default;
.container-fluid.container-limited.flash-text {
background: transparent; background: transparent;
} }
} }
&.flash-container-page {
margin-bottom: 0;
.flash-notice, .flash-alert {
border-radius: 0;
}
}
}
@media (max-width: $screen-md-min) {
ul.notes {
.flash-container.timeline-content {
margin-left: 0;
}
}
} }
...@@ -175,6 +175,12 @@ ul.content-list { ...@@ -175,6 +175,12 @@ ul.content-list {
.panel > .content-list > li { .panel > .content-list > li {
padding: $gl-padding-top $gl-padding; padding: $gl-padding-top $gl-padding;
&.commit {
@media (min-width: $screen-sm-min) {
padding-left: 46px + $gl-padding;
}
}
} }
ul.controls { ul.controls {
......
...@@ -77,10 +77,10 @@ ...@@ -77,10 +77,10 @@
&.sub-nav { &.sub-nav {
text-align: center; text-align: center;
background-color: $background-color; background-color: $dark-background-color;
.container-fluid { .container-fluid {
background-color: $background-color; background-color: $dark-background-color;
margin-bottom: 0; margin-bottom: 0;
} }
......
...@@ -3,6 +3,12 @@ ...@@ -3,6 +3,12 @@
padding-bottom: 25px; padding-bottom: 25px;
transition: padding $sidebar-transition-duration; transition: padding $sidebar-transition-duration;
&.page-sidebar-pinned {
.sidebar-wrapper {
@include box-shadow(none);
}
}
.sidebar-wrapper { .sidebar-wrapper {
position: fixed; position: fixed;
top: 0; top: 0;
...@@ -11,6 +17,7 @@ ...@@ -11,6 +17,7 @@
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
transition: width $sidebar-transition-duration; transition: width $sidebar-transition-duration;
@include box-shadow(2px 0 16px 0 #bbb);
} }
} }
......
...@@ -12,10 +12,11 @@ $sidebar-breakpoint: 1024px; ...@@ -12,10 +12,11 @@ $sidebar-breakpoint: 1024px;
/* /*
* UI elements * UI elements
*/ */
$border-color: #e5e5e5; $border-color: #e5e5e5;
$focus-border-color: #3aabf0; $focus-border-color: #3aabf0;
$table-border-color: #f0f0f0; $table-border-color: #f0f0f0;
$background-color: #fafafa; $background-color: #fafafa;
$dark-background-color: #f7f7f7;
/* /*
* Text * Text
...@@ -153,9 +154,6 @@ $warning-message-bg: #fbf2d9; ...@@ -153,9 +154,6 @@ $warning-message-bg: #fbf2d9;
$warning-message-color: #9e8e60; $warning-message-color: #9e8e60;
$warning-message-border: #f0e2bb; $warning-message-border: #f0e2bb;
/* header */
$light-grey-header: #faf9f9;
/* tanuki logo colors */ /* tanuki logo colors */
$tanuki-red: #e24329; $tanuki-red: #e24329;
$tanuki-orange: #fc6d26; $tanuki-orange: #fc6d26;
......
...@@ -63,8 +63,8 @@ form.edit-issue { ...@@ -63,8 +63,8 @@ form.edit-issue {
.merge-request, .merge-request,
.issue { .issue {
&.today { &.today {
background: #efe; background: #f8feef;
border-color: #cec; border-color: #e1e8d5;
} }
&.closed { &.closed {
......
...@@ -87,6 +87,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController ...@@ -87,6 +87,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:version_check_enabled, :version_check_enabled,
:admin_notification_email, :admin_notification_email,
:user_oauth_applications, :user_oauth_applications,
:user_default_external,
:shared_runners_enabled, :shared_runners_enabled,
:shared_runners_text, :shared_runners_text,
:max_artifacts_size, :max_artifacts_size,
......
module DiffForPath
extend ActiveSupport::Concern
def render_diff_for_path(diffs, diff_refs, project)
diff_file = safe_diff_files(diffs, diff_refs: diff_refs, repository: project.repository).find do |diff|
diff.old_path == params[:old_path] && diff.new_path == params[:new_path]
end
return render_404 unless diff_file
diff_commit = commit_for_diff(diff_file)
blob = diff_file.blob(diff_commit)
@expand_all_diffs = true
locals = {
diff_file: diff_file,
diff_commit: diff_commit,
diff_refs: diff_refs,
blob: blob,
project: project
}
render json: { html: view_to_html_string('projects/diffs/_content', locals) }
end
end
...@@ -23,10 +23,9 @@ class Projects::ArtifactsController < Projects::ApplicationController ...@@ -23,10 +23,9 @@ class Projects::ArtifactsController < Projects::ApplicationController
entry = build.artifacts_metadata_entry(params[:path]) entry = build.artifacts_metadata_entry(params[:path])
if entry.exists? if entry.exists?
render json: { archive: build.artifacts_file.path, send_artifacts_entry(build, entry)
entry: Base64.encode64(entry.path) }
else else
render json: {}, status: 404 render_404
end end
end end
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
# Not to be confused with CommitsController, plural. # Not to be confused with CommitsController, plural.
class Projects::CommitController < Projects::ApplicationController class Projects::CommitController < Projects::ApplicationController
include CreatesCommit include CreatesCommit
include DiffForPath
include DiffHelper include DiffHelper
# Authorize # Authorize
...@@ -11,29 +12,14 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -11,29 +12,14 @@ class Projects::CommitController < Projects::ApplicationController
before_action :authorize_update_build!, only: [:cancel_builds, :retry_builds] before_action :authorize_update_build!, only: [:cancel_builds, :retry_builds]
before_action :authorize_read_commit_status!, only: [:builds] before_action :authorize_read_commit_status!, only: [:builds]
before_action :commit before_action :commit
before_action :define_show_vars, only: [:show, :builds] before_action :define_commit_vars, only: [:show, :diff_for_path, :builds]
before_action :define_status_vars, only: [:show, :builds]
before_action :define_note_vars, only: [:show, :diff_for_path]
before_action :authorize_edit_tree!, only: [:revert, :cherry_pick] before_action :authorize_edit_tree!, only: [:revert, :cherry_pick]
def show def show
apply_diff_view_cookie! apply_diff_view_cookie!
@grouped_diff_notes = commit.notes.grouped_diff_notes
@notes = commit.notes.non_diff_notes.fresh
Banzai::NoteRenderer.render(
@grouped_diff_notes.values.flatten + @notes,
@project,
current_user,
)
@note = @project.build_commit_note(commit)
@noteable = @commit
@comments_target = {
noteable_type: 'Commit',
commit_id: @commit.id
}
respond_to do |format| respond_to do |format|
format.html format.html
format.diff { render text: @commit.to_diff } format.diff { render text: @commit.to_diff }
...@@ -41,6 +27,10 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -41,6 +27,10 @@ class Projects::CommitController < Projects::ApplicationController
end end
end end
def diff_for_path
render_diff_for_path(@diffs, @commit.diff_refs, @project)
end
def builds def builds
end end
...@@ -114,7 +104,7 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -114,7 +104,7 @@ class Projects::CommitController < Projects::ApplicationController
@ci_builds ||= Ci::Build.where(pipeline: pipelines) @ci_builds ||= Ci::Build.where(pipeline: pipelines)
end end
def define_show_vars def define_commit_vars
return git_not_found! unless commit return git_not_found! unless commit
opts = diff_options opts = diff_options
...@@ -122,7 +112,28 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -122,7 +112,28 @@ class Projects::CommitController < Projects::ApplicationController
@diffs = commit.diffs(opts) @diffs = commit.diffs(opts)
@notes_count = commit.notes.count @notes_count = commit.notes.count
end
def define_note_vars
@grouped_diff_notes = commit.notes.grouped_diff_notes
@notes = commit.notes.non_diff_notes.fresh
Banzai::NoteRenderer.render(
@grouped_diff_notes.values.flatten + @notes,
@project,
current_user,
)
@note = @project.build_commit_note(commit)
@noteable = @commit
@comments_target = {
noteable_type: 'Commit',
commit_id: @commit.id
}
end
def define_status_vars
@statuses = CommitStatus.where(pipeline: pipelines) @statuses = CommitStatus.where(pipeline: pipelines)
@builds = Ci::Build.where(pipeline: pipelines) @builds = Ci::Build.where(pipeline: pipelines)
end end
......
require 'addressable/uri' require 'addressable/uri'
class Projects::CompareController < Projects::ApplicationController class Projects::CompareController < Projects::ApplicationController
include DiffForPath
include DiffHelper include DiffHelper
# Authorize # Authorize
before_action :require_non_empty_project before_action :require_non_empty_project
before_action :authorize_download_code! before_action :authorize_download_code!
before_action :assign_ref_vars, only: [:index, :show] before_action :define_ref_vars, only: [:index, :show, :diff_for_path]
before_action :define_diff_vars, only: [:show, :diff_for_path]
before_action :merge_request, only: [:index, :show] before_action :merge_request, only: [:index, :show]
def index def index
end end
def show def show
compare = CompareService.new. end
execute(@project, @head_ref, @project, @start_ref, diff_options)
def diff_for_path
return render_404 unless @compare
render_diff_for_path(@diffs, @diff_refs, @project)
end
def create
redirect_to namespace_project_compare_path(@project.namespace, @project,
params[:from], params[:to])
end
private
if compare def define_ref_vars
@commits = Commit.decorate(compare.commits, @project) @start_ref = Addressable::URI.unescape(params[:from])
@ref = @head_ref = Addressable::URI.unescape(params[:to])
end
def define_diff_vars
@compare = CompareService.new.execute(@project, @head_ref, @project, @start_ref)
if @compare
@commits = Commit.decorate(@compare.commits, @project)
@start_commit = @project.commit(@start_ref) @start_commit = @project.commit(@start_ref)
@commit = @project.commit(@head_ref) @commit = @project.commit(@head_ref)
@base_commit = @project.merge_base_commit(@start_ref, @head_ref) @base_commit = @project.merge_base_commit(@start_ref, @head_ref)
@diffs = compare.diffs(diff_options) @diffs = @compare.diffs(diff_options)
@diff_refs = Gitlab::Diff::DiffRefs.new( @diff_refs = Gitlab::Diff::DiffRefs.new(
base_sha: @base_commit.try(:sha), base_sha: @base_commit.try(:sha),
start_sha: @start_commit.try(:sha), start_sha: @start_commit.try(:sha),
...@@ -35,18 +57,6 @@ class Projects::CompareController < Projects::ApplicationController ...@@ -35,18 +57,6 @@ class Projects::CompareController < Projects::ApplicationController
end end
end end
def create
redirect_to namespace_project_compare_path(@project.namespace, @project,
params[:from], params[:to])
end
private
def assign_ref_vars
@start_ref = Addressable::URI.unescape(params[:from])
@ref = @head_ref = Addressable::URI.unescape(params[:to])
end
def merge_request def merge_request
@merge_request ||= @project.merge_requests.opened. @merge_request ||= @project.merge_requests.opened.
find_by(source_project: @project, source_branch: @head_ref, target_branch: @start_ref) find_by(source_project: @project, source_branch: @head_ref, target_branch: @start_ref)
......
class Projects::MergeRequestsController < Projects::ApplicationController class Projects::MergeRequestsController < Projects::ApplicationController
include ToggleSubscriptionAction include ToggleSubscriptionAction
include DiffForPath
include DiffHelper include DiffHelper
include IssuableActions include IssuableActions
include ToggleAwardEmoji include ToggleAwardEmoji
...@@ -9,10 +10,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -9,10 +10,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController
:edit, :update, :show, :diffs, :commits, :builds, :merge, :merge_check, :edit, :update, :show, :diffs, :commits, :builds, :merge, :merge_check,
:ci_status, :toggle_subscription, :cancel_merge_when_build_succeeds, :remove_wip :ci_status, :toggle_subscription, :cancel_merge_when_build_succeeds, :remove_wip
] ]
before_action :closes_issues, only: [:edit, :update, :show, :diffs, :commits, :builds]
before_action :validates_merge_request, only: [:show, :diffs, :commits, :builds] before_action :validates_merge_request, only: [:show, :diffs, :commits, :builds]
before_action :define_show_vars, only: [:show, :diffs, :commits, :builds] before_action :define_show_vars, only: [:show, :diffs, :commits, :builds]
before_action :define_widget_vars, only: [:merge, :cancel_merge_when_build_succeeds, :merge_check] before_action :define_widget_vars, only: [:merge, :cancel_merge_when_build_succeeds, :merge_check]
before_action :define_commit_vars, only: [:diffs]
before_action :define_diff_comment_vars, only: [:diffs]
before_action :ensure_ref_fetched, only: [:show, :diffs, :commits, :builds] before_action :ensure_ref_fetched, only: [:show, :diffs, :commits, :builds]
# Allow read any merge_request # Allow read any merge_request
...@@ -53,12 +55,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -53,12 +55,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end end
def show def show
@note_counts = Note.where(commit_id: @merge_request.commits.map(&:id)).
group(:commit_id).count
respond_to do |format| respond_to do |format|
format.html format.html
format.json do format.json do
render json: @merge_request render json: @merge_request
end end
...@@ -80,25 +79,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -80,25 +79,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def diffs def diffs
apply_diff_view_cookie! apply_diff_view_cookie!
@commit = @merge_request.diff_head_commit @merge_request_diff = @merge_request.merge_request_diff
@base_commit = @merge_request.diff_base_commit || @merge_request.likely_diff_base_commit
@comments_target = {
noteable_type: 'MergeRequest',
noteable_id: @merge_request.id
}
@use_legacy_diff_notes = !@merge_request.support_new_diff_notes?
@grouped_diff_notes = @merge_request.notes.grouped_diff_notes
Banzai::NoteRenderer.render(
@grouped_diff_notes.values.flatten,
@project,
current_user,
@path,
@project_wiki,
@ref
)
respond_to do |format| respond_to do |format|
format.html format.html
...@@ -106,10 +87,37 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -106,10 +87,37 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end end
end end
# With an ID param, loads the MR at that ID. Otherwise, accepts the same params as #new
# and uses that (unsaved) MR.
#
def diff_for_path
if params[:id]
merge_request
define_diff_comment_vars
else
build_merge_request
@diff_notes_disabled = true
@grouped_diff_notes = {}
end
define_commit_vars
diffs = @merge_request.diffs(diff_options)
render_diff_for_path(diffs, @merge_request.diff_refs, @merge_request.project)
end
def commits def commits
respond_to do |format| respond_to do |format|
format.html { render 'show' } format.html { render 'show' }
format.json { render json: { html: view_to_html_string('projects/merge_requests/show/_commits') } } format.json do
# Get commits from repository
# or from cache if already merged
@commits = @merge_request.commits
@note_counts = Note.where(commit_id: @commits.map(&:id)).
group(:commit_id).count
render json: { html: view_to_html_string('projects/merge_requests/show/_commits') }
end
end end
end end
...@@ -121,8 +129,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -121,8 +129,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end end
def new def new
params[:merge_request] ||= ActionController::Parameters.new(source_project: @project) build_merge_request
@merge_request = MergeRequests::BuildService.new(project, current_user, merge_request_params).execute
@noteable = @merge_request @noteable = @merge_request
@target_branches = if @merge_request.target_project @target_branches = if @merge_request.target_project
...@@ -308,10 +315,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -308,10 +315,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
alias_method :issuable, :merge_request alias_method :issuable, :merge_request
alias_method :awardable, :merge_request alias_method :awardable, :merge_request
def closes_issues
@closes_issues ||= @merge_request.closes_issues
end
def authorize_update_merge_request! def authorize_update_merge_request!
return render_404 unless can?(current_user, :update_merge_request, @merge_request) return render_404 unless can?(current_user, :update_merge_request, @merge_request)
end end
...@@ -340,14 +343,33 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -340,14 +343,33 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end end
def define_show_vars def define_show_vars
@noteable = @merge_request
@commits_count = @merge_request.commits.count
@pipeline = @merge_request.pipeline
@statuses = @pipeline.statuses if @pipeline
if @merge_request.locked_long_ago?
@merge_request.unlock_mr
@merge_request.close
end
if request.format == :html || action_name == 'show'
define_show_html_vars
end
end
# Discussion tab data is only required on html requests
def define_show_html_vars
# Build a note object for comment form # Build a note object for comment form
@note = @project.notes.new(noteable: @merge_request) @note = @project.notes.new(noteable: @noteable)
@discussions = @merge_request.mr_and_commit_notes. @discussions = @noteable.mr_and_commit_notes.
inc_author_project_award_emoji. inc_author_project_award_emoji.
fresh. fresh.
discussions discussions
# This is not executed lazily
@notes = Banzai::NoteRenderer.render( @notes = Banzai::NoteRenderer.render(
@discussions.flatten, @discussions.flatten,
@project, @project,
...@@ -356,28 +378,35 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -356,28 +378,35 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@project_wiki, @project_wiki,
@ref @ref
) )
@noteable = @merge_request
# Get commits from repository
# or from cache if already merged
@commits = @merge_request.commits
@merge_request_diff = @merge_request.merge_request_diff
@pipeline = @merge_request.pipeline
@statuses = @pipeline.statuses if @pipeline
if @merge_request.locked_long_ago?
@merge_request.unlock_mr
@merge_request.close
end
end end
def define_widget_vars def define_widget_vars
@pipeline = @merge_request.pipeline @pipeline = @merge_request.pipeline
@pipelines = [@pipeline].compact @pipelines = [@pipeline].compact
closes_issues end
def define_commit_vars
@commit = @merge_request.diff_head_commit
@base_commit = @merge_request.diff_base_commit || @merge_request.likely_diff_base_commit
end
def define_diff_comment_vars
@comments_target = {
noteable_type: 'MergeRequest',
noteable_id: @merge_request.id
}
@use_legacy_diff_notes = !@merge_request.support_new_diff_notes?
@grouped_diff_notes = @merge_request.notes.grouped_diff_notes
Banzai::NoteRenderer.render(
@grouped_diff_notes.values.flatten,
@project,
current_user,
@path,
@project_wiki,
@ref
)
end end
def invalid_mr def invalid_mr
...@@ -408,4 +437,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -408,4 +437,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController
params[:merge_when_build_succeeds].present? && params[:merge_when_build_succeeds].present? &&
@merge_request.pipeline && @merge_request.pipeline.active? @merge_request.pipeline && @merge_request.pipeline.active?
end end
def build_merge_request
params[:merge_request] ||= ActionController::Parameters.new(source_project: @project)
@merge_request = MergeRequests::BuildService.new(project, current_user, merge_request_params).execute
end
end end
...@@ -2,12 +2,14 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController ...@@ -2,12 +2,14 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
# Authorize # Authorize
before_action :require_non_empty_project before_action :require_non_empty_project
before_action :authorize_admin_project! before_action :authorize_admin_project!
before_action :load_protected_branch, only: [:show, :update, :destroy]
layout "project_settings" layout "project_settings"
def index def index
@branches = @project.protected_branches.to_a @protected_branches = @project.protected_branches.order(:name).page(params[:page])
@protected_branch = @project.protected_branches.new @protected_branch = @project.protected_branches.new
gon.push({ open_branches: @project.open_branches.map { |br| { text: br.name, id: br.name, title: br.name } } })
end end
def create def create
...@@ -16,26 +18,24 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController ...@@ -16,26 +18,24 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
@project) @project)
end end
def update def show
protected_branch = @project.protected_branches.find(params[:id]) @matching_branches = @protected_branch.matching(@project.repository.branches)
end
if protected_branch &&
protected_branch.update_attributes(
developers_can_push: params[:developers_can_push]
)
def update
if @protected_branch && @protected_branch.update_attributes(protected_branch_params)
respond_to do |format| respond_to do |format|
format.json { render json: protected_branch, status: :ok } format.json { render json: @protected_branch, status: :ok }
end end
else else
respond_to do |format| respond_to do |format|
format.json { render json: protected_branch.errors, status: :unprocessable_entity } format.json { render json: @protected_branch.errors, status: :unprocessable_entity }
end end
end end
end end
def destroy def destroy
@project.protected_branches.find(params[:id]).destroy @protected_branch.destroy
respond_to do |format| respond_to do |format|
format.html { redirect_to namespace_project_protected_branches_path } format.html { redirect_to namespace_project_protected_branches_path }
...@@ -45,6 +45,10 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController ...@@ -45,6 +45,10 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
private private
def load_protected_branch
@protected_branch = @project.protected_branches.find(params[:id])
end
def protected_branch_params def protected_branch_params
params.require(:protected_branch).permit(:name, :developers_can_push) params.require(:protected_branch).permit(:name, :developers_can_push)
end end
......
...@@ -53,11 +53,11 @@ class ProjectsController < Projects::ApplicationController ...@@ -53,11 +53,11 @@ class ProjectsController < Projects::ApplicationController
notice: "Project '#{@project.name}' was successfully updated." notice: "Project '#{@project.name}' was successfully updated."
) )
end end
format.js
else else
format.html { render 'edit' } format.html { render 'edit' }
format.js
end end
format.js
end end
end end
......
...@@ -31,7 +31,7 @@ module AppearancesHelper ...@@ -31,7 +31,7 @@ module AppearancesHelper
end end
end end
def navbar_icon(icon_name) def navbar_icon(icon_name, size: 16)
render "shared/icons/#{icon_name}.svg" render "shared/icons/#{icon_name}.svg", size: size
end end
end end
...@@ -8,6 +8,10 @@ module DiffHelper ...@@ -8,6 +8,10 @@ module DiffHelper
[marked_old_line, marked_new_line] [marked_old_line, marked_new_line]
end end
def expand_all_diffs?
@expand_all_diffs || params[:expand_all_diffs].present?
end
def diff_view def diff_view
diff_views = %w(inline parallel) diff_views = %w(inline parallel)
...@@ -18,16 +22,14 @@ module DiffHelper ...@@ -18,16 +22,14 @@ module DiffHelper
end end
end end
def diff_hard_limit_enabled?
params[:force_show_diff].present?
end
def diff_options def diff_options
options = { ignore_whitespace_change: hide_whitespace? } default_options = Commit.max_diff_options
if diff_hard_limit_enabled?
options.merge!(Commit.max_diff_options) if action_name == 'diff_for_path'
default_options[:paths] = params.values_at(:old_path, :new_path)
end end
options
default_options.merge(ignore_whitespace_change: hide_whitespace?)
end end
def safe_diff_files(diffs, diff_refs: nil, repository: nil) def safe_diff_files(diffs, diff_refs: nil, repository: nil)
...@@ -90,7 +92,7 @@ module DiffHelper ...@@ -90,7 +92,7 @@ module DiffHelper
def commit_for_diff(diff_file) def commit_for_diff(diff_file)
return diff_file.content_commit if diff_file.content_commit return diff_file.content_commit if diff_file.content_commit
if diff_file.deleted_file if diff_file.deleted_file
@base_commit || @commit.parent || @commit @base_commit || @commit.parent || @commit
else else
......
...@@ -55,6 +55,10 @@ module MergeRequestsHelper ...@@ -55,6 +55,10 @@ module MergeRequestsHelper
end.sort.to_sentence end.sort.to_sentence
end end
def mr_closes_issues
@mr_closes_issues ||= @merge_request.closes_issues
end
def mr_change_branches_path(merge_request) def mr_change_branches_path(merge_request)
new_namespace_project_merge_request_path( new_namespace_project_merge_request_path(
@project.namespace, @project, @project.namespace, @project,
...@@ -92,4 +96,8 @@ module MergeRequestsHelper ...@@ -92,4 +96,8 @@ module MergeRequestsHelper
["#{source_path}:#{source_branch}", "#{target_path}:#{target_branch}"] ["#{source_path}:#{source_branch}", "#{target_path}:#{target_branch}"]
end end
end end
def merge_request_button_visibility(merge_request, closed)
return 'hidden' if merge_request.closed? == closed || (merge_request.merged? == closed && !merge_request.closed?)
end
end end
...@@ -23,4 +23,11 @@ module TimeHelper ...@@ -23,4 +23,11 @@ module TimeHelper
def date_from_to(from, to) def date_from_to(from, to)
"#{from.to_s(:short)} - #{to.to_s(:short)}" "#{from.to_s(:short)} - #{to.to_s(:short)}"
end end
def duration_in_numbers(finished_at, started_at)
diff_in_seconds = finished_at.to_i - started_at.to_i
time_format = diff_in_seconds < 1.hour ? "%M:%S" : "%H:%M:%S"
Time.at(diff_in_seconds).utc.strftime(time_format)
end
end end
...@@ -28,4 +28,10 @@ module WorkhorseHelper ...@@ -28,4 +28,10 @@ module WorkhorseHelper
headers.store(*Gitlab::Workhorse.send_git_archive(repository, ref: ref, format: format)) headers.store(*Gitlab::Workhorse.send_git_archive(repository, ref: ref, format: format))
head :ok head :ok
end end
# Send an entry from artifacts through Workhorse
def send_artifacts_entry(build, entry)
headers.store(*Gitlab::Workhorse.send_artifacts_entry(build, entry))
head :ok
end
end end
...@@ -142,6 +142,7 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -142,6 +142,7 @@ class ApplicationSetting < ActiveRecord::Base
send_user_confirmation_email: false, send_user_confirmation_email: false,
container_registry_token_expire_delay: 5, container_registry_token_expire_delay: 5,
repository_storage: 'default', repository_storage: 'default',
user_default_external: false,
) )
end end
......
...@@ -13,6 +13,7 @@ module Ci ...@@ -13,6 +13,7 @@ module Ci
scope :ignore_failures, ->() { where(allow_failure: false) } scope :ignore_failures, ->() { where(allow_failure: false) }
scope :with_artifacts, ->() { where.not(artifacts_file: nil) } scope :with_artifacts, ->() { where.not(artifacts_file: nil) }
scope :with_expired_artifacts, ->() { with_artifacts.where('artifacts_expire_at < ?', Time.now) } scope :with_expired_artifacts, ->() { with_artifacts.where('artifacts_expire_at < ?', Time.now) }
scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) }
mount_uploader :artifacts_file, ArtifactUploader mount_uploader :artifacts_file, ArtifactUploader
mount_uploader :artifacts_metadata, ArtifactUploader mount_uploader :artifacts_metadata, ArtifactUploader
...@@ -25,10 +26,6 @@ module Ci ...@@ -25,10 +26,6 @@ module Ci
after_create :execute_hooks after_create :execute_hooks
class << self class << self
def last_month
where('created_at > ?', Date.today - 1.month)
end
def first_pending def first_pending
pending.unstarted.order('created_at ASC').first pending.unstarted.order('created_at ASC').first
end end
......
...@@ -23,7 +23,7 @@ class CommitRange ...@@ -23,7 +23,7 @@ class CommitRange
attr_reader :commit_from, :notation, :commit_to attr_reader :commit_from, :notation, :commit_to
attr_reader :ref_from, :ref_to attr_reader :ref_from, :ref_to
# Optional Project model # The Project model
attr_accessor :project attr_accessor :project
# The beginning and ending refs can be named or SHAs, and # The beginning and ending refs can be named or SHAs, and
...@@ -56,7 +56,7 @@ class CommitRange ...@@ -56,7 +56,7 @@ class CommitRange
# Initialize a CommitRange # Initialize a CommitRange
# #
# range_string - The String commit range. # range_string - The String commit range.
# project - An optional Project model. # project - The Project model.
# #
# Raises ArgumentError if `range_string` does not match `PATTERN`. # Raises ArgumentError if `range_string` does not match `PATTERN`.
def initialize(range_string, project) def initialize(range_string, project)
......
...@@ -19,7 +19,7 @@ class MergeRequest < ActiveRecord::Base ...@@ -19,7 +19,7 @@ class MergeRequest < ActiveRecord::Base
after_create :create_merge_request_diff, unless: :importing? after_create :create_merge_request_diff, unless: :importing?
after_update :update_merge_request_diff after_update :update_merge_request_diff
delegate :commits, :diffs, :real_size, to: :merge_request_diff, prefix: nil delegate :commits, :real_size, to: :merge_request_diff, prefix: nil
# When this attribute is true some MR validation is ignored # When this attribute is true some MR validation is ignored
# It allows us to close or modify broken merge requests # It allows us to close or modify broken merge requests
...@@ -164,6 +164,10 @@ class MergeRequest < ActiveRecord::Base ...@@ -164,6 +164,10 @@ class MergeRequest < ActiveRecord::Base
merge_request_diff ? merge_request_diff.first_commit : compare_commits.first merge_request_diff ? merge_request_diff.first_commit : compare_commits.first
end end
def diffs(*args)
merge_request_diff ? merge_request_diff.diffs(*args) : compare.diffs(*args)
end
def diff_size def diff_size
merge_request_diff.size merge_request_diff.size
end end
...@@ -318,11 +322,11 @@ class MergeRequest < ActiveRecord::Base ...@@ -318,11 +322,11 @@ class MergeRequest < ActiveRecord::Base
end end
def merge_event def merge_event
self.target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::MERGED).last @merge_event ||= target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::MERGED).last
end end
def closed_event def closed_event
self.target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::CLOSED).last @closed_event ||= target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::CLOSED).last
end end
WIP_REGEX = /\A\s*(\[WIP\]\s*|WIP:\s*|WIP\s+)+\s*/i.freeze WIP_REGEX = /\A\s*(\[WIP\]\s*|WIP:\s*|WIP\s+)+\s*/i.freeze
......
...@@ -46,7 +46,8 @@ class MergeRequestDiff < ActiveRecord::Base ...@@ -46,7 +46,8 @@ class MergeRequestDiff < ActiveRecord::Base
compare.diffs(options) compare.diffs(options)
end end
else else
@diffs ||= load_diffs(st_diffs, options) @diffs ||= {}
@diffs[options] ||= load_diffs(st_diffs, options)
end end
end end
...@@ -144,6 +145,12 @@ class MergeRequestDiff < ActiveRecord::Base ...@@ -144,6 +145,12 @@ class MergeRequestDiff < ActiveRecord::Base
def load_diffs(raw, options) def load_diffs(raw, options)
if raw.respond_to?(:each) if raw.respond_to?(:each)
if paths = options[:paths]
raw = raw.select do |diff|
paths.include?(diff[:old_path]) || paths.include?(diff[:new_path])
end
end
Gitlab::Git::DiffCollection.new(raw, options) Gitlab::Git::DiffCollection.new(raw, options)
else else
Gitlab::Git::DiffCollection.new([]) Gitlab::Git::DiffCollection.new([])
......
...@@ -425,8 +425,8 @@ class Project < ActiveRecord::Base ...@@ -425,8 +425,8 @@ class Project < ActiveRecord::Base
container_registry_repository.tags.any? container_registry_repository.tags.any?
end end
def commit(id = 'HEAD') def commit(ref = 'HEAD')
repository.commit(id) repository.commit(ref)
end end
def merge_base_commit(first_commit_id, second_commit_id) def merge_base_commit(first_commit_id, second_commit_id)
...@@ -802,18 +802,12 @@ class Project < ActiveRecord::Base ...@@ -802,18 +802,12 @@ class Project < ActiveRecord::Base
@repo_exists = false @repo_exists = false
end end
# Branches that are not _exactly_ matched by a protected branch.
def open_branches def open_branches
# We're using a Set here as checking values in a large Set is faster than exact_protected_branch_names = protected_branches.reject(&:wildcard?).map(&:name)
# checking values in a large Array. branch_names = repository.branches.map(&:name)
protected_set = Set.new(protected_branch_names) non_open_branch_names = Set.new(exact_protected_branch_names).intersection(Set.new(branch_names))
repository.branches.reject { |branch| non_open_branch_names.include? branch.name }
repository.branches.reject do |branch|
protected_set.include?(branch.name)
end
end
def protected_branch_names
@protected_branch_names ||= protected_branches.pluck(:name)
end end
def root_ref?(branch) def root_ref?(branch)
...@@ -830,11 +824,12 @@ class Project < ActiveRecord::Base ...@@ -830,11 +824,12 @@ class Project < ActiveRecord::Base
# Check if current branch name is marked as protected in the system # Check if current branch name is marked as protected in the system
def protected_branch?(branch_name) def protected_branch?(branch_name)
protected_branch_names.include?(branch_name) @protected_branches ||= self.protected_branches.to_a
ProtectedBranch.matching(branch_name, protected_branches: @protected_branches).present?
end end
def developers_can_push_to_protected_branch?(branch_name) def developers_can_push_to_protected_branch?(branch_name)
protected_branches.any? { |pb| pb.name == branch_name && pb.developers_can_push } protected_branches.matching(branch_name).any?(&:developers_can_push)
end end
def forked? def forked?
......
...@@ -112,15 +112,7 @@ class IrkerService < Service ...@@ -112,15 +112,7 @@ class IrkerService < Service
# Authorize both irc://domain.com/#chan and irc://domain.com/chan # Authorize both irc://domain.com/#chan and irc://domain.com/chan
if uri.is_a?(URI) && uri.scheme[/^ircs?\z/] && !uri.path.nil? if uri.is_a?(URI) && uri.scheme[/^ircs?\z/] && !uri.path.nil?
# Do not authorize irc://domain.com/ uri.to_s
if uri.fragment.nil? && uri.path.length > 1
uri.to_s
else
# Authorize irc://domain.com/smthg#chan
# The irker daemon will deal with it by concatenating smthg and
# chan, thus sending messages on #smthgchan
uri.to_s
end
end end
end end
end end
...@@ -8,4 +8,51 @@ class ProtectedBranch < ActiveRecord::Base ...@@ -8,4 +8,51 @@ class ProtectedBranch < ActiveRecord::Base
def commit def commit
project.commit(self.name) project.commit(self.name)
end end
# Returns all protected branches that match the given branch name.
# This realizes all records from the scope built up so far, and does
# _not_ return a relation.
#
# This method optionally takes in a list of `protected_branches` to search
# through, to avoid calling out to the database.
def self.matching(branch_name, protected_branches: nil)
(protected_branches || all).select { |protected_branch| protected_branch.matches?(branch_name) }
end
# Returns all branches (among the given list of branches [`Gitlab::Git::Branch`])
# that match the current protected branch.
def matching(branches)
branches.select { |branch| self.matches?(branch.name) }
end
# Checks if the protected branch matches the given branch name.
def matches?(branch_name)
return false if self.name.blank?
exact_match?(branch_name) || wildcard_match?(branch_name)
end
# Checks if this protected branch contains a wildcard
def wildcard?
self.name && self.name.include?('*')
end
protected
def exact_match?(branch_name)
self.name == branch_name
end
def wildcard_match?(branch_name)
wildcard_regex === branch_name
end
def wildcard_regex
@wildcard_regex ||= begin
name = self.name.gsub('*', 'STAR_DONT_ESCAPE')
quoted_name = Regexp.quote(name)
regex_string = quoted_name.gsub('STAR_DONT_ESCAPE', '.*?')
/\A#{regex_string}\z/
end
end
end end
...@@ -78,9 +78,9 @@ class Repository ...@@ -78,9 +78,9 @@ class Repository
end end
end end
def commit(id = 'HEAD') def commit(ref = 'HEAD')
return nil unless exists? return nil unless exists?
commit = Gitlab::Git::Commit.find(raw_repository, id) commit = Gitlab::Git::Commit.find(raw_repository, ref)
commit = ::Commit.new(commit, @project) if commit commit = ::Commit.new(commit, @project) if commit
commit commit
rescue Rugged::OdbError rescue Rugged::OdbError
......
...@@ -72,6 +72,19 @@ class SentNotification < ActiveRecord::Base ...@@ -72,6 +72,19 @@ class SentNotification < ActiveRecord::Base
end end
end end
def position=(new_position)
if new_position.is_a?(String)
new_position = JSON.parse(new_position) rescue nil
end
if new_position.is_a?(Hash)
new_position = new_position.with_indifferent_access
new_position = Gitlab::Diff::Position.new(new_position)
end
super(new_position)
end
def to_param def to_param
self.reply_key self.reply_key
end end
......
...@@ -15,7 +15,7 @@ class User < ActiveRecord::Base ...@@ -15,7 +15,7 @@ class User < ActiveRecord::Base
add_authentication_token_field :authentication_token add_authentication_token_field :authentication_token
default_value_for :admin, false default_value_for :admin, false
default_value_for :external, false default_value_for(:external) { current_application_settings.user_default_external }
default_value_for :can_create_group, gitlab_config.default_can_create_group default_value_for :can_create_group, gitlab_config.default_can_create_group
default_value_for :can_create_team, false default_value_for :can_create_team, false
default_value_for :hide_no_ssh_key, false default_value_for :hide_no_ssh_key, false
......
...@@ -3,7 +3,7 @@ require 'securerandom' ...@@ -3,7 +3,7 @@ require 'securerandom'
# Compare 2 branches for one repo or between repositories # Compare 2 branches for one repo or between repositories
# and return Gitlab::Git::Compare object that responds to commits and diffs # and return Gitlab::Git::Compare object that responds to commits and diffs
class CompareService class CompareService
def execute(source_project, source_branch, target_project, target_branch, diff_options = {}) def execute(source_project, source_branch, target_project, target_branch)
source_commit = source_project.commit(source_branch) source_commit = source_project.commit(source_branch)
return unless source_commit return unless source_commit
......
...@@ -61,19 +61,14 @@ module MergeRequests ...@@ -61,19 +61,14 @@ module MergeRequests
merge_requests.each do |merge_request| merge_requests.each do |merge_request|
if merge_request.source_branch == @branch_name || force_push? if merge_request.source_branch == @branch_name || force_push?
merge_request.reload_diff merge_request.reload_diff
merge_request.mark_as_unchecked
else else
mr_commit_ids = merge_request.commits.map(&:id) mr_commit_ids = merge_request.commits.map(&:id)
push_commit_ids = @commits.map(&:id) push_commit_ids = @commits.map(&:id)
matches = mr_commit_ids & push_commit_ids matches = mr_commit_ids & push_commit_ids
merge_request.reload_diff if matches.any?
if matches.any?
merge_request.reload_diff
merge_request.mark_as_unchecked
else
merge_request.mark_as_unchecked
end
end end
merge_request.mark_as_unchecked
end end
end end
......
...@@ -3,14 +3,14 @@ ...@@ -3,14 +3,14 @@
%tr %tr
%td %td
- if user - if user
= link_to user.name, [:admin, user] = link_to user.name, user
.light.small .light.small
Joined #{time_ago_with_tooltip(user.created_at)} Joined #{time_ago_with_tooltip(user.created_at)}
- else - else
(removed) (removed)
%td %td
- if reporter - if reporter
= link_to reporter.name, [:admin, reporter] = link_to reporter.name, reporter
- else - else
(removed) (removed)
.light.small .light.small
......
...@@ -100,6 +100,13 @@ ...@@ -100,6 +100,13 @@
= f.label :user_oauth_applications do = f.label :user_oauth_applications do
= f.check_box :user_oauth_applications = f.check_box :user_oauth_applications
Allow users to register any application to use GitLab as an OAuth provider Allow users to register any application to use GitLab as an OAuth provider
.form-group
= f.label :user_default_external, 'New users set to external', class: 'control-label col-sm-2'
.col-sm-10
.checkbox
= f.label :user_default_external do
= f.check_box :user_default_external
Newly registered users will by default be external
%fieldset %fieldset
%legend Sign-in Restrictions %legend Sign-in Restrictions
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
%legend Access %legend Access
.form-group .form-group
= f.label :projects_limit, class: 'control-label' = f.label :projects_limit, class: 'control-label'
.col-sm-10= f.number_field :projects_limit, class: 'form-control' .col-sm-10= f.number_field :projects_limit, min: 0, class: 'form-control'
.form-group .form-group
= f.label :can_create_group, class: 'control-label' = f.label :can_create_group, class: 'control-label'
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
- if current_user - if current_user
.pull-right .pull-right
= link_to new_snippet_path, class: "btn btn-new", title: "New Snippet" do = link_to new_snippet_path, class: "btn btn-new", title: "New Snippet" do
= icon('plus')
New Snippet New Snippet
.oneline .oneline
......
.flash-container .flash-container.flash-container-page
- if alert - if alert
.flash-alert .flash-alert
= alert = alert
......
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/cropper.js')
= page_specific_javascript_tag('profile/application.js')
- page_title "Account" - page_title "Account"
= render 'profiles/head'
- if current_user.ldap_user? - if current_user.ldap_user?
.alert.alert-info .alert.alert-info
......
- page_title "Audit Log" - page_title "Audit Log"
= render 'profiles/head'
.row.prepend-top-default .row.prepend-top-default
.col-lg-3.profile-settings-sidebar .col-lg-3.profile-settings-sidebar
......
- page_title "Emails" - page_title "Emails"
= render 'profiles/head'
.row.prepend-top-default .row.prepend-top-default
.col-lg-3.profile-settings-sidebar .col-lg-3.profile-settings-sidebar
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
.form-group .form-group
= f.label :key, class: 'label-light' = f.label :key, class: 'label-light'
= f.text_area :key, class: "form-control", rows: 8, required: true = f.text_area :key, class: "form-control", rows: 8, required: true, placeholder: "Don't paste the private part of the SSH key. Paste the public part, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'."
.form-group .form-group
= f.label :title, class: 'label-light' = f.label :title, class: 'label-light'
= f.text_field :title, class: "form-control", required: true = f.text_field :title, class: "form-control", required: true
......
- page_title @key.title, "SSH Keys" - page_title @key.title, "SSH Keys"
= render 'profiles/head'
= render "key_details" = render "key_details"
- page_title "Notifications" - page_title "Notifications"
= render 'profiles/head'
%div %div
- if @user.errors.any? - if @user.errors.any?
......
- page_title "Personal Access Tokens" - page_title "Personal Access Tokens"
= render 'profiles/head'
.row.prepend-top-default .row.prepend-top-default
.col-lg-3.profile-settings-sidebar .col-lg-3.profile-settings-sidebar
......
- page_title 'Preferences' - page_title 'Preferences'
= render 'profiles/head'
= form_for @user, url: profile_preferences_path, remote: true, method: :put, html: {class: 'row prepend-top-default js-preferences-form'} do |f| = form_for @user, url: profile_preferences_path, remote: true, method: :put, html: {class: 'row prepend-top-default js-preferences-form'} do |f|
.col-lg-3.profile-settings-sidebar .col-lg-3.profile-settings-sidebar
......
= render 'profiles/head'
= form_for @user, url: profile_path, method: :put, html: { multipart: true, class: "edit-user prepend-top-default" }, authenticity_token: true do |f| = form_for @user, url: profile_path, method: :put, html: { multipart: true, class: "edit-user prepend-top-default" }, authenticity_token: true do |f|
= form_errors(@user) = form_errors(@user)
......
- page_title 'Two-Factor Authentication', 'Account' - page_title 'Two-Factor Authentication', 'Account'
- header_title "Two-Factor Authentication", profile_two_factor_auth_path - header_title "Two-Factor Authentication", profile_two_factor_auth_path
= render 'profiles/head'
.row.prepend-top-default .row.prepend-top-default
.col-lg-3 .col-lg-3
......
...@@ -67,4 +67,4 @@ ...@@ -67,4 +67,4 @@
= render "sidebar" = render "sidebar"
:javascript :javascript
new CiBuild("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{namespace_project_build_url(@project.namespace, @project, @build, :json)}", "#{@build.status}", "#{trace_with_state[:state]}") new Build("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{namespace_project_build_url(@project.namespace, @project, @build, :json)}", "#{@build.status}", "#{trace_with_state[:state]}")
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
%td %td
- if pipeline.started_at && pipeline.finished_at - if pipeline.started_at && pipeline.finished_at
%p.duration %p.duration
#{duration_in_words(pipeline.finished_at, pipeline.started_at)} = duration_in_numbers(pipeline.finished_at, pipeline.started_at)
%td %td
.controls.hidden-xs.pull-right .controls.hidden-xs.pull-right
......
.diff-content.diff-wrap-lines
- # Skip all non non-supported blobs
- return unless blob.respond_to?(:text?)
- if diff_file.too_large?
.nothing-here-block This diff could not be displayed because it is too large.
- elsif blob.only_display_raw?
.nothing-here-block This file is too large to display.
- elsif blob_text_viewable?(blob)
- if !project.repository.diffable?(blob)
.nothing-here-block This diff was suppressed by a .gitattributes entry.
- elsif diff_file.diff_lines.length > 0
- if diff_file.collapsed_by_default? && !expand_all_diffs?
- url = url_for(params.merge(action: :diff_for_path, old_path: diff_file.old_path, new_path: diff_file.new_path))
.nothing-here-block.diff-collapsed{data: { diff_for_path: url } }
This diff is collapsed. Click to expand it.
- elsif diff_view == 'parallel'
= render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob
- else
= render "projects/diffs/text_file", diff_file: diff_file
- else
- if diff_file.mode_changed?
.nothing-here-block File mode changed
- elsif diff_file.renamed_file
.nothing-here-block File moved
- elsif blob.image?
- old_blob = diff_file.old_blob(diff_commit)
= render "projects/diffs/image", diff_file: diff_file, old_file: old_blob, file: blob
- else
.nothing-here-block No preview for this file type
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
.content-block.oneline-block.files-changed .content-block.oneline-block.files-changed
.inline-parallel-buttons .inline-parallel-buttons
- unless expand_all_diffs?
= link_to 'Expand all', url_for(params.merge(expand_all_diffs: 1, format: 'html')), class: 'btn btn-default'
- if show_whitespace_toggle - if show_whitespace_toggle
- if current_controller?(:commit) - if current_controller?(:commit)
= commit_diff_whitespace_link(@project, @commit, class: 'hidden-xs') = commit_diff_whitespace_link(@project, @commit, class: 'hidden-xs')
......
...@@ -16,28 +16,4 @@ ...@@ -16,28 +16,4 @@
= view_file_btn(diff_commit.id, diff_file, project) = view_file_btn(diff_commit.id, diff_file, project)
.diff-content.diff-wrap-lines = render 'projects/diffs/content', diff_file: diff_file, diff_commit: diff_commit, diff_refs: diff_refs, blob: blob, project: project
- # Skip all non non-supported blobs
- return unless blob.respond_to?(:text?)
- if diff_file.too_large?
.nothing-here-block This diff could not be displayed because it is too large.
- elsif blob.only_display_raw?
.nothing-here-block This file is too large to display.
- elsif blob_text_viewable?(blob)
- if !project.repository.diffable?(blob)
.nothing-here-block This diff was suppressed by a .gitattributes entry.
- elsif diff_file.diff_lines.length > 0
- if diff_view == 'parallel'
= render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob, index: i
- else
= render "projects/diffs/text_file", diff_file: diff_file, index: i
- else
- if diff_file.mode_changed?
.nothing-here-block File mode changed
- elsif diff_file.renamed_file
.nothing-here-block File moved
- elsif blob.image?
- old_blob = diff_file.old_blob(diff_commit)
= render "projects/diffs/image", diff_file: diff_file, old_file: old_blob, file: blob, index: i
- else
.nothing-here-block No preview for this file type
...@@ -2,9 +2,6 @@ ...@@ -2,9 +2,6 @@
%h4 %h4
Too many changes to show. Too many changes to show.
.pull-right .pull-right
- unless diff_hard_limit_enabled?
= link_to "Reload with full diff", url_for(params.merge(force_show_diff: true, format: nil)), class: "btn btn-sm"
- if current_controller?(:commit) or current_controller?(:merge_requests) - if current_controller?(:commit) or current_controller?(:merge_requests)
- if current_controller?(:commit) - if current_controller?(:commit)
= link_to "Plain diff", namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff), class: "btn btn-sm" = link_to "Plain diff", namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff), class: "btn btn-sm"
......
...@@ -6,21 +6,37 @@ ...@@ -6,21 +6,37 @@
- if current_user - if current_user
= auto_discovery_link_tag(:atom, namespace_project_issues_url(@project.namespace, @project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues") = auto_discovery_link_tag(:atom, namespace_project_issues_url(@project.namespace, @project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues")
%div{ class: container_class } %div{ class: (container_class) }
.top-area - if @project.issues.any?
= render 'shared/issuable/nav', type: :issues .top-area
.nav-controls = render 'shared/issuable/nav', type: :issues
- if current_user .nav-controls
= link_to namespace_project_issues_path(@project.namespace, @project, :atom, { private_token: current_user.private_token }), class: 'btn append-right-10' do - if current_user
= icon('rss') = link_to namespace_project_issues_path(@project.namespace, @project, :atom, { private_token: current_user.private_token }), class: 'btn append-right-10' do
%span.icon-label = icon('rss')
Subscribe %span.icon-label
= render 'shared/issuable/search_form', path: namespace_project_issues_path(@project.namespace, @project) Subscribe
= render 'shared/issuable/search_form', path: namespace_project_issues_path(@project.namespace, @project)
- if can? current_user, :create_issue, @project
= link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { assignee_id: @issuable_finder.assignee.try(:id), milestone_id: @issuable_finder.milestones.try(:first).try(:id) }), class: "btn btn-new", title: "New Issue", id: "new_issue_link" do
New Issue
= render 'shared/issuable/filter', type: :issues
.issues-holder
= render "issues"
- else
.blank-state.blank-state-welcome
%h2.blank-state-title.blank-state-welcome-title
Welcome to GitLab Issues
%p.blank-state-text
Code, test, and deploy together
.blank-state
.blank-state-icon
= navbar_icon("issues", size: 50)
%h3.blank-state-title
You don't have any issues right now.
%p.blank-state-text
Issues are the best way to track your project progress
- if can? current_user, :create_issue, @project - if can? current_user, :create_issue, @project
= link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { assignee_id: @issuable_finder.assignee.try(:id), milestone_id: @issuable_finder.milestones.try(:first).try(:id) }), class: "btn btn-new", title: "New Issue", id: "new_issue_link" do = link_to new_namespace_project_issue_path(@project.namespace, @project), class: "btn btn-new", title: "New Issue", id: "new_issue_link" do
New Issue New Issue
= render 'shared/issuable/filter', type: :issues
.issues-holder
= render "issues"
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
= succeed '.' do = succeed '.' do
= link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal" = link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal"
- if @commits.present? - if @commits_count.nonzero?
%ul.merge-request-tabs.nav-links.no-top.no-bottom %ul.merge-request-tabs.nav-links.no-top.no-bottom
%li.notes-tab %li.notes-tab
= link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#notes', action: 'notes', toggle: 'tab'} do = link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#notes', action: 'notes', toggle: 'tab'} do
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
%li.commits-tab %li.commits-tab
= link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#commits', action: 'commits', toggle: 'tab'} do = link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#commits', action: 'commits', toggle: 'tab'} do
Commits Commits
%span.badge= @commits.size %span.badge= @commits_count
- if @pipeline - if @pipeline
%li.builds-tab %li.builds-tab
= link_to builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#builds', action: 'builds', toggle: 'tab'} do = link_to builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#builds', action: 'builds', toggle: 'tab'} do
......
...@@ -19,13 +19,13 @@ ...@@ -19,13 +19,13 @@
Options Options
.dropdown-menu.dropdown-menu-align-right.hidden-lg .dropdown-menu.dropdown-menu-align-right.hidden-lg
%ul %ul
%li{ class: issue_button_visibility(@merge_request, true) } %li{ class: merge_request_button_visibility(@merge_request, true) }
= link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, title: 'Close merge request' = link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, title: 'Close merge request'
%li{ class: issue_button_visibility(@merge_request, false) } %li{ class: merge_request_button_visibility(@merge_request, false) }
= link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: 'reopen-mr-link', title: 'Reopen merge request' = link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: 'reopen-mr-link', title: 'Reopen merge request'
%li %li
= link_to 'Edit', edit_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: 'issuable-edit' = link_to 'Edit', edit_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: 'issuable-edit'
= link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, class: "hidden-xs hidden-sm btn btn-grouped btn-close #{issue_button_visibility(@merge_request, true)}", title: 'Close merge request' = link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, class: "hidden-xs hidden-sm btn btn-grouped btn-close #{merge_request_button_visibility(@merge_request, true)}", title: 'Close merge request'
= link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "hidden-xs hidden-sm btn btn-grouped btn-reopen reopen-mr-link #{issue_button_visibility(@merge_request, false)}", title: 'Reopen merge request' = link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "hidden-xs hidden-sm btn btn-grouped btn-reopen reopen-mr-link #{merge_request_button_visibility(@merge_request, false)}", title: 'Reopen merge request'
= link_to edit_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: "hidden-xs hidden-sm btn btn-grouped issuable-edit" do = link_to edit_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: "hidden-xs hidden-sm btn btn-grouped issuable-edit" do
Edit Edit
...@@ -22,10 +22,10 @@ ...@@ -22,10 +22,10 @@
- elsif @merge_request.can_be_merged? - elsif @merge_request.can_be_merged?
= render 'projects/merge_requests/widget/open/accept' = render 'projects/merge_requests/widget/open/accept'
- if @closes_issues.present? - if mr_closes_issues.present?
.mr-widget-footer .mr-widget-footer
%span %span
%i.fa.fa-check %i.fa.fa-check
Accepting this merge request will close #{"issue".pluralize(@closes_issues.size)} Accepting this merge request will close #{"issue".pluralize(mr_closes_issues.size)}
= succeed '.' do = succeed '.' do
!= markdown issues_sentence(@closes_issues), pipeline: :gfm, author: @merge_request.author != markdown issues_sentence(mr_closes_issues), pipeline: :gfm, author: @merge_request.author
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
= render "projects/notes/notes" = render "projects/notes/notes"
%ul.notes.notes-form.timeline %ul.notes.notes-form.timeline
%li.timeline-entry %li.timeline-entry
.flash-container.timeline-content
- if can? current_user, :create_note, @project - if can? current_user, :create_note, @project
.timeline-icon.hidden-xs.hidden-sm .timeline-icon.hidden-xs.hidden-sm
%a.author_link{ href: user_path(current_user) } %a.author_link{ href: user_path(current_user) }
......
%h5.prepend-top-0 %h5.prepend-top-0
Already Protected (#{@branches.size}) Already Protected (#{@protected_branches.size})
- if @branches.empty? - if @protected_branches.empty?
%p.settings-message.text-center %p.settings-message.text-center
No branches are protected, protect a branch with the form above. No branches are protected, protect a branch with the form above.
- else - else
...@@ -9,33 +9,18 @@ ...@@ -9,33 +9,18 @@
%table.table.protected-branches-list %table.table.protected-branches-list
%colgroup %colgroup
%col{ width: "30%" } %col{ width: "30%" }
%col{ width: "30%" } %col{ width: "25%" }
%col{ width: "25%" } %col{ width: "25%" }
- if can_admin_project - if can_admin_project
%col %col
%thead %thead
%tr %tr
%th Branch %th Protected Branch
%th Last commit %th Commit
%th Developers can push %th Developers Can Push
- if can_admin_project - if can_admin_project
%th %th
%tbody %tbody
- @branches.each do |branch| = render partial: @protected_branches, locals: { can_admin_project: can_admin_project }
- @url = namespace_project_protected_branch_path(@project.namespace, @project, branch)
%tr = paginate @protected_branches, theme: 'gitlab'
%td
= link_to(branch.name, namespace_project_commits_path(@project.namespace, @project, branch.name))
- if @project.root_ref?(branch.name)
%span.label.label-info.prepend-left-5 default
%td
- if commit = branch.commit
= link_to(commit.short_id, namespace_project_commit_path(@project.namespace, @project, commit.id), class: 'commit_short_id')
#{time_ago_with_tooltip(commit.committed_date)}
- else
(branch was removed from repository)
%td
= check_box_tag("developers_can_push", branch.id, branch.developers_can_push, data: { url: @url })
- if can_admin_project
%td
= link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-warning btn-sm"
= f.hidden_field(:name)
= dropdown_tag("Protected Branch",
options: { title: "Pick protected branch", toggle_class: 'js-protected-branch-select js-filter-submit',
filter: true, dropdown_class: "dropdown-menu-selectable", placeholder: "Search protected branches",
footer_content: true,
data: { show_no: true, show_any: true, show_upcoming: true,
selected: params[:protected_branch_name],
project_id: @project.try(:id) } }) do
%ul.dropdown-footer-list.hidden.protected-branch-select-footer-list
%li
= link_to '#', title: "New Protected Branch", class: "create-new-protected-branch" do
Create new
:javascript
new ProtectedBranchSelect();
%tr
%td
= link_to matching_branch.name, namespace_project_tree_path(@project.namespace, @project, matching_branch.name)
- if @project.root_ref?(matching_branch.name)
%span.label.label-info.prepend-left-5 default
%td
- commit = @project.commit(matching_branch.name)
= link_to(commit.short_id, namespace_project_commit_path(@project.namespace, @project, commit.id), class: 'commit_short_id')
= time_ago_with_tooltip(commit.committed_date)
- url = namespace_project_protected_branch_path(@project.namespace, @project, protected_branch)
%tr
%td
= protected_branch.name
- if @project.root_ref?(protected_branch.name)
%span.label.label-info.prepend-left-5 default
%td
- if protected_branch.wildcard?
- matching_branches = protected_branch.matching(repository.branches)
= link_to pluralize(matching_branches.count, "matching branch"), namespace_project_protected_branch_path(@project.namespace, @project, protected_branch)
- else
- if commit = protected_branch.commit
= link_to(commit.short_id, namespace_project_commit_path(@project.namespace, @project, commit.id), class: 'commit_short_id')
= time_ago_with_tooltip(commit.committed_date)
- else
(branch was removed from repository)
%td
= check_box_tag("developers_can_push", protected_branch.id, protected_branch.developers_can_push, data: { url: url })
- if can_admin_project
%td
= link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, protected_branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-warning btn-sm pull-right"
...@@ -4,30 +4,38 @@ ...@@ -4,30 +4,38 @@
.col-lg-3 .col-lg-3
%h4.prepend-top-0 %h4.prepend-top-0
= page_title = page_title
%p Keep stable branches secure and force developers to use Merge Requests %p Keep stable branches secure and force developers to use merge requests.
.col-lg-9 %p.prepend-top-20
%h5.prepend-top-0 Protected branches are designed to:
Protect a branch
.account-well.append-bottom-default
%p.light-header.append-bottom-0 Protected branches are designed to
%ul %ul
%li prevent pushes from everybody except #{link_to "masters", help_page_path("permissions", "permissions"), class: "vlink"} %li prevent pushes from everybody except #{link_to "masters", help_page_path("permissions", "permissions"), class: "vlink"}
%li prevent anyone from force pushing to the branch %li prevent anyone from force pushing to the branch
%li prevent anyone from deleting the branch %li prevent anyone from deleting the branch
%p.append-bottom-0 Read more about #{link_to "project permissions", help_page_path("permissions", "permissions"), class: "underlined-link"} %p.append-bottom-0 Read more about #{link_to "project permissions", help_page_path("permissions", "permissions"), class: "underlined-link"}
.col-lg-9
%h5.prepend-top-0
Protect a branch
- if can? current_user, :admin_project, @project - if can? current_user, :admin_project, @project
= form_for [@project.namespace.becomes(Namespace), @project, @protected_branch] do |f| = form_for [@project.namespace.becomes(Namespace), @project, @protected_branch] do |f|
= form_errors(@protected_branch) = form_errors(@protected_branch)
.form-group .form-group
= f.label :name, "Branch", class: "label-light" = f.label :name, "Branch", class: "label-light"
= f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , {include_blank: true}, {class: "select2", data: {placeholder: "Select branch"}}) = render partial: "dropdown", locals: { f: f }
%p.help-block
= link_to "Wildcards", help_page_path(category: 'workflow', file: 'protected_branches', format: 'md', anchor: "wildcard-protected-branches")
such as
%code *-stable
or
%code production/*
are supported.
.form-group .form-group
= f.check_box :developers_can_push, class: "pull-left" = f.check_box :developers_can_push, class: "pull-left"
.prepend-left-20 .prepend-left-20
= f.label :developers_can_push, "Developers can push", class: "label-light append-bottom-0" = f.label :developers_can_push, "Developers can push", class: "label-light append-bottom-0"
%p.light.append-bottom-0 %p.light.append-bottom-0
Allow developers to push to this branch Allow developers to push to this branch
= f.submit "Protect", class: "btn-create btn" = f.submit "Protect", class: "btn-create btn protect-branch-btn", disabled: true
%hr %hr
= render "branches_list" = render "branches_list"
- page_title @protected_branch.name, "Protected Branches"
.row.prepend-top-default.append-bottom-default
.col-lg-3
%h4.prepend-top-0
= @protected_branch.name
.col-lg-9
%h5 Matching Branches
- if @matching_branches.present?
.table-responsive
%table.table.protected-branches-list
%colgroup
%col{ width: "30%" }
%col{ width: "30%" }
%thead
%tr
%th Branch
%th Last commit
%tbody
- @matching_branches.each do |matching_branch|
= render partial: "matching_branch", object: matching_branch
- else
%p.settings-message.text-center
Couldn't find any matching branches.
.hidden-xs .hidden-xs
= link_to new_namespace_project_snippet_path(@project.namespace, @project), class: 'btn btn-grouped btn-create new-snippet-link', title: "New Snippet" do - if can?(current_user, :create_project_snippet, @project)
= icon('plus') = link_to new_namespace_project_snippet_path(@project.namespace, @project), class: 'btn btn-grouped btn-create new-snippet-link', title: "New Snippet" do
New Snippet New Snippet
- if can?(current_user, :update_project_snippet, @snippet) - if can?(current_user, :update_project_snippet, @snippet)
= link_to edit_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-grouped snippable-edit" do = link_to edit_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-grouped snippable-edit" do
Edit Edit
- if can?(current_user, :update_project_snippet, @snippet) - if can?(current_user, :update_project_snippet, @snippet)
= link_to namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-warning", title: 'Delete Snippet' do = link_to namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-warning", title: 'Delete Snippet' do
Delete Delete
.visible-xs-block.dropdown - if can?(current_user, :create_project_snippet, @project) || can?(current_user, :update_project_snippet, @snippet)
%button.btn.btn-default.btn-block.append-bottom-0.prepend-top-5{ data: { toggle: "dropdown" } } .visible-xs-block.dropdown
Options %button.btn.btn-default.btn-block.append-bottom-0.prepend-top-5{ data: { toggle: "dropdown" } }
%span.caret Options
.dropdown-menu.dropdown-menu-full-width %span.caret
%ul .dropdown-menu.dropdown-menu-full-width
%li %ul
= link_to new_namespace_project_snippet_path(@project.namespace, @project), title: "New Snippet" do - if can?(current_user, :create_project_snippet, @project)
New Snippet %li
- if can?(current_user, :update_project_snippet, @snippet) = link_to new_namespace_project_snippet_path(@project.namespace, @project), title: "New Snippet" do
%li New Snippet
= link_to edit_namespace_project_snippet_path(@project.namespace, @project, @snippet) do - if can?(current_user, :update_project_snippet, @snippet)
Edit %li
- if can?(current_user, :update_project_snippet, @snippet) = link_to edit_namespace_project_snippet_path(@project.namespace, @project, @snippet) do
%li Edit
= link_to namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, title: 'Delete Snippet' do - if can?(current_user, :update_project_snippet, @snippet)
Delete %li
= link_to namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, title: 'Delete Snippet' do
Delete
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
.row-content-block.top-block .row-content-block.top-block
.pull-right .pull-right
= link_to new_namespace_project_snippet_path(@project.namespace, @project), class: "btn btn-new", title: "New Snippet" do - if can?(current_user, :create_project_snippet, @project)
= icon('plus') = link_to new_namespace_project_snippet_path(@project.namespace, @project), class: "btn btn-new", title: "New Snippet" do
New Snippet New Snippet
.oneline .oneline
Share code pastes with others out of git repository Share code pastes with others out of git repository
......
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 3.7.2 (28276) - http://www.bohemiancoding.com/sketch -->
<title>Group</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group" fill="#7E7C7C">
<path d="M8,0 C3.581,0 0,3.581 0,8 C0,12.419 3.581,16 8,16 C12.419,16 16,12.419 16,8 C16,3.581 12.419,0 8,0 M8,2 C11.308,2 14,4.692 14,8 C14,11.308 11.308,14 8,14 C4.692,14 2,11.308 2,8 C2,4.692 4.692,2 8,2" id="Fill-1"></path>
<path d="M7.1597,4 L8.8887,4 L8.8887,8 L7.1107,8 L7.1597,4 Z M7.1597,9.6667 L8.8887,9.6667 L8.8887,11.4447 L7.1107,11.4447 L7.1597,9.6667 Z" id="Combined-Shape"></path>
</g>
</g>
</svg>
\ No newline at end of file
<svg width="<%= size %>" height="<%= size %>" viewBox="0 0 16 16" class="gitlab-icon">
<path fill="#7E7C7C" d="M8,0 C3.581,0 0,3.581 0,8 C0,12.419 3.581,16 8,16 C12.419,16 16,12.419 16,8 C16,3.581 12.419,0 8,0 M8,2 C11.308,2 14,4.692 14,8 C14,11.308 11.308,14 8,14 C4.692,14 2,11.308 2,8 C2,4.692 4.692,2 8,2"></path>
<path fill="#7E7C7C" d="M7.1597,4 L8.8887,4 L8.8887,8 L7.1107,8 L7.1597,4 Z M7.1597,9.6667 L8.8887,9.6667 L8.8887,11.4447 L7.1107,11.4447 L7.1597,9.6667 Z"></path>
</svg>
.hidden-xs .hidden-xs
= link_to new_snippet_path, class: "btn btn-grouped btn-create new-snippet-link", title: "New Snippet" do - if current_user
= icon('plus') = link_to new_snippet_path, class: "btn btn-grouped btn-create new-snippet-link", title: "New Snippet" do
New Snippet New Snippet
- if can?(current_user, :update_personal_snippet, @snippet) - if can?(current_user, :update_personal_snippet, @snippet)
= link_to edit_snippet_path(@snippet), class: "btn btn-grouped snippable-edit" do = link_to edit_snippet_path(@snippet), class: "btn btn-grouped snippable-edit" do
Edit Edit
- if can?(current_user, :admin_personal_snippet, @snippet) - if can?(current_user, :admin_personal_snippet, @snippet)
= link_to snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-warning", title: 'Delete Snippet' do = link_to snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-danger", title: 'Delete Snippet' do
Delete Delete
.visible-xs-block.dropdown - if current_user
%button.btn.btn-default.btn-block.append-bottom-0.prepend-top-5{ data: { toggle: "dropdown" } } .visible-xs-block.dropdown
Options %button.btn.btn-default.btn-block.append-bottom-0.prepend-top-5{ data: { toggle: "dropdown" } }
%span.caret Options
.dropdown-menu.dropdown-menu-full-width %span.caret
%ul .dropdown-menu.dropdown-menu-full-width
%li %ul
= link_to new_snippet_path, title: "New Snippet" do
New Snippet
- if can?(current_user, :update_personal_snippet, @snippet)
%li %li
= link_to edit_snippet_path(@snippet) do = link_to new_snippet_path, title: "New Snippet" do
Edit New Snippet
- if can?(current_user, :admin_personal_snippet, @snippet) - if can?(current_user, :update_personal_snippet, @snippet)
%li %li
= link_to snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, title: 'Delete Snippet' do = link_to edit_snippet_path(@snippet) do
Delete Edit
- if can?(current_user, :admin_personal_snippet, @snippet)
%li
= link_to snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, title: 'Delete Snippet' do
Delete
...@@ -29,6 +29,11 @@ ...@@ -29,6 +29,11 @@
&nbsp; &nbsp;
= link_to user_path(@user, :atom, { private_token: current_user.private_token }), class: 'btn btn-gray' do = link_to user_path(@user, :atom, { private_token: current_user.private_token }), class: 'btn btn-gray' do
= icon('rss') = icon('rss')
- if current_user.admin?
&nbsp;
= link_to [:admin, @user], class: 'btn btn-gray', title: 'View user in admin area',
data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('users')
.avatar-holder .avatar-holder
= link_to avatar_icon(@user, 400), target: '_blank' do = link_to avatar_icon(@user, 400), target: '_blank' do
......
...@@ -84,6 +84,7 @@ module Gitlab ...@@ -84,6 +84,7 @@ module Gitlab
config.assets.precompile << "graphs/application.js" config.assets.precompile << "graphs/application.js"
config.assets.precompile << "users/application.js" config.assets.precompile << "users/application.js"
config.assets.precompile << "network/application.js" config.assets.precompile << "network/application.js"
config.assets.precompile << "profile/application.js"
config.assets.precompile << "lib/utils/*.js" config.assets.precompile << "lib/utils/*.js"
config.assets.precompile << "lib/*.js" config.assets.precompile << "lib/*.js"
......
...@@ -615,10 +615,18 @@ Rails.application.routes.draw do ...@@ -615,10 +615,18 @@ Rails.application.routes.draw do
post :retry_builds post :retry_builds
post :revert post :revert
post :cherry_pick post :cherry_pick
get :diff_for_path
end end
end end
resources :compare, only: [:index, :create] resources :compare, only: [:index, :create] do
collection do
get :diff_for_path
end
end
get '/compare/:from...:to', to: 'compare#show', as: 'compare', constraints: { from: /.+/, to: /.+/ }
resources :network, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ } resources :network, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ }
resources :graphs, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ } do resources :graphs, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ } do
...@@ -629,9 +637,6 @@ Rails.application.routes.draw do ...@@ -629,9 +637,6 @@ Rails.application.routes.draw do
end end
end end
get '/compare/:from...:to' => 'compare#show', :as => 'compare',
:constraints => { from: /.+/, to: /.+/ }
resources :snippets, constraints: { id: /\d+/ } do resources :snippets, constraints: { id: /\d+/ } do
member do member do
get 'raw' get 'raw'
...@@ -706,12 +711,14 @@ Rails.application.routes.draw do ...@@ -706,12 +711,14 @@ Rails.application.routes.draw do
post :toggle_subscription post :toggle_subscription
post :toggle_award_emoji post :toggle_award_emoji
post :remove_wip post :remove_wip
get :diff_for_path
end end
collection do collection do
get :branch_from get :branch_from
get :branch_to get :branch_to
get :update_branches get :update_branches
get :diff_for_path
end end
end end
...@@ -720,7 +727,7 @@ Rails.application.routes.draw do ...@@ -720,7 +727,7 @@ Rails.application.routes.draw do
resource :release, only: [:edit, :update] resource :release, only: [:edit, :update]
end end
resources :protected_branches, only: [:index, :create, :update, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } resources :protected_branches, only: [:index, :show, :create, :update, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex }
resources :variables, only: [:index, :show, :update, :create, :destroy] resources :variables, only: [:index, :show, :update, :create, :destroy]
resources :triggers, only: [:index, :create, :destroy] resources :triggers, only: [:index, :create, :destroy]
......
class AddUserDefaultExternalToApplicationSettings < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
def up
add_column_with_default(:application_settings, :user_default_external, :boolean,
default: false, allow_null: false)
end
def down
remove_column(:application_settings, :user_default_external)
end
end
...@@ -4,12 +4,12 @@ class RemoveDuplicatedKeys < ActiveRecord::Migration ...@@ -4,12 +4,12 @@ class RemoveDuplicatedKeys < ActiveRecord::Migration
select_all("SELECT fingerprint FROM #{quote_table_name(:keys)} GROUP BY fingerprint HAVING COUNT(*) > 1").each do |row| select_all("SELECT fingerprint FROM #{quote_table_name(:keys)} GROUP BY fingerprint HAVING COUNT(*) > 1").each do |row|
fingerprint = connection.quote(row['fingerprint']) fingerprint = connection.quote(row['fingerprint'])
execute(%Q{ execute(%Q{
DELETE FROM keys DELETE FROM #{quote_table_name(:keys)}
WHERE fingerprint = #{fingerprint} WHERE fingerprint = #{fingerprint}
AND id != ( AND id != (
SELECT id FROM ( SELECT id FROM (
SELECT max(id) AS id SELECT max(id) AS id
FROM keys FROM #{quote_table_name(:keys)}
WHERE fingerprint = #{fingerprint} WHERE fingerprint = #{fingerprint}
) max_ids ) max_ids
) )
......
# Updates project records containing invalid URLs using the AddressableUrlValidator.
# This is optimized assuming the number of invalid records is low, but
# we still need to loop through all the projects with an +import_url+
# so we use batching for the latter.
#
# This migration is non-reversible as we would have to keep the old data.
class FixNoValidatableImportUrl < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
class SqlBatches
attr_reader :results, :query
def initialize(batch_size: 100, query:)
@offset = 0
@batch_size = batch_size
@query = query
@results = []
end
def next?
@results = ActiveRecord::Base.connection.exec_query(batched_sql)
@offset += @batch_size
@results.any?
end
private
def batched_sql
"#{@query} LIMIT #{@batch_size} OFFSET #{@offset}"
end
end
# AddressableValidator - Snapshot of AddressableUrlValidator
module AddressableUrlValidatorSnap
extend self
def valid_url?(value)
return false unless value
valid_uri?(value) && valid_protocol?(value)
rescue Addressable::URI::InvalidURIError
false
end
def valid_uri?(value)
Addressable::URI.parse(value).is_a?(Addressable::URI)
end
def valid_protocol?(value)
value =~ /\A#{URI.regexp(%w(http https ssh git))}\z/
end
end
def up
unless defined?(Addressable::URI::InvalidURIError)
say('Skipping cleaning up invalid import URLs as class from Addressable is missing')
return
end
say('Cleaning up invalid import URLs... This may take a few minutes if we have a large number of imported projects.')
invalid_import_url_project_ids.each { |project_id| cleanup_import_url(project_id) }
end
def invalid_import_url_project_ids
ids = []
batches = SqlBatches.new(query: "SELECT id, import_url FROM projects WHERE import_url IS NOT NULL")
while batches.next?
batches.results.each do |result|
ids << result['id'] unless valid_url?(result['import_url'])
end
end
ids
end
def valid_url?(url)
AddressableUrlValidatorSnap.valid_url?(url)
end
def cleanup_import_url(project_id)
execute("UPDATE projects SET import_url = NULL WHERE id = #{project_id}")
end
end
...@@ -84,6 +84,7 @@ ActiveRecord::Schema.define(version: 20160705163108) do ...@@ -84,6 +84,7 @@ ActiveRecord::Schema.define(version: 20160705163108) do
t.string "health_check_access_token" t.string "health_check_access_token"
t.boolean "send_user_confirmation_email", default: false t.boolean "send_user_confirmation_email", default: false
t.integer "container_registry_token_expire_delay", default: 5 t.integer "container_registry_token_expire_delay", default: 5
t.boolean "user_default_external", default: false, null: false
t.text "after_sign_up_text" t.text "after_sign_up_text"
t.string "repository_storage", default: "default" t.string "repository_storage", default: "default"
t.string "enabled_git_access_protocol" t.string "enabled_git_access_protocol"
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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