Commit 3be2c3f5 authored by Lin Jen-Shin's avatar Lin Jen-Shin

Merge branch 'master' into artifacts-from-ref-and-build-name

* master: (335 commits)
  Disable transaction when adding index for Ci::Pipeline
  added changelog
  allow empty repos on import/export
  Modify test for Build tabs
  Add tests to project builds for pending tab
  Remove unused .js-running-count class
  Add test for new pending tab and update tests for running tab
  Add Pending Tab to Admin Builds
  added changelog
  limit project expor retry to only 3
  use method in validates statement
  Fix spec to set import_url before attempting to create import_data
  Allow a project import URL to be blank to prevent false positives preventing settings from being saved
  Refactor gitlab_ci_yaml_processor variables tests
  Fix CI yaml example
  Align cancel and retry buttons
  Remove deploy to production button
  Remove irrelevant comments
  Fix gitlab_ci_yaml_processor_spec.rb
  Fix AddWhenAndYamlVariablesToCiBuilds migration
  ...
parents e51d4a05 4e898b9b
# Prefer single quotes
StringLiterals:
EnforcedStyle: single_quotes
Enabled: true
This diff is collapsed.
This diff is collapsed.
stage:
before:
- cp config/gitlab.teatro.yml config/gitlab.yml
- mkdir /apps/gitlab-satellites
- mkdir /apps/repositories
database:
- RAILS_ENV=development force=yes bundle exec rake db:create gitlab:setup
\ No newline at end of file
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 8.10.0 (unreleased) v 8.10.0 (unreleased)
- Expose {should,force}_remove_source_branch (Ben Boeckel)
- Disable PostgreSQL statement timeout during migrations
- Fix projects dropdown loading performance with a simplified api cal. !5113 (tiagonbotelho)
- Fix commit builds API, return all builds for all pipelines for given commit. !4849 - Fix commit builds API, return all builds for all pipelines for given commit. !4849
- Replace Haml with Hamlit to make view rendering faster. !3666 - Replace Haml with Hamlit to make view rendering faster. !3666
- Refresh the branch cache after `git gc` runs
- Refactor repository paths handling to allow multiple git mount points - Refactor repository paths handling to allow multiple git mount points
- Optimize system note visibility checking by memoizing the visible reference count !5070
- Add Application Setting to configure default Repository Path for new projects - Add Application Setting to configure default Repository Path for new projects
- Delete award emoji when deleting a user
- 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 tooltip for "Copy to Clipboard" button !5164 (winniehell)
- Use default cursor for table header of project files !5165 (winniehell)
- Store when and yaml variables in builds table
- Display last commit of deleted branch in push events !4699 (winniehell) - Display last commit of deleted branch in push events !4699 (winniehell)
- Escape file extension when parsing search results !5141 (winniehell) - Escape file extension when parsing search results !5141 (winniehell)
- Apply the trusted_proxies config to the rack request object for use with rack_attack - Apply the trusted_proxies config to the rack request object for use with rack_attack
- Upgrade to Rails 4.2.7. !5236
- Add Sidekiq queue duration to transaction metrics. - Add Sidekiq queue duration to transaction metrics.
- Add a new column `artifacts_size` to table `ci_builds` !4964 - Add a new column `artifacts_size` to table `ci_builds` !4964
- Let Workhorse serve format-patch diffs - Let Workhorse serve format-patch diffs
- Display tooltip for mentioned users and groups !5261 (winniehell)
- Added day name to contribution calendar tooltips
- Make images fit to the size of the viewport !4810 - Make images fit to the size of the viewport !4810
- Fix check for New Branch button on Issue page !4630 (winniehell) - Fix check for New Branch button on Issue page !4630 (winniehell)
- Fix MR-auto-close text added to description. !4836 - Fix MR-auto-close text added to description. !4836
- Support U2F devices in Firefox. !5177
- 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.
- Fix fetching LFS objects for private CI projects
- Add syntax for multiline blockquote using `>>>` fence !3954 - 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
- Updated compare dropdown menus to use GL dropdown
- Eager load award emoji on notes
- 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 - 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
- Issuable collapsed assignee tooltip is now the users name
- 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
- Update health_check gem to version 2.1.0
- Add notification settings dropdown for groups - Add notification settings dropdown for groups
- Render inline diffs for multiple changed lines following eachother
- Wildcards for protected branches. !4665 - 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: Expose `due_date` for issues (Robert Schilling)
- API: Todos !3188 (Robert Schilling) - API: Todos !3188 (Robert Schilling)
- API: Expose shared groups for projects and shared projects for groups !5050 (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
- 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. - Only show New Snippet button to users that can create snippets.
- PipelinesFinder uses git cache data - PipelinesFinder uses git cache data
- Track a user who created a pipeline
- Actually render old and new sections of parallel diff next to each other
- 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)
- Fix mentioned users list on diff notes
- Fix creation of deployment on build that is retried, redeployed or rollback
- 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
- Fix stage status shown for pipelines
- Cache todos pending/done dashboard query counts.
- 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
- ObjectRenderer retrieve renderer content using Rails.cache.read_multi
- 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. - 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
- Be explicit to define merge request discussion variables
- Metrics for Rouge::Plugins::Redcarpet and Rouge::Formatters::HTMLGitlab - Metrics for Rouge::Plugins::Redcarpet and Rouge::Formatters::HTMLGitlab
- 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)
...@@ -55,14 +88,47 @@ v 8.10.0 (unreleased) ...@@ -55,14 +88,47 @@ v 8.10.0 (unreleased)
- 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
- Aliases of award emoji should be stored as original name. !5060 (dixpac)
- Handle custom Git hook result in GitLab UI - Handle custom Git hook result in GitLab UI
- Allow to access Container Registry for Public and Internal projects
- Allow '?', or '&' for label names - Allow '?', or '&' for label names
- Support redirected blobs for Container Registry integration
- 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
- Added setting to set new users by default as external !4545 (Dravere) - 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 min value for project limit field on user's form !3622 (jastkand)
- Reset project pushes_since_gc when we enqueue the git gc call
- Add reminder to not paste private SSH keys !4399 (Ingo Blechschmidt) - Add reminder to not paste private SSH keys !4399 (Ingo Blechschmidt)
- Remove duplicate `description` field in `MergeRequest` entities (Ben Boeckel)
- Style of import project buttons were fixed in the new project page. !5183 (rdemirbay)
- Fix GitHub client requests when rate limit is disabled
- Optimistic locking for Issues and Merge Requests (Title and description overriding prevention)
- Redesign Builds and Pipelines pages
- Change status color and icon for running builds
- Fix markdown rendering for: consecutive labels references, label references that begin with a digit or contains `.`
- Project export filename now includes the project and namespace path
- Fix last update timestamp on issues not preserved on gitlab.com and project imports
- Fix issues importing projects from EE to CE
- Fix creating group with space in group path
- Create Todos for Issue author when assign or mention himself (Katarzyna Kobierska)
- Limit the number of retries on error to 3 for exporting projects
- Allow empty repositories on project import/export
v 8.9.6
- Fix importing of events under notes for GitLab projects. !5154
- Fix log statements in import/export. !5129
- Fix commit avatar alignment in compare view. !5128
- Fix broken migration in MySQL. !5005
- Overwrite Host and X-Forwarded-Host headers in NGINX !5213
- Keeps issue number when importing from Gitlab.com
- Add Pending tab for Builds (Katarzyna Kobierska, Urszula Budziszewska)
v 8.9.7 (unreleased)
- Fix import_data wrongly saved as a result of an invalid import_url
v 8.9.6
- 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
...@@ -223,6 +289,7 @@ v 8.9.0 ...@@ -223,6 +289,7 @@ v 8.9.0
- Add rake task 'gitlab:db:configure' for conditionally seeding or migrating the database - Add rake task 'gitlab:db:configure' for conditionally seeding or migrating the database
- Changed the Slack build message to use the singular duration if necessary (Aran Koning) - Changed the Slack build message to use the singular duration if necessary (Aran Koning)
- Fix race condition on merge when build succeeds - Fix race condition on merge when build succeeds
- Added shortcut to focus filter search fields and added documentation #18120
- Links from a wiki page to other wiki pages should be rewritten as expected - Links from a wiki page to other wiki pages should be rewritten as expected
- Add option to project to only allow merge requests to be merged if the build succeeds (Rui Santos) - Add option to project to only allow merge requests to be merged if the build succeeds (Rui Santos)
- Added navigation shortcuts to the project pipelines, milestones, builds and forks page. !4393 - Added navigation shortcuts to the project pipelines, milestones, builds and forks page. !4393
...@@ -2184,8 +2251,6 @@ v 7.7.0 ...@@ -2184,8 +2251,6 @@ v 7.7.0
- Fixes for edit comments: drag-n-drop images, preview mode, selecting images, save & update - Fixes for edit comments: drag-n-drop images, preview mode, selecting images, save & update
- Remove password strength indicator - Remove password strength indicator
v 7.6.0 v 7.6.0
- Fork repository to groups - Fork repository to groups
- New rugged version - New rugged version
...@@ -2611,13 +2676,13 @@ v 6.5.0 ...@@ -2611,13 +2676,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
......
...@@ -145,7 +145,8 @@ might be edited to make them small and simple. ...@@ -145,7 +145,8 @@ might be edited to make them small and simple.
You are encouraged to use the template below for feature proposals. You are encouraged to use the template below for feature proposals.
``` ```
## Description including problem, use cases, benefits, and/or goals ## Description
Include problem, use cases, benefits, and/or goals
## Proposal ## Proposal
......
source 'https://rubygems.org' source 'https://rubygems.org'
gem 'rails', '4.2.6' gem 'rails', '4.2.7'
gem 'rails-deprecated_sanitizer', '~> 1.0.3' gem 'rails-deprecated_sanitizer', '~> 1.0.3'
# Responders respond_to and respond_with # Responders respond_to and respond_with
...@@ -61,7 +61,7 @@ gem 'gitlab_omniauth-ldap', '~> 1.2.1', require: 'omniauth-ldap' ...@@ -61,7 +61,7 @@ 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
gem 'gollum-lib', '~> 4.1.0', require: false gem 'gollum-lib', '~> 4.2', require: false
gem 'gollum-rugged_adapter', '~> 0.4.2', require: false gem 'gollum-rugged_adapter', '~> 0.4.2', require: false
# Language detection # Language detection
...@@ -105,7 +105,7 @@ gem 'seed-fu', '~> 2.3.5' ...@@ -105,7 +105,7 @@ 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'
gem 'task_list', '~> 1.0.2', require: 'task_list/railtie' gem 'task_list', '~> 1.0.2', require: 'task_list/railtie'
gem 'github-markup', '~> 1.3.1' gem 'github-markup', '~> 1.4'
gem 'redcarpet', '~> 3.3.3' gem 'redcarpet', '~> 3.3.3'
gem 'RedCloth', '~> 4.3.2' gem 'RedCloth', '~> 4.3.2'
gem 'rdoc', '~>3.6' gem 'rdoc', '~>3.6'
...@@ -113,7 +113,7 @@ gem 'org-ruby', '~> 0.9.12' ...@@ -113,7 +113,7 @@ gem 'org-ruby', '~> 0.9.12'
gem 'creole', '~> 0.5.0' gem 'creole', '~> 0.5.0'
gem 'wikicloth', '0.8.1' gem 'wikicloth', '0.8.1'
gem 'asciidoctor', '~> 1.5.2' gem 'asciidoctor', '~> 1.5.2'
gem 'rouge', '~> 1.11' gem 'rouge', '~> 2.0'
# See https://groups.google.com/forum/#!topic/ruby-security-ann/aSbgDiwb24s # See https://groups.google.com/forum/#!topic/ruby-security-ann/aSbgDiwb24s
# and https://groups.google.com/forum/#!topic/ruby-security-ann/Dy7YiKb_pMM # and https://groups.google.com/forum/#!topic/ruby-security-ann/Dy7YiKb_pMM
...@@ -299,7 +299,7 @@ group :development, :test do ...@@ -299,7 +299,7 @@ group :development, :test do
gem 'spring-commands-spinach', '~> 1.1.0' gem 'spring-commands-spinach', '~> 1.1.0'
gem 'spring-commands-teaspoon', '~> 0.0.2' gem 'spring-commands-teaspoon', '~> 0.0.2'
gem 'rubocop', '~> 0.40.0', require: false gem 'rubocop', '~> 0.41.2', require: false
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
...@@ -344,7 +344,7 @@ gem 'oauth2', '~> 1.2.0' ...@@ -344,7 +344,7 @@ gem 'oauth2', '~> 1.2.0'
gem 'paranoia', '~> 2.0' gem 'paranoia', '~> 2.0'
# Health check # Health check
gem 'health_check', '~> 1.5.1' gem 'health_check', '~> 2.1.0'
# System information # System information
gem 'vmstat', '~> 2.1.0' gem 'vmstat', '~> 2.1.0'
......
...@@ -3,34 +3,34 @@ GEM ...@@ -3,34 +3,34 @@ GEM
specs: specs:
RedCloth (4.3.2) RedCloth (4.3.2)
ace-rails-ap (4.0.2) ace-rails-ap (4.0.2)
actionmailer (4.2.6) actionmailer (4.2.7)
actionpack (= 4.2.6) actionpack (= 4.2.7)
actionview (= 4.2.6) actionview (= 4.2.7)
activejob (= 4.2.6) activejob (= 4.2.7)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 1.0, >= 1.0.5) rails-dom-testing (~> 1.0, >= 1.0.5)
actionpack (4.2.6) actionpack (4.2.7)
actionview (= 4.2.6) actionview (= 4.2.7)
activesupport (= 4.2.6) activesupport (= 4.2.7)
rack (~> 1.6) rack (~> 1.6)
rack-test (~> 0.6.2) rack-test (~> 0.6.2)
rails-dom-testing (~> 1.0, >= 1.0.5) rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2) rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (4.2.6) actionview (4.2.7)
activesupport (= 4.2.6) activesupport (= 4.2.7)
builder (~> 3.1) builder (~> 3.1)
erubis (~> 2.7.0) erubis (~> 2.7.0)
rails-dom-testing (~> 1.0, >= 1.0.5) rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2) rails-html-sanitizer (~> 1.0, >= 1.0.2)
activejob (4.2.6) activejob (4.2.7)
activesupport (= 4.2.6) activesupport (= 4.2.7)
globalid (>= 0.3.0) globalid (>= 0.3.0)
activemodel (4.2.6) activemodel (4.2.7)
activesupport (= 4.2.6) activesupport (= 4.2.7)
builder (~> 3.1) builder (~> 3.1)
activerecord (4.2.6) activerecord (4.2.7)
activemodel (= 4.2.6) activemodel (= 4.2.7)
activesupport (= 4.2.6) activesupport (= 4.2.7)
arel (~> 6.0) arel (~> 6.0)
activerecord-session_store (1.0.0) activerecord-session_store (1.0.0)
actionpack (>= 4.0, < 5.1) actionpack (>= 4.0, < 5.1)
...@@ -38,7 +38,7 @@ GEM ...@@ -38,7 +38,7 @@ GEM
multi_json (~> 1.11, >= 1.11.2) multi_json (~> 1.11, >= 1.11.2)
rack (>= 1.5.2, < 3) rack (>= 1.5.2, < 3)
railties (>= 4.0, < 5.1) railties (>= 4.0, < 5.1)
activesupport (4.2.6) activesupport (4.2.7)
i18n (~> 0.7) i18n (~> 0.7)
json (~> 1.7, >= 1.7.7) json (~> 1.7, >= 1.7.7)
minitest (~> 5.1) minitest (~> 5.1)
...@@ -58,7 +58,7 @@ GEM ...@@ -58,7 +58,7 @@ GEM
faraday_middleware-multi_json (~> 0.0) faraday_middleware-multi_json (~> 0.0)
oauth2 (~> 1.0) oauth2 (~> 1.0)
asciidoctor (1.5.3) asciidoctor (1.5.3)
ast (2.2.0) ast (2.3.0)
attr_encrypted (3.0.1) attr_encrypted (3.0.1)
encryptor (~> 3.0.0) encryptor (~> 3.0.0)
attr_required (1.0.0) attr_required (1.0.0)
...@@ -264,7 +264,7 @@ GEM ...@@ -264,7 +264,7 @@ GEM
escape_utils (~> 1.1.0) escape_utils (~> 1.1.0)
mime-types (>= 1.19) mime-types (>= 1.19)
rugged (>= 0.23.0b) rugged (>= 0.23.0b)
github-markup (1.3.3) github-markup (1.4.0)
gitlab-flowdock-git-hook (1.0.1) gitlab-flowdock-git-hook (1.0.1)
flowdock (~> 0.7) flowdock (~> 0.7)
gitlab-grit (>= 2.4.1) gitlab-grit (>= 2.4.1)
...@@ -287,13 +287,13 @@ GEM ...@@ -287,13 +287,13 @@ GEM
rubyntlm (~> 0.3) rubyntlm (~> 0.3)
globalid (0.3.6) globalid (0.3.6)
activesupport (>= 4.1.0) activesupport (>= 4.1.0)
gollum-grit_adapter (1.0.0) gollum-grit_adapter (1.0.1)
gitlab-grit (~> 2.7, >= 2.7.1) gitlab-grit (~> 2.7, >= 2.7.1)
gollum-lib (4.1.0) gollum-lib (4.2.1)
github-markup (~> 1.3.3) github-markup (~> 1.4.0)
gollum-grit_adapter (~> 1.0) gollum-grit_adapter (~> 1.0)
nokogiri (~> 1.6.4) nokogiri (~> 1.6.4)
rouge (~> 1.9) rouge (~> 2.0)
sanitize (~> 2.1.0) sanitize (~> 2.1.0)
stringex (~> 2.5.1) stringex (~> 2.5.1)
gollum-rugged_adapter (0.4.2) gollum-rugged_adapter (0.4.2)
...@@ -322,8 +322,8 @@ GEM ...@@ -322,8 +322,8 @@ GEM
thor thor
tilt tilt
hashie (3.4.3) hashie (3.4.3)
health_check (1.5.1) health_check (2.1.0)
rails (>= 2.3.0) rails (>= 4.0)
hipchat (1.5.2) hipchat (1.5.2)
httparty httparty
mimemagic mimemagic
...@@ -473,7 +473,7 @@ GEM ...@@ -473,7 +473,7 @@ GEM
orm_adapter (0.5.0) orm_adapter (0.5.0)
paranoia (2.1.4) paranoia (2.1.4)
activerecord (~> 4.0) activerecord (~> 4.0)
parser (2.3.1.0) parser (2.3.1.2)
ast (~> 2.2) ast (~> 2.2)
pg (0.18.4) pg (0.18.4)
pkg-config (1.1.7) pkg-config (1.1.7)
...@@ -515,16 +515,16 @@ GEM ...@@ -515,16 +515,16 @@ GEM
rack rack
rack-test (0.6.3) rack-test (0.6.3)
rack (>= 1.0) rack (>= 1.0)
rails (4.2.6) rails (4.2.7)
actionmailer (= 4.2.6) actionmailer (= 4.2.7)
actionpack (= 4.2.6) actionpack (= 4.2.7)
actionview (= 4.2.6) actionview (= 4.2.7)
activejob (= 4.2.6) activejob (= 4.2.7)
activemodel (= 4.2.6) activemodel (= 4.2.7)
activerecord (= 4.2.6) activerecord (= 4.2.7)
activesupport (= 4.2.6) activesupport (= 4.2.7)
bundler (>= 1.3.0, < 2.0) bundler (>= 1.3.0, < 2.0)
railties (= 4.2.6) railties (= 4.2.7)
sprockets-rails sprockets-rails
rails-deprecated_sanitizer (1.0.3) rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha) activesupport (>= 4.2.0.alpha)
...@@ -534,9 +534,9 @@ GEM ...@@ -534,9 +534,9 @@ GEM
rails-deprecated_sanitizer (>= 1.0.1) rails-deprecated_sanitizer (>= 1.0.1)
rails-html-sanitizer (1.0.3) rails-html-sanitizer (1.0.3)
loofah (~> 2.0) loofah (~> 2.0)
railties (4.2.6) railties (4.2.7)
actionpack (= 4.2.6) actionpack (= 4.2.7)
activesupport (= 4.2.6) activesupport (= 4.2.7)
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0) thor (>= 0.18.1, < 2.0)
rainbow (2.1.0) rainbow (2.1.0)
...@@ -578,7 +578,7 @@ GEM ...@@ -578,7 +578,7 @@ GEM
railties (>= 4.2.0, < 5.1) railties (>= 4.2.0, < 5.1)
rinku (2.0.0) rinku (2.0.0)
rotp (2.1.2) rotp (2.1.2)
rouge (1.11.0) rouge (2.0.3)
rqrcode (0.7.0) rqrcode (0.7.0)
chunky_png chunky_png
rqrcode-rails3 (0.1.7) rqrcode-rails3 (0.1.7)
...@@ -606,8 +606,8 @@ GEM ...@@ -606,8 +606,8 @@ GEM
rspec-retry (0.4.5) rspec-retry (0.4.5)
rspec-core rspec-core
rspec-support (3.5.0) rspec-support (3.5.0)
rubocop (0.40.0) rubocop (0.41.2)
parser (>= 2.3.1.0, < 3.0) parser (>= 2.3.1.1, < 3.0)
powerpack (~> 0.1) powerpack (~> 0.1)
rainbow (>= 1.99.1, < 3.0) rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
...@@ -697,7 +697,7 @@ GEM ...@@ -697,7 +697,7 @@ GEM
spring (>= 0.9.1) spring (>= 0.9.1)
spring-commands-teaspoon (0.0.2) spring-commands-teaspoon (0.0.2)
spring (>= 0.9.1) spring (>= 0.9.1)
sprockets (3.6.2) sprockets (3.6.3)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
rack (> 1, < 3) rack (> 1, < 3)
sprockets-rails (3.1.1) sprockets-rails (3.1.1)
...@@ -758,7 +758,7 @@ GEM ...@@ -758,7 +758,7 @@ GEM
unf (0.1.4) unf (0.1.4)
unf_ext unf_ext
unf_ext (0.0.7.2) unf_ext (0.0.7.2)
unicode-display_width (1.0.5) unicode-display_width (1.1.0)
unicorn (4.9.0) unicorn (4.9.0)
kgio (~> 2.6) kgio (~> 2.6)
rack rack
...@@ -859,18 +859,18 @@ DEPENDENCIES ...@@ -859,18 +859,18 @@ DEPENDENCIES
gemnasium-gitlab-service (~> 0.2) gemnasium-gitlab-service (~> 0.2)
gemojione (~> 2.6) gemojione (~> 2.6)
github-linguist (~> 4.7.0) github-linguist (~> 4.7.0)
github-markup (~> 1.3.1) github-markup (~> 1.4)
gitlab-flowdock-git-hook (~> 1.0.1) gitlab-flowdock-git-hook (~> 1.0.1)
gitlab_git (~> 10.2) gitlab_git (~> 10.2)
gitlab_meta (= 7.0) gitlab_meta (= 7.0)
gitlab_omniauth-ldap (~> 1.2.1) gitlab_omniauth-ldap (~> 1.2.1)
gollum-lib (~> 4.1.0) gollum-lib (~> 4.2)
gollum-rugged_adapter (~> 0.4.2) gollum-rugged_adapter (~> 0.4.2)
gon (~> 6.0.1) gon (~> 6.0.1)
grape (~> 0.13.0) grape (~> 0.13.0)
grape-entity (~> 0.4.2) grape-entity (~> 0.4.2)
hamlit (~> 2.5) hamlit (~> 2.5)
health_check (~> 1.5.1) health_check (~> 2.1.0)
hipchat (~> 1.5.0) hipchat (~> 1.5.0)
html-pipeline (~> 1.11.0) html-pipeline (~> 1.11.0)
httparty (~> 0.13.3) httparty (~> 0.13.3)
...@@ -920,7 +920,7 @@ DEPENDENCIES ...@@ -920,7 +920,7 @@ DEPENDENCIES
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.7)
rails-deprecated_sanitizer (~> 1.0.3) rails-deprecated_sanitizer (~> 1.0.3)
rainbow (~> 2.1.0) rainbow (~> 2.1.0)
rblineprof (~> 0.3.6) rblineprof (~> 0.3.6)
...@@ -933,11 +933,11 @@ DEPENDENCIES ...@@ -933,11 +933,11 @@ DEPENDENCIES
request_store (~> 1.3.0) request_store (~> 1.3.0)
rerun (~> 0.11.0) rerun (~> 0.11.0)
responders (~> 2.0) responders (~> 2.0)
rouge (~> 1.11) rouge (~> 2.0)
rqrcode-rails3 (~> 0.1.7) rqrcode-rails3 (~> 0.1.7)
rspec-rails (~> 3.5.0) rspec-rails (~> 3.5.0)
rspec-retry (~> 0.4.5) rspec-retry (~> 0.4.5)
rubocop (~> 0.40.0) rubocop (~> 0.41.2)
rubocop-rspec (~> 1.5.0) rubocop-rspec (~> 1.5.0)
ruby-fogbugz (~> 0.2.1) ruby-fogbugz (~> 0.2.1)
sanitize (~> 2.0) sanitize (~> 2.0)
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
groupPath: "/api/:version/groups/:id.json" groupPath: "/api/:version/groups/:id.json"
namespacesPath: "/api/:version/namespaces.json" namespacesPath: "/api/:version/namespaces.json"
groupProjectsPath: "/api/:version/groups/:id/projects.json" groupProjectsPath: "/api/:version/groups/:id/projects.json"
projectsPath: "/api/:version/projects.json" projectsPath: "/api/:version/projects.json?simple=true"
labelsPath: "/api/:version/projects/:id/labels" labelsPath: "/api/:version/projects/:id/labels"
licensePath: "/api/:version/licenses/:key" licensePath: "/api/:version/licenses/:key"
gitignorePath: "/api/:version/gitignores/:key" gitignorePath: "/api/:version/gitignores/:key"
......
...@@ -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 u2f
window.slugify = (text) -> window.slugify = (text) ->
text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase() text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase()
......
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
class @CompareAutocomplete
constructor: ->
@initDropdown()
initDropdown: ->
$('.js-compare-dropdown').each ->
$dropdown = $(@)
selected = $dropdown.data('selected')
$dropdown.glDropdown(
data: (term, callback) ->
$.ajax(
url: $dropdown.data('refs-url')
data:
ref: $dropdown.data('ref')
).done (refs) ->
callback(refs)
selectable: true
filterable: true
filterByText: true
fieldName: $dropdown.attr('name')
filterInput: 'input[type="text"]'
renderRow: (ref) ->
if ref.header?
$('<li />')
.addClass('dropdown-header')
.text(ref.header)
else
link = $('<a />')
.attr('href', '#')
.addClass(if ref is selected then 'is-active' else '')
.text(ref)
.attr('data-ref', escape(ref))
$('<li />')
.append(link)
id: (obj, $el) ->
$el.attr('data-ref')
toggleLabel: (obj, $el) ->
$el.text().trim()
)
class @Diff class @Diff
UNFOLD_COUNT = 20 UNFOLD_COUNT = 20
constructor: -> constructor: ->
$('.files .diff-file').singleFileDiff()
@filesCommentButton = $('.files .diff-file').filesCommentButton()
$(document).off('click', '.js-unfold') $(document).off('click', '.js-unfold')
$(document).on('click', '.js-unfold', (event) => $(document).on('click', '.js-unfold', (event) =>
target = $(event.target) target = $(event.target)
...@@ -36,7 +39,7 @@ class @Diff ...@@ -36,7 +39,7 @@ class @Diff
# see https://gitlab.com/gitlab-org/gitlab-ce/issues/707 # see https://gitlab.com/gitlab-org/gitlab-ce/issues/707
indent: 1 indent: 1
$.get(link, params, (response) => $.get(link, params, (response) ->
target.parent().replaceWith(response) target.parent().replaceWith(response)
) )
) )
......
...@@ -137,6 +137,8 @@ class Dispatcher ...@@ -137,6 +137,8 @@ class Dispatcher
new Project() new Project()
new ProjectAvatar() new ProjectAvatar()
switch path[1] switch path[1]
when 'compare'
new CompareAutocomplete()
when 'edit' when 'edit'
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
new ProjectNew() new ProjectNew()
......
class @FilesCommentButton
COMMENT_BUTTON_CLASS = '.add-diff-note'
COMMENT_BUTTON_TEMPLATE = _.template '<button name="button" type="submit" class="btn <%- COMMENT_BUTTON_CLASS %> js-add-diff-note-button" title="Add a comment to this line"><i class="fa fa-comment-o"></i></button>'
LINE_HOLDER_CLASS = '.line_holder'
LINE_NUMBER_CLASS = 'diff-line-num'
LINE_CONTENT_CLASS = 'line_content'
UNFOLDABLE_LINE_CLASS = 'js-unfold'
EMPTY_CELL_CLASS = 'empty-cell'
OLD_LINE_CLASS = 'old_line'
NEW_CLASS = 'new'
LINE_COLUMN_CLASSES = ".#{LINE_NUMBER_CLASS}, .line_content"
TEXT_FILE_SELECTOR = '.text-file'
DEBOUNCE_TIMEOUT_DURATION = 100
constructor: (@filesContainerElement) ->
@VIEW_TYPE = $('input#view[type=hidden]').val()
debounce = _.debounce @render, DEBOUNCE_TIMEOUT_DURATION
$(document)
.on 'mouseover', LINE_COLUMN_CLASSES, debounce
.on 'mouseleave', LINE_COLUMN_CLASSES, @destroy
render: (e) =>
$currentTarget = $(e.currentTarget)
buttonParentElement = @getButtonParent $currentTarget
return unless @shouldRender e, buttonParentElement
textFileElement = @getTextFileElement $currentTarget
lineContentElement = @getLineContent $currentTarget
buttonParentElement.append @buildButton
noteableType: textFileElement.attr 'data-noteable-type'
noteableID: textFileElement.attr 'data-noteable-id'
commitID: textFileElement.attr 'data-commit-id'
noteType: lineContentElement.attr 'data-note-type'
position: lineContentElement.attr 'data-position'
lineType: lineContentElement.attr 'data-line-type'
discussionID: lineContentElement.attr 'data-discussion-id'
lineCode: lineContentElement.attr 'data-line-code'
return
destroy: (e) =>
return if @isMovingToSameType e
$(COMMENT_BUTTON_CLASS, @getButtonParent $(e.currentTarget)).remove()
return
buildButton: (buttonAttributes) ->
initializedButtonTemplate = COMMENT_BUTTON_TEMPLATE
COMMENT_BUTTON_CLASS: COMMENT_BUTTON_CLASS.substr 1
$(initializedButtonTemplate).attr
'data-noteable-type': buttonAttributes.noteableType
'data-noteable-id': buttonAttributes.noteableID
'data-commit-id': buttonAttributes.commitID
'data-note-type': buttonAttributes.noteType
'data-line-code': buttonAttributes.lineCode
'data-position': buttonAttributes.position
'data-discussion-id': buttonAttributes.discussionID
'data-line-type': buttonAttributes.lineType
getTextFileElement: (hoveredElement) ->
$(hoveredElement.closest TEXT_FILE_SELECTOR)
getLineContent: (hoveredElement) ->
return hoveredElement if hoveredElement.hasClass LINE_CONTENT_CLASS
$(".#{LINE_CONTENT_CLASS + @diffTypeClass hoveredElement}", hoveredElement.parent())
getButtonParent: (hoveredElement) ->
if @VIEW_TYPE is 'inline'
return hoveredElement if hoveredElement.hasClass OLD_LINE_CLASS
$(".#{OLD_LINE_CLASS}", hoveredElement.parent())
else
return hoveredElement if hoveredElement.hasClass LINE_NUMBER_CLASS
$(".#{LINE_NUMBER_CLASS + @diffTypeClass hoveredElement}", hoveredElement.parent())
diffTypeClass: (hoveredElement) ->
if hoveredElement.hasClass(NEW_CLASS) then '.new' else '.old'
isMovingToSameType: (e) ->
newButtonParent = @getButtonParent $(e.toElement)
return false unless newButtonParent
newButtonParent.is @getButtonParent $(e.currentTarget)
shouldRender: (e, buttonParentElement) ->
(not buttonParentElement.hasClass(EMPTY_CELL_CLASS) and \
not buttonParentElement.hasClass(UNFOLDABLE_LINE_CLASS) and \
$(COMMENT_BUTTON_CLASS, buttonParentElement).length is 0)
$.fn.filesCommentButton = ->
return unless this and @parent().data('can-create-note')?
@each ->
unless $.data this, 'filesCommentButton'
$.data this, 'filesCommentButton', new FilesCommentButton $(this)
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)
...@@ -456,6 +456,8 @@ class GitLabDropdown ...@@ -456,6 +456,8 @@ class GitLabDropdown
rowClicked: (el) -> rowClicked: (el) ->
fieldName = @options.fieldName fieldName = @options.fieldName
isInput = $(@el).is('input')
if @renderedData if @renderedData
groupName = el.data('group') groupName = el.data('group')
if groupName if groupName
...@@ -466,10 +468,19 @@ class GitLabDropdown ...@@ -466,10 +468,19 @@ class GitLabDropdown
selectedObject = @renderedData[selectedIndex] selectedObject = @renderedData[selectedIndex]
value = if @options.id then @options.id(selectedObject, el) else selectedObject.id value = if @options.id then @options.id(selectedObject, el) else selectedObject.id
field = @dropdown.parent().find("input[name='#{fieldName}'][value='#{value}']")
if isInput
field = $(@el)
else
field = @dropdown.parent().find("input[name='#{fieldName}'][value='#{value}']")
if el.hasClass(ACTIVE_CLASS) if el.hasClass(ACTIVE_CLASS)
el.removeClass(ACTIVE_CLASS) el.removeClass(ACTIVE_CLASS)
field.remove()
if isInput
field.val('')
else
field.remove()
# Toggle the dropdown label # Toggle the dropdown label
if @options.toggleLabel if @options.toggleLabel
...@@ -490,7 +501,9 @@ class GitLabDropdown ...@@ -490,7 +501,9 @@ class GitLabDropdown
else else
if not @options.multiSelect or el.hasClass('dropdown-clear-active') if not @options.multiSelect or el.hasClass('dropdown-clear-active')
@dropdown.find(".#{ACTIVE_CLASS}").removeClass ACTIVE_CLASS @dropdown.find(".#{ACTIVE_CLASS}").removeClass ACTIVE_CLASS
@dropdown.parent().find("input[name='#{fieldName}']").remove()
unless isInput
@dropdown.parent().find("input[name='#{fieldName}']").remove()
if !value? if !value?
field.remove() field.remove()
...@@ -505,7 +518,9 @@ class GitLabDropdown ...@@ -505,7 +518,9 @@ class GitLabDropdown
if !field.length and fieldName if !field.length and fieldName
@addInput(fieldName, value) @addInput(fieldName, value)
else else
field.val value field
.val value
.trigger 'change'
return selectedObject return selectedObject
......
...@@ -32,13 +32,11 @@ issuable_created = false ...@@ -32,13 +32,11 @@ issuable_created = false
$search = $('#issue_search') $search = $('#issue_search')
$form = $('.js-filter-form') $form = $('.js-filter-form')
$input = $("input[name='#{$search.attr('name')}']", $form) $input = $("input[name='#{$search.attr('name')}']", $form)
if $input.length is 0 if $input.length is 0
$form.append "<input type='hidden' name='#{$search.attr('name')}' value='#{_.escape($search.val())}'/>" $form.append "<input type='hidden' name='#{$search.attr('name')}' value='#{_.escape($search.val())}'/>"
else else
$input.val $search.val() $input.val $search.val()
Issuable.filterResults $form if $search.val() isnt ''
Issuable.filterResults $form
, 500) , 500)
initLabelFilterRemove: -> initLabelFilterRemove: ->
......
...@@ -2,10 +2,14 @@ ...@@ -2,10 +2,14 @@
w.gl ?= {} w.gl ?= {}
w.gl.utils ?= {} w.gl.utils ?= {}
w.gl.utils.days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
w.gl.utils.formatDate = (datetime) -> w.gl.utils.formatDate = (datetime) ->
dateFormat(datetime, 'mmm d, yyyy h:MMtt Z') dateFormat(datetime, 'mmm d, yyyy h:MMtt Z')
w.gl.utils.getDayName = (date) ->
this.days[date.getDay()]
w.gl.utils.localTimeAgo = ($timeagoEls, setTimeago = true) -> w.gl.utils.localTimeAgo = ($timeagoEls, setTimeago = true) ->
$timeagoEls.each( -> $timeagoEls.each( ->
$el = $(@) $el = $(@)
......
...@@ -153,17 +153,18 @@ class @MergeRequestTabs ...@@ -153,17 +153,18 @@ class @MergeRequestTabs
loadDiff: (source) -> loadDiff: (source) ->
return if @diffsLoaded return if @diffsLoaded
@_get @_get
url: "#{source}.json" + @_location.search url: "#{source}.json" + @_location.search
success: (data) => success: (data) =>
$('#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")
@highlighSelectedLine() @highlighSelectedLine()
@filesCommentButton = $('.files .diff-file').filesCommentButton()
$(document) $(document)
.off 'click', '.diff-line-num a' .off 'click', '.diff-line-num a'
......
...@@ -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
......
...@@ -5,13 +5,12 @@ ...@@ -5,13 +5,12 @@
this.initPagination() this.initPagination()
initSearch: -> initSearch: ->
@timer = null projectsListFilter = $('.projects-list-filter')
$(".projects-list-filter").on('keyup', -> debounceFilter = _.debounce ProjectsList.filterResults, 500
clearTimeout(@timer) projectsListFilter.on 'keyup', (e) ->
@timer = setTimeout(ProjectsList.filterResults, 500) debounceFilter() if projectsListFilter.val() isnt ''
)
filterResults: => filterResults: ->
$('.projects-list-holder').fadeTo(250, 0.5) $('.projects-list-holder').fadeTo(250, 0.5)
form = null form = null
......
...@@ -2,9 +2,10 @@ class @Shortcuts ...@@ -2,9 +2,10 @@ class @Shortcuts
constructor: (skipResetBindings) -> constructor: (skipResetBindings) ->
@enabledHelp = [] @enabledHelp = []
Mousetrap.reset() if not skipResetBindings Mousetrap.reset() if not skipResetBindings
Mousetrap.bind('?', @onToggleHelp) Mousetrap.bind '?', @onToggleHelp
Mousetrap.bind('s', Shortcuts.focusSearch) Mousetrap.bind 's', Shortcuts.focusSearch
Mousetrap.bind(['ctrl+shift+p', 'command+shift+p'], @toggleMarkdownPreview) Mousetrap.bind 'f', (e) => @focusFilter e
Mousetrap.bind ['ctrl+shift+p', 'command+shift+p'], @toggleMarkdownPreview
Mousetrap.bind('t', -> Turbolinks.visit(findFileURL)) if findFileURL? Mousetrap.bind('t', -> Turbolinks.visit(findFileURL)) if findFileURL?
onToggleHelp: (e) => onToggleHelp: (e) =>
...@@ -32,10 +33,16 @@ class @Shortcuts ...@@ -32,10 +33,16 @@ class @Shortcuts
$('.js-more-help-button').remove() $('.js-more-help-button').remove()
) )
focusFilter: (e) ->
@filterInput ?= $('input[type=search]', '.nav-controls')
@filterInput.focus()
e.preventDefault()
@focusSearch: (e) -> @focusSearch: (e) ->
$('#search').focus() $('#search').focus()
e.preventDefault() e.preventDefault()
$(document).on 'click.more_help', '.js-more-help-button', (e) -> $(document).on 'click.more_help', '.js-more-help-button', (e) ->
$(@).remove() $(@).remove()
$('.hidden-shortcut').show() $('.hidden-shortcut').show()
......
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
...@@ -6,8 +6,20 @@ ...@@ -6,8 +6,20 @@
class @U2FAuthenticate class @U2FAuthenticate
constructor: (@container, u2fParams) -> constructor: (@container, u2fParams) ->
@appId = u2fParams.app_id @appId = u2fParams.app_id
@challenges = u2fParams.challenges @challenge = u2fParams.challenge
@signRequests = u2fParams.sign_requests
# The U2F Javascript API v1.1 requires a single challenge, with
# _no challenges per-request_. The U2F Javascript API v1.0 requires a
# challenge per-request, which is done by copying the single challenge
# into every request.
#
# In either case, we don't need the per-request challenges that the server
# has generated, so we can remove them.
#
# Note: The server library fixes this behaviour in (unreleased) version 1.0.0.
# This can be removed once we upgrade.
# https://github.com/castle/ruby-u2f/commit/103f428071a81cd3d5f80c2e77d522d5029946a4
@signRequests = u2fParams.sign_requests.map (request) -> _(request).omit('challenge')
start: () => start: () =>
if U2FUtil.isU2FSupported() if U2FUtil.isU2FSupported()
...@@ -16,7 +28,7 @@ class @U2FAuthenticate ...@@ -16,7 +28,7 @@ class @U2FAuthenticate
@renderNotSupported() @renderNotSupported()
authenticate: () => authenticate: () =>
u2f.sign(@appId, @challenges, @signRequests, (response) => u2f.sign(@appId, @challenge, @signRequests, (response) =>
if response.errorCode if response.errorCode
error = new U2FError(response.errorCode) error = new U2FError(response.errorCode)
@renderError(error); @renderError(error);
......
class @U2FUtil
@isU2FSupported: ->
window.u2f
# Helper class for U2F (universal 2nd factor) device registration and authentication.
class @U2FUtil
@isU2FSupported: ->
if @testMode
true
else
gon.u2f.browser_supports_u2f
@enableTestMode: ->
@testMode = true
<% if Rails.env.test? %>
U2FUtil.enableTestMode();
<% end %>
...@@ -87,14 +87,15 @@ class @Calendar ...@@ -87,14 +87,15 @@ class @Calendar
.attr 'width', @daySize .attr 'width', @daySize
.attr 'height', @daySize .attr 'height', @daySize
.attr 'title', (stamp) => .attr 'title', (stamp) =>
date = new Date(stamp.date)
contribText = 'No contributions' contribText = 'No contributions'
if stamp.count > 0 if stamp.count > 0
contribText = "#{stamp.count} contribution#{if stamp.count > 1 then 's' else ''}" contribText = "#{stamp.count} contribution#{if stamp.count > 1 then 's' else ''}"
date = dateFormat(stamp.date, 'mmm d, yyyy') dateText = dateFormat(date, 'mmm d, yyyy')
"#{contribText}<br />#{date}" "#{contribText}<br />#{gl.utils.getDayName(date)} #{dateText}"
.attr 'class', 'user-contrib-cell js-tooltip' .attr 'class', 'user-contrib-cell js-tooltip'
.attr 'fill', (stamp) => .attr 'fill', (stamp) =>
if stamp.count isnt 0 if stamp.count isnt 0
......
...@@ -56,6 +56,11 @@ class @UsersSelect ...@@ -56,6 +56,11 @@ class @UsersSelect
username: '' username: ''
avatar: '' avatar: ''
$value.html(assigneeTemplate(user)) $value.html(assigneeTemplate(user))
$collapsedSidebar
.attr('title', user.name)
.tooltip('fixTitle')
$collapsedSidebar.html(collapsedAssigneeTemplate(user)) $collapsedSidebar.html(collapsedAssigneeTemplate(user))
...@@ -63,7 +68,6 @@ class @UsersSelect ...@@ -63,7 +68,6 @@ class @UsersSelect
'<% if( avatar ) { %> '<% if( avatar ) { %>
<a class="author_link" href="/u/<%- username %>"> <a class="author_link" href="/u/<%- username %>">
<img width="24" class="avatar avatar-inline s24" alt="" src="<%- avatar %>"> <img width="24" class="avatar avatar-inline s24" alt="" src="<%- avatar %>">
<span class="author">Toni Boehm</span>
</a> </a>
<% } else { %> <% } else { %>
<i class="fa fa-user"></i> <i class="fa fa-user"></i>
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
} }
&.s16 { width: 16px; height: 16px; margin-right: 6px; } &.s16 { width: 16px; height: 16px; margin-right: 6px; }
&.s20 { width: 20px; height: 20px; margin-right: 7px; }
&.s24 { width: 24px; height: 24px; margin-right: 8px; } &.s24 { width: 24px; height: 24px; margin-right: 8px; }
&.s26 { width: 26px; height: 26px; margin-right: 8px; } &.s26 { width: 26px; height: 26px; margin-right: 8px; }
&.s32 { width: 32px; height: 32px; margin-right: 10px; } &.s32 { width: 32px; height: 32px; margin-right: 10px; }
......
...@@ -20,9 +20,12 @@ ...@@ -20,9 +20,12 @@
.blank-state-icon { .blank-state-icon {
padding-bottom: 20px; padding-bottom: 20px;
color: $gray-darkest;
font-size: 56px;
path { path,
fill: $gray-darkest; polygon {
fill: currentColor;
} }
} }
...@@ -37,6 +40,10 @@ ...@@ -37,6 +40,10 @@
margin-top: 0; margin-top: 0;
margin-bottom: $gl-padding; margin-bottom: $gl-padding;
font-size: 15px; font-size: 15px;
> strong {
font-weight: 600;
}
} }
.blank-state-welcome-title { .blank-state-welcome-title {
......
...@@ -16,6 +16,15 @@ ...@@ -16,6 +16,15 @@
font-weight: normal; font-weight: normal;
font-size: 16px; font-size: 16px;
line-height: 36px; line-height: 36px;
&.diff-collapsed {
padding: 5px;
cursor: pointer;
&:hover {
background-color: $row-hover;
}
}
} }
.row-content-block { .row-content-block {
......
...@@ -270,21 +270,6 @@ table { ...@@ -270,21 +270,6 @@ table {
} }
} }
.dashboard-intro-icon {
float: left;
text-align: center;
font-size: 32px;
color: #aaa;
width: 60px;
}
.dashboard-intro-text {
display: inline-block;
margin-left: -60px;
padding-left: 60px;
width: 100%;
}
.btn-sign-in { .btn-sign-in {
text-shadow: none; text-shadow: none;
......
.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;
}
}
} }
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
.toggle-nav-collapse, .toggle-nav-collapse,
.pin-nav-btn { .pin-nav-btn {
color: $color-light; color: $color-light;
background: $color;
&:hover { &:hover {
color: $white-light; color: $white-light;
......
...@@ -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 $black-transparent);
} }
} }
...@@ -48,10 +55,6 @@ ...@@ -48,10 +55,6 @@
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
@media (min-width: $sidebar-breakpoint) {
bottom: 50px;
}
&.navbar-collapse { &.navbar-collapse {
padding: 0 !important; padding: 0 !important;
} }
...@@ -69,7 +72,7 @@ ...@@ -69,7 +72,7 @@
} }
a { a {
padding: 7px 15px 7px 12px; padding: 7px $gl-sidebar-padding;
font-size: $gl-font-size; font-size: $gl-font-size;
line-height: 24px; line-height: 24px;
display: block; display: block;
...@@ -101,7 +104,7 @@ ...@@ -101,7 +104,7 @@
} }
} }
.toggle-nav-collapse { .sidebar-action-buttons {
width: $sidebar_width; width: $sidebar_width;
position: absolute; position: absolute;
top: 0; top: 0;
...@@ -110,12 +113,37 @@ ...@@ -110,12 +113,37 @@
padding: 5px 0; padding: 5px 0;
font-size: 18px; font-size: 18px;
line-height: 30px; line-height: 30px;
.toggle-nav-collapse {
left: 0;
}
.pin-nav-btn {
right: 0;
display: none;
@media (min-width: $sidebar-breakpoint) {
display: block;
}
.fa {
transition: transform .15s;
}
&.is-active {
.fa {
transform: rotate(90deg);
}
}
}
} }
.nav-header-btn { .nav-header-btn {
padding: 10px 5px; padding: 10px $gl-sidebar-padding;
color: inherit; color: inherit;
transition-duration: .3s; transition-duration: .3s;
position: absolute;
top: 0;
&:hover, &:hover,
&:focus { &:focus {
...@@ -124,30 +152,6 @@ ...@@ -124,30 +152,6 @@
} }
} }
.pin-nav-btn {
display: none;
position: absolute;
left: 0;
bottom: 0;
height: 50px;
width: $sidebar_width;
line-height: 30px;
@media (min-width: $sidebar-breakpoint) {
display: block;
}
.fa {
transition: transform .15s;
}
&.is-active {
.fa {
transform: rotate(90deg);
}
}
}
.page-sidebar-collapsed { .page-sidebar-collapsed {
padding-left: 0; padding-left: 0;
......
...@@ -17,6 +17,7 @@ $focus-border-color: #3aabf0; ...@@ -17,6 +17,7 @@ $focus-border-color: #3aabf0;
$table-border-color: #f0f0f0; $table-border-color: #f0f0f0;
$background-color: #fafafa; $background-color: #fafafa;
$dark-background-color: #f7f7f7; $dark-background-color: #f7f7f7;
$table-text-gray: #8f8f8f;
/* /*
* Text * Text
...@@ -63,6 +64,7 @@ $gl-btn-padding: 10px; ...@@ -63,6 +64,7 @@ $gl-btn-padding: 10px;
$gl-input-padding: 10px; $gl-input-padding: 10px;
$gl-vert-padding: 6px; $gl-vert-padding: 6px;
$gl-padding-top: 10px; $gl-padding-top: 10px;
$gl-sidebar-padding: 22px;
/* /*
* Misc * Misc
......
...@@ -88,13 +88,7 @@ ...@@ -88,13 +88,7 @@
.user-name { .user-name {
display: inline-block; display: inline-block;
font-weight: bold; font-weight: 600;
}
.controls {
> .btn, > .dropdown {
margin-left: 5px;
}
} }
.dropdown { .dropdown {
......
...@@ -83,14 +83,6 @@ ...@@ -83,14 +83,6 @@
} }
} }
table.builds {
.build-link {
a {
color: $gl-dark-link-color;
}
}
}
.build-trace { .build-trace {
background: $ci-output-bg; background: $ci-output-bg;
color: $ci-text-color; color: $ci-text-color;
......
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
font-size: 0; font-size: 0;
} }
.btn-transparent { .btn-clipboard, .btn-transparent {
padding-left: 0; padding-left: 0;
padding-right: 0; padding-right: 0;
} }
......
...@@ -38,33 +38,6 @@ ...@@ -38,33 +38,6 @@
margin-right: 15px; margin-right: 15px;
} }
} }
&.group-admin {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
.group-avatar, .group-details, .group-controls {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.group-details {
flex: 1 1 auto;
flex-direction: column;
min-width: 0;
}
.group-controls {
align-items: center;
a {
margin-left: 5px;
}
}
}
} }
.ldap-group-links { .ldap-group-links {
......
...@@ -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 {
......
...@@ -162,9 +162,15 @@ ...@@ -162,9 +162,15 @@
} }
.filtered-labels { .filtered-labels {
font-size: 0;
padding: 12px 16px;
.label-row { .label-row {
margin-top: 4px;
margin-bottom: 4px;
&:not(:last-child) { &:not(:last-child) {
margin-right: 5px; margin-right: 8px;
} }
} }
......
...@@ -73,11 +73,14 @@ ...@@ -73,11 +73,14 @@
color: #888; color: #888;
} }
&.ci-pending, &.ci-pending {
&.ci-running {
color: $gl-warning; color: $gl-warning;
} }
&.ci-running {
color: $blue-normal;
}
&.ci-failed, &.ci-failed,
&.ci-error { &.ci-error {
color: $gl-danger; color: $gl-danger;
......
.pipelines { .pipelines {
.stage { .stage {
max-width: 100px; max-width: 80px;
width: 80px;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
.duration, .finished_at {
margin: 4px 0;
}
.commit-title { .commit-title {
margin: 0; margin: 0;
} }
...@@ -22,3 +19,156 @@ ...@@ -22,3 +19,156 @@
margin: 4px; margin: 4px;
} }
} }
.content-list {
&.pipelines,
&.builds-content-list {
width: 100%;
overflow: auto;
}
}
.table.builds {
min-width: 1100px;
tr {
th {
padding: 16px;
border: none;
}
}
tbody {
border-top-width: 1px;
}
.commit-link {
a:hover {
text-decoration: none;
}
}
.branch-commit {
.branch-name {
margin-left: 8px;
font-weight: bold;
max-width: 180px;
overflow: hidden;
display: inline-block;
white-space: nowrap;
vertical-align: top;
text-overflow: ellipsis;
}
svg {
margin: 0 6px;
height: 14px;
width: auto;
vertical-align: middle;
}
.commit-id {
color: $gl-link-color;
margin-right: 8px;
}
.commit-title {
margin-top: 4px;
max-width: 320px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.avatar {
margin-left: 0;
}
.label {
margin-right: 4px;
}
.label-container {
font-size: 0;
.label {
margin-top: 5px;
}
}
}
.duration,
.finished-at {
color: $table-text-gray;
margin: 4px 0;
.fa {
font-size: 12px;
}
svg {
height: 12px;
width: auto;
vertical-align: middle;
}
.fa,
svg {
margin-right: 5px;
}
}
.pipeline-actions {
.btn {
margin: 0;
color: $table-text-gray;
}
.cancel-retry-btns {
vertical-align: middle;
.btn:not(:first-child) {
margin-left: 8px;
}
}
.dropdown-toggle,
.dropdown-menu {
color: $table-text-gray;
.fa {
color: $table-text-gray;
margin-right: 6px;
font-size: 14px;
}
}
.btn-remove {
color: $white-light;
}
.btn-group {
&.open {
.btn-default {
background-color: $white-normal;
border-color: $border-white-normal;
}
}
}
}
.build-link {
a {
color: $gl-dark-link-color;
}
}
.btn-group.open .dropdown-toggle {
box-shadow: none;
}
}
...@@ -340,23 +340,30 @@ a.deploy-project-label { ...@@ -340,23 +340,30 @@ a.deploy-project-label {
.project-import { .project-import {
.form-group { .form-group {
margin-bottom: 0; margin-bottom: 5px;
} }
.import-buttons { .import-buttons {
padding-left: 0; padding-left: 0;
display: -webkit-flex; display: -webkit-flex;
display: flex; display: flex;
-webkit-flex-wrap: wrap; -webkit-flex-wrap: wrap;
flex-wrap: wrap; flex-wrap: wrap;
.btn { .btn {
margin-right: 10px; margin: 0 10px 10px 0;
padding: 8px 12px; padding: 8px;
} }
&> div {
margin-bottom: 14px; > div {
padding-left: 0; padding-left: 0;
&:last-child { &:last-child {
margin-bottom: 0; margin-bottom: 0;
.btn {
margin-right: 0;
}
} }
} }
} }
...@@ -475,6 +482,10 @@ pre.light-well { ...@@ -475,6 +482,10 @@ pre.light-well {
a:hover { a:hover {
text-decoration: none; text-decoration: none;
} }
> span {
margin-left: 10px;
}
} }
} }
...@@ -632,3 +643,9 @@ pre.light-well { ...@@ -632,3 +643,9 @@ pre.light-well {
width: 300px; width: 300px;
} }
} }
.compare-form-group {
.dropdown-menu {
width: 300px;
}
}
...@@ -185,7 +185,7 @@ ...@@ -185,7 +185,7 @@
padding-right: $gl-padding + 15px; padding-right: $gl-padding + 15px;
} }
.btn-search { .btn-search, .btn-new {
width: 100%; width: 100%;
margin-top: 5px; margin-top: 5px;
......
...@@ -32,11 +32,15 @@ ...@@ -32,11 +32,15 @@
border-color: $gl-gray; border-color: $gl-gray;
} }
&.ci-pending, &.ci-pending {
&.ci-running {
color: $gl-warning; color: $gl-warning;
border-color: $gl-warning; border-color: $gl-warning;
} }
&.ci-running {
color: $blue-normal;
border-color: $blue-normal;
}
} }
.ci-status-icon-success { .ci-status-icon-success {
...@@ -45,10 +49,12 @@ ...@@ -45,10 +49,12 @@
.ci-status-icon-failed { .ci-status-icon-failed {
color: $gl-danger; color: $gl-danger;
} }
.ci-status-icon-running,
.ci-status-icon-pending { .ci-status-icon-pending {
color: $gl-warning; color: $gl-warning;
} }
.ci-status-icon-running {
color: $blue-normal;
}
.ci-status-icon-canceled, .ci-status-icon-canceled,
.ci-status-icon-disabled, .ci-status-icon-disabled,
.ci-status-icon-not-found, .ci-status-icon-not-found,
......
...@@ -23,12 +23,11 @@ ...@@ -23,12 +23,11 @@
} }
&:hover { &:hover {
cursor: pointer;
td { td {
background-color: $row-hover; background-color: $row-hover;
border-top: 1px solid $row-hover-border; border-top: 1px solid $row-hover-border;
border-bottom: 1px solid $row-hover-border; border-bottom: 1px solid $row-hover-border;
cursor: pointer;
} }
} }
......
...@@ -5,8 +5,10 @@ class Admin::BuildsController < Admin::ApplicationController ...@@ -5,8 +5,10 @@ class Admin::BuildsController < Admin::ApplicationController
@builds = @all_builds.order('created_at DESC') @builds = @all_builds.order('created_at DESC')
@builds = @builds =
case @scope case @scope
when 'pending'
@builds.pending.reverse_order
when 'running' when 'running'
@builds.running_or_pending.reverse_order @builds.running.reverse_order
when 'finished' when 'finished'
@builds.finished @builds.finished
else else
......
...@@ -344,10 +344,6 @@ class ApplicationController < ActionController::Base ...@@ -344,10 +344,6 @@ class ApplicationController < ActionController::Base
session[:skip_tfa] && session[:skip_tfa] > Time.current session[:skip_tfa] && session[:skip_tfa] > Time.current
end end
def browser_supports_u2f?
browser.chrome? && browser.version.to_i >= 41 && !browser.device.mobile?
end
def redirect_to_home_page_url? def redirect_to_home_page_url?
# If user is not signed-in and tries to access root_path - redirect him to landing page # If user is not signed-in and tries to access root_path - redirect him to landing page
# Don't redirect to the default URL to prevent endless redirections # Don't redirect to the default URL to prevent endless redirections
......
...@@ -57,7 +57,7 @@ module AuthenticatesWithTwoFactor ...@@ -57,7 +57,7 @@ module AuthenticatesWithTwoFactor
# Authenticate using the response from a U2F (universal 2nd factor) device # Authenticate using the response from a U2F (universal 2nd factor) device
def authenticate_with_two_factor_via_u2f(user) def authenticate_with_two_factor_via_u2f(user)
if U2fRegistration.authenticate(user, u2f_app_id, user_params[:device_response], session[:challenges]) if U2fRegistration.authenticate(user, u2f_app_id, user_params[:device_response], session[:challenge])
# Remove any lingering user data from login # Remove any lingering user data from login
session.delete(:otp_user_id) session.delete(:otp_user_id)
session.delete(:challenges) session.delete(:challenges)
...@@ -77,11 +77,9 @@ module AuthenticatesWithTwoFactor ...@@ -77,11 +77,9 @@ module AuthenticatesWithTwoFactor
if key_handles.present? if key_handles.present?
sign_requests = u2f.authentication_requests(key_handles) sign_requests = u2f.authentication_requests(key_handles)
challenges = sign_requests.map(&:challenge) session[:challenge] ||= u2f.challenge
session[:challenges] = challenges gon.push(u2f: { challenge: session[:challenge], app_id: u2f_app_id,
gon.push(u2f: { challenges: challenges, app_id: u2f_app_id, sign_requests: sign_requests })
sign_requests: sign_requests,
browser_supports_u2f: browser_supports_u2f? })
end end
end end
end end
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
class Dashboard::TodosController < Dashboard::ApplicationController class Dashboard::TodosController < Dashboard::ApplicationController
include TodosHelper
before_action :find_todos, only: [:index, :destroy_all] before_action :find_todos, only: [:index, :destroy_all]
def index def index
...@@ -13,7 +11,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController ...@@ -13,7 +11,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController
respond_to do |format| respond_to do |format|
format.html { redirect_to dashboard_todos_path, notice: 'Todo was successfully marked as done.' } format.html { redirect_to dashboard_todos_path, notice: 'Todo was successfully marked as done.' }
format.js { head :ok } format.js { head :ok }
format.json { render json: { count: todos_pending_count, done_count: todos_done_count } } format.json { render json: todos_counts }
end end
end end
...@@ -23,7 +21,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController ...@@ -23,7 +21,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController
respond_to do |format| respond_to do |format|
format.html { redirect_to dashboard_todos_path, notice: 'All todos were marked as done.' } format.html { redirect_to dashboard_todos_path, notice: 'All todos were marked as done.' }
format.js { head :ok } format.js { head :ok }
format.json { render json: { count: todos_pending_count, done_count: todos_done_count } } format.json { render json: todos_counts }
end end
end end
...@@ -36,4 +34,11 @@ class Dashboard::TodosController < Dashboard::ApplicationController ...@@ -36,4 +34,11 @@ class Dashboard::TodosController < Dashboard::ApplicationController
def find_todos def find_todos
@todos ||= TodosFinder.new(current_user, params).execute @todos ||= TodosFinder.new(current_user, params).execute
end end
def todos_counts
{
count: TodosFinder.new(current_user, state: :pending).execute.count,
done_count: TodosFinder.new(current_user, state: :done).execute.count
}
end
end end
...@@ -12,13 +12,12 @@ class HelpController < ApplicationController ...@@ -12,13 +12,12 @@ class HelpController < ApplicationController
end end
def show def show
@category = clean_path_info(path_params[:category]) @path = clean_path_info(path_params[:path])
@file = path_params[:file]
respond_to do |format| respond_to do |format|
format.any(:markdown, :md, :html) do format.any(:markdown, :md, :html) do
# Note: We are purposefully NOT using `Rails.root.join` # Note: We are purposefully NOT using `Rails.root.join`
path = File.join(Rails.root, 'doc', @category, "#{@file}.md") path = File.join(Rails.root, 'doc', "#{@path}.md")
if File.exist?(path) if File.exist?(path)
@markdown = File.read(path) @markdown = File.read(path)
...@@ -33,7 +32,7 @@ class HelpController < ApplicationController ...@@ -33,7 +32,7 @@ class HelpController < ApplicationController
# Allow access to images in the doc folder # Allow access to images in the doc folder
format.any(:png, :gif, :jpeg) do format.any(:png, :gif, :jpeg) do
# Note: We are purposefully NOT using `Rails.root.join` # Note: We are purposefully NOT using `Rails.root.join`
path = File.join(Rails.root, 'doc', @category, "#{@file}.#{params[:format]}") path = File.join(Rails.root, 'doc', "#{@path}.#{params[:format]}")
if File.exist?(path) if File.exist?(path)
send_file(path, disposition: 'inline') send_file(path, disposition: 'inline')
...@@ -57,8 +56,7 @@ class HelpController < ApplicationController ...@@ -57,8 +56,7 @@ class HelpController < ApplicationController
private private
def path_params def path_params
params.require(:category) params.require(:path)
params.require(:file)
params params
end end
......
...@@ -107,7 +107,11 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController ...@@ -107,7 +107,11 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
# Only allow properly saved users to login. # Only allow properly saved users to login.
if @user.persisted? && @user.valid? if @user.persisted? && @user.valid?
log_audit_event(@user, with: oauth['provider']) log_audit_event(@user, with: oauth['provider'])
sign_in_and_redirect(@user) if @user.two_factor_enabled?
prompt_for_two_factor(@user)
else
sign_in_and_redirect(@user)
end
else else
error_message = @user.errors.full_messages.to_sentence error_message = @user.errors.full_messages.to_sentence
......
...@@ -100,7 +100,6 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController ...@@ -100,7 +100,6 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
gon.push(u2f: { challenges: session[:challenges], app_id: u2f_app_id, gon.push(u2f: { challenges: session[:challenges], app_id: u2f_app_id,
register_requests: registration_requests, register_requests: registration_requests,
sign_requests: sign_requests, sign_requests: sign_requests })
browser_supports_u2f: browser_supports_u2f? })
end end
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
......
...@@ -10,8 +10,10 @@ class Projects::BuildsController < Projects::ApplicationController ...@@ -10,8 +10,10 @@ class Projects::BuildsController < Projects::ApplicationController
@builds = @all_builds.order('created_at DESC') @builds = @all_builds.order('created_at DESC')
@builds = @builds =
case @scope case @scope
when 'pending'
@builds.pending.reverse_order
when 'running' when 'running'
@builds.running_or_pending.reverse_order @builds.running.reverse_order
when 'finished' when 'finished'
@builds.finished @builds.finished
else else
......
...@@ -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
...@@ -12,6 +13,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -12,6 +13,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
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,8 +56,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -53,8 +56,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def show def show
respond_to do |format| respond_to do |format|
format.html format.html { define_discussion_vars }
format.json do format.json do
render json: @merge_request render json: @merge_request
end end
...@@ -78,35 +81,38 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -78,35 +81,38 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@merge_request_diff = @merge_request.merge_request_diff @merge_request_diff = @merge_request.merge_request_diff
@commit = @merge_request.diff_head_commit
@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 { define_discussion_vars }
format.json { render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") } } format.json { render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") } }
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 do
define_discussion_vars
render 'show'
end
format.json do format.json do
# Get commits from repository # Get commits from repository
# or from cache if already merged # or from cache if already merged
...@@ -121,14 +127,17 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -121,14 +127,17 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def builds def builds
respond_to do |format| respond_to do |format|
format.html { render 'show' } format.html do
define_discussion_vars
render 'show'
end
format.json { render json: { html: view_to_html_string('projects/merge_requests/show/_builds') } } format.json { render json: { html: view_to_html_string('projects/merge_requests/show/_builds') } }
end end
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
...@@ -352,14 +361,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -352,14 +361,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@merge_request.unlock_mr @merge_request.unlock_mr
@merge_request.close @merge_request.close
end end
if request.format == :html || action_name == 'show'
define_show_html_vars
end
end end
# Discussion tab data is only required on html requests # Discussion tab data is rendered on html responses of actions
def define_show_html_vars # :show, :diff, :commits, :builds. but not when request the data through AJAX
def define_discussion_vars
# Build a note object for comment form # Build a note object for comment form
@note = @project.notes.new(noteable: @noteable) @note = @project.notes.new(noteable: @noteable)
...@@ -384,6 +390,30 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -384,6 +390,30 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@pipelines = [@pipeline].compact @pipelines = [@pipeline].compact
end 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
def invalid_mr def invalid_mr
# Render special view for MR with removed source or target branch # Render special view for MR with removed source or target branch
render 'invalid' render 'invalid'
...@@ -412,4 +442,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -412,4 +442,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
...@@ -5,7 +5,7 @@ class Projects::TodosController < Projects::ApplicationController ...@@ -5,7 +5,7 @@ class Projects::TodosController < Projects::ApplicationController
todo = TodoService.new.mark_todo(issuable, current_user) todo = TodoService.new.mark_todo(issuable, current_user)
render json: { render json: {
count: current_user.todos_pending_count, count: TodosFinder.new(current_user, state: :pending).execute.count,
delete_path: dashboard_todo_path(todo) delete_path: dashboard_todo_path(todo)
} }
end end
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
# action_id: integer # action_id: integer
# author_id: integer # author_id: integer
# project_id; integer # project_id; integer
# state: 'pending' or 'done' # state: 'pending' (default) or 'done'
# type: 'Issue' or 'MergeRequest' # type: 'Issue' or 'MergeRequest'
# #
...@@ -37,7 +37,7 @@ class TodosFinder ...@@ -37,7 +37,7 @@ class TodosFinder
private private
def action_id? def action_id?
action_id.present? && [Todo::ASSIGNED, Todo::MENTIONED, Todo::BUILD_FAILED, Todo::MARKED].include?(action_id.to_i) action_id.present? && Todo::ACTION_NAMES.has_key?(action_id.to_i)
end end
def action_id def action_id
......
...@@ -31,7 +31,7 @@ module AppearancesHelper ...@@ -31,7 +31,7 @@ module AppearancesHelper
end end
end end
def navbar_icon(icon_name, size: 16) def custom_icon(icon_name, size: 16)
render "shared/icons/#{icon_name}.svg", size: size render "shared/icons/#{icon_name}.svg", size: size
end end
end end
module BlobHelper module BlobHelper
def highlighter(blob_name, blob_content, repository: nil, nowrap: false) def highlight(blob_name, blob_content, repository: nil, plain: false)
Gitlab::Highlight.new(blob_name, blob_content, nowrap: nowrap, repository: repository) highlighted = Gitlab::Highlight.highlight(blob_name, blob_content, plain: plain, repository: repository)
end raw %(<pre class="code highlight"><code>#{highlighted}</code></pre>)
def highlight(blob_name, blob_content, repository: nil, nowrap: false, plain: false)
Gitlab::Highlight.highlight(blob_name, blob_content, nowrap: nowrap, plain: plain, repository: repository)
end end
def no_highlight_files def no_highlight_files
......
...@@ -15,29 +15,13 @@ module ButtonHelper ...@@ -15,29 +15,13 @@ module ButtonHelper
# #
# See http://clipboardjs.com/#usage # See http://clipboardjs.com/#usage
def clipboard_button(data = {}) def clipboard_button(data = {})
data = { toggle: 'tooltip', placement: 'bottom', container: 'body' }.merge(data)
content_tag :button, content_tag :button,
icon('clipboard'), icon('clipboard'),
class: "btn btn-clipboard", class: "btn btn-clipboard",
data: data, data: data,
type: :button type: :button,
end title: "Copy to Clipboard"
# Output a "Copy to Clipboard" button with a custom CSS class
#
# data - Data attributes passed to `content_tag`
# css_class - Class passed to the `content_tag`
#
# Examples:
#
# # Define the target element
# clipboard_button_with_class({clipboard_target: "div#foo"}, css_class: "btn-clipboard")
# # => "<button class='btn btn-clipboard' data-clipboard-target='div#foo'>...</button>"
def clipboard_button_with_class(data = {}, css_class: 'btn-clipboard')
content_tag :button,
icon('clipboard'),
class: "btn #{css_class}",
data: data,
type: :button
end end
def http_clone_button(project, placement = 'right', append_link: true) def http_clone_button(project, placement = 'right', append_link: true)
......
...@@ -29,8 +29,10 @@ module CiStatusHelper ...@@ -29,8 +29,10 @@ module CiStatusHelper
'check' 'check'
when 'failed' when 'failed'
'close' 'close'
when 'running', 'pending' when 'pending'
'clock-o' 'clock-o'
when 'running'
'spinner'
else else
'circle' 'circle'
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)
...@@ -35,7 +37,7 @@ module DiffHelper ...@@ -35,7 +37,7 @@ module DiffHelper
end end
def unfold_bottom_class(bottom) def unfold_bottom_class(bottom)
bottom ? 'js-unfold-bottom' : '' bottom ? 'js-unfold js-unfold-bottom' : ''
end end
def unfold_class(unfold) def unfold_class(unfold)
...@@ -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
......
...@@ -61,7 +61,7 @@ module IssuablesHelper ...@@ -61,7 +61,7 @@ module IssuablesHelper
output = content_tag :strong, "#{text} #{issuable.to_reference}", class: "identifier" output = content_tag :strong, "#{text} #{issuable.to_reference}", class: "identifier"
output << " opened #{time_ago_with_tooltip(issuable.created_at)} by ".html_safe output << " opened #{time_ago_with_tooltip(issuable.created_at)} by ".html_safe
output << content_tag(:strong) do output << content_tag(:strong) do
author_output = link_to_member(project, issuable.author, size: 24, mobile_classes: "hidden-xs") author_output = link_to_member(project, issuable.author, size: 24, mobile_classes: "hidden-xs", tooltip: true)
author_output << link_to_member(project, issuable.author, size: 24, by_username: true, avatar: false, mobile_classes: "hidden-sm hidden-md hidden-lg") author_output << link_to_member(project, issuable.author, size: 24, by_username: true, avatar: false, mobile_classes: "hidden-sm hidden-md hidden-lg")
end end
end end
......
...@@ -96,4 +96,8 @@ module MergeRequestsHelper ...@@ -96,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
...@@ -24,7 +24,15 @@ module NotesHelper ...@@ -24,7 +24,15 @@ module NotesHelper
}.to_json }.to_json
end end
def link_to_new_diff_note(line_code, position, line_type = nil) def diff_view_data
return {} unless @comments_target
@comments_target.slice(:noteable_id, :noteable_type, :commit_id)
end
def diff_view_line_data(line_code, position, line_type)
return if @diff_notes_disabled
use_legacy_diff_note = @use_legacy_diff_notes use_legacy_diff_note = @use_legacy_diff_notes
# If the controller doesn't force the use of legacy diff notes, we # If the controller doesn't force the use of legacy diff notes, we
# determine this on a line-by-line basis by seeing if there already exist # determine this on a line-by-line basis by seeing if there already exist
...@@ -41,11 +49,8 @@ module NotesHelper ...@@ -41,11 +49,8 @@ module NotesHelper
end end
data = { data = {
noteable_type: @comments_target[:noteable_type], line_code: line_code,
noteable_id: @comments_target[:noteable_id], line_type: line_type,
commit_id: @comments_target[:commit_id],
line_type: line_type,
line_code: line_code
} }
if use_legacy_diff_note if use_legacy_diff_note
...@@ -73,11 +78,7 @@ module NotesHelper ...@@ -73,11 +78,7 @@ module NotesHelper
) )
end end
button_tag(class: 'btn add-diff-note js-add-diff-note-button', data
data: data,
title: 'Add a comment to this line') do
icon('comment-o')
end
end end
def link_to_reply_discussion(note, line_type = nil) def link_to_reply_discussion(note, line_type = nil)
......
...@@ -19,7 +19,7 @@ module ProjectsHelper ...@@ -19,7 +19,7 @@ module ProjectsHelper
end end
def link_to_member(project, author, opts = {}, &block) def link_to_member(project, author, opts = {}, &block)
default_opts = { avatar: true, name: true, size: 16, author_class: 'author', title: ":name" } default_opts = { avatar: true, name: true, size: 16, author_class: 'author', title: ":name", tooltip: false }
opts = default_opts.merge(opts) opts = default_opts.merge(opts)
return "(deleted)" unless author return "(deleted)" unless author
...@@ -33,7 +33,8 @@ module ProjectsHelper ...@@ -33,7 +33,8 @@ module ProjectsHelper
if opts[:by_username] if opts[:by_username]
author_html << content_tag(:span, sanitize("@#{author.username}"), class: opts[:author_class]) if opts[:name] author_html << content_tag(:span, sanitize("@#{author.username}"), class: opts[:author_class]) if opts[:name]
else else
author_html << content_tag(:span, sanitize(author.name), class: opts[:author_class]) if opts[:name] tooltip_data = { placement: 'top' }
author_html << content_tag(:span, sanitize(author.name), class: [opts[:author_class], ('has-tooltip' if opts[:tooltip])], title: (author.to_reference if opts[:tooltip]), data: (tooltip_data if opts[:tooltip])) if opts[:name]
end end
author_html << capture(&block) if block author_html << capture(&block) if block
...@@ -60,7 +61,7 @@ module ProjectsHelper ...@@ -60,7 +61,7 @@ module ProjectsHelper
project_link = link_to simple_sanitize(project.name), project_path(project), { class: "project-item-select-holder" } project_link = link_to simple_sanitize(project.name), project_path(project), { class: "project-item-select-holder" }
if current_user if current_user
project_link << icon("chevron-down", class: "dropdown-toggle-caret js-projects-dropdown-toggle", data: { target: ".js-dropdown-menu-projects", toggle: "dropdown" }) project_link << icon("chevron-down", class: "dropdown-toggle-caret js-projects-dropdown-toggle", aria: { label: "Toggle switch project dropdown" }, data: { target: ".js-dropdown-menu-projects", toggle: "dropdown" })
end end
full_title = "#{namespace_link} / #{project_link}".html_safe full_title = "#{namespace_link} / #{project_link}".html_safe
......
...@@ -43,15 +43,15 @@ module SearchHelper ...@@ -43,15 +43,15 @@ module SearchHelper
# Autocomplete results for internal help pages # Autocomplete results for internal help pages
def help_autocomplete def help_autocomplete
[ [
{ category: "Help", label: "API Help", url: help_page_path("api", "README") }, { category: "Help", label: "API Help", url: help_page_path("api/README") },
{ category: "Help", label: "Markdown Help", url: help_page_path("markdown", "markdown") }, { category: "Help", label: "Markdown Help", url: help_page_path("markdown/markdown") },
{ category: "Help", label: "Permissions Help", url: help_page_path("permissions", "permissions") }, { category: "Help", label: "Permissions Help", url: help_page_path("user/permissions") },
{ category: "Help", label: "Public Access Help", url: help_page_path("public_access", "public_access") }, { category: "Help", label: "Public Access Help", url: help_page_path("public_access/public_access") },
{ category: "Help", label: "Rake Tasks Help", url: help_page_path("raketasks", "README") }, { category: "Help", label: "Rake Tasks Help", url: help_page_path("raketasks/README") },
{ category: "Help", label: "SSH Keys Help", url: help_page_path("ssh", "README") }, { category: "Help", label: "SSH Keys Help", url: help_page_path("ssh/README") },
{ category: "Help", label: "System Hooks Help", url: help_page_path("system_hooks", "system_hooks") }, { category: "Help", label: "System Hooks Help", url: help_page_path("system_hooks/system_hooks") },
{ category: "Help", label: "Webhooks Help", url: help_page_path("web_hooks", "web_hooks") }, { category: "Help", label: "Webhooks Help", url: help_page_path("web_hooks/web_hooks") },
{ category: "Help", label: "Workflow Help", url: help_page_path("workflow", "README") }, { category: "Help", label: "Workflow Help", url: help_page_path("workflow/README") },
] ]
end end
......
module TodosHelper module TodosHelper
def todos_pending_count def todos_pending_count
TodosFinder.new(current_user, state: :pending).execute.count @todos_pending_count ||= TodosFinder.new(current_user, state: :pending).execute.count
end end
def todos_done_count def todos_done_count
TodosFinder.new(current_user, state: :done).execute.count @todos_done_count ||= TodosFinder.new(current_user, state: :done).execute.count
end end
def todo_action_name(todo) def todo_action_name(todo)
...@@ -13,6 +13,7 @@ module TodosHelper ...@@ -13,6 +13,7 @@ module TodosHelper
when Todo::MENTIONED then 'mentioned you on' when Todo::MENTIONED then 'mentioned you on'
when Todo::BUILD_FAILED then 'The build failed for your' when Todo::BUILD_FAILED then 'The build failed for your'
when Todo::MARKED then 'added a todo for' when Todo::MARKED then 'added a todo for'
when Todo::APPROVAL_REQUIRED then 'set you as an approver for'
end end
end end
......
module U2fHelper
def inject_u2f_api?
browser.chrome? && browser.version.to_i >= 41 && !browser.device.mobile?
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
...@@ -29,7 +29,8 @@ module Emails ...@@ -29,7 +29,8 @@ module Emails
# used in notify layout # used in notify layout
@target_url = @message.target_url @target_url = @message.target_url
@project = Project.find(project_id) @project = Project.find(project_id)
@diff_notes_disabled = true
add_project_headers add_project_headers
headers['X-GitLab-Author'] = @message.author_username headers['X-GitLab-Author'] = @message.author_username
......
...@@ -204,7 +204,8 @@ class Ability ...@@ -204,7 +204,8 @@ class Ability
:download_code, :download_code,
:fork_project, :fork_project,
:read_commit_status, :read_commit_status,
:read_pipeline :read_pipeline,
:read_container_image
] ]
end end
......
...@@ -5,6 +5,7 @@ module Ci ...@@ -5,6 +5,7 @@ module Ci
belongs_to :erased_by, class_name: 'User' belongs_to :erased_by, class_name: 'User'
serialize :options serialize :options
serialize :yaml_variables
validates :coverage, numericality: true, allow_blank: true validates :coverage, numericality: true, allow_blank: true
validates_presence_of :ref validates_presence_of :ref
...@@ -52,7 +53,10 @@ module Ci ...@@ -52,7 +53,10 @@ module Ci
new_build.stage = build.stage new_build.stage = build.stage
new_build.stage_idx = build.stage_idx new_build.stage_idx = build.stage_idx
new_build.trigger_request = build.trigger_request new_build.trigger_request = build.trigger_request
new_build.yaml_variables = build.yaml_variables
new_build.when = build.when
new_build.user = user new_build.user = user
new_build.environment = build.environment
new_build.save new_build.save
MergeRequests::AddTodoWhenBuildFailsService.new(build.project, nil).close(new_build) MergeRequests::AddTodoWhenBuildFailsService.new(build.project, nil).close(new_build)
new_build new_build
...@@ -117,7 +121,12 @@ module Ci ...@@ -117,7 +121,12 @@ module Ci
end end
def variables def variables
predefined_variables + yaml_variables + project_variables + trigger_variables variables = []
variables += predefined_variables
variables += yaml_variables if yaml_variables
variables += project_variables
variables += trigger_variables
variables
end end
def merge_request def merge_request
...@@ -394,30 +403,6 @@ module Ci ...@@ -394,30 +403,6 @@ module Ci
self.update(erased_by: user, erased_at: Time.now, artifacts_expire_at: nil) self.update(erased_by: user, erased_at: Time.now, artifacts_expire_at: nil)
end end
def yaml_variables
global_yaml_variables + job_yaml_variables
end
def global_yaml_variables
if pipeline.config_processor
pipeline.config_processor.global_variables.map do |key, value|
{ key: key, value: value, public: true }
end
else
[]
end
end
def job_yaml_variables
if pipeline.config_processor
pipeline.config_processor.job_variables(name).map do |key, value|
{ key: key, value: value, public: true }
end
else
[]
end
end
def project_variables def project_variables
project.variables.map do |variable| project.variables.map do |variable|
{ key: variable.key, value: variable.value, public: false } { key: variable.key, value: variable.value, public: false }
......
...@@ -6,6 +6,8 @@ module Ci ...@@ -6,6 +6,8 @@ module Ci
self.table_name = 'ci_commits' self.table_name = 'ci_commits'
belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id
belongs_to :user
has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id
has_many :builds, class_name: 'Ci::Build', foreign_key: :commit_id has_many :builds, class_name: 'Ci::Build', foreign_key: :commit_id
has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest', foreign_key: :commit_id has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest', foreign_key: :commit_id
...@@ -223,6 +225,8 @@ module Ci ...@@ -223,6 +225,8 @@ module Ci
end end
def keep_around_commits def keep_around_commits
return unless project
project.repository.keep_around(self.sha) project.repository.keep_around(self.sha)
project.repository.keep_around(self.before_sha) project.repository.keep_around(self.before_sha)
end end
......
...@@ -65,8 +65,7 @@ module Awardable ...@@ -65,8 +65,7 @@ module Awardable
def create_award_emoji(name, current_user) def create_award_emoji(name, current_user)
return unless emoji_awardable? return unless emoji_awardable?
award_emoji.create(name: normalize_name(name), user: current_user)
award_emoji.create(name: name, user: current_user)
end end
def remove_award_emoji(name, current_user) def remove_award_emoji(name, current_user)
...@@ -80,4 +79,10 @@ module Awardable ...@@ -80,4 +79,10 @@ module Awardable
create_award_emoji(emoji_name, current_user) create_award_emoji(emoji_name, current_user)
end end
end end
private
def normalize_name(name)
Gitlab::AwardEmoji.normalize_emoji_name(name)
end
end end
...@@ -14,14 +14,14 @@ module Mentionable ...@@ -14,14 +14,14 @@ module Mentionable
attr = attr.to_s attr = attr.to_s
mentionable_attrs << [attr, options] mentionable_attrs << [attr, options]
end end
end
included do
# Accessor for attributes marked mentionable. # Accessor for attributes marked mentionable.
def mentionable_attrs cattr_accessor :mentionable_attrs, instance_accessor: false do
@mentionable_attrs ||= [] []
end end
end
included do
if self < Participable if self < Participable
participant -> (user, ext) { all_references(user, extractor: ext) } participant -> (user, ext) { all_references(user, extractor: ext) }
end end
......
...@@ -41,9 +41,12 @@ module Participable ...@@ -41,9 +41,12 @@ module Participable
def participant(attr) def participant(attr)
participant_attrs << attr participant_attrs << attr
end end
end
def participant_attrs included do
@participant_attrs ||= [] # Accessor for participant attributes.
cattr_accessor :participant_attrs, instance_accessor: false do
[]
end end
end end
......
...@@ -52,14 +52,17 @@ class Label < ActiveRecord::Base ...@@ -52,14 +52,17 @@ class Label < ActiveRecord::Base
# This pattern supports cross-project references. # This pattern supports cross-project references.
# #
def self.reference_pattern def self.reference_pattern
# NOTE: The id pattern only matches when all characters on the expression
# are digits, so it will match ~2 but not ~2fa because that's probably a
# label name and we want it to be matched as such.
@reference_pattern ||= %r{ @reference_pattern ||= %r{
(#{Project.reference_pattern})? (#{Project.reference_pattern})?
#{Regexp.escape(reference_prefix)} #{Regexp.escape(reference_prefix)}
(?: (?:
(?<label_id>\d+) | # Integer-based label ID, or (?<label_id>\d+(?!\S\w)\b) | # Integer-based label ID, or
(?<label_name> (?<label_name>
[A-Za-z0-9_\-\?&]+ | # String-based single-word label title, or [A-Za-z0-9_\-\?\.&]+ | # String-based single-word label title, or
"[^,]+" # String-based multi-word label surrounded in quotes ".+?" # String-based multi-word label surrounded in quotes
) )
) )
}x }x
......
...@@ -38,7 +38,7 @@ class LegacyDiffNote < Note ...@@ -38,7 +38,7 @@ class LegacyDiffNote < Note
end end
def diff_line def diff_line
@diff_line ||= diff_file.line_for_line_code(self.line_code) @diff_line ||= diff_file.line_for_line_code(self.line_code) if diff_file
end end
def for_line?(line) def for_line?(line)
...@@ -55,7 +55,7 @@ class LegacyDiffNote < Note ...@@ -55,7 +55,7 @@ class LegacyDiffNote < Note
def active? def active?
return @active if defined?(@active) return @active if defined?(@active)
return true if for_commit? return true if for_commit?
return true unless self.diff return true unless diff_line
return false unless noteable return false unless noteable
noteable_diff = find_noteable_diff noteable_diff = find_noteable_diff
......
...@@ -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
......
...@@ -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([])
......
...@@ -10,6 +10,10 @@ class Note < ActiveRecord::Base ...@@ -10,6 +10,10 @@ class Note < ActiveRecord::Base
# Banzai::ObjectRenderer. # Banzai::ObjectRenderer.
attr_accessor :note_html attr_accessor :note_html
# An Array containing the number of visible references as generated by
# Banzai::ObjectRenderer
attr_accessor :user_visible_reference_count
default_value_for :system, false default_value_for :system, false
attr_mentionable :note, pipeline: :note attr_mentionable :note, pipeline: :note
...@@ -193,7 +197,15 @@ class Note < ActiveRecord::Base ...@@ -193,7 +197,15 @@ class Note < ActiveRecord::Base
end end
def cross_reference_not_visible_for?(user) def cross_reference_not_visible_for?(user)
cross_reference? && referenced_mentionables(user).empty? cross_reference? && !has_referenced_mentionables?(user)
end
def has_referenced_mentionables?(user)
if user_visible_reference_count.present?
user_visible_reference_count > 0
else
referenced_mentionables(user).any?
end
end end
def award_emoji? def award_emoji?
...@@ -217,8 +229,7 @@ class Note < ActiveRecord::Base ...@@ -217,8 +229,7 @@ class Note < ActiveRecord::Base
end end
def award_emoji_name def award_emoji_name
original_name = note.match(Banzai::Filter::EmojiFilter.emoji_pattern)[1] note.match(Banzai::Filter::EmojiFilter.emoji_pattern)[1]
Gitlab::AwardEmoji.normalize_emoji_name(original_name)
end end
private private
......
...@@ -470,8 +470,8 @@ class Project < ActiveRecord::Base ...@@ -470,8 +470,8 @@ class Project < ActiveRecord::Base
return super(value) unless Gitlab::UrlSanitizer.valid?(value) return super(value) unless Gitlab::UrlSanitizer.valid?(value)
import_url = Gitlab::UrlSanitizer.new(value) import_url = Gitlab::UrlSanitizer.new(value)
create_or_update_import_data(credentials: import_url.credentials)
super(import_url.sanitized_url) super(import_url.sanitized_url)
create_or_update_import_data(credentials: import_url.credentials)
end end
def import_url def import_url
...@@ -483,7 +483,13 @@ class Project < ActiveRecord::Base ...@@ -483,7 +483,13 @@ class Project < ActiveRecord::Base
end end
end end
def valid_import_url?
valid? || errors.messages[:import_url].nil?
end
def create_or_update_import_data(data: nil, credentials: nil) def create_or_update_import_data(data: nil, credentials: nil)
return unless import_url.present? && valid_import_url?
project_import_data = import_data || build_import_data project_import_data = import_data || build_import_data
if data if data
project_import_data.data ||= {} project_import_data.data ||= {}
...@@ -1038,8 +1044,8 @@ class Project < ActiveRecord::Base ...@@ -1038,8 +1044,8 @@ class Project < ActiveRecord::Base
pipelines.order(id: :desc).find_by(sha: sha, ref: ref) pipelines.order(id: :desc).find_by(sha: sha, ref: ref)
end end
def ensure_pipeline(sha, ref) def ensure_pipeline(sha, ref, current_user = nil)
pipeline(sha, ref) || pipelines.create(sha: sha, ref: ref) pipeline(sha, ref) || pipelines.create(sha: sha, ref: ref, user: current_user)
end end
def enable_ci def enable_ci
......
...@@ -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
......
class Todo < ActiveRecord::Base class Todo < ActiveRecord::Base
ASSIGNED = 1 ASSIGNED = 1
MENTIONED = 2 MENTIONED = 2
BUILD_FAILED = 3 BUILD_FAILED = 3
MARKED = 4 MARKED = 4
APPROVAL_REQUIRED = 5 # This is an EE-only feature
ACTION_NAMES = { ACTION_NAMES = {
ASSIGNED => :assigned, ASSIGNED => :assigned,
MENTIONED => :mentioned, MENTIONED => :mentioned,
BUILD_FAILED => :build_failed, BUILD_FAILED => :build_failed,
MARKED => :marked MARKED => :marked,
APPROVAL_REQUIRED => :approval_required
} }
belongs_to :author, class_name: "User" belongs_to :author, class_name: "User"
......
...@@ -85,9 +85,10 @@ class User < ActiveRecord::Base ...@@ -85,9 +85,10 @@ class User < ActiveRecord::Base
has_one :abuse_report, dependent: :destroy has_one :abuse_report, dependent: :destroy
has_many :spam_logs, dependent: :destroy has_many :spam_logs, dependent: :destroy
has_many :builds, dependent: :nullify, class_name: 'Ci::Build' has_many :builds, dependent: :nullify, class_name: 'Ci::Build'
has_many :pipelines, dependent: :nullify, class_name: 'Ci::Pipeline'
has_many :todos, dependent: :destroy has_many :todos, dependent: :destroy
has_many :notification_settings, dependent: :destroy has_many :notification_settings, dependent: :destroy
has_many :award_emoji, as: :awardable, dependent: :destroy has_many :award_emoji, dependent: :destroy
# #
# Validations # Validations
......
...@@ -36,7 +36,9 @@ module Ci ...@@ -36,7 +36,9 @@ module Ci
:allow_failure, :allow_failure,
:stage, :stage,
:stage_idx, :stage_idx,
:environment) :environment,
:when,
:yaml_variables)
build_attrs.merge!(pipeline: @pipeline, build_attrs.merge!(pipeline: @pipeline,
ref: @pipeline.ref, ref: @pipeline.ref,
......
...@@ -2,6 +2,7 @@ module Ci ...@@ -2,6 +2,7 @@ module Ci
class CreatePipelineService < BaseService class CreatePipelineService < BaseService
def execute def execute
pipeline = project.pipelines.new(params) pipeline = project.pipelines.new(params)
pipeline.user = current_user
unless ref_names.include?(params[:ref]) unless ref_names.include?(params[:ref])
pipeline.errors.add(:base, 'Reference not found') pipeline.errors.add(:base, 'Reference not found')
......
...@@ -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
......
...@@ -14,7 +14,13 @@ class CreateCommitBuildsService ...@@ -14,7 +14,13 @@ class CreateCommitBuildsService
return false return false
end end
@pipeline = Ci::Pipeline.new(project: project, sha: sha, ref: ref, before_sha: before_sha, tag: tag) @pipeline = Ci::Pipeline.new(
project: project,
sha: sha,
ref: ref,
before_sha: before_sha,
tag: tag,
user: user)
## ##
# Skip creating pipeline if no gitlab-ci.yml is found # Skip creating pipeline if no gitlab-ci.yml is found
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment